Dry7
@Dry7
Web разработчик

Почему LIMIT так сильно влияет на скорость?

Добрый день.

Есть таблица.
CREATE TABLE warehouses_changes
(
    id INT(11) UNSIGNED PRIMARY KEY NOT NULL COMMENT 'ID' AUTO_INCREMENT,
    company INT(11) UNSIGNED NOT NULL COMMENT 'Компания',
    point INT(11) UNSIGNED NOT NULL COMMENT 'Точка продаж',
    manager INT(11) UNSIGNED NOT NULL COMMENT 'Бариста',
    work_shift INT(11) UNSIGNED NOT NULL COMMENT 'Смена',
    supplier INT(11) NOT NULL COMMENT 'Поставщик',
    bill INT(11) UNSIGNED COMMENT 'Чек',
    ingredient INT(11) UNSIGNED NOT NULL COMMENT 'Ингредиент',
    direction TINYINT(1) NOT NULL COMMENT 'Увеличение/уменьшение',
    card INT(11) UNSIGNED COMMENT 'Card',
    date INT(11) UNSIGNED NOT NULL COMMENT 'Дата',
    value DECIMAL(30,3) UNSIGNED NOT NULL COMMENT 'Количество',
    description TINYTEXT COMMENT 'Описание'
);
CREATE INDEX warehouses_changes_date_bill_company ON warehouses_changes (date, bill, company);


В ней 5 400 000 элементов.

Она вертится на AWS t2.micro.

Вопрос:

Почему запрос
SELECT * FROM `warehouses_changes` WHERE (`bill`=0) AND (`company`=1) ORDER BY `date` DESC LIMIT 20;

Выполняется 46 секунд

а запрос
SELECT * FROM `warehouses_changes` WHERE (`bill`=0) AND (`company`=1) ORDER BY `date` DESC;

4 секунды?

По логике наоборот должно быть.

И второй вопрос - долгие запросы следствие слабого сервера или в базе данных что-то можно улучшить?
  • Вопрос задан
  • 464 просмотра
Решения вопроса 1
@lnked
Попробуйте так выполнить оба запроса, увидите что с лимитом выполняется быстрее
SELECT SQL_NO_CACHE * FROM `warehouses_changes` ...
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
alsopub
@alsopub
Если вы их выполняли именно в этой последовательности, то ничего странного нет.
В первом случае была перелопачена база, отобраны 20 записей, а во втором случае - все уже лежало в кеше.
Ответ написан
Комментировать
@AlikDex
1) Проверьте селективность запроса (гугл в помощь).
Вероятнее всего будет лучше сделать (т.к. компаний скорее всего меньше чем чеков):
SELECT * FROM `warehouses_changes` WHERE (`company`=1) AND (`bill`=0)  ORDER BY `date` DESC LIMIT 20;


2)Удалите текущий индекс, и для этого запроса сделайте:
CREATE INDEX warehouses_changes_date_bill_company ON warehouses_changes (company, bill, date);

И у вас запрос будет занимать меньше половины секунды. Возможно даже тысячные доли секунды.

Подсказка: Индекс следует делать именно в том порядке, в котором делаете выборку данных. Т.е. первым параметром у вас стоят компании - следовательно в индексе должно стоять первым колонка company, потом чек и сортировка `date`.
Ответ написан
Комментировать
@lubezniy
Думаю, стоит попробовать date вывести в отдельный индекс. Даже несмотря на Sending data.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы