Mysql优化
InnoDB | MyISAM | |
---|---|---|
事务处理 | 支持 | 不支持 |
全文搜索 | 不支持 | 支持 |
SELECT ,UPDATE,INSERT,DELETE | 大量INSERT或UPDATE | DELETE 表一行一行的删除 | 大量SELECTDELETE | DELETE表先DROP再重建 |
AUTO_INCREMENT | 自增计数器仅存储在主内存中 | |
锁 | 表锁,行级锁 | 表锁 |
外键 | 支持 | 不支持 |
行数 | 扫描表来计算 | 保存行数 |
存储 | 把数据和索引存放在表空间里面 | 表被存放在三个文件 |
跨平台 | 跨平台可直接拷贝使用 | 跨平台很难直接拷贝 |
压缩 | 难 | 易 |
哈希索引 | 支持 | 不支持 |
事务ACID | 支持 | 不支持 |
储存容量 | 64T | 没上限 |
0. 一条sql语句在Mysql中如何执行
1. 预编译
sql语句执行过程分为:
词法语义解析、语句优化、制定执行计划
一条sql语句可能会反复执行,或者每次执行的时候只有个别的值不同,且每次都需要经过上面的词法语义解析、语句优化、制定执行计划等,效率就底下
预编译语句就是将这类语句中的值用占位符替代,可以视为将sql语句模板化或者说参数化,一次编译、多次运行,省去了解析优化等过程
缓存预编译
预编译语句被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行,并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略
作用
优化 sql 的执行,预编译之后的 sql 多数情况下可以直接执行,DBMS 不需要再次编译,越复杂的sql,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作
防止SQL注入
使用预编译,而其后注入的参数将不会再进行SQL编译,也就是说其后注入进来的参数系统将不会认为它会是一条SQL语句,而默认其是一个参数,参数中的or或者and 等就不是SQL语法保留字了
2. 选择最有效率的表名顺序
数据库从左到右处理FROM子句中的表名
多表无关系:数据,列名最少的表放左边
多表有关系(连接):将引用最多的表放左边(on中被引用)
3. WHERE子句中的连接顺序
数据库从左到右解析WHERE子句
筛选掉最多数量记录的条件必须写在右边,表之间的连接必须写在左边
SELECT * FROM <表1>,<表2> WHERE (table.a > 1000) AND (table1.a = table2.b)
4. SELECT子句中避免使用*号
数据库会查询数据字典,将*依次转换成所有的列名,非常耗时,也不直观,建议手写
安全性问题,后期修改字段,查询出来处理会出现异常
5. 用TRUNCATE替代DELETE
DELETE一条条删
TRUNCATE删表重建
6. 使用表、列的别名
名字太长要解析,耗资源
7. 使用内部函数提高SQL效率
这些函数内部优化过了,比我们操作更优秀
8. 避免在索引列上使用NOT、<>、!=
范围搜索会转而执行全表扫描,最左匹配
9. 用 >= 替代 >
低效:
SELECT * FROM <表名> WHERE id > 3
定位到id=3,扫描第一个id大于3的数据
高效:
SELECT * FROM <表名> WHERE id >= 4
直接跳到第一个id等于4的数据
10. 善用索引
查询多,条件字段加索引,增删多就别加了
索引上不使用函数,因为是通过索引来匹配查找的
11. 使用like关键字通配符%置于要查询字段的前面那么数据库将走全表扫描而不走索引
12. 用IN替代OR
IN列表中的数值进行排序,对于查询每次使用二分查找去匹配IN列表的数值
OR每次都要遍历
13. 避免在索引列上使用计算
SELECT * FROM <表名> WHERE hh*10 > 1000(低效,优化器不再使用索引)
Select * from T where hh > 1000/10(更高效,优化器将使用索引)
14. 应用层操作大连接
数据查询大连接消耗大量资源,降低并发,转而放到应用层来操作,减低数据库负担
15. 提高并发
主从复制、读写分离、分库分表切分