新手心得:数据库索引到底在帮你省什么时间
刚接触数据库的时候,我对“索引”这个词的理解很模糊:建了它查询就变快,不建也照样能跑。那它到底快在哪,又为这份快付出了什么?后来把它想成图书馆的检索目录,整件事就清楚了。
没有索引的查询,就像走进一座没有目录的图书馆找一本书。你只知道书名,却不知道它在哪个架子、哪一层,只能从第一排开始一本一本看过去。书少的时候无所谓,书到了一百万本,这种“逐本翻”就慢得没法接受。数据库里这就叫全表扫描:把每一行都读出来、逐一比对,直到找到符合条件的那几行。
索引就是给这座图书馆补上一套目录卡。数据库会另外维护一份结构:里面按某一列的值排好序,每个值后面记着它对应整行数据的位置。查的时候先翻目录卡,定位到位置,再直接去取那几行,不用把全馆翻一遍。关键点是:索引不是表的第二份复制,它只是“值到位置”的一份有序快捷方式,真正的数据仍在表里。
那目录卡本身怎么做到翻得快?主流关系型数据库默认用的是一种叫 B 树(更准确说是 B+ 树)的结构,可以把它理解成分层的目录。顶层目录只写大致的分界:你要找的值落在哪个区间,就顺着那个区间往下一层走;每一层都把范围再缩小一截,直到叶子层找到确切位置。因为每一层都砍掉一大半候选,一百万行的数据,往往走三四层就能定位,而不是比对一百万次。这就是“有序”带来的红利:排序让查找可以不断二分、不断缩小范围,而不是逐个试。
索引还顺带帮了排序和连接的忙:查询要按索引列排序时,常可直接顺着索引读,省去临时排序;两表按字段关联时,有索引的一方也能快速定位匹配行。
但目录卡不是免费的午餐,维护它要花钱——花的是写操作的成本和存储空间。每次往表里插入、删除或修改一行,数据库除了改表本身,还得同步改动相关的索引:新值要插进有序结构里的正确位置,位置满了还可能要拆分节点;删掉的行也要把目录卡上的条目清掉。索引建得越多,每次写数据要同步改的地方就越多。所以写得多、读得少的表,索引建多了反而会拖慢写入;索引本身也要占磁盘空间,建得滥,空间开销同样可观。
由此也破掉几个常见误解。第一,索引不是建得越多越好,正确做法是给真正经常用来查、用来关联、用来排序的列建,而不是把每一列都加上。第二,索引不是万能提速器:如果一次查询本来就要返回表里的大部分行,走索引再逐行去取,反而可能比直接扫描更折腾,这时数据库宁可直接全表扫描。第三,小表不一定需要索引:数据只有几十上百行,翻一遍的成本本来就极低,走索引的绕路未必划算。第四,索引帮不了“没按索引列查”的查询:比如对多列组合索引,只用后一列过滤,往往用不上前面那份有序性,就像目录卡是按作者排的,你只知道书名,翻这套卡也帮不上忙。
记住一条判断标准就够了:索引省的是“在一大堆数据里定位少数几行”的时间。读得多、量大、每次只要少数几行,是它最擅长的场景;写得多、量小、每次要的又多,就先掂量掂量。下次听到“查询慢,加个索引试试”,就知道它在省什么、又在花什么了。
- 点赞
- 收藏
- 关注作者
评论(0)