Supposons que vous ayez un long tableau de caractères qui sont soit 1 soit 0, un peu comme un vecteur de bits, mais sur une colonne de base de données. Comment pourriez-vous faire une requête pour savoir quelles valeurs sont définies ou non définies ? Supposons que vous ayez besoin de savoir si les caractères 500 et 1500 sont "vrais" ou non.
Réponses
Trop de publicités?SELECT
Id
FROM
BitVectorTable
WHERE
SUBSTRING(BitVector, 500, 1) = '1'
AND SUBSTRING(BitVector, 1000, 1) = '1'
Aucun index ne peut être utilisé pour ce type de requête. Lorsque vous avez beaucoup de lignes, cela devient très vite lent.
Edit : Sur SQL Server au moins, toutes les fonctions de chaînes de caractères intégrées sont déterministe . Cela signifie que vous pourriez envisager la possibilité de créer des colonnes calculées basées sur les résultats de SUBSTRING() pour l'ensemble de la valeur combinée, mettre un index sur chacun d'entre eux . Les insertions seront plus lentes, la taille des tables augmentera, mais les recherches seront très rapides.
SELECT
Id
FROM
BitVectorTable
WHERE
BitVector_0500 = '1'
AND BitVector_1000 = '1'
Edit #2 : Le limites pour SQL Server sont :
- 1 024 colonnes par table normale
- 30 000 colonnes par table "large
Dans MySQL, l'utilisation de sous-chaîne comme
select foo from bar
where substring(col, 500,1)='1' and substring(col, 1500,1)='1';
Cela sera cependant assez inefficace, vous devriez peut-être repenser votre schéma. Par exemple, vous pourriez stocker chaque bit séparément afin d'échanger de l'espace contre de la vitesse...
create table foo
(
id int not null,
bar varchar(128),
primary key(id)
);
create table foobit
(
int foo_id int not null,
int idx int not null,
value tinyint not null,
primary key(foo_id,idx),
index(idx,value)
);
Qui serait interrogé
select foo.bar from foo
inner join foobit as bit500
on(foo.id=bit500.foo_id and bit500.idx=500)
inner join foobit as bit1500
on(foo.id=bit1500.foo_id and bit1500.idx=1500)
where
bit500.value=1 and bit1500.value=1;
Elle consomme évidemment plus d'espace de stockage, mais devrait être plus rapide pour ces opérations d'interrogation puisqu'un index sera utilisé.
Je convertirais la colonne en plusieurs colonnes de bits et réécrirais le code correspondant - les masques de bits sont tellement plus rapides que les comparaisons de chaînes. Mais si vous ne pouvez pas faire cela, vous devez utiliser des fonctions spécifiques à la base de données. Les expressions régulières pourraient être une option
-- Flavor: MySql
SELECT * FROM table WHERE column REGEXP "^.{499}1.{999}1"