在性能方面,索引字段+限制1与唯一字段比较MySQL的

时间:2016-12-29 13:07:08

标签: mysql performance indexing

示例1。字段c.alias是唯一的。

Select c.* from category c where c.alias = 'some-alias'

示例2。字段c.alias只是编入索引。

Select c.* from category c where c.alias = 'some-alias' limit 1

这两个示例在查询性能方面是否有所不同?

2 个答案:

答案 0 :(得分:1)

你的问题的答案是测试并找出答案。

但是,如果存在差异,我希望它非常非常小。在这两种情况下,where子句都应该使用索引。你真的在问MySQL和#34;是否知道"在第一场比赛后停止(由于唯一索引)。或者MySQL需要查看下一个值才能看出它是不同的。第二步的开销很小。

我还会提出,如果这是一个关于优化代码的严重问题,那么你可能会找错了地方。这种微观优化(在这种情况下可能是纳米)通常不会有用。

我应该注意,如果您将主键索引与常规索引进行比较,您可能会发现可衡量的差异。在MySQL中,主键是自动聚类的,可能是(小但可测量的)性能差异。

答案 1 :(得分:1)

(戈登的答案很好。但我有几个不同的话要说......)

SELECT ... WHERE unique_col = constant - 这将从表中读取一行(如果有的话)。除了简单的解析时间之外,LIMIT 1没有任何影响。

SELECT ... WHERE non_uniq_col = constant - 这将读取,直到找到不匹配的行。也就是说,它将读取N + 1行以传送N行。对于这种情况,LIMIT 1会阻止它。现在的问题不是关于性能(如果N很小则没有太大区别),而是关于功能(你想要1行还是N)。

在InnoDB中,PRIMARY KEY是"群集"与数据,隐含UNIQUE。所以它如上所述。

使用辅助键,还有一个额外的步骤。首先在索引 BTree中找到(col=const)行。在该BTree的叶子节点是所需行的PK。额外的步骤是向下钻取PK的BTree以找到该行。这需要额外的费用,但对于中小型桌子来说很少值得担心。 (LIMIT 1问题仍然适用,并且很小。)

如果 all SELECT中引用的列在同一个二级索引中(包括PK的隐式副本),则该索引被称为"覆盖& #34 ;.因此,查询可以完全在二级索引的BTree中执行,从而避免了额外的步骤。同样,这通常很小,但值得做。 "覆盖"在EXPLAIN中通过"使用索引" (不是"使用索引条件",它指的是不同的东西)。

我建议你先学习Indexing Cookbook,而不是先学习血腥细节。我的文档为您提供了重要的性能,并省略了一些不太重要的细节,例如这个问题正在讨论什么。

对于小批量项目中的 tiny 表,这些都不重要 对于巨大的表,磁盘命中数是主要的性能指标;最小化成为目标。特别是,二级索引的额外步骤通常涉及N个磁盘命中(对于N行)。

但是...... SELECT ... GROUP BY ... ORDER BY ... LIMIT 1可能涉及获取一堆行,对它们进行排序,最后提供1行。 如果无法在索引中使用排序,则可能会多次操作N行。在案例中,LIMIT 1仅在花费了99%的努力后才会采取行动。这是对新手LIMIT的常见误解。