Я бы посоветовал вам узнать, как использовать EXPLAIN
для анализа плана базы данных для оптимизации запросов. Также см. Презентацию барона Шварца ОБЪЯСНИТЕ Демистифицировано (ссылка на PDF его слайдов находится на этой странице).
Узнайте, как создавать индексы - это не то же самое, что первичный ключ или псевдоключ с автоинкрементом. Смотрите презентацию Подробнее о совершенствовании искусства индексирования . Автор - Yoshinori Matsunobu.
Ваша таблица может использовать индекс для CP_FLAG
и WEB_STATUS
.
CREATE INDEX CW ON RAW_LAW_20100503 (CP_FLAG, WEB_STATUS);
Это помогает искать подмножество строк на основе вашего условия cp_flag.
Тогда вы все еще сталкиваетесь с печальной неэффективностью MySQL с GROUP BY
запросами. Он копирует промежуточный набор результатов во временный файл на диске и сортирует его там. Дисковый ввод-вывод снижает производительность.
Вы можете увеличивать параметр конфигурации sort_buffer_size
, пока он не станет достаточно большим, чтобы MySQL мог сортировать результирующий набор в памяти, а не на диске. Но это может не сработать.
Возможно, вам придется прибегнуть к предварительному расчету COUNT()
, который вам нужен, и периодически обновлять эту статистику.
Комментарий @Marcus дал мне другую идею. Вы группируете по веб-статусу, и набор различных значений веб-статуса - довольно короткий список, и они не меняются. Таким образом, вы можете выполнить отдельный запрос для каждого отдельного значения и сгенерировать нужные вам результаты гораздо быстрее, чем с помощью запроса GROUP BY
, который создает временную таблицу для выполнения сортировки. Или вы можете запустить подзапрос для каждого значения состояния и UNION
их вместе:
(SELECT COUNT(*), WEB_STATUS FROM RAW_LOG_20100504 WHERE CP_FLAG > 0 AND WEB_STATUS = 200)
UNION
(SELECT COUNT(*), WEB_STATUS FROM RAW_LOG_20100504 WHERE CP_FLAG > 0 AND WEB_STATUS = 404)
UNION
(SELECT COUNT(*), WEB_STATUS FROM RAW_LOG_20100504 WHERE CP_FLAG > 0 AND WEB_STATUS = 304)
UNION
...etc...
ORDER BY 1 DESC;
Поскольку ваш покрывающий индекс включает CP_FLAG
и WEB_STATUS
, эти запросы никогда не должны считывать фактические строки в таблице. Они только читают записи в индексе, к которым они могут получить доступ намного быстрее, потому что (а) они находятся в отсортированном дереве, и (б) они могут быть кэшированы в памяти, если вы выделите достаточно для key_buffer_size
.
Отчет EXPLAIN
, который я пробовал (с 1М строк тестовых данных), показывает, что он хорошо использует индексы и не создает временную таблицу:
+------+--------------+------------------+------+--------------------------+
| id | select_type | table | key | Extra |
+------+--------------+------------------+------+--------------------------+
| 1 | PRIMARY | RAW_LOG_20100504 | CW | Using where; Using index |
| 2 | UNION | RAW_LOG_20100504 | CW | Using where; Using index |
| 3 | UNION | RAW_LOG_20100504 | CW | Using where; Using index |
| NULL | UNION RESULT | <union1,2,3> | NULL | Using filesort |
+------+--------------+------------------+------+--------------------------+
Using filesort
для последней строки означает, что она должна сортироваться без индекса. Но сортировка трех строк, созданных подзапросами, тривиальна, и MySQL делает это в памяти.
При разработке оптимальных решений для баз данных редко даются простые ответы. Многое зависит от того, как вы используете данные и какие запросы имеют более высокий приоритет для быстрого выполнения. Если бы был один простой ответ, который работал бы при любых обстоятельствах, программа просто включила бы этот дизайн по умолчанию, и вам не пришлось бы ничего делать.
Вам действительно нужно прочитать много руководств, книг и блогов, чтобы понять, как максимально эффективно использовать все функции, доступные вам.
Да, я все равно рекомендую использовать индексы. Очевидно, что раньше это не работало, когда вы запрашивали 100 миллионов строк без преимущества индекса.
Вы должны понимать, что вы должны разрабатывать индексы, которые будут полезны для конкретного запроса, который вы хотите выполнить. У меня нет возможности узнать, подходит ли индекс, который вы только что описали в своем комментарии, потому что вы не показали другой запрос, который пытаетесь ускорить.
Индексирование - сложная тема. Если вы определяете индекс для неправильных столбцов или если столбцы расположены в неправильном порядке, он может быть недоступен для данного запроса. Я поддерживаю разработчиков SQL с 1994 года, и я никогда не нашел ни одного краткого правила, объясняющего, как создавать индексы.
Похоже, вам нужен наставник, потому что вы находитесь на этапе, когда вам нужно ответить на множество вопросов. Есть ли у вас на работе кто-то, кого вы могли бы попросить помочь?