2013-10-09 4 views
0

Мне нужно поддерживать приложение с помощью команд SQL (управление статьями).Оптимизировать запрос MySQL со многими подзапросами

Один запрос выглядит следующим образом:

SET @from_timestamp = '2013-07-01 00:00:00'; 
SET @serialnumber = '%aaaa01%'; 

SELECT 
    test1.article, 
    test1.serialnumber, 
    test2.`timestamp` as test2_timestamp, 
    test2.additionalinfo, 
    test1.`timestamp` AS test1_timestamp, 
    test1.text0 AS test1_text0, 
    test1.text1 AS test1_text1, 
    test1.text2 AS test1_text2, 
    test1.text3 AS test1_text, 
    test3.text1 as test3_text1, 
    test3.`timestamp` AS test3_timestamp, 
    test3.`status`, 
    TIMESTAMPDIFF(MINUTE, test1.`timestamp`, test3.`timestamp`) as DeltaT 
FROM (
    SELECT 
     max(`timestamp`) AS TIMESTAMP, 
     article, 
     serialnumber, 
     text1, 
     text2, 
     text3, 
     text4 
    FROM exampleTable 
    WHERE 
     test = 'test1' AND 
     `timestamp` >= @from_timestamp AND 
     os0 LIKE @serialnumber 
    GROUP BY serialnumber 
) AS test1 
LEFT JOIN (
    SELECT 
     max(`timestamp`) AS TIMESTAMP, 
     serialnumber, 
     status, 
     text1 
    FROM exampleTable 
    WHERE 
     test = 'test3' AND 
     `timestamp` >= @from_timestamp 
    GROUP BY serialnumber 
) AS test3 
ON test1.serialnumber = test3.serialnumber 
LEFT JOIN (
    SELECT 
     max(`timestamp`) AS TIMESTAMP, 
     serialnumber, 
     article, 
     text1 
    FROM exampleTable 
    WHERE 
     LENGTH(serialnumber) = 13 AND 
     test = 'test2' AND 
     `status` = -1 AND 
     `timestamp` >= @from_timestamp 
    GROUP BY serialnumber 
) AS test2 
ON test1.serialnumber = test2.serialnumber 
ORDER BY test1.`timestamp` 

Он работает только с одной таблицей, в которой сохранен данные продукта. Но, как и ожидалось, этот запрос выполняется очень медленно. Возможна ли оптимизация?

Edit: Attached image of the explain sql result

Edit2: Таблица содержит много данных (последний COUNT (*) обеспечивает 39589279 ;-))

Edit3: Attached image of the explain table result

Edit4: Пожалуйста, не вините меня за определение таблицы, он очень старый, разработанный другими ребятами, и его невозможно изменить без нарушения.

+0

Какие столбцы имеют индекс? – Kuzgun

+0

Можете ли вы показать нам результат «EXPLAIN»? – Kermit

+0

Существуют следующие индексы: id (первичный ключ), статья, тест, серийный номер, временная метка –

ответ

2

Прежде всего, вы запрашиваете три раза одну и ту же таблицу и присоединяетесь впоследствии. Первое упрощение было бы использовать только один выбор:

SELECT 
    article, 
    serialnumber, 
    text1, 
    text2, 
    text3, 
    text4, 
    max(case when 
     test = 'test1' AND 
     os0 LIKE @serialnumber 
    then `timestamp` else null end) AS test1_timestamp, 
    max(case when 
     LENGTH(serialnumber) = 13 AND 
     test = 'test2' AND 
     `status` = -1 
    then `timestamp` else null end) AS test2_timestamp, 
    max(case when 
     test = 'test3' 
    then `timestamp` else null end) AS test3_timestamp, 
FROM exampleTable 
WHERE 
    test in ('test1', 'test2', 'test3') AND 
    `timestamp` >= @from_timestamp 
GROUP BY serialnumber 

Это уже даст вам большое улучшение.

Во-вторых, вам нужно указать индекс на столбце timestamp, чтобы улучшить скорость.

+0

Это выглядит хорошо, но я хочу отображать значения text1-4 из строки с test = test1 и дополнительный текст1 из другой строки с тем же значением в поле serialnumber с test = test3. Это просто еще один случай? –

+0

Да, вы могли бы так сделать. Но поскольку вы группируетесь на 'serialnumer', вы также должны использовать групповую функцию в этих строках и помещать' case when' внутрь. –

+0

Я протестировал ваш запрос без изменений (только имена полей), и он был ОЧЕНЬ медленным по сравнению с утверждением в вопросе (продолжительность 27.391 сек/выборка 55.468 сек, в то время как исходный запрос занимает: продолжительность 21.812 с/выборка 0.156 сек). –

Смежные вопросы