Этот сценарий несколько упрощен, чтобы прояснить проблему.
Моя ситуация связана с набором записей данных в MySQL.
CREATE TABLE `records` (
`id` bigint(20) NOT NULL,
`property1` bigint(20) NOT NULL,
`property2` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `property1` (`property1`),
KEY `property2` (`property2`)
);
Из каждой записи мы генерируем и храним переменное количество ключей (хэшей) на основе данных записи.
CREATE TABLE `rkeys` (
`rKey` bigint(20) NOT NULL,
`rId` bigint(20) NOT NULL,
KEY `rKey` (`rKey`),
KEY `rId` (`rId`),
FOREIGN KEY (`rId`) REFERENCES `records` (`id`)
);
(Ключевыми значениями являются хэши, чтобы распределить их по пространству клавиш более равномерно.)
Может быть, например, 5 миллионов записей и 50 миллионов ключей.
То, что я пытаюсь сделать, - это нечеткий поиск по набору ключей - сопоставить запись с записями в базе данных с наибольшим количеством общих ключей. Результаты также необходимо отфильтровать по свойствам в таблице записей.
Запрос, с которым я работал, выглядит следующим образом:
SELECT rkeys.rId, records.property1, SUM(1) as score
FROM rkeys, records
WHERE
(rKey = 10 OR rKey = 11 OR rKey = 13 OR rKey = 14) AND
rkeys.rId = records.id AND
records.property1 = 1 AND
records.property2 = 2
GROUP BY rId ORDER BY score DESC;
Производительность в порядке, если число записей с любым заданным ключом довольно мало; проблема в том, что я нажимаю клавишу, которая появляется в нескольких тысячах записей (скажем, 5000). Внезапно производительность GROUP BY / ORDER BY падает с обрыва (15-20 с на запрос). Обратите внимание, что сглаживание распределения ключей на самом деле не вариант - сами данные записи распределены неравномерно.
Кажется, что проблема объединения с записями не является ядром проблемы - я просто включаю ее для контекста. Я все еще вижу ту же проблему, если все, что я хочу сделать, это:
SELECT rId, SUM(1) as score
FROM rkeys
WHERE rKey = 10 OR rKey = 11 OR rKey = 13 OR rKey = 14
GROUP BY rId ORDER BY score DESC;
Объяснить вывод:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: rkeys
type: index
possible_keys: rKey
key: rKey
key_len: 8
ref: NULL
rows: 1
Extra: Using where; Using temporary; Using filesort
Есть ли способ, которым я могу реструктурировать эту таблицу или запрос, чтобы ускорить эту операцию?