mysql查询优化
1.count优化
1 2 3 4 | #a语句: SELECT COUNT (*) FROM users WHERE id>5; #b语句: SELECT ( SELECT COUNT (*) FROM users ) - COUNT (*) FROM users WHERE id<=5; |
a语句当行数超过11行的时候需要扫描的行数比b语句要多, b语句扫描了6行,此种情况下,b语句比a语句更有效率。
当没有where语句的时候直接select count(*) from world.city这样会更快,因为mysql总是知道表的行数。
2.数据不兼容会拉低效率
例如float和int、char和varchar、binary和varbinary是不兼容的。数据类型的不兼容可能使优化器无法执行一些本来可以进行的优化操作。
在程序中,保证在实现功能的基础上,尽量减少对数据库的访问次数;
通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担;
能够分开的操作尽量分开处理,提高每次的响应速度;
在数据窗口使用SQL时,尽量把使用的索引放在选择的首列;算法的结构尽量简单;
在查询时,不要过多地使用通配符如 SELECT * FROM T1语句,要用到几列就选择几列如:SELECT COL1,COL2 FROM T1;
在可能的情况下尽量限制尽量结果集行数如:SELECT TOP 300 COL1,COL2,COL3 FROM T1,因为某些情况下用户是不需要那么多的数据的。
不要在应用中使用数据库游标,游标是非常有用的工具,但比使用常规的、面向集的SQL语句需要更大的开销;按照特定顺序提取数据的查找。
3.索引列进行运算会让索引失效
如下:b语句进行了运算,会使索引失效,从而降低查询效率
1 2 3 4 5 6 | #创建索引 CREATE INDEX index_age ON users(age); #a语句 SELECT * FROM WHERE age<12; #b语句 SELECT * FROM WHERE age*2<24; |
4.避免使用 !=/<>/is null/is not null/in/not in等这样的操作符
使用这类操作符会使系统无法使用索引,而只能直接搜索表中的数据
1 2 3 4 | #a语句 SELECT COUNT (*) FROM users WHERE age IN ( SELECT age FROM users WHERE id>100); #b语句 SELECT COUNT (*) FROM users WHERE EXISTS ( SELECT age FROM users WHERE id>100); |
a语句使用了in关键字,会降低效率
5.尽量使用数字类型的字段
数字类型占用内存小
对于字符串类型,数字类型易于作比较
比较长的数据使用字符串(例如身份证号、电话号码等...)
6.合理使用where < 0 和 exists
1 2 3 4 5 6 7 8 | CREATE TABLE t1(c1 INT ,c2 INT ); CREATE TABLE t2(c1 INT ,c2 INT ); INSERT INTO t1(c1,c2) VALUES (11,22),(22,33),(33,44); INSERT INTO t2(c1,c2) VALUES (44,33),(33,22),(22,11); #a语句: SELECT t1.c1 FROM t1 WHERE ( SELECT COUNT (*) FROM t2 WHERE t2.c2=t1.c2 > 0); #b语句: SELECT t1.c1 FROM t1 WHERE EXISTS ( SELECT COUNT (*) FROM t2 WHERE t2.c2=t1.c2); |
b语句查询速度高于a语句
7.能使用between,就不使用in。(连续的范围,可以使用索引,between...and...)
1 2 | #查询年龄100到200之间的数据 SELECT * FROM users WHERE age BETWEEN 100 AND 200; |
8.能使用distinct(去重),就不使用group by(分组)
1 2 | SELECT DISTINCT NAME FROM users; SELECT NAME FROM users GROUP BY NAME ; |
9.尽量不要使用select into语句,该语句会导致‘表锁定’,组织其他用户访问
10. 强制使用索引
1 2 3 4 | #a语句:不使用索引 SELECT * FROM users WHERE tid=3 AND uid IN (10,8,5); #b语句:强制使用索引 --force index(索引名称) SELECT * FROM users FORCE INDEX (id_uid) WHERE tid=3 AND uid IN (10,8,5); |
11. 消除顺序读取,使用索引
1 2 3 4 5 6 | #a语句:不使用索引 SELECT * FROM users WHERE (tid=5 AND uid>20) OR uid =15; #b语句:拆分,使用索引 SELECT * FROM users WHERE tid=8 AND uid>20 UNION SELECT * FROM users WHERE uid =15; |
12. 模糊查询(where like)时,字母打头'a%'会使用索引,非字母打头'%a%'不会使用索引
1 2 3 4 5 | #a语句不会使用索引 SELECT * FROM aaa WHERE NAME LIKE '%F%' ; SELECT * FROM aaa WHERE SUBSTRING ( NAME ,3,2)= 'F' ; #b语句会使用索引 SELECT * FROM aaa WHERE NAME LIKE 'F%' ; |
13.虽然UPDATE、DELETE语句的写法基本固定,但是还是对UPDATE语句给点建议:
a) 尽量不要修改主键字段。
b) 当修改VARCHAR型字段时,尽量使用相同长度内容的值代替。
c) 尽量最小化对于含有UPDATE触发器的表的UPDATE操作。
d) 避免UPDATE将要复制到其他数据库的列。
e) 避免UPDATE建有很多索引的列。
f) 避免UPDATE在WHERE子句条件中的列。
14.能使用union all,就不要使用union
union会默认进行去重、排序操作,会降低效率
UNION ALL不执行SELECT DISTINCT函数,这样就会减少很多不必要的资源 在跨多个不同的数据库时使用UNION是一个有趣的优化方法,UNION从两个互不关联的表中返回数据,这就意味着不会出现重复的行,同时也必须对数据进行排序,我们知道排序是非常耗费资源的,特别是对大表的排序。
UNION ALL可以大大加快速度,如果你已经知道你的数据不会包括重复行,或者你不在乎是否会出现重复的行,在这两种情况下使用UNION ALL更适合。此外,还可以在应用程序逻辑中采用某些方法避免出现重复的行,这样UNION ALL和UNION返回的结果都是一样的,但UNION ALL不会进行排序。
15. 字段数据类型优化:
a. 避免使用NULL类型:NULL对于大多数数据库都需要特殊处理,MySQL也不例外,它需要更多的代码,更多的检查和特殊的索引逻辑,有些开发人员完全没有意识到,创建表时NULL是默认值,但大多数时候应该使用NOT NULL,或者使用一个特殊的值,如0,-1作为默认值。
b. 尽可能使用更小的字段,MySQL从磁盘读取数据后是存储到内存中的,然后使用cpu周期和磁盘I/O读取它,这意味着越小的数据类型占用的空间越小,从磁盘读或打包到内存的效率都更好,但也不要太过执着减小数据类型,要是以后应用程序发生什么变化就没有空间了。修改表将需要重构,间接地可能引起代码的改变,这是很头疼的问题,因此需要找到一个平衡点。
c. 优先使用定长型
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?