我有一张表格
CREATE TABLE data
{
pk INT PRIMARY KEY AUTO_INCREMENT,
dt BLOB
};
它在 blob 列中有大约 160,000 行和大约 2GB 的数据(平均每个 blob 14kb)。另一个表具有该表的外键。
大约有 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;
由于其他原因,我碰巧有一个具有 blob 大小的表:
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 秒。
好的,问题是:我会比第二个选择好得多吗?如果是这样,怎么做?
一个推论是:如果我有一个表,其中键列的使用非常频繁,但其余的应该很少使用,那么我最好添加该表的另一个连接以鼓励索引扫描而不是完整的表扫描?
#mysql@irc.freenode.net 上的 Xgc 指出,添加一个实用程序表(如大小但具有唯一约束)fk
可能会有很大帮助。触发器带来一些乐趣,而不会让它保持最新状态甚至还不错。