MySQL, запрос слишком медленный, как его улучшить? - PullRequest
1 голос
/ 21 октября 2011

Проблема

Я выполняю запрос, используя Workbench 5.2.35 и сервер MySQL 5.5, и у меня появляется ошибка «Код ошибки: 2013. Потеря соединения с сервером MySQL во время запроса» через 600,516 секунд.после небольших изменений в запросе.Запрос имеет две роли:

  1. выберите определенный тип записей, для которых характерно наличие «value1» в «col1» (переход от этапа A к этапу B)
  2. удалитьзаписи, в которых значение в 'col2' совпадает со значением в 'col2' следующего результата (переход от этапа B к этапу C)

    Stage A             Stage B             Stage C
    ***************     ***************     ***************
    *ID *col1*col2*     *ID *col1*col2*     *ID *col1*col2*
    ***************     ***************     ***************
    *1  * A  * a  *     *3  * C  * a  *     *3  * C  * a  *
    *2  * B  * a  *     *7  * C  * f  *     *7  * C  * f  *
    *3  * C  * a  *     *8  * C  * f  *     *16 * C  * b  *
    *4  * S  * a  *     *9  * C  * f  *     *18 * C  * c  *
    *5  * B  * a  *     *16 * C  * b  *
    *6  * A  * g  *     *17 * C  * b  *
    *7  * C  * f  *     *18 * C  * c  *
    *8  * C  * f  *
    *9  * C  * f  *
    *10 * A  * f  *
    *11 * B  * f  *
    *12 * D  * f  *
    *13 * S  * f  *
    *14 * F  * f  *
    *15 * F  * f  *
    *16 * C  * b  *
    *17 * C  * b  *
    *18 * C  * c  *
    

и являетсяобобщение: MySQL, выберите строки, где значение параметра зависит от значения, которое он имеет в другой строке

Запрос:

SELECT t.id, t.col2, t.col3, t.col4, t.col5 FROM tablename t
WHERE t.id < 1000000
    AND t.col1 = 'value1' 
    AND t.col2 <> 
    (SELECT col2 FROM tablename
        WHERE col1 = 'value1' 
        AND id > t.id 
        LIMIT 1);

Причина дляошибка

Теперь из этого поста https://serverfault.com/questions/29597/what-does-mysql-error-2013-mean причины этой ошибки могут быть:

  1. Кто-то УБИЛ запрос
  2. Проблемы с сетью вызвали соединениечтобы умереть
  3. Сервер упал / умер
  4. Ваше соединение не использовалось в течение wait_timeout и было прервано
  5. Клиент не получал данные достаточно быстро для net_wait_timeout и был убит

но так как запрос останавливается на 600,516 секунд, я думаю, что профессионалblem в этом случае номер 4 (тайм-аут).

Возможные проблемы и решения

Первой идеей было бы увеличить время ожидания в тайм-ауте, но я думаю, что это вызвано предыдущей ошибкой:запрос ничего не возвращает, но продолжает выполняться.Предел t.id <1000000 </strong> используется именно для проверки запроса в достаточно ограниченном подмножестве (в базе данных около 200 миллионов записей). Итак, я думаю, что в запросе есть какая-то проблема,в частности, в переходе между этапом B и этапом C (предыдущий шаг тривиален)

Любая идея об ошибке или запросе будет высоко оценена.

Спасибо


Решение

это рабочий код, вдохновленный лучшим ответом.Команда DISTINCT работает, но в конце концов я использовал GROUP BY и ORDER BY, чтобы лучше представить результаты.

SELECT id, col1, col2, ..., coln FROM tablename
    WHERE col1 = 'value1' 
    AND col2 = 'value2'
    ... 
    AND coln = 'valuen'
    GROUP BY col2
    ORDER BY id;

Ответы [ 2 ]

0 голосов
/ 21 октября 2011

SELECT DISTINCT Par FROM table_name

http://www.w3schools.com/sql/sql_distinct.asp

0 голосов
/ 21 октября 2011

Я бы переписал его, используя not in для оптимизатора запросов есть специальный случай для этого.
Также я бы использовал другой трюк, чтобы ограничить количество результатов одним.

Проблема с limit заключается в том, что сначала создается временная таблица с всеми результатами, а затем выбирается 1 строка из этого.

SELECT t.id, t.col2, t.col3, t.col4, t.col5 
FROM tablename t
WHERE t.id < 1000000
    AND t.col1 = 'value1' 
    AND t.col2 NOT IN 
    (SELECT col2 FROM tablename
        WHERE col1 = 'value1' 
        AND id = t.id+1)    <<--- assuming that `id` is the primary key.

Если у вас составной индекс (col1, col2) и вы используете id в качестве первичного ключа, запрос не должен выполняться вечно.

Глядя на ваш запрос, я бы переписал его как:

SELECT t.id, t.col2, t.col3, t.col4, t.col5 
FROM tablename t
WHERE t.id IN ( 
  SELECT t2.id 
  FROM tablename t2
  WHERE t2.col1 = 'value1'
  GROUP BY t.col2)

Это должно сработать, если я правильно изучил этапы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...