2010-12-06 10 views
0

La requête SQL suivante prend environ 1 min. 15 sec. à exécuter lorsqu'il est entré directement dans la console SQL. Il y a 6636 enregistrements dans la table qv_attribute.Requête MySQL lente

La durée d'exécution de cette requête est-elle normale? Est-il possible de réduire le temps nécessaire pour exécuter cette opération en modifiant les paramètres de la base de données ou en optimisant la requête?

SELECT a.node_id, 
MAX(CASE WHEN(b.att_id = 9003) THEN a.att_description END) AS 'ICS_Owner', 
MAX(CASE WHEN(b.att_id = 9004) THEN a.att_description END) AS 'Service', 
MAX(CASE WHEN(t.rel_id = 12092) THEN t.att_description END) AS 'Contact_Name', 
MAX(CASE WHEN(t.rel_id = 12610) THEN t.att_description END) AS 'Address_1', 
MAX(CASE WHEN(t.rel_id = 9007) THEN t.att_description END) AS 'Address_2', 
MAX(CASE WHEN(t.rel_id = 12612) THEN t.att_description END) AS 'City', 
MAX(CASE WHEN(t.rel_id = 12614) THEN t.att_description END) AS 'State', 
MAX(CASE WHEN(t.rel_id = 13508) THEN t.att_description END) AS 'a', 
MAX(CASE WHEN(t.rel_id = 13509) THEN t.att_description END) AS 'b', 
MAX(CASE WHEN(b.att_id = 13132) THEN a.att_description END) AS 'Description', 
MAX(CASE WHEN(des.node_id = 10824) THEN des.att_description END) AS 'Row_Description' 
FROM `qv_attribute` t, `qv_attribute` a, `qv_attribute` b, `qv_attribute` des 
     WHERE b.att_id IN (9003,9004,13132,14542) 
     AND b.att_name = a.att_name 
     AND ((a.node_id = 1554 AND 
       ((t.node_id = 1776 AND des.att_order = 1) 
       OR (t.node_id = 1780 AND des.att_order = 2) 
       OR (t.node_id = 1781 AND des.att_order = 3) 
       OR (t.node_id = 1782 AND des.att_order = 4) 
       OR (t.node_id = 1783 AND des.att_order = 5) 
       OR (t.node_id = 1784 AND des.att_order = 6) 
       OR (t.node_id = 1778 AND des.att_order = 7) 
       OR (t.node_id = 1777 AND des.att_order = 8))) 
      OR (a.node_id = 1574 AND 
       ((t.node_id = 1574 AND des.att_order = 1) 
       OR (t.node_id = 1779 AND des.att_order = 2) 
       OR (t.node_id = 1576 AND des.att_order = 3) 
       OR (t.node_id = 1577 AND des.att_order = 4) 
       OR (t.node_id = 1710 AND des.att_order = 5) 
       OR (t.node_id = 1711 AND des.att_order = 6) 
       OR (t.node_id = 1712 AND des.att_order = 7))) 
      OR (a.node_id = 1803 AND 
       ((t.node_id = 1838 AND des.att_order = 1) 
       OR (t.node_id = 1839 AND des.att_order = 2) 
       OR (t.node_id = 1840 AND des.att_order = 3) 
       OR (t.node_id = 1805 AND des.att_order = 4))) 
      OR (a.node_id = 1831 AND 
       ((t.node_id = 1842 AND des.att_order = 1) 
       OR (t.node_id = 1847 AND des.att_order = 2) 
       OR (t.node_id = 1833 AND des.att_order = 3) 
       OR (t.node_id = 1848 AND des.att_order = 4) 
       OR (t.node_id = 1845 AND des.att_order = 5) 
       OR (t.node_id = 1846 AND des.att_order = 6) 
       OR (t.node_id = 1841 AND des.att_order = 7) 
       OR (t.node_id = 1844 AND des.att_order = 8) 
       OR (t.node_id = 1843 AND des.att_order = 9))) 
      OR (a.node_id = 1810 AND 
       ((t.node_id = 1854 AND des.att_order = 1) 
       OR (t.node_id = 1849 AND des.att_order = 2) 
       OR (t.node_id = 1851 AND des.att_order = 3) 
       OR (t.node_id = 1853 AND des.att_order = 4) 
       OR (t.node_id = 1852 AND des.att_order = 5) 
       OR (t.node_id = 1812 AND des.att_order = 6) 
       OR (t.node_id = 1850 AND des.att_order = 7)))) 
     GROUP BY a.node_id, t.node_id 

EXPLAIN ETENDU:

+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | Extra          | 
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+ 
| 1 | SIMPLE  | b  | range | PRIMARY  | PRIMARY | 4  | NULL | 4 | Using where; Using temporary; Using filesort | 
| 1 | SIMPLE  | des | ALL | NULL   | NULL | NULL | NULL | 6695 | Using where         | 
| 1 | SIMPLE  | t  | range | node_id  | node_id | 4  | NULL | 629 | Using where         | 
| 1 | SIMPLE  | a  | range | node_id  | node_id | 4  | NULL | 139 | Using where         | 
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+ 
4 rows in set, 1 warning (0.00 sec) 
+0

Veuillez inclure 'EXPLAIN EXTEND YOUR_SLOW_QUERY' aussi ... – ajreal

+0

Vous besoin de trouver une meilleure approche que le tuple non lié de t.node_id et des.att_order –

+0

@OMG: exactement le point de ma réponse, en mettant ces tuples dans une table, ils deviennent liés, puis ils peuvent simplement être rejoint. – Hogan

Répondre

2

Je pense que le problème est que vous ne spécifiez aucune condition de jointure pour t ou des et que vous leur faites des tonnes de comparaisons. Donc vous répétez chaque match de a et b avec chaque combinaison de t et de, ce qui n'est probablement pas ce que vous voulez.

Le tableau résultant a le nombre de lignes égal à (une jointure b) * t * des

Voici ce que votre clause where est en ébullition jusqu'à:

AND ((a.node_id = 1554 AND 
    ((t.node_id IN 1776, 1780, 1781, 1782, 1784, 1778, 1777) AND des.att_order BETWEEN 1 AND 8) 
OR (a.node_id = 1574 AND 
    ((t.node_id IN 1779, 1576, 1577, 1710, 1711, 1712) AND des.att_order BETWEEN 1 AND 7) 

...

Cette requête est assez moche, mais à ~ 7k lignes un pivot avec un groupe de filtres ne devrait pas prendre plus d'une minute

+0

Merci PMV, votre réponse était exactement ce dont j'avais besoin! – Charles

0

En supposant que vous avez déjà indexé votre table - le ralentissement provient de vos CASE WHEN combinaisons. Divisez-le en 11 requêtes distinctes et vous observerez une accélération. D'un autre côté, si vous devez exécuter cette requête assez souvent si 1 minute est trop longue, vous pouvez envisager de redéfinir la structure de la base de données pour conserver des informations redondantes mais à requête rapide.

Bonne chance!

+1

Le problème pourrait également être dans la déclaration de fou où. – Hogan

2

Il suffit de penser de la magie que vous pourriez faire si vous avez créé une table qui ressemblait à ceci:

a_node_id t_node_id att_order 
1554   1776  1 
1554   1780  2 
1554   1781  3 
1554   1782  4 
1554   1783  5 
1554   1784  6 
1554   1778  7 
1554   1777  8 

1574   1574  1 
1574   1779  2 
1574   1576  3 
1574   1577  4 
1574   1710  5 
1574   1711  6 
1574   1712  7 

1803   1838  1 
1803   1839  2 
1803   1840  3 
1803   1805  4 

etc 

indice supplémentaire: Mettre cela dans une table et à gauche se joindre à cette table - beaucoup plus rapide que le où clause que vous avez actuellement.

+0

+1: Pour la santé mentale! –

Questions connexes