У меня есть таблица из примерно 360 000 записей, и здесь выполняется запрос по двум индексированным полям:
SELECT COUNT(*)
FROM emails
WHERE
department_id IN(1,2,3,4)
AND category_id IN (5,6,7,8)
(Time: 0.9624802)
id: 1
select_type: SIMPLE
table: emails
type: range
possible_keys: emails_department_id_idx,emails_category_id_idx
key: emails_category_id_idx
key_len: 5
ref: NULL
rows: 54018
Extra: Using where
Таким образом, там используется только один индекс.(Я могу заставить слияние индексов работать при использовании более простых сравнений или критериев диапазона, но мне нужно выполнить подобные проверки со списком идентификаторов).
Здесь я создал две новые таблицы для сопоставления этой взаимосвязи, ииспользуя JOIN'ы, я воспроизвел те же результаты:
SELECT COUNT(*)
FROM emails
LEFT JOIN email_to_department ON (email_to_department.email_id = emails.id AND email_to_department.department_id IN (1,2,3,4))
LEFT JOIN email_to_category ON (email_to_category.email_id = emails.id AND email_to_category.category_id IN (5,6,7,8))
WHERE
email_to_department.department_id IS NOT NULL
AND email_to_category.category_id IS NOT NULL
(Time: 0.5217777)
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: email_to_category
type: range
possible_keys: PRIMARY,category_id
key: category_id
key_len: 4
ref: NULL
rows: 61282
Extra: Using where; Using index
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: email_to_department
type: ref
possible_keys: PRIMARY,department_id
key: PRIMARY
key_len: 4
ref: testdb.email_to_category.email_id
rows: 1
Extra: Using where; Using index
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: emails
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: testdb.email_to_category.email_id
rows: 1
Extra: Using index
3 rows in set (0.38 sec)
Таким образом, каждый запрос теперь использует индекс и обрезает почти половину времени ожидания.Это плохой дизайн?Должен ли я написать остальные эти отношения таким же образом?
Если я добавлю больше критериев таким же образом, версия запроса JOIN, похоже, станет быстрее, а другая останется более или менее такой же.
Выполнение простого запроса только по одному индексируемому полю, конечно, очень и очень быстро:
SELECT COUNT(*)
FROM emails
WHERE department_id IN(1,2,3,4)
Есть ли еще какая-нибудь стратегия, которую я мог бы использовать для ускорения подобных запросов?Существуют и другие свойства, которые также необходимо фильтровать и в разных комбинациях, поэтому создание многостолбечных индексов на самом деле не поможет.