我不同意其他答案中提出的主键顺序。
您的理想方案(对于您的确切示例查询)是将所有相关记录彼此相邻。这将启用对您的数据的单次搜索。例如,(d1, s1, time)
用作集群主键,您将存储数据如下...
d1 | s1 | time
----+----+------
1 | 1 | 1234
1 | 1 | 1235 \
1 | 1 | 1236 SELECT * FROM table WHERE d1 = 1 AND s1 = 1 AND time BETWEEN 1235 AND 1237
1 | 1 | 1237 /
1 | 1 | 1238
1 | 2 | 1234
1 | 2 | 1235
1 | 2 | 1236
1 | 2 | 1237
1 | 2 | 1238
如果按照其他人的建议,您time
将聚集索引中的第一个字段作为第一个字段,那么您不会将所有数据放在一个连续的块中。相反,您会为每个单独的时间值获得一次搜索...
time | d1 | s1
------+----+----
1234 | 1 | 1 *Desired Row 1
1234 | 1 | 2
1235 | 1 | 1 *Desired Row 2
1235 | 1 | 2
1236 | 1 | 1 *Desired Row 3
1236 | 1 | 2
1237 | 1 | 1 *Desired Row 4
1237 | 1 | 2
1238 | 1 | 1 *Desired Row 5
1238 | 1 | 2
这种结构实际上非常适合不同的查询......
SELECT * FROM yourTable WHERE time = 1234 AND d1 = 1 AND s2 BETWEEN 2 AND 3
这表明不存在单一的普遍完美的聚集索引。那么,由于只能有一个聚集索引,您如何选择创建聚集索引?
这取决于您的数据和查询。对于每个查询,您需要查看要提取多少不同的连续数据块。尽量减少这些块的数量是一个非常好的主意。但是维护数据的顺序也是如此,以便它适合您的 GROUP BY 或 ORDER by 子句。JOIN 进一步加重了这一点。
对于您的示例查询,我建议的第一个索引确实是最好的。但不适用于您的所有查询。
此外,您需要考虑碎片。数据存储在页面中,您需要考虑插入数据的方式(考虑时将更新视为删除和插入)。因为很可能任何插入通常会比现有数据更新时间值,所以time
在聚集索引中具有第一个将减少碎片。
例如,假设每个页面只能容纳三行数据。上面建议的两个索引看起来像这样......
d1 | s1 | time time | d1 | s1
----+----+------ ------+----+----
1 | 1 | 1234 \ 1234 | 1 | 1 \
1 | 1 | 1235 Page 1 1234 | 1 | 2 Page 1
1 | 1 | 1236 / 1235 | 1 | 1 /
----+----+------ ------+----+----
1 | 1 | 1237 \ 1235 | 1 | 2 \
1 | 1 | 1238 Page 2 1236 | 1 | 1 Page 2
1 | 2 | 1234 / 1236 | 1 | 2 /
----+----+------ ------+----+----
1 | 2 | 1235 \ 1237 | 1 | 1 \
1 | 2 | 1236 Page 3 1237 | 1 | 2 Page 3
1 | 2 | 1237 / 1238 | 1 | 1 /
----+----+------ ------+----+----
1 | 2 | 1238 -Page 4 1238 | 1 | 2 -Page 4
现在,尝试插入d1 = 1, s1 = 1, time = 1239
.
d1 | s1 | time time | d1 | s1
----+----+------ ------+----+----
1 | 1 | 1234 \ 1234 | 1 | 1 \
1 | 1 | 1235 Page 1 1234 | 1 | 2 Page 1
1 | 1 | 1236 / 1235 | 1 | 1 /
----+----+------ ------+----+----
1 | 1 | 1237 \ 1235 | 1 | 2 \
1 | 1 | 1238 Page 2 1236 | 1 | 1 Page 2
*1 | 1 | 1239*/ 1236 | 1 | 2 /
----+----+------ ------+----+----
1 | 2 | 1234 -Page 3 1237 | 1 | 1 \
----+----+------ 1237 | 1 | 2 Page 3
1 | 2 | 1235 \ 1238 | 1 | 1 /
1 | 2 | 1236 Page 4 ------+----+----
1 | 2 | 1237 / 1238 | 1 | 2 -Page 4
----+----+------ 1239 | 1 | 1 /
1 | 2 | 1238 -Page 5
左边的版本必须创建一个新页面。右边的版本只是继续填充现有页面。
当出现碎片时,通常有可以修复碎片的维护计划。这通常是一个通宵的过程。
这有点复杂不是吗?嗯,有整本书都是关于这个主题的。
在它成为一个问题之前,我通常不会太担心碎片化。但这确实是值得牢记的事情。