【问题标题】:Will DATE in primary key gain performance in range scans?主键中的 DATE 会在范围扫描中获得性能吗?
【发布时间】:2014-09-26 16:53:48
【问题描述】:

我们有一个庞大的(并且不断增长的)鸟类记录的 MySQL 数据库。目前我们主要有三个表,简化如下:

RECORDS (id, birdid, tripid, gender, age) PRIMARY KEY id
BIRDTRIPS (id, locid, date, starttime, endtime, notes) PRIMARY KEY id
LOCATIONS (id, description, centerlat, centerlng) PRIMARY KEY id

所有 id 都是 INT,日期是 DATE 类型。

为了获得性能,我决定通过将 date 和 locid 复制到 RECORDS 中来进行一些非规范化:

RECORDS (id, birdid, tripid, gender, age, locid, date) PRIMARY KEY id

这样,许多查询将避免昂贵的 BIRDTRIPS 和 LOCATIONS 连接。

MySQL 每个表只有一个聚集索引,并且始终是主键。我被诱惑了
在 RECORDS 上尝试PRIMARY KEY (date, id) 以利用聚集索引对日期列和表分区进行更快的范围扫描。 id 仅包含在键中,因为同一日期可能有许多记录。 从理论上讲,主键通常在 id 上有点“浪费”,其中非聚集的 UNIQUE 索引就足以进行查找。

现在我的问题是:

你们中有人有这种方法的实践经验吗?有没有我可能忽略的缺点?

【问题讨论】:

    标签: mysql sql clustered-index non-clustered-index


    【解决方案1】:

    我会回答我自己的问题,以防有人偶然发现它。我发现这篇非常不错的博文已经针对这种方法进行了性能测试:Clustered indexing and query performance

    博文中进行的实验的结论是:

    优点:

    1. 使用复合主键(在我的例子中是 PRIMARY KEY (date, id))可以将日期范围查询速度提高大约 9 倍。

    2. 随着表的增长,日期范围查询的性能将保持接近恒定,而如果主键仅在“id”上,则性能会逐渐下降。

    缺点:

    1. 使用复合索引对 'id' 列进行简单查找(例如,表上的连接)几乎要慢三倍。

    2. 较大的聚集索引会导致磁盘利用率明显增加。这是因为所有其他索引都指向聚集索引,这意味着大型聚集索引会增加所有其他索引的大小。这可能会减少查询的缓存命中率,因为更少的表可以放入内存。

    因此,如果针对该表的查询的主要部分是业务关键日期范围查询,并且您的系统可以“承受”查找的损失,那么这种方法可能会对您有所帮助。

    我自己的结论是,我不敢在生产中这样做。相反,我将对日期列的 YEAR 进行表分区,以防止对日期范围查询进行全表扫描。

    希望这对面临类似挑战的人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-19
      • 1970-01-01
      • 2014-02-04
      • 1970-01-01
      • 1970-01-01
      • 2022-09-23
      • 2021-07-03
      相关资源
      最近更新 更多