【问题标题】:Optimizing MySQL GROUP BY/ORDER BY for calculating set intersection优化 MySQL GROUP BY/ORDER BY 计算集合交集
【发布时间】:2011-01-12 19:57:26
【问题描述】:

为了使问题更清晰,这个场景被稍微简化了。 我的情况涉及到 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;

解释输出:

*************************** 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

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

【问题讨论】:

    标签: mysql sql performance optimization group-by


    【解决方案1】:

    您是否尝试向这些字段添加非聚集索引(索引)?除了主键声明在某些 SQL 引擎中所做的一些隐式聚集索引创建之外,我还没有看到 Keys 会自动执行此操作。

    【讨论】:

    【解决方案2】:

    我是菜鸟,但尝试在 (rKey, rId) 或 (rId, rKey) 上使用复合索引

    【讨论】:

      【解决方案3】:

      试试这样的

      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 替换为 count,但应该没有太大区别。 (无论如何在 MSSQL 中)

      【讨论】:

        【解决方案4】:

        “键值是散列,以便在键空间上更均匀地分布它们”实际上是一个糟糕的性能想法。一旦数据变得太大而无法缓存,您将被随机性拖慢。

        Keys 闻起来很像many:many 映射表。 Here 是提高此类表性能的几个技巧。它可能会加快您的SELECT

        您的SELECT 应该通过这个“综合”和“覆盖”索引显着改善:

        INDEX(property1, property2, id)
        

        More tips 创建最佳索引。)

        【讨论】:

          猜你喜欢
          • 2012-12-31
          • 2012-06-12
          • 2013-01-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多