V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
geekyoung
V2EX  ›  程序员

关于数据库中单列索引顺序的一个问题

  •  
  •   geekyoung · 2019-01-05 21:51:02 +08:00 · 2549 次点击
    这是一个创建于 2151 天前的主题,其中的信息可能已经有所发展或是发生改变。

    偶然看到了一个题目: 给定 yfd_interviewer 数据库表结构如下:

    CREATE TABLE `yfd_interviewer` (
      `id` INT(11) NOT NULL AUTO_INCREMENT,
      `name` VARCHAR(32) NOT NULL DEFAULT '',
      `age` INT(11) NOT NULL,
      `createdTime` BIGINT(20) NOT NULL,
      `updatedTime` BIGINT(20) NOT NULL,
      PRIMARY KEY (`id`),
      KEY `name_index` (`name`),
      KEY `age_index` (`age`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    给定以下 SQL:

    S1: SELECT * FROM `yfd_interviewer` WHERE name = ‘ kebi ’;
    S2: SELECT * FROM `yfd_interviewer` WHERE age = 20;
    S3: SELECT * FROM `yfd_interviewer` WHERE name = ‘ kenan ’ AND age = 20;
    S4: SELECT * FROM `yfd_interviewer` WHERE age = 20 AND name = ‘ kenan ’;
    

    以下关于索引使用描述不正确的是哪个?

    • A S1 可能使用索引 name_index
    • B S2 可能使用索引 age_index\n
    • C S3 可能使用索引 name_index 或 age_index
    • D 相比 S3,S4 会优先使用 age_index

    答案是 D,但是我不太明白,这个表里面 name 和 age 都是单列索引,虽然 S4 age 在前,SQL 在执行查询优化的时候会根据字段的顺序,优先选择 name 索引?谢谢大家

    13 条回复    2019-01-06 15:21:49 +08:00
    Allianzcortex
        1
    Allianzcortex  
       2019-01-05 22:12:42 +08:00   ❤️ 2
    是。关键不是在查询语句上,而是在创建语句上。创建 SQL 表时为了提高性能需要把最常用的 index/key 放在前面(原话是 you should put columns that will be the most selective at the beginning of the index declaration)。在这个表里 name 比 index 索引在前,所以对 C D 选项都是会优先查询 name 再查 age。
    junan0708
        2
    junan0708  
       2019-01-05 22:21:16 +08:00 via Android
    @Allianzcortex 这个和索引顺序无关,只是理论上 name 的区分度更好
    Allianzcortex
        3
    Allianzcortex  
       2019-01-05 22:28:15 +08:00
    @junan0708 是有的呀。我找了下当时的笔记,是看的这个问题: https://stackoverflow.com/questions/2292662/how-important-is-the-order-of-columns-in-indexes . 对创建语句:The order of columns is critical。对查询语句:For seeks the order of columns is irrelevant. 就是题目里 C/D 说的这样。
    liprais
        4
    liprais  
       2019-01-05 22:30:23 +08:00   ❤️ 1
    "you should put columns that will be the most selective at the beginning of the index declaration" 并不是最常用的 index / key
    selectivity 的概念了解一下
    zeraba
        5
    zeraba  
       2019-01-05 22:34:22 +08:00 via Android
    @junan0708 索引不是最左么 两个限制条件,多个索引,优先使用第一个索引,区分度的话没有做数据分布的统计还不好说吧
    Allianzcortex
        6
    Allianzcortex  
       2019-01-05 22:36:46 +08:00 via iPhone
    @liprais 口误口误。想表达的意思就是最能区分出,不是最常用的
    hilbertz
        7
    hilbertz  
       2019-01-05 23:03:10 +08:00   ❤️ 4
    explain 你自己看下,没有绝对的答案,这取决于具体的数据分布,可能只用一个返回最少的,可能 2 个都用,也可能根本不用
    Allianzcortex
        8
    Allianzcortex  
       2019-01-05 23:08:40 +08:00
    @hilbertz 是的,但从这道题目来说应该是不用考虑数据分布,单纯从索引的角度来看
    min
        9
    min  
       2019-01-05 23:11:35 +08:00
    楼上 hilbertz 说得对,实际执行的时候用哪个索引是不一定的
    charles2java
        10
    charles2java  
       2019-01-06 00:12:40 +08:00 via Android
    排除法,前面 3 个都是对的
    winoros
        11
    winoros  
       2019-01-06 04:02:00 +08:00
    D 的反面并不是会优先选另一个索引
    索引的选择考虑的过滤效果等影响,条件的顺序几乎不会是某个 RDBMS 选择索引的一个影响比较大的引子
    通常 RDBMS 的实现中,第三个 SQL 和第四个 SQL 最后选择的情况会是一样的
    pathbox
        12
    pathbox  
       2019-01-06 08:12:48 +08:00 via iPhone   ❤️ 1
    和你表的数据情况有关吧,用 explain 看,能查的快的就是有效索引
    HiJackXD
        13
    HiJackXD  
       2019-01-06 15:21:49 +08:00
    联合索引才是把最具区分度的排前面,因为是最左侧匹配。
    至于 D,where 里的字段排序不会影响索引的使用。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5895 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 01:55 · PVG 09:55 · LAX 17:55 · JFK 20:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.