2016-10-09 2 views
1

Décrire:mysql requête lent pour peu de données mis

Le tableau profit a environ 20 colonnes, et aucune grande colonne comme text, et ont deux indexs:

  1. index idx_uid sur la colonne uid
  2. index uid_acc_fId_date sur la colonne uid,acc,fid and date

La requête SQL lente est:

select * from profit where (((uid='1111') and (flag=32)) and (fId='2222')) and (date='20161008') limit 1; 

et expliquer la sortie est:

id:1 
select_type:SIMPLE 
table:profit 
type:ref 
possible_keys:uid_acc_fId_date 
key:uid_acc_fId_date 
key_len:4 
ref:const 
rows:267 
Extra:Using where 

Execute SQL avec sql_no_cache passera environ 2 s, et exécuter le même sql avec sql_no_cache deuxième fois dépenser environ 0,1s.

Env:

  1. mysql 5.5.49-37.9, InnoDB, Percona
  2. SATA HDD
  3. Le bénéfice de table a environ un million de lignes
  4. Centos 2.6 noyau
  5. lignes compte pour uid=1111 est seulement

PS:

Mysql sera tous les jours de sauvegarde à minuit, et innodb_old_blocks_time est 0, je pense que la sauvegarde videra toutes les données de tampon chaud pool.But même il passe trop de temps pour faire la ci-dessus query.So, est-ce le problème de disque

+0

Combien de lignes sont trouvées si vous supprimez 'flag = 32'? Parce que pour 'flag' vous n'avez pas spécifié d'index, mysql a besoin de toutes les lignes ayant' uid = '1111' et fId = '2222' et date = '20161008'' et ensuite vérifie chacune d'elles si le 'drapeau 'est' 32'. –

+0

Merci pour votre temps. Et toutes les lignes de données pour 'uid = 1111' ont seulement 270 lignes –

+0

S'il vous plaît fournir' SHOW CREATE TABLE'. –

Répondre

1

expansion sur le commentaire ci-dessus, l'indice changement uid_acc_fId_date à (uid, fid, date, acc) et changer la requête:

SELECT columns 
    , I 
    , actually 
    , want 
    FROM profit 
WHERE uid = 1111 
    AND fId = 2222 
    AND date='20161008' 
    AND flag = 32 
ORDER 
    BY uid 
LIMIT 1; 
0

Utilisez toujours le nom de colonne lorsque vous essayez de sélectionner une requête. Comme le nom SELECT, nom_classe de nom_table;

+0

Merci! C'est une bonne suggestion, peut-être que je vais essayer, mais c'est très difficile pour notre projet, car il y en a trop à modifier, et il est risqué de modifier le code précédent.En fait, je ne pense pas que ce soit la clé pour cette question –

+0

Bon conseil, mais probablement pas pertinent pour la lenteur ici. –

0

Essayez de supprimer toutes les parenthèses dans l'état où. Parenthèses inutiles car mysql ne peut pas utiliser correctement l'index.

select * 
from profit 
where 
    uid='1111' 
    and flag=32 
    and fId='2222' 
    and date='20161008' 
limit 1; 
+0

Merci pour votre temps! Les parenthèses sont ajoutées par cadre. Comme vous le dites, j'enlève toutes les parenthèses, et la sortie d'explication est la même. –

+0

Comme vous le dites, toutes les lignes de données pour uid = 1111 ont seulement 270 lignes. Si l'index de uid_acc_fId_date est utilisé, il est impossible d'utiliser 2s. –

+0

L'analyseur syntaxique MySQL permet d'ignorer les parenthèses redondantes. –