Вы можете добавить составной индекс (concept, attrib, value, business_key)
, чтобы запрос (если MySQL решит использовать этот индекс) мог найти всю информацию в индексе, не считывая всю таблицу.
Ваш запрос эквивалентен:
SELECT DISTINCT business_key
FROM Memory
WHERE NOT (concept = 'case' AND attrib = 'status' AND value = 'closed')
и этому (что, вероятно, даст тот же план выполнения):
SELECT business_key
FROM Memory
WHERE NOT (concept = 'case' AND attrib = 'status' AND value = 'closed')
GROUP BY business_key
Так как 4все столбцы, которые нужно поместить в индекс, равны VARCHAR(255)
, длина индекса будет довольно большой.MyISAM не допустит более 1000 байтов, а InnoDB - не более 3072.
Одно из решений - сократить длину последней части, сделав длину индекса менее 1000: 255+255+255+230 = 995
:
(concept, attrib, value, business_key(220))
Это будет работать, но на самом деле не очень хорошо иметь такую большую длину индексов, с точки зрения производительности.
Другой вариант - уменьшить длину всех или некоторых из этих 4 столбцов,если это соответствует данным, которые вы ожидаете там хранить.Не нужно объявлять длину 255
, если вы ожидаете, что в столбце будет максимум 100
.
Другой вариант, который вы можете рассмотреть, - поместить эти 4 столбца в 4 отдельные справочные таблицы.(Или только столбцы, в которых есть повторяющиеся данные. Похоже, что business_key
будет содержать повторяющиеся данные, но не так много. Поэтому не очень хорошо будет создать справочную таблицу для этого столбца.)
Пример: поместите concept
значения в новую таблицу с чем-то вроде:
CREATE TABLE Concept_Ref
( concept_id INT AUTO_INCREMENT
, concept VARCHAR(255)
, PRIMARY KEY concept_id
, UNIQUE INDEX concept_idx (concept)
) ;
INSERT INTO Concept_Ref
( concept )
SELECT DISTINCT
concept
FROM
Memory ;
, а затем измените таблицу Memory
на:
ALTER TABLE Memory
ADD COLUMN concept_id INT ;
сделайте это (один раз):
UPDATE
Memory m
JOIN
Concept_Ref c
ON c.concept = m.concept
SET m.concept_id = c.concept_id
, а затем опустите столбец Memory.concept
:
ALTER TABLE Memory
DROP COLUMN concept ;
Вы также можете добавить ссылки FOREIGN KEY
, если измените таблицы с MyISAM на InnoDB.
После того, как вы проделали то же самое для всех 4 столбцов, не только длина нового составного индекса в таблице Memory
будет намного меньше, но и размер вашей таблицы будет намного меньше.Кроме того, любой другой индекс, использующий любой из этих столбцов, будет иметь меньшую длину.
Конечно, для запроса потребуется 4 соединения.И любые операторы INSERT
, UPDATE
или DELETE
в этой таблице должны быть изменены и тщательно продуманы.
Но в целом, я думаю, у вас будет лучшая производительность.С дизайном, который у вас сейчас есть, кажется, что такие значения, как 'case'
, 'status'
и 'closed'
повторяются много раз.