MySQL:制作3个字段的复合索引,或者制作3个单独的索引?

Pet*_*uza 14 mysql indexing compound-index

我有一个MySQL表,除其他属性外,还有时间戳,类型和user_id.
所有这些都是可搜索和/或可排序的.
为每个索引创建一个索引,或者用这三个或两者创建一个复合索引是否更好?

Unr*_*son 10

巴勃罗的答案是正确的,但也许你不会意识到复合指数可能是合理的.

你可以有多个指标,并具有idx1(tstamp, user_id)不从具有排除,你indx2(tstamp, type)还是idx1reverse(user_id, tstamp)等等...

当复合索引覆盖查询中的所有条件时,它们最有用,因此您建议的索引最有用

SELECT * FROM my_table WHERE tstamp = @ts1 AND user_id = @uid AND type = @type
Run Code Online (Sandbox Code Playgroud)

如果要提高此类查询的性能,可以考虑添加复合索引.

索引的缺点是,它会减慢所有的更新操作.然而,最常用的应用程序做更多的选择,然后更新(无论是在条件交易,即报表,尤其是受影响/检索的记录单位的数值),并在同一时间都更加宽容更新较慢的(用户大多判断的速度该系统不是由时间,必须更新记录,但所需的时间来检索记录;再次YMMV并有不按这些规则玩)的应用.

最好的是,如果你有一些方法来测试在典型的工作负载方面的数据库性能(创建一些典型的SQL脚本,独立的和可重复的,或在创建应用程序级的单元测试),然后你可以客观地调整你的数据库.

编辑 还意识到可以添加和删除索引,而不会影响系统的功能.因此,您可以稍后在系统的实际使用期间调整索引 - 通常,您将收集并分析慢速SQL查询,以查找可能从添加索引中受益的条件.


Pab*_*ruz 9

如果要分别对这些字段执行搜索,则可能需要单独的索引才能使查询运行得更快.

如果您有这样的索引:

mysql> create index my_idx on my_table(tstamp, user_id, type);
Run Code Online (Sandbox Code Playgroud)

你查询的是:

mysql> select * from my_table where type = 'A';
Run Code Online (Sandbox Code Playgroud)

然后my_idx对你的查询没有帮助,MySQL将最终进行全表扫描来解决它.

  • 是的,实际上它只对该列的索引有帮助.它可能会因为索引更大而变慢 - 但是,如果单列上的索引有用(即高选择性),那么复合索引将是有用的 - mysql可能会查看更大的索引,但btree索引是有组织的作为树,因此增加了大小,结合只需要访问树的一部分这一事实,结合I/O操作以块大小发生的事实,转换为:具有相同起始列的索引同样有用该栏目的条件. (4认同)
  • 另外,蠕动数据库会将索引保留在RAM中,因此它进一步降低了性能差异(这里假设复合索引本身是合理的).换句话说 - 通常在引入复合指数时,我倾向于丢弃第一列的单列索引. (2认同)