52条SQL优化规则
1、优化查询,尽量避免全表扫描。 首先考虑在WHERE和ORDER BY涉及的列上创建索引。
2、尽量避免WHERE子句中字段的NULL值判断。 NULL是创建表时的默认值,但大多数时候应该使用NOT NULL,或者使用特殊的值,如0、-1作为默认值。
3. 尽量避免在WHERE子句中使用!=或运算符。 MySQL 仅对以下运算符使用索引:=、IN,有时还有 LIKE。
4、尽量避免在WHERE子句中使用OR来连接条件,否则引擎会放弃使用索引而进行全表扫描。 您可以使用 UNION 合并查询: id from t where num=10 union all id from t where num= 20。
5、IN和NOT IN也要谨慎使用,否则会导致全表扫描。 对于连续值,如果可以的话,不要使用 IN:id from t where num 1 and 3。
6. 以下查询也将导致全表扫描:id from t where name like'%abc%' 或 id from t where name like'%abc'。 为了提高效率,可以考虑全文检索。 该索引仅用于 t where name like'abc%' 的 id。
7、如果WHERE子句中使用了参数,也会引起全表扫描。
8、尽量避免对WHERE子句中的字段进行表达式操作,尽量避免对WHERE子句中的字段进行函数操作。
9. 很多时候,替换 IN: num from a where num in( num from b) 是一个不错的选择。 替换为以下语句:num from a where (1 from b where num=a.num)。
10、索引虽然可以提高相应的效率,但同时也降低了相应的效率。 因为索引可能时不时地需要重建,所以如何构建索引需要仔细考虑,并根据具体情况而定。 一个表上的索引最好不要超过6个。 如果太多,就应该考虑是否有必要对一些不常用的列建立索引。
11. 应尽可能避免更新索引数据列,因为索引数据列的顺序就是表记录的物理存储顺序。 一旦列值发生变化,整个表记录的顺序就会调整,这会消耗相当大的资源。 如果应用系统需要频繁更新索引数据列,那么就需要考虑是否应该将索引建为索引。
12. 尝试使用数字字段。 如果字段只包含数字信息,尽量不要将其设计为字符字段。 这会降低查询和连接的性能,并增加存储开销。
13、尽可能使用/代替char/nchar。 因为首先变长字段的存储空间较小,可以节省存储空间。 其次,对于查询来说,在相对较小的领域内搜索效率明显更高。
14. 最好不要使用 all: * from t,使用特定的字段列表代替*,并且不要返回任何未使用的字段。
15.尽量避免向客户端返回大量数据。 如果数据量太大,就应该考虑相应的要求是否合理。
16.使用表别名(Alias):在SQL语句中连接多个表时,请使用表别名,并在每个表前加上别名前缀。 这减少了解析时间并减少了由歧义引起的语法错误。
17、使用“临时表”临时存储中间结果:
简化SQL语句的一个重要方法是使用临时表来临时存储中间结果。 但临时表的好处远不止这些。 临时结果存储在临时表中,后续查询可以执行。 这样可以避免程序中对主表的多次扫描,也大大减少了程序执行过程中的“共享锁”阻塞。 更新锁”,减少阻塞,提高并发性能。
18. 应该添加一些读和写会互相阻塞的SQL查询语句,以提高并发性能。 对于某些查询,可以添加允许读时写,但缺点是可能会读到未提交的脏数据。
使用原则有3条:
19. 常见的简化规则如下:
不要有超过5个表连接(JOIN),考虑使用临时表或表变量来存储中间结果。 少用子查询,并且不要嵌套视图太深。 一般嵌套视图不超过2个为宜。
20、预先计算出需要查询的结果放入表中,然后再次查询。 这是SQL7.0之前最重要的方法,比如医院住院费计算。
21、使用OR的句子可以分解为多个查询,多个查询可以通过UNION连接起来。 它们的速度只与是否使用索引有关。 如果查询需要联合索引,UNION all 执行效率会更高。 多个OR语句没有使用索引,所以改写为UNION的形式,并尝试匹配索引。 一个关键问题是是否使用索引。
22、IN后的值列表中,将出现次数最多的值放在前面,出现次数最少的值放在最后,以减少判断次数。
23、尽量把数据处理工作放在服务器上,以减少网络开销,例如使用存储过程。
存储过程是经过编译、优化、组织成执行计划并存储在数据库中的 SQL 语句。 它们是控制流语言的集合,当然速度很快。 重复执行的动态SQL可以使用临时存储过程(临时表)。
24、当服务器内存足够时,配置线程数=最大连接数+5,这样才能达到最大效率; 否则,使用配置的线程数<最大连接数并启用SQL线程池来解决问题。 如果数量仍然=最大连接数+5,严重损害服务器的性能。
25、查询关联与书写顺序相同:
select a.personMemberID, * from chineseresume a,personmember b where personMemberID = b.referenceid and a.personMemberID = 'JCNPRH39681' (A = B, B = '号码')
select a.personMemberID, * from chineseresume a,personmember b where a.personMemberID = b.referenceid and a.personMemberID = 'JCNPRH39681' and b.referenceid = 'JCNPRH39681' (A = B, B = '号码', A = '号码')
select a.personMemberID, * from chineseresume a,personmember b where b.referenceid = 'JCNPRH39681' and a.personMemberID = 'JCNPRH39681' (B = '号码', A = '号码')
26. 尝试改用count(1)来判断记录是否存在。 count函数仅在统计表中所有行时使用,count(1)比count(*)效率更高。
27. 尝试使用“">=”而不是“>”。
28、索引使用规范:
29、以下SQL条件语句中的列索引正确,但执行速度很慢:
SELECT * FROM record WHERE substrINg(card_no, 1, 4) = '5378' --13秒
SELECT * FROM record WHERE amount/30 < 1000 --11秒
SELECT * FROM record WHERE convert(char(10), date, 112) = '19991201' --10秒
分析:
SQL运行时,WHERE子句中对列的任何操作的结果都是逐列计算的,因此必须在不使用列索引的情况下进行表搜索。
如果这些结果在查询编译时可用,则可以通过 SQL 优化器使用索引并避免表搜索来优化它们,因此按如下方式重写 SQL:
SELECT * FROM record WHERE card_no like '5378%' -- < 1秒
SELECT * FROM record WHERE amount < 1000*30 -- < 1秒
SELECT * FROM record WHERE date = '1999/12/01' -- < 1秒
30.当有批量插入或更新时,使用批量插入或批量更新,而不是一条一条更新记录。
31、所有的存储过程中,如果可以使用SQL语句,我绝对不会使用循环来实现。
32.选择最有效的表名顺序(仅在基于规则的优化器中有效):
解析器按照从右到左的顺序处理 FROM 子句中的表名。 FROM 子句中最后写入的表(基表表)将首先被处理。 当FROM子句Next中包含多个表时,必须选择记录数最少的表作为基表。
如果查询连接的表超过3个,则需要选择一个交叉表(表)作为基表。 交叉表是指被其他表引用的表。
33、为了提高GROUP BY语句的效率,可以在GROUP BY之前过滤掉不需要的记录。 以下两个查询返回相同的结果,但第二个查询明显更快。
效率低下:
SELECT JOB, AVG(SAL)
FROM EMP
GROUP BY JOB
HAVING JOB = 'PRESIDENT'
OR JOB = 'MANAGER'
高效的:
SELECT JOB, AVG(SAL)
FROM EMP
WHERE JOB = 'PRESIDENT'
OR JOB = 'MANAGER'
GROUP BY JOB
34、SQL语句使用大写字母,因为SQL语句总是先解析,小写字母在执行前转换为大写字母。
35. 别名的使用。 别名是大型数据库的一种应用技术。 即在查询中表名和列名使用一个字母作为别名。 查询速度比建连接表快1.5倍。
36. 为了避免死锁,在存储过程和触发器中始终以相同的顺序访问同一个表; 事务应尽可能缩短,并且事务所涉及的数据量应尽可能减少; 从不在事务中等待用户输入。
37.避免使用临时表。 除非必要,尽量避免使用临时表。 相反,您可以使用表变量来代替。 大多数时候(99%),表变量驻留在内存中,因此比驻留在数据库中的临时表更快,因此对临时表的操作需要跨数据库通信,自然会慢一些。
38.最好不要使用触发器:
39. 索引创建规则:
40、MySQL查询优化总结:
使用慢查询日志来发现慢查询,使用执行计划来确定查询是否正常运行,并始终测试查询以查看它们是否以最佳状态运行。
性能总是会随着时间的推移而改变,避免对整个表使用count(*),它可能会锁定整个表,使查询一致以便后续类似的查询可以使用查询缓存,在适当的情况下使用GROUP BY代替,使用索引WHERE、GROUP BY 和 ORDER BY 子句中的列,保持索引简单,并且不要在多个索引中包含相同的列。
有时MySQL会使用错误的索引。 在这种情况下,使用USE INDEX并检查使用=的问题。 对于少于5条记录的索引字段,在UNION中使用LIMIT并不意味着使用OR。
为避免更新前使用ON KEY,请勿使用MAX; 使用索引字段和 ORDER BY 子句 LIMIT M, N 在某些情况下实际上会减慢查询速度,请谨慎使用,在 WHERE 子句中使用 UNION 而不是子查询。 重新启动 MySQL 后,请记住预热数据库,以确保数据在内存中并且查询速度快。 考虑持久连接而不是多个连接以减少开销。
基准查询,包括使用服务器上的负载。 有时,一个简单的查询可能会影响其他查询。 当服务器上的负载增加时,使用 SHOW 查看缓慢且有问题的查询。 对开发环境中生成的镜像数据进行全部测试。 可疑的询问。
41、MySQL备份流程:
42. 查询缓冲区不会自动处理空格。 因此,在编写SQL语句时,应尽量减少使用空格,尤其是SQL开头和结尾的空格(因为查询缓存不会自动截取开头和结尾的空格)。
43、以mid为标准分表查询方便吗? 一般业务需求中,基本都会用到查询依据。 一般情况下应该是通过做hash取模来分表的。
说到分表,MySQL的作用就是这么做的,而且对代码是透明的; 在代码层面实现似乎不合理。
44、数据库中每个表都应该设置一个ID作为主键,最好是INT类型(推荐),并设置自增标志。
45. 在所有存储过程和触发器的开头设置 SET ON,在末尾设置 SET OFF。 存储过程和触发器的每条语句执行完毕后无需向客户端发送消息。
46.MySQL查询可以启用高速查询缓存。 这是提高数据库性能的有效MySQL优化方法之一。 当多次执行同一个查询时,从缓存中拉取数据并直接从数据库返回要快得多。
47、查询用于跟踪观看效果:
使用关键字可以让您了解 MySQL 如何处理您的 SQL 语句。 这可以帮助您分析查询语句或表结构的性能瓶颈。 查询结果还将告诉您如何使用索引主键以及如何搜索和排序数据表。
48. 当只有一行数据时使用 LIMIT 1:
有时当你查询一张表时,你已经知道结果只会是一个结果,但是因为你可能需要获取游标,或者你可能想检查返回的记录数。
在这种情况下,添加 LIMIT 1 可以提高性能。 这样,MySQL数据库引擎在找到一条数据后就会停止搜索,而不是继续搜索下一条与该记录匹配的数据。
49.为表选择合适的存储引擎:
50、优化表的数据类型,选择合适的数据类型:
原则:越小越好,简单越好,所有字段必须有默认值,并尽量避免NULL。
例如:在设计数据库表时,尽可能使用较小的整数类型,以占用更少的磁盘空间。 (比 int 更合适)
例如,时间字段:和。 占用8字节,占用4字节,只用了一半。 表达的范围是1970-2037年,适合更新时间。
MySQL可以很好地支持大量数据的访问,但一般来说,数据库中的表越小,对其执行查询的速度就越快。
因此,在创建表时,为了获得更好的性能,我们可以将表中字段的宽度设置得尽可能小。
例如:在定义邮政编码字段时,如果设置为CHAR(255),显然会给数据库增加不必要的空间。 即使使用这种类型也是多余的,因为 CHAR(6) 可以很好地完成这项工作。
同样,如果可能的话,我们应该使用BIGIN来定义整型字段,并尽量将字段设置为NOT NULL,这样数据库以后执行查询时就不需要比较NULL值了。
对于一些文本字段,例如“省份”或“性别”,我们可以将它们定义为ENUM类型。 因为在MySQL中,ENUM类型被视为数值数据,而数值数据的处理速度比文本类型要快得多。 这样,我们就可以提高数据库的性能。
51. 字符串数据类型:char、、text。 选择差异。
52、对列的任何操作都会导致表扫描,其中包括数据库函数、计算表达式等,查询时应尽量将操作移至等号右侧。