优化MySQL GROUP BY / ORDER BY以计算集合交集

时间:2011-01-12 19:57:26

标签: mysql sql performance optimization group-by

这种情况有所简化,以使问题更加清晰。 我的情况涉及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

有没有办法可以重组此表或查询以加快此操作?

4 个答案:

答案 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)

"关键值是哈希值,以便更均匀地在键空间上分布它们#34;实际上是一个糟糕的性能理念。一旦数据太大而无法缓存,您将会因随机性而变慢。

Keys闻起来很像很多:很多映射表。 Here是提高此类表格性能的几个提示。它可能会加快你的SELECT

您的SELECT应该通过这个'复合材料来显着改善。并且'覆盖'指数:

INDEX(property1, property2, id)

More tips创建最佳索引。)