У меня есть таблица вида
CREATE TABLE data
{
pk INT PRIMARY KEY AUTO_INCREMENT,
dt BLOB
};
В столбце BLOB-объектов содержится около 160 000 строк и около 2 ГБ данных (в среднем 14 КБ на каждый блок). В другой таблице есть внешние ключи к этой таблице.
Что-то вроде 3000 сгустков идентичны. Поэтому мне нужен запрос, который даст мне таблицу повторных сопоставлений, которая позволит мне удалить дубликаты.
Наивный подход занял около часа на 30-40k строках:
SELECT a.pk, MIN(b.pk)
FROM data AS a
JOIN data AS b
ON a.dt=b.dt
WHERE b.pk < a.pk
GROUP BY a.pk;
У меня, по другим причинам, есть таблица размеров блобов:
CREATE TABLE sizes
(
fk INT, // note: non-unique
sz INT
// other cols
);
При построении индексов для fk и другого для sz прямой запрос от этого занимает около 24 секунд с 50k строками:
SELECT da.pk,MIN(db.pk)
FROM data AS da
JOIN data AS db
JOIN sizes AS sa
JOIN sizes AS sb
ON
sa.size=sb.size
AND da.pk=sa.fk
AND db.pk=sb.fk
WHERE
sb.fk<sa.fk
AND da.dt=db.dt
GROUP BY da.pk;
Однако при этом выполняется полное сканирование таблицы da (таблица данных). Учитывая, что частота попаданий должна быть довольно низкой, я думаю, что индексное сканирование будет лучше. Имея это в виду, добавил 3-ю копию данных в качестве 5-го объединения, чтобы получить это, и потерял около 3 секунд.
ОК, поэтому на вопрос: Собираюсь ли я стать намного лучше, чем второй выбор? Если да, то как?
Небольшое следствие: если у меня есть таблица, в которой ключевой столбец используется очень интенсивно, а остальные должны использоваться редко, мне лучше будет добавить еще одно объединение этой таблицы, чтобы стимулировать сканирование индекса против . полное сканирование таблицы?
Xgc на #mysql@irc.freenode.net указывает, что добавление вспомогательной таблицы, подобной размерам, но с уникальным ограничением на fk
может очень помочь. Немного веселья с триггерами и тем, что не может сделать это даже неплохо, чтобы быть в курсе событий.