关联查询字段没索引会怎样
在写SQL的时候,经常要通过JOIN连接两张表,比如订单表和用户表,靠user_id把它们连起来。这时候如果user_id没有加索引,查询速度可能慢得让人抓狂。
数据库执行关联查询时,会逐行扫描被连接的表。比如从订单表取出一条记录,然后去用户表里找对应的user_id。如果没有索引,就得全表扫一遍用户表。订单有1万条,用户表也得被扫1万遍,这种操作叫“嵌套循环”,效率极低。
响应时间明显变长
一个原本0.1秒能出结果的页面,可能变成5秒甚至更久。用户点一下订单详情,转圈圈半天出不来,客服电话立马就响了。线上系统一旦遇到高并发,数据库CPU直接飙到100%,服务卡死很常见。
举个例子:公司刚上线时数据少,没加索引也能撑住。半年后订单涨到百万级,某天运营要做一次跨表统计,SQL一跑,整个系统瘫痪了十分钟。查下来问题就是关联字段没索引,导致全表扫描拖垮了性能。
磁盘IO压力猛增
没有索引意味着更多数据页需要从磁盘读取。内存缓存命中率下降,数据库不断从硬盘加载数据块,IOPS(每秒输入输出次数)飙升。硬盘扛不住,响应自然越来越慢。
像MySQL的InnoDB引擎,即使数据在内存里,全表扫描也会遍历大量无效记录。这不仅占IO,还浪费内存资源,影响其他正常查询。
锁竞争加剧
长时间运行的查询会持有锁更久。比如你扫用户表找匹配记录,过程中其他修改用户信息的操作就得排队等。容易引发锁等待超时,甚至死锁,业务逻辑直接报错。
特别是UPDATE或DELETE涉及关联条件时,如果条件字段无索引,不仅自己慢,还会波及整个事务系统的流畅性。
怎么判断是不是缺索引
用EXPLAIN看执行计划最直接。比如有这么一句:
EXPLAIN SELECT o.order_no, u.name FROM orders o JOIN users u ON o.user_id = u.user_id;如果发现type列是ALL,key列是NULL,基本可以确定users表走了全表扫描。这时候给user_id加上索引:
ALTER TABLE users ADD INDEX idx_user_id (user_id);再跑一遍,type变成ref或者eq_ref,rows大幅减少,说明索引生效了。
实际开发中,别等到出问题才想起加索引。建表时就要考虑哪些字段常用于关联或查询条件。宁可提前建几个用不上的,也别让关键路径裸奔。
有时候联合查询多个字段,单个索引不够用,还得上复合索引。比如订单按用户和状态一起查,index(user_id, status)比单独两个索引更高效。
索引不是万能药,多了会影响写入速度,但关键的关联字段不加,读取性能损失更大。权衡的重点应该放在“哪些查询最频繁、数据量最大”上。