Как ускорить sql с помощью GROUP BY и WHERE? - PullRequest
2 голосов
/ 30 марта 2020

Я знаю, что использование индекса может оптимизировать SQL с помощью GROUP BY или WHERE. Но как оптимизировать SQL с GROUP BY и WHERE? Пожалуйста, посмотрите мой случай.

У меня есть таблица для хранения данных traffi c и я использую ее для рисования топологии сетевого трафика c. Ниже приведена структура таблицы:

DROP TABLE IF EXISTS `data`;

CREATE TABLE `data` 
(
    `sip` varbinary(16) DEFAULT NULL,
    `dip` varbinary(16) DEFAULT NULL,
    `app` char(96) DEFAULT NULL,
    `up` bigint(20) DEFAULT NULL,
    `down` bigint(20) DEFAULT NULL,
    `dtime` datetime DEFAULT CURRENT_TIMESTAMP,
    KEY `dtime` (`dtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

И создайте индекс по столбцу dtime.

Упрощенная SQL - это

SELECT
    INET6_NTOA(sip),
    INET6_NTOA(dip),
    app,
    sum(up) AS up,
    sum(down) AS down
FROM
    `data`
WHERE
    `data`.dtime > FROM_UNIXTIME(1583031879)
AND `data`.dtime < FROM_UNIXTIME(1585537477)
GROUP BY
    sip,
    dip,
    app

. В таблице может храниться около 10 000 000 записей в течение одного месяца, и наше требование - нарисовать топологию сетевого трафика c с детализацией за последние 30 дней. , Последние 24 часа, Последние 1 час.

Очевидно, что индекс dtime полезен для запроса данных за последние 1 час или последние 24 часа. Но при запросе за последние 30 дней это полное сканирование таблицы.

В крайнем случае запрос в течение 24 часов стоит 5 с, что является приемлемым, в то время как запрос в течение 30 дней стоит 60 с +, что трудно принять.

Создать индекс для sip, dip, app? Кажется бесполезным, потому что сначала я должен фильтровать данные по dtime. Я погуглил различные решения по индексированию, которые могут мне не подойти.

Есть идеи, как ускорить мой SQL? Или есть идеи по улучшению дизайна стола? Большое спасибо.

Ответы [ 2 ]

1 голос
/ 31 марта 2020

Проще говоря, «диапазон» в WHERE предотвращает использование индекса для GROUP BY или ORDER BY. Вы можете добавить INDEX(sip, dip, app), чтобы предоставить Оптимизатору выбор.

Для каждой таблицы требуется PRIMARY KEY. Возможно, это может быть PRIMARY KEY(sip, dip, app)? Или просто (sip, dip)? Обратите внимание, что создание этого PK было бы лучше, чем простое INDEX.

Но реальный выигрыш в производительности для этих отчетов состоял бы в создании и ведении «сводной таблицы» с детализацией в 1 час. Один час позволил бы вам эффективно получить час, день, месяц и т. Д. c. См. http://mysql.rjweb.org/doc.php/summarytables И, поскольку итоговая таблица будет намного меньше, не будет иметь значения, когда потребуется сканирование таблицы.

Являются ли VARBINARY(16) некоторой формой ha sh? Или пара IP-адресов? Если они фиксированной длины, рассмотрим CHAR(16).

Насколько большими могут быть up и down? Возможно, вам не нужен 8-байтный BIGINT? (Экономия места может повысить производительность.

MySQL использует только один индекс на SELECT. Оптимизатор просматривает каждый индекс (включая PRIMARY KEY), чтобы оценить, какой один будет быть лучшим. В вашем случае было бы взвешенным выбор между использованием INDEX(dtime) для фильтрации и использованием INDEX(sip,dip,app), чтобы избежать сортировки.

Если предложение WHERE отфильтровывает до очень небольшого числа строк; dtime Индекс будет лучше, а Оптимизатор , вероятно, будет его использовать. И наоборот.

0 голосов
/ 30 марта 2020

не могли бы вы попробовать использовать индекс (sip, dip, app) (индекс из 3 столбцов)? Я думаю, это может быть полезно.

...