当我在列上创建索引时会发生什么?

时间:2016-06-13 11:34:24

标签: mysql sql indexing

我已经询问了有关索引的多个问题。像这样:

以下查询会从此索引中受益吗? mytable(col1, col2, col3)

. . . WHERE col1 = ? AND col3 = ?
. . . WHERE col2 = ?
. . . WHERE col1 IN (?, ?)
. . . WHERE col3 = ? AND col1 NOT IN (?, ?)
. . . WHERE col1 = ? OR col2 = ?
. . . WHERE col2 = ? AND col1 = ?
. . . WHERE col1 = ? AND col2 > ?
. . . WHERE col1 = ? AND col3 > ?

-- each question was containing one of these queries ;-)

每当我得到该问题中提到的特定查询的答案时,我仍然不能判断这样的索引对于这样的查询是否有用。 (或如何使其更优化)

所以我决定提出这个问题并希望了解后台。当我在列上创建索引时会发生什么?索引是由什么组成的?多列索引包含哪些行(因为顺序很重要)?它如何工作导致查询更快?

实际上我需要一些有关索引的信息才能让我能够如何为查询确定正确的索引(多列或单列)

注意:我有一些使用EXPLAIN的经验。是的,我知道使用EXPLAIN在这些情况下非常有用。现在我只需要一些进一步的信息。

4 个答案:

答案 0 :(得分:1)

此eval仅基于您显示的where子句...可以根据选择列进行更改

    . . . WHERE col1 = ? AND col3 = ?               yes partial (only col1)
    . . . WHERE col2 = ?                            no
    . . . WHERE col1 IN (?, ?)                      yes 
    . . . WHERE col3 = ? AND col1 NOT IN (?, ?)     yes partial (only col1)
    . . . WHERE col1 = ? OR col2 = ?                yes
    . . . WHERE col2 = ? AND col1 = ?               yes
    . . . WHERE col1 = ? AND col2 > ?               yes 
    . . . WHERE col1 = ? AND col3 > ?               yes partial (only col1)

有关索引如何在mysql上工作的一个很好的解释,你可以看到这个引用http://dev.mysql.com/doc/refman/5.7/en/mysql-indexes.html

来自doc

  

MySQL使用索引进行这些操作:

     

快速查找与WHERE子句匹配的行。

     

消除行的考虑。如果之间有选择   多个索引,MySQL通常使用找到的索引   最小行数(最具选择性的索引)。如果表有   多列索引,可以使用索引的任何最左前缀   由优化器查找行。例如,如果你有   三列索引(col1,col2,col3),你已经索引搜索   (col1),(col1,col2)和(col1,col2,col3)上的功能。更多   有关信息,请参见第9.3.5节“多列索引”。

     

在执行连接时从其他表中检索行。 MySQL可以   如果声明为列,则更有效地使用列上的索引   相同的类型和大小。在此上下文中,考虑了VARCHAR和CHAR   如果它们被声明为相同的大小,则相同。例如,   VARCHAR(10)和CHAR(10)大小相同,但是VARCHAR(10)和   CHAR(15)不是。

     

对于非二进制字符串列之间的比较,两列都应该   使用相同的字符集。例如,将utf8列与。进行比较   latin1列不允许使用索引。

     

不同列的比较(将字符串列与a。比较   例如,时间或数字列可能会阻止使用索引   如果没有转换,则无法直接比较值。对于给定的   数值列中的值如1,它可能比较等于任何值   字符串列中的值的数量,例如' 1',' 1',' 00001',或   ' 01.e1&#39 ;.这排除了对字符串列的任何索引的使用。

     

查找特定索引列的MIN()或MAX()值   key_col上。这是由检查您是否的预处理器优化的   正在使用WHERE key_part_N =常量发生的所有关键部分   在索引中的key_col之前。在这种情况下,MySQL只做一个密钥   查找每个MIN()或MAX()表达式并用a替换它   不变。如果所有表达式都替换为常量,则查询   马上回来。例如:

     

如果对a进行排序或分组,则对表进行排序或分组   可用索引的最左前缀(例如,ORDER BY key_part1,   key_part2)。如果所有关键部分后面都是DESC,则读入密钥   相反的顺序。请参见第9.2.1.15节“ORDER BY Optimization”和   第9.2.1.16节“GROUP BY优化”。

     

在某些情况下,可以优化查询以在不使用的情况下检索值   咨询数据行。 (提供所有必要条件的索引   查询的结果称为覆盖索引。)如果查询使用from   一个表中仅包含在某个索引中的列,即选中的列   可以从索引树中检索值以获得更快的速度:

答案 1 :(得分:1)

索引将值或值的一部分放入RAM中,以便更快地访问。具有多个列的索引会聚合内容。

所以包含(col1, col2, col3)的索引对包含col1查找的所有查询都很有用,因为col1是最左边的。

查找col1col2会更加有益,因为在获得col1的所有匹配后,它也可以使用col2部分。

最后,col3部分只会在col1col2已被使用的情况下使用,因此它不太可能有用。但它可能是。

答案 2 :(得分:1)

嗯,关于索引的答案永远不会正确,每次正确的答案都会有所不同,具体取决于数据的大小,列的类型和ETC。

在决定哪种索引最适合表格时,您应该考虑以下因素:

  • 我在这张桌子上最常见的功能是什么?
  • 这一功能每天发生多少次?
  • 影响我表现的最慢查询是什么?

之后,如果您有实际需要改进的查询(发生了很多更新,选择/加入和ETC),您可以根据每个查询的解释计划确定哪个是正确的索引。

你应该知道,当像你的例子mytable(col1, col2, col3)一样编制索引时,只要在索引中首先提到所需的列

,它就能使用部分索引。

因此,Col1的每次使用都可以使用此索引。只有Col2Col1结合才会使用Col3 col1(必须与col2和{{1}}结合使用为了使用)。

您可以找到有关索引on MySQL documantation .

的大量信息

答案 3 :(得分:1)

  

以下查询是否会受益于此索引mytable(col1,col2,col3)

. . . WHERE col1 = ? AND col3 = ?

col1从索引中获益,并且可以使用col3残差谓词

. . . WHERE col2 = ?

SQL可能会选择扫描您拥有的索引,如果它具有成本效益,那么总的来说这不会被使用

. . . WHERE col1 IN (?, ?)

将使用索引

. . . WHERE col3 = ? AND col1 NOT IN (?, ?)

col1受益于索引,col3残差谓词将被使用

. . . WHERE col1 = ? OR col2 = ?

将使用索引

. . . WHERE col2 = ? AND col1 = ?

将使用索引

. . . WHERE col1 = ? AND col2 > ?

将使用索引

. . . WHERE col1 = ? AND col3 > ?

将使用索引

残差谓词是一种探测器,SQL应用于应用第一个索引后留下的行。