2009-10-20 10 views
4

J'ai une table avec la structure suivante:Comment créer une requête GROUP BY SUBSTRING plus rapidement?

id bigNumber   text 
30011010233 "an item with some text" 
30011014563 "another item with some more text" 
3 3120323434432211133 "more...." 
. 
. 
. 

Le tableau contient environ 50 000 dossiers. Je veux faire la requête suivante, mais il est lent:

SELECT COUNT(*), 
     bigNumber 
    FROM items 
GROUP BY substr(bigNumber, 1, X) 

où X varie de 2 et 19.

Serait-il plus rapide de créer 19 colonnes avec des parties du numéro dans chaque colonne pour pouvoir utiliser un index?

Répondre

-1

Je pense que le résultat que vous recherchez est LIKE _X%. Cela n'utilisera pas l'index si.

SELECT count(*) FROM items WHERE bignumber LIKE "_2%" 
SELECT count(*) FROM items WHERE bignumber LIKE "_19%" 

_ signifie un caractère

% signifie un nombre de caractères

Voir MySQL docs pour plus d'informations.

+0

Merci, mais je dois utiliser la méthode GROUP BY. X varie de 1 à 19, c'est-à-dire que je veux regrouper les éléments en fonction des premiers nombres X dans bigNumber. – Eric

+0

Je suggérerais de séparer les parties importantes du grand nombre puis d'utiliser la commande par. –

0

Vous pouvez utiliser un index sans ajouter de colonnes, il suffit de créer un index sur votre colonne bigNumber:

create index bignum_index on items (bigNumber); 

peut être utilisé l'index sur un varchar (bigNumber est un varchar, non?) Pour rechercher n'importe quel préfixe de chaîne. Cela dit, vous devrez effectuer une analyse de table complète pour répondre à votre requête. Un index ne vous aidera donc pas beaucoup.

+0

Merci à tous pour vos réponses incroyablement rapides !! Est-ce que quelqu'un sait si je pourrais justifier l'utilisation de 19 colonnes à la place? Je sais que c'est une solution sale, mais ma seule préoccupation en ce moment est la vitesse :) Peut-être qu'il y a une autre solution là-bas, autre chose que substr? Pour clarifier: la requête réelle que je cours est un peu différente et nécessite un groupe par puisque je demande aussi moy pour quelques cols basés sur le groupe. Merci encore! – Eric

+0

Tant que vous avez encore besoin d'une analyse de table complète, ajouter plus de données à votre table va rendre votre requête plus lente. Donc, si c'est «sale» n'est pas pertinent - ce n'est pas une solution du tout. –

2

Je suggère au lieu de 19 colonnes distinctes, peut-être seulement 3 ou 4, comme ceci:

alter table items 
add column bignumber_l1 char(1) 
, add column bignumber_l3 varchar(3) 
, add column bignumber_l6 varchar(6); 

update items 
set bignumber_l1 = left(bignumber, 1) 
, bignumber_l3 = left(bignumber, 3) 
, bignumber_l6 = left(bignumber, 6); 

alter table items 
add index bignumber_l1 
, add index bignumber_l3 
, add index bignumber_l6; 

puis quand vous interrogez pour les chaînes de longueur x, écrire la requête avec le plus long match sans aller plus :

SELECT COUNT(*), 
     bigNumber 
    FROM items 
GROUP BY bignumber_l3, substr(bigNumber, 1, 4) 

cette requête peut utiliser un index et améliorer vos performances de manière significative. notez que puisque vous demandez la table entière, mysql peut décider que vous avez besoin d'une analyse de table même avec les index ci-dessus, vous devrez donc utiliser FORCE INDEX.

Questions connexes