【问题标题】:What happens when I create an index on a column?当我在列上创建索引时会发生什么?
【发布时间】:2016-06-13 11:34:24
【问题描述】:

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

以下查询会从该索引中受益吗? 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 非常有用。现在我只需要一些进一步的信息。

【问题讨论】:

    标签: mysql sql indexing


    【解决方案1】:

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

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

    这对于查找col1col2 将更加有利,因为在获得col1 的所有匹配项后,它也可以使用col2 部分。

    最后,col3 部分只有在 col1col2 已经被使用过的情况下才会被使用,所以它不太可能有用。但它可能是。

    【讨论】:

      【解决方案2】:

      此评估仅基于您显示的 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 上工作的一个很好的解释,你可以看到这个 ref http://dev.mysql.com/doc/refman/5.7/en/mysql-indexes.html

      来自文档

      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 列禁止使用索引。

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

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

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

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

      【讨论】:

      • 谢谢@Stack ..我已经添加了mysql的部分文档..希望有用
      【解决方案3】:

      好吧,关于索引从来没有一个正确的答案,正确的答案每次都会有所不同,具体取决于数据的大小、列的类型和 ETC。

      在决定哪些索引最适合表时,您应该考虑以下几点:

      • 我在这张桌子上最常用的功能是什么?
      • 这个函数一天发生多少次?
      • 对我的性能影响最大的最慢查询是什么?

      之后,当您有实际需要改进的查询(经常发生的更新、选择/连接和 ETC)时,您可以根据每个查询的解释计划确定哪些是正确的索引。

      您应该知道,当像您的示例 mytable(col1, col2, col3) 那样进行索引时,只要在索引中首先提到所需的列,它就可以使用索引的一部分

      所以,每次使用Col1 确实可以使用这个索引。 Col2 将仅在与Col1 组合使用的情况下使用,以此类推Col3(必须与col1col2 组合才能使用)。

      你可以找到很多关于索引on MySQL documantation .的信息

      【讨论】:

        【解决方案4】:

        以下查询是否会从此索引 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 应用于应用第一个索引后剩余的行的探针。

        【讨论】:

          猜你喜欢
          • 2023-01-17
          • 1970-01-01
          • 2011-03-03
          • 2023-04-08
          • 1970-01-01
          • 1970-01-01
          • 2015-02-24
          • 2015-09-16
          • 1970-01-01
          相关资源
          最近更新 更多