本文已参与「新人创作礼」活动,一起开启掘金创作之路。
说一说你对数据库优化的理解
优化文件系统,提高磁盘IO的读写速度;优化操作系统调度策略,提高MYSQL的负载能力;优化表结构、索引、查询语句等使查询响应更快。
针对查询,可以通过避免索引失效、使用连接代替子查询、分解大连接查询的方式来提高查询速度。
针对慢查询,可以通过分析慢查询日志、使用Explain命令,从而有针对性的进行优化。
针对插入,可以通过禁用索引、禁用检查等方式来提高插入速度,在插入之后再启用索引和检查。
针对数据库结构,可以通过将字段很多的表拆分成多张表、增加中间表、增加冗余字段等方式进行优化。
MySQL查询优化
(1)建立并使用索引,并且避免索引失效(联合索引、Like、OR、where、null)
(2)避免SELECT * 语句(会查找不必要的字段,增加IO数据大小;查具体数据可能不需要回表查询)
(3)优化子查询
子查询可以进行SELIECT语句的嵌套查询,虽然灵活但执行效率低。需要为内层查询语句的查的结果建立一个临时表。然后外层查询语句从临时表中查询,所以大数据量的情况下速度慢。
使用 (JOIN)连接查询来替代子查询 。连接查询不需要建立临时表,速度更快。
(4)将大连接查询分解成对每个表进行单表查询,然后在应用程序中进行关联,好处是:减少锁竞争
减少冗余的查询:分解成多个单表查询,这些单表查询的缓存结果更可能被其它查询使用到;
让缓存更高效:对于连接查询,如果其中一个表发生变化,那么整个查询缓存就无法使用,而分解后的多个查询,即使其中一个表发生变化,对其它表的查询缓存依然可以使用;
(5)分页查询优化:连接查询优化、限定id优化
-- 在所有的查询结果中,返回前5行记录。
SELECT prod_name FROM products LIMIT 5;
--在所有的查询结果中,从第5行开始,返回5行记录。
SELECT prod_name FROM products LIMIT 5,5;
--总之,带一个值的LIMIT总是从第一行开始,给出的数为返回的行数。
--带两个值的LIMIT可以指定从行号为第一个值的位置开始。
连接查询优化
使用连接查询进行优化,先使用二级索引查出id,再使用内连接将id关联回其他列(利用了聚簇索引)进行limit查询,达到“延迟关联”的效果。
select id, name from a order by title limit 50, 5;
如果a表非常大,那么这个查询最好改写成下面形式:
select a.id , a.name from a inner join (select a.id from a order by title limit 50,5) as limit using(a.id);
这让MySQL扫描尽可能少的页面,利用二级索引(覆盖索引) 获取记录的id,再根据关联列返回原表查询需要的所有列,因为利用了聚簇索引扫描。
限定id优化
假设数据表的id是递增的,则根据查询的页数和查询的记录数可以算出查询的id范围,可以使用 id between and 来查询:
select id, name from a order by title limit 50, 5 where position between 50 and 54 order by position
注意select * 导致性能变差的情况
select *会查找不必要的字段,增加IO传输的数据量,降低速度。
当二级索引可以作为覆盖索引使用时(包含查询所需的所有字段时),使用sleect *会使性能变差。在回表查询过程中,如果使用select明确的字段的话,从二级索引就能获得所有的数据,则不必再到聚集索引中查询。
比如查询的数据所有字段就只有主键ID和name字段,通过name查询数据时select*会先查二级索引,拿到主键再去聚集索引查所有数据。