Медленный MySQL Query - PullRequest
       2

Медленный MySQL Query

0 голосов
/ 07 декабря 2010

Следующий запрос SQL занимает примерно 1 мин. 15 секунд для выполнения при вводе непосредственно в консоль SQL. В таблице qv_attribute 6636 записей .

Является ли время выполнения этого запроса нормальным? Есть ли способ сократить время выполнения этой операции, изменив настройки базы данных или оптимизировав запрос?

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

ОБЪЯСНИТЬ, РАСШИРЕНО:

+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+
| 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)

Ответы [ 3 ]

2 голосов
/ 07 декабря 2010

Только подумайте о магии, которую вы могли бы сделать, если бы вы создали таблицу, которая выглядела так:

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

Дополнительная подсказка: поместите это в таблицу и оставьте соединение с этой таблицей - намного быстрее, чем предложение where, которое у вас есть.

2 голосов
/ 07 декабря 2010

Я думаю, что проблема в том, что вы не указываете какие-либо условия соединения для t или des, а проводите множество сравнений с ними. Таким образом, вы повторяете каждое совпадение a и b с каждой комбинацией t и des, что, вероятно, не то, что вы намерены.

Полученная таблица имеет количество строк, равное (объединение b) * t * des

Вот то, к чему сводится ваше положение where:

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)

...

Этот запрос довольно уродливый, но при ~ 7 тыс. Строк поворот с кучей фильтров не должен занимать больше минуты

0 голосов
/ 07 декабря 2010

Предполагая, что вы уже проиндексировали свою таблицу - замедление происходит из-за ваших комбинаций CASE WHEN.Разбейте его на 11 отдельных запросов, и вы заметите ускорение.

Кстати, если вам придется выполнять этот запрос достаточно часто, когда 1 минута слишком длинная - возможно, вы захотите пересмотреть базу данных.структура для хранения некоторой избыточной, но быстро запрашиваемой информации.

Удачи!

...