这种情况有所简化,以使问题更加清晰。 我的情况涉及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`)
);
(键值是哈希值,可以更均匀地在键空间上分配它们。)
例如,可能有500万条记录和5000万条密钥。我正在尝试做的是对密钥集进行模糊搜索 - 将记录与数据库中的记录匹配,并使用最常用的密钥。结果还需要根据记录表中的属性进行过滤。
我一直在使用的查询如下所示:
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;
EXPLAIN输出:
*************************** 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
有没有办法可以重组此表或查询以加快此操作?
答案 0 :(得分:0)
您是否尝试过向这些字段添加非聚集索引(索引)?除了在一些SQL引擎中主键声明所做的一些隐式聚簇索引创建之外,我还没有看到Keys在过去自动执行此操作。
答案 1 :(得分:0)
我是菜鸟,但在(rKey,rId)或(rId,rKey)上尝试复合索引
答案 2 :(得分:0)
尝试这样的事情
SELECT rId, Count(*) as score
FROM rkeys
WHERE rKey = 10 OR rKey = 11 OR rKey = 13 OR rKey = 14
GROUP BY rId ORDER BY score DESC
并向表中添加索引
(rKey,rId)
虽然用计数代替Sum,但不应该有太大区别。 (无论如何,在MSSQL中)
答案 3 :(得分:0)