索引是利用一定规律的数据结构与实际数据之间的关系来加速数据查找的函数。我们的数据库存储了大量的内容,索引可以根据特定的规则和算法通过数据节点快速找到该节点对应的实际文件的位置。简单来说,索引就像是一本书的目录,可以帮助我们准确定位到这本书的具体内容。最近在学习索引的时候遇到了一个问题。让我们通过复制它来了解一下。首先创建一个测试表如下:CREATETABLE`simple_table`(`id`intNOTNULLAUTO_INCREMENT,`c1`datetimeDEFAULTNULL,`c2`datetimeDEFAULTNULL,PRIMARYKEY(`id`),KEY`c2__idx`(`c2`),KEY`fun_c1_idx`((cast(`c1`asdate))))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COLLATE=utf8mb4_0900_ai_ci;fun_c1_idx:是mysql8支持的函数索引然后随机插入1000条数据进去这张桌子。select*fromsimple_tablewheredate(c2)='2022-01-01';可以看到上面的SQL语句是不能使用索引的。因为列的实际值和主键值存储在索引树中,所以对条件字段执行函数操作会使索引失效。简单的说,如果你用'2022-01-01'去匹配,你将无法在索引树中定位到该值。所以,正确的选择是放弃索引,选择全表扫描。让我们看下一条SQL。从simple_table中选择id,c2,其中date(c2)='2022-01-01';与第一个不同的是,这个SQL只返回了一些列,而这些列都在索引中。然后我们用explain来分析这条SQL的执行计划,判断是否可以到索引:从上图可以清楚的看到key值为c2__idx,也就是索引没有了。这里很奇怪。不是说对条件字段的函数操作会让索引失效吗?为什么这里的索引不见了?这是我在学习的时候遇到的问题,后来发现是因为没有理解“走指数”的意思。大家都知道索引可以加快查询速度,但是你知道为什么索引可以加快查询速度吗?答案是减少查询次数。现在我们回到上面的SQL,可以看到虽然key值为c2__idx,但是rows值为1000,也就是扫描了整张表,也就是扫描了c2__idx的所有记录。但是因为c2__idx已经包含了所有需要查询的列,所以优化器选择使用这个索引。最后我们再思考一个问题,使用索引就一定更快吗?我们通过一个具体的例子来看一下这个问题:select*fromsimple_table;select*fromsimple_tablewhereid>0;不进行explain分析,可以看到第一条SQL没有使用索引,第二条SQL使用了主键。指数。可见不使用索引的速度更快。这是因为虽然使用了索引,但是从主键索引最左边的叶子节点向右扫描整棵索引树,进行了全表扫描,使得索引没有意义。.总结一下:一个查询是否使用索引,仅仅表明了一条SQL语句的执行过程;是否是慢查询是由它的执行时间决定的,也就是说是否使用索引和是否是慢查询之间没有确定性联系。我们在使用索引的时候,不能仅仅关注它是否起作用,而是索引是否减少了查询扫描的数据行数,减少的扫描行数会提高效率。对于大表,不仅要创建索引,还要考虑索引的过滤性。过滤性好,执行速度就会快。推荐阅读Base64编码知识,一篇文章尽在掌握!Golang常用设计模式之单例模式
