关于数据库索引的所有文章,都会告诉你不要对这种字段建索引。
但这些文章不会告诉你的一个事实是:
如果表里面这个字段的值分布极度不均匀的情况下,而且你需要查询分布较少的记录的话,索引就非常有用了
举个例子,假设表中有一千万条记录,某个状态为0的记录总数大概会有100条,那么你想查询状态为0的记录时,有没有索引影响非常大,而查询状态为1的记录,则索引基本无用。如果两种状态的记录数相差无几的话,索引也基本无用。
所有的关于索引的文章,建议你不要为这种字段建索引的依据,都是以值分布是均匀为前提的。但如果值分布不均匀的时候,这个建议就不一定是正确的了。当我们需要查询的记录恰好是分布较少的记录的时候,值分布越是不均匀,索引就越有价值!
索引的本质就是排序,因为大家都排好了队,所以一样的数据都依次排在一块了。这个时候,就像奥运会开幕式入场的运动员们一样,中国队、美国队、德国队。。。队长都举着自己国家的小牌子,让人远远地就能看到那个瑞典队在什么地方(有索引)。这个时候,你要采访瑞典队,直接跑过去就行了。当散场后你再想去餐厅找瑞典队采访(没有索引),估计就得按个问过去:兄弟,你是不是瑞典队的?等你找到采访对象,还是算了吧,人家都吃完饭走人了(查询超时)。。。
二值的情况下,形象点说,就是你在上海人民广场找人,看你找的是中国人还是外国人。找10个中国人很简单,基本上是逮着一个算一个。但要找10个外国人,就比较费时间了。。。这个时候如果大家都排队,中国人排前面,外国人排后面,你就可以直奔队伍的末尾去喊上10个外国人了。
现在大家明白了这种字段的索引到底要不要建了吧。
我们的索引一般都是非唯一的B+树索引;
目的是为了提高查询效率;
我本来以为,一般一个表都有多个字段,比如有20个字段,如果我们不用索引,那么就是全表扫描;
最理想的情况,20个字段的数据连续存放,如果我只是查询一个字段的信息,并且where条件里也是这个字段;
比如 select field1 from table1 where field1='xxx';
那么由于Field1... field20 占用的是连续的空间,所以执行查询的时候,实际上要把field2...field20跳开;
但是,如果我们这个表只有一个字段,那么,查询的空间是连续的;所以速度要快些;
这个也许是索引能速度快的原因,索引记载的就是这个索引字段的信息和rowId,所以它可以劈开field2...field20的干扰;
但是假如这个表只有一个字段(字段值不唯一,所以没有加主键),那么加不加索引不是一样吗?
我做了简单的实验,发现以上想法有问题,实践证明,哪怕某个表只有一个字段,加不加索引差距也是巨大的!
实验内容:
A表 20个字段,160万条记录;
B表 1个字段, 160万条记录;
B表先没有索引,执行
select field1 from B表 where field1='xxx';
消耗0.55秒时间;
然后建立field1的非唯一索引,在执行以上的语句;
消耗实践仅有0.02秒,速度提高了30倍左右;
所以哪怕只有一个字段,有无索引差距也是巨大的;
A表和B表的索引一样,也是field1为索引;
执行
select field1 from A表 where field1='xxx';
消耗也是 0.02秒 ;
所以如果一个表有索引,那么针对该字段的查询,字段的多少对速度的影响不大;
在执行下面两句:
select field1 from A表 where field1 like '%xxx%';
select field1 from B表 where field1 like '%xxx%';
也就是故意不用索引而用全表扫描;
发现这两句话速度差不多都是为3秒多,差距不大;
所以就算是全表扫描,字段少的表的查询速度未必比字段多的表好到那里。
然后我有查询了user_segments里的 segment_name 值为: B表和对应的索引 的 字节数;
发现 索引占用的空间反而比表大!
不过这个也可以理解,因为毕竟索引的查询速度快很多啊。它内部可能有其他的附加信息;
为何仅有一个字段的表也需要索引?
我个人以为,索引内部可能有排序,所以它查找起来就通过查找范围段就行了;
而全表扫描某个字段,是没有排序的,所以它必须查找所有。
想法未必正确,后者说未必全面;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2019-06-11 win10文件夹或文件已在另一程序中打开
2019-06-11 指定网卡IP进行ping操作
2019-06-11 C# 使用WebClient时,在多网卡IP时,指定IP发送Web请求
2010-06-11 在ASP.NET中如何实现和利用URL重写(转)