mysql - 主键中的 DATE 会在范围扫描中获得性能吗?

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

我们有一个大型(并且还在不断增长)的鸟类记录 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类型。

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

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

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

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

现在我的问题是:

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

最佳答案

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

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

优点:

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

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

缺点:

  1. 使用复合索引,“id”列上的简单查找(例如表上的连接)将慢近三倍。

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

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

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

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

关于mysql - 主键中的 DATE 会在范围扫描中获得性能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25114906/

相关文章:

php - SQL,如果PHP值为空则忽略原因

php - 在 SQL 配对系统中,如何避免因滞后而导致过度匹配?

MYSQL SELECT 行的总和超过 200

sql - 动态跳过 Where 子句

indexing - 索引和聚集索引对数据库性能有多重要?

php - 正则表达式 php 获取 mysql 插入值

mysql - Mysql 多操作触发器上出现错误 1064

大表上的 SQL 查询先快后慢

sql - 联结表的主键/聚集键

mysql - 数据库查询和索引