У меня есть таблица формы
CREATE TABLE data
{
pk INT PRIMARY KEY AUTO_INCREMENT,
dt BLOB
};
Он имеет около 160 000 строк и около 2 ГБ данных в столбце большого двоичного объекта (в среднем 14 КБ на большой двоичный объект). В другой таблице есть внешние ключи в этой таблице.
Примерно 3000 одинаковых капель. Итак, мне нужен запрос, который даст мне таблицу повторной карты, которая позволит мне удалить дубликаты.
Наивный подход занял около часа на 30-40к строк:
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 секунд с 50 тыс. Строк:
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 на #[email protected] указывает, что добавление служебной таблицы, такой как размеры, но с уникальным ограничением для fk, может очень помочь. Немного повеселитесь с триггерами, а что нет, возможно, даже не так уж плохо, чтобы идти в ногу со временем.






Вы всегда можете использовать хеш-функцию (MD5 или SHA1) для своих данных, а затем сравнить хеши.
Вопрос в том, можно ли сохранить хеши в своей базе данных?
+1: кажется наиболее эффективным способом (по крайней мере, он сократит количество больших двоичных объектов, которые вам нужно сравнить.)
+1: Я согласен с этим. Если вам нужно делать байт для сравнения байтов каждый раз, когда запрос будет зависать. Убедитесь, что код, добавляющий записи, также хеширует их и генерирует хеши для всех существующих строк. Теперь вам нужно только сравнить размеры и хеши больших двоичных объектов.