mysql知识盘点【壹】_SQL优化


简单一点,上来就说说数据库优化。本文都是基于mysql数据库的优化建议。分为四个方面:索引优化、sql优化、建表优化和参数优化。


索引优化


首先介绍下索引。索引是数据库中一个排序的数据结构,用于快速查询和更新数据。根据结构形式可分为B树索引(B-tree)、散列索引(hash)、空间索引(R-tree)和全文索引(full-text)。


mysql有两大数据库引擎,分别为MYISAM和innodb,其中innodb支持事务。下面说说innodb的索引结构:索引键值的逻辑顺序和索引锁服务的表相应的物理顺序相同(即聚集索引,Cluster index),也就是说,数据和索引(B+树)在一起,记录被真实保存在索引叶子中。如下图所示:


1

需要注意的是,mysql索引仅支持最左前缀原则(比如 LIKE 'xx%'),同时不支持函数索引和使用IN范围查找。


索引使用还有如下原则


1.索引字段不要超过5个,单表索引尽量不超过5个;

2.ORDER BY、GROUP BY和DISTINCT字段放在复合索引的后面,即复合索引前面字段用于等值查询,后面字段用于判断;

3.UPDATE语句根据WHERE条件增加索引;

4.把范围条件放在符合索引的最后,因为BETWEEN、<、<=、>、>=会导致后面条件用不了索引;

5.数据区分度不大的字段不宜使用索引;



sql优化


ORDER BY、GROUP BY优化


1.尽量对较少的行排序;

2.如果连接多张表。ORDER BY的列应该属于连接顺序第一张表;

3.ORDER BY、GROUP BY的列尽量都在第一张表中;

4.保证索引列和ORDER BY列相同,且顺序一致;

5.增加read_rnd_buffer_size(MySQL的随机读缓冲区大小)


分页语句优化


mysql的分页语句为:


select * from table where col = xxx limit M , N;


越往后翻页速度越慢,因为mysql会读取M+N条数据,M越大性能越差。可考虑改为如下方式:


select t1.* from table t1 ,

(select col from table where col  = xxx limit M , N) t2

where t1.col = t2.col ;


或当条件是主键id时:


select * from table where id>=2345 limit 11;

select * from table where id>=(select id from table limit 10000,1) limit 10;

select * from table inner join (select id from table limit 10000,10) using (id);


子查询优化


当有如下sql:


select first_name from employee where emp_no IN (

  select emp_no from salary where salary = 5000);


这样会遍历employee表每条记录带入子查询中,可改为:


select first_name from emplyee emp ,

  (select emp_no from salary where salary = 5000) sal

where emp.emp_no = sal.emp_no;


其他一些sql建议


尽量不用select  *

1.减少表变化时的影响;

2.可以使用到covering index;

3.select/join减少硬盘临时表生成


OR条件改为IN

OR时间复杂度:O(n);IN时间复杂度:O(Log n)。[n最好小于200条]


避免负向查询NOT、!和<>

1.不能使用索引

2.很可能全表扫描


数值比对

1.数字对数字,字符对字符;

2.数值和字符比较先转换为双精度进行比对;

3.字符和数字比较:字符转数值,不会使用索引;


建表优化


建表前首先对数据量预估,一年内的单表数据量纯int不超1000W,含char不超500W。如果会超过,建议考虑分表,可基于userid、date或area合理实现。


建议单库不超过300-400个表,表的字段少而精,好处IO高效,遍历快,修复快,提高并发,alter快。单表字段数控制在20-50个,不超50个纯INT,20个CHAR(10)。


避免使用null字段:1.很难查询优化;2.null加索引,需要额外空间;3.含null复合索引无效。尽量不用TEXT/BLOB数据类型:强制生成硬盘临时表;浪费空间,可想办法拆分字段到单独的表。


尽量不用外键:1.额外开销;2.逐行操作;3.高并发容易死锁。

数字型的索引比字符串型快:更高效,查询更快,空间更小。


参数优化


innodb_buffer_pool_size

innodb引擎缓冲池大小,主要缓存了索引和数据。如果sql查询的数据在缓存中已缓存,则不需要从磁盘中读取,建议设置为主机内存的70-80%。


Innodb缓冲池
缓存了行数据、索引、插入缓冲和锁等。innodb还使用缓冲池帮助延迟写入,这样就可以合并多个写入操作一起顺序写回。


innodb_log_file_size

日志组里日志文件大小。建议256M或更大,默认5M。


innodb_flush_log_at_trx_commit

默认1。设为2时,每个事务提交时日志缓冲被写到文件上,但不对日志文件做刷盘操作。刷盘每秒发生一次。建议设2。


sysc_binlog

默认0。不实时将二进制日志中的语句刷盘。设置大于1时实时。建议设0。


tmp_table_size

决定内部内存临时表最大值,每个线程都会分配,如果内存临时表超过限制,mysql就会把它转为基于磁盘的MYISAM表。GROUP BY和DISTINCT等不能走索引的sql会总临时表,适当加大tmp_table_size和max_heap_table_size的值。


table_open_cache

指定表高速缓存大小。每当mysql访问一张表,如果表缓冲区还有空间,该表就被打开放入其中,这样可以加快访问表内容。


query_cache_size

控制mysql query cache的大小。如果mysql开启query cache,在执行每个query时会先锁住query cache,然后判断是否存在query cache,如果存在则返回;不存在则进行引擎查询。同时insert、update和delete会将query cache失效掉,所以适合写少读多的情况。





猜你喜欢

转载自blog.csdn.net/xinzun/article/details/79619457
今日推荐