你有没有遇到过这种情况:在公司系统里查一个客户信息,等了十几秒才出结果,急得直拍桌子?而别人查同样的数据,几乎秒出。问题可能不在网络,也不在电脑,而是数据库里的“索引”没整明白。
什么是索引?
可以把它想象成一本书的目录。比如你想找《西游记》里孙悟空大闹天宫是哪一章,如果没有目录,就得一页一页翻。但如果有目录,直接翻到对应页码,快得多。数据库里的索引就是这个“目录”,它记录了数据的位置,让查询不用全表扫描。
加了索引,真的快吗?
真快。比如有一张用户表,里面有100万条数据。要查手机号是13800138000的用户:
SELECT * FROM users WHERE phone = '13800138000';
如果没有索引,数据库得一条一条比对,像人工查电话簿。如果加了 phone 字段的索引,数据库直接跳到目标位置,速度从几秒降到毫秒级。
那所有字段都加索引不就完了?
不行。索引不是免费的午餐。每加一个索引,数据写入时就得同步更新索引结构。就像你写书,每改一段内容,还得手动改一遍目录,多了也累。插入、更新、删除数据时,带索引的表会更慢。
而且索引要占磁盘空间。一个大表上建了三四个索引,可能索引文件比数据还大。服务器硬盘不是大风刮来的。
什么时候该加索引?
优先给经常用来查询、排序、做条件的字段加。比如用户的ID、订单号、登录时间这些。像“性别”这种只有男女两个值的字段,加了也没啥用——数据库一看,查男的要扫一半数据,还不如直接全表扫。
还有,联合查询的字段也可以考虑建联合索引。比如总按“城市 + 年龄”查用户:
CREATE INDEX idx_city_age ON users (city, age);
这样比单独给 city 和 age 各建一个索引更高效。
索引也不是万能的
有时候你明明建了索引,查询还是慢。可能是用了函数:
SELECT * FROM users WHERE YEAR(create_time) = 2023;
数据库没法用 create_time 的索引,因为被 YEAR() 包了一层。改成这样才行:
SELECT * FROM users WHERE create_time >= '2023-01-01' AND create_time < '2024-01-01';
另外,数据量太小的表,建索引意义不大。就像家里三口人,还专门搞个通讯录?翻开户口本就看到了。
索引是个好东西,但得用对地方。查得慢的时候别光骂电脑,看看是不是数据库“目录”没做好。”}