mysql> show variables like 'query_cache%'; mysql> set global query_cache_type=1; mysql> set global query_cache_size=1024*1024*32
注意:mysql
select goods_id,cat_id,goods_name from good where cat_id in(select cat_id form category where parent_id=6); 这条语句执行会很是慢,由于它会扫描goods全表,逐行与category表对照 缘由:mysql的查询优化器,针对in型作了优化,优化成了exists的执行效果。 改进:用链接查询代替子查询 select goods_id,g.cat_id,g.goods_name from goods as g inner join (select cat_id from category where parent_id=6) as t;
内层 from 语句查到的临时表,没有索引,因此from返回的内容要尽可能少算法
没有查询条件时count(*)很是快,不须要查表。但当有查询条件时,速度将减慢。
可使用缩小范围的方法优化查询。
eg.sql
须要统计good_id>100的总数时通常会写为: select count(*) form goods where good_id>100; 优化为: slect (select count(*) from goods)-(select count(*) from goods where id<100); 这样,就把范围由无限大缩小到了100
默认状况下,MySQL 对全部 group by col1, col2, …… 的字段进行排序。这与查询中指定 order by col1,col2,…… 相似。所以,若是显示包括一个包含相同列的 order by 子句,则对 MySQL 的实际执行性能没有什么影响。 数据库
若是查询包括 group by 但用户想要避免排序结果的消耗,则能够指定 order by null 禁止排序。缓存
select col1 from table group by col2 order by null;
union all 不过滤 效率提升,如非必须,请用union all
由于 union去重的代价很是高, 放在程序里去重.服务器
limit offset,n 当offset很是大时,效率极低。mysql并非跳过offset行,而后单取n行,而是取offset+n行,返回放弃前offset行,返回n行。
优化:性能
在一些sql请求中,mysql会建立临时表,可能建立到内存中,也可能由内存中转存到磁盘。
会建立临时表的查询:优化
若是是空的 myisam 表,默认就是先导入数据才建立索引的,不存在优化问题。
对于非空的 myisam 表,在一次性插入大量数据时,能够经过设置 disable keys 和 enable keys 来提升导入的效率。线程
# 假设给 test 表一次性插入大量数据 alert table test disable keys; loading the data …… alert table test enable keys;
disable keys 的方式适用于 myisam 引擎,但不适用于 innodb 引擎。指针
使用多个值表的 insert 语句,能够减小客户端与数据库之间的链接、关闭等资源消耗
insert into test values (1,1),(2,2),(3,3)……
delayed 的含义是让 insert 语句立刻执行,其实数据都被放在内存的队列中,并无真正的写入磁盘,这比每条土局分别插入要快的多;
low_priority 恰好相反,在全部其余用户对表的读写完成后才进行插入(好比记录日志的场景)
尽可能减小额外的排序,经过索引直接返回有序数据。
where 条件和 order_by 使用相同的索引,而且 order_by 的顺序和索引的顺序相同,而且 order by 的字段都是升序或者降序。不然确定须要额外的排序操做,这样就会出现 filesort 。
在某些不得不使用 filesort 的场景中,须要想办法加快 filesort 的操做。对于 filesort ,MySQL 有两种排序算法。
首先根据条件取出排序字段和行指针信息,以后在排序区 sort_buffer 中排序。若是排序区 sort buffer 不够,则在临时表 temporary table 汇总存储排序结果,完成排序后根据行指针回表读取记录。这种算法须要两次访问数据,第一次获取排序字段和行指针信息,第二次根据行指针获取记录,尤为是第二次读取操做可能致使大量随机 I/O 操做;优势是排序的时候内存开销较少
。
一次性取出知足条件的行的全部字段,而后在排序区 sort buffer 中排序后直接输出结果集,排序的时候内存开销较大,可是排序效率比两次扫描算法要高。
mysql 经过比较系统变量 max_length_for_sort_data 的大小和 query 语句取出的字段总大小来判断使用哪一种排序算法。若是 max_length_for_sort_data 更大,那么使用第二种优化以后的算法,不然使用第一种算法。
适当加大系统变量 max_length_for_sort_data 的值,可以让 MySQL 选择更优化的 filesort 的排序算法,固然,设置过大,会形成cpu利用率太低和磁盘 I/O 太高
适当加大 sort_buffer_size 排序区,尽可能让排序在内存中完成,而不是经过建立临时表放在文件中进行;固然也不能不限制加大 sort_buffer_size 排序区,由于 sort_buffer_size 参数时每一个线程独占的,因此要考虑数据库活动链接数和服务器内存的大小来适当设置排序区。
尽可能只使用必要的字段,select 具体的字段名称,而不是 select * 选择全部字段,这样能够减小排序区使用,提升 sql 性能。
sql 提示(sql hint) 是优化数据库的一个重要手段,简单来讲就是在 sql 语句中加入一些人为的提示来达到优化操做的目的。
select sql_buffer_results * from ……
这个语句将强制 MySQL 生成一个临时结果集。只要临时结果集生成后,全部表上的锁定均被释放。 这能再遇到表锁定问题时或要花很长时间将结果传给客户端时有所帮助,由于能够尽快释放锁资源。
经常使用的 sql 提示: