美文网首页
[InnoDB]性别字段为什么不适合加索引

[InnoDB]性别字段为什么不适合加索引

作者: gnocuohz | 来源:发表于2018-11-02 20:27 被阅读0次

    表结构与数据

    id为主键,id为奇数sex=1,id为偶数sex=0
    sex=0,50000条数据;sex=1,50000条数据


    表结构
    数据示例
    CREATE TABLE `people` (
      `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
      `name` varchar(255) DEFAULT NULL,
      `sex` tinyint(1) unsigned DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=100001 DEFAULT CHARSET=utf8;
    
    CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_initData`()
    BEGIN
        DECLARE i INT DEFAULT 1;
        WHILE i<=100000 DO
            INSERT INTO people(name, sex) VALUES(CONCAT('姓名',i),0);
            SET i = i+1;
        END WHILE;
    END
    
    CALL proc_initData();
    UPDATE people SET sex = 1 WHERE MOD(id,2) = 1;
    
    添加的索引类型

    测试结果:

    SELECT * FROM people WHERE sex = 0;
    SELECT * FROM people WHERE sex = 1;
    
    无sex索引 有sex索引
    sex=0
    sex=1

    可以看到相同的sql,加索引之后比不加索引慢许多。

    原因

    在InnoDB中每一个表都会有聚集索引,如果表定义了主键,则主键就是聚集索引。一个表只有一个聚集索引,其余为普通索引。
    索引的结构是B+树,非叶子节点存储key,叶子节点存储value。

    1. 聚集索引,叶子节点存储行记录,InnoDB索引和记录是存储在一起的。
    2. 普通索引,叶子节点存储了主键的值。

    以上表的索引结构示例如下(PS:索引结构仅供参考)

    聚集索引
    sex列普通索引
    在使用普通索引查询时,会先加载普通索引,通过普通索引查询到实际行的主键。再使用主键通过聚集索引查询相应的行。以此循环查询所有的行。
    若直接全量搜索聚集索引,则不需要在普通索引和聚集索引中来回切换。
    相比两种操作的总开销可能扫描全表效率更高。

    感谢:
    https://mp.weixin.qq.com/s/tmkRAmc1M_Y23ynduBeP3Q
    https://blog.jcole.us/innodb/
    https://blog.csdn.net/u012978884/article/details/52416997?utm_source=blogxgwz0
    https://draveness.me/mysql-innodb

    相关文章

      网友评论

          本文标题:[InnoDB]性别字段为什么不适合加索引

          本文链接:https://www.haomeiwen.com/subject/xkxhxqtx.html