第18章 SQL优化
2015-10-27 08:58
330 查看
查看统计参数:默认session
show [session|global] status [like 'com_%']
global:自数据库上次启动至今
com_select 一次查询增加一次
com_insert 批量inset算一次
com_update;统计的是执行次数,提交或回滚都会计算
com_delete
com_commit
com_roooback
基本信息:
connections:试图链接的次数
uptime:服务器工作时间
slow_queries:慢查询的次数
InnoDb 特有
Innode_ros_read: select 返回行数
Innode_ros_inserted:insert行数
Innode_ros_updated:更新行数。
Innode_ros_deleted:
EXPLAIN
id: 1
select_type: SIMPLE,primary,union,subquery(子查询中第一个select)
table: temp
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 2
Extra: NULL
type:all,index,range,ref,eq_ref(多表连接时用主键或唯一索引作为关联条件),const,system,null(无表,无索引)
EXPLAIN EXTENDED select * from temp\G
show warning\G(对于复杂查询,可以得到精简语句)
explain partitions 查看分区相关的查询。
5.0.37后支持。
select @@have_profiling;//查看是否支持
select @@profiling;//查看是否开启
set @@profiling = 1;//开启
1,select count(*) from temp;
2,show profiles;
3,show profile for query 2;
4,show profile cpu for query 2;//只查询cup的耗时。all,cpu,block io,context switch,page faults的更明细类型。
以下语句未明确执行:
select state,sum(duration) as total_r,
round(100*sum(duration)/
(select (sum(duration)
from information_schema.profiling
where query_id = 2
),2) as pct_r,
count(*) as calls,
sum(duration) / count(*) as "r/Call"
from information_schema.profiling
where query_id = 2
group by state
order by tatal_r desc;
trace:(5.6)
打开并设置格式:当前session有效:
set optimizer_trace="enabled=on",end_markers_in_json=on;
设置最大能够使用的内存:(默认较小)
set optimizer_trace_max_mem_size=1000000;
select * from information_schema.optimizer_trace\G
索引:
b-tree:
hash:只有memory支持
full-text:5.6之后innodb开始支持。之前只有MyISAM支持。
前缀索引:create index idx_title on temp(name(10));
b-tree 不是二叉树(binary) 是平衡树(balanced)
创建索引:
alter table temp drop index index_name;
alter table temp add index index_name(id,name,age);
使用索引的典型场景:
1,match the full value:索引的所有值进行等值匹配
2,match a range of valu
4000
e;
3,match a leftmost prefix:针对复合索引的左起索引。B-Tred使用的首要原则
4,index only query:覆盖索引扫描
5,match a column prefix:列前缀
6,match one part exactly and match a range on another part:范围索引查数据+覆盖索引取数据。extra:using where;using index;
7,column is null;-->type:ref;
8,5.6以后,index condition pushdown(ICP)索引下放:where dat1 < xxx1 and dat1 > xxx2 and age < 30;extra:using index condition
存在索引但不能使用:
1,%开头的like语句。
一:fullText 全文索引
二:Innodb 聚簇索引(需要在like字段创建索引):explain select * from (select actor_id from actor where last_name like '%NI%')a,
actor b where a.actor_id = b.actor_id \G
2,数据类型隐式转换的时候:字符串,一定加引号
如:name = 1 (不使用索引) ;name = '1':(使用索引)
3,复合索引,不符合leftmost规则。index_name(name,age):name ok;age ok; name age ok; age name no;
4,mysql估计使用索引比全表扫描更慢,则不使用索引,如like 'S%',选择率比较低。通过trace可以查看cost代价。
5,用or分割的条件:or前有索引,or后无索引,则不会使用索引。因为有一个无索引,所以肯定走全表扫面,另一个走索引也意义了。
查看索引使用情况:
show status like 'handler_read%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Handler_read_first | 2 |
| Handler_read_key | 4 |如索引正在工作,该值高。一个行被索引值读到的次数。低表明增加索引得到的性能改善不高,因为索引并不经常用。
| Handler_read_last | 0 |
| Handler_read_next | 0 |值高说明表索引不正确或写入的查询没有利用索引。
| Handler_read_prev | 0 |
| Handler_read_rnd | 0 |
| Handler_read_rnd_next | 8 |高代表查询运行低效,应建索引补救。数据文件中,读下一行的请求数。
+-----------------------+-------+
两个简单实用的优化方法:
1,定期分析和检查表:
analyze table payment;用户分析和存储表的关键字分布,使得系统得到准确的统计信息,达到sql生成正确的执行计划的目的。
如用户感觉实际执行计划不是预期执行计划,执行一次表分析可能会解决问题。
check table temp;对innodb和myisam用用。myisam中,关键字统计数据会被更新。
check table还可以检查视图是否有错误,如依赖的表不存在,则报错。
2,定期优化表
optimize table temp;
如表已删除大部分,或变长字段varchar,blob,text进行了很多修改,则应使用,消除空间浪费。对innodeb,myisam,dbd起作用。
对于innodb,可以设置innodb_file_per_table参数,设置独立表空间模式,减轻innodb表的空间回收问题。
在删除大量数据后,可以通过alter table temp engine=innodb来回收空间,实际存储引擎没有改变。
以上命令执行期间进行行锁定,一定注意在数据库不繁忙的时候执行。
常用sql优化:
1,大批量插入数据
对于myisam的非空表:
alter table tbl_name disable keys;
load data infile '/home/mysql/film_test.txt' into tble film_test2;
alter table tbl_name enable keys;//打开非唯一索引更新
如果是空表,默认是先导入,后建非唯一索引,无影响
对于innodb:
1,按照主键顺序存储,所以导入数据按主键顺序,可有效提高导入数据的效率。(提高效果有限)
2,临时关闭唯一索引:
set unique_checks=0/1;(提高效果有限)
3,set autocommit=0/1;
临时关闭自动提交。(提高效果有限)
insert语句:
1,insert into table1 values(1,2),(2,3);
2,load tata infile 装载表比insert快20倍。
order by
mysql排序两种方式:
1,通过有序索引,顺序扫描,直接返回有序数据。
explain:extra: using index;
2,通过对返回的数据进行排序。不代表通过磁盘文件排序,只是说进行了一个排序操作,是否使用磁盘文件或临时表,取决于参数和数据大小。
sort_buffer_size 内存排序区中进行排序。独占的,同一时刻可有多个。
以下会使用索引:
select * from tabname order by key_part,key_part2 关键字顺序正确。
select * from tabname where key_part1=1 order by key_part1 desc,key_part2 desc; where 关键字与排序关键字相同
select * from tabname order by key_part1 desc,key_part2 desc;排序方向一样,都是desc
以下不会使用索引:
order by key_part1 desc,key_part2 asc;熟悉怒混乱
where key1=constant order by key2 ;where 与 order不同
order by eky1,key2 不同的关键字排序
filesort的优化:
对于filesort 的两种排序算法:
两次扫描算法:1,查询排序字段,主键id,排序,2;根据id查询数据
一次扫描算法:查询所有字段,内存中排序。适当加大排序内存。因为内存一致,所以select id,name,age 优于 select * 。
group by
默认对group by col1,col2 的字段进行排序,同ordey col1,col2 .因此,显示包括order by 对性能无影响。
order by null 禁止排序,减少filesort,提高性能。
优化嵌套查询:
select * from customer where customer_id not in (select customer_id from payment) \G 需要临时表,逻辑上需要两步。
select * from customer a left join payment b on a.customer_id = b.customer_id and b.customer_id is null 一步查询完成。如果payment 表的customer_id 有索引,效率更高。
OR条件的优化:
where name = 'lisi' or age = 23 ;//name和age都有单独的索引的时候才能使用索引。是两个select的查询进行union操作。
name和age的复合索引不能使用(排序操作可以)。
分页优化:
第一种(推荐):select name,age from temp order by name limit 50,5\G不用索引
select a.name,a.age from temp a inner join (select id from temp order by name linit 50,5) b on a.id = b.id //用索引排序
第二种(只适用于排序字段不重复的字段,如主键,否则数据不准确):和前天商榷,出入上一页最后一条数据的id。
select * from temp where id < 3343 order by id desc limit 5\G // 讲limit n,m 转化成limit n 查询
使用sql提示
explain select count(*) from rental use index(idx+rental_date)\G 参考索引,不考虑其他可用索引。但如果全表扫描效率高,则会使用全表扫描。
ingnre index(xxx) :忽略一个或多个索引
force index (xxx) :强制使用某个索引
常用sql技巧:
1,regular expression
regexp
2,rand()取随机行
order by rand();
3,group by 的with rollup 进行统计。与order by互斥,在limit之前。
4,big_or(xxx) and big_and(xxx) 做统计。
select big_or(kind) group by user_id;//统计用户买过商品的种类。
select big_and(king) group by user_id;//统计用户每次都会购买的商品。
show [session|global] status [like 'com_%']
global:自数据库上次启动至今
com_select 一次查询增加一次
com_insert 批量inset算一次
com_update;统计的是执行次数,提交或回滚都会计算
com_delete
com_commit
com_roooback
基本信息:
connections:试图链接的次数
uptime:服务器工作时间
slow_queries:慢查询的次数
InnoDb 特有
Innode_ros_read: select 返回行数
Innode_ros_inserted:insert行数
Innode_ros_updated:更新行数。
Innode_ros_deleted:
EXPLAIN
id: 1
select_type: SIMPLE,primary,union,subquery(子查询中第一个select)
table: temp
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 2
Extra: NULL
type:all,index,range,ref,eq_ref(多表连接时用主键或唯一索引作为关联条件),const,system,null(无表,无索引)
EXPLAIN EXTENDED select * from temp\G
show warning\G(对于复杂查询,可以得到精简语句)
explain partitions 查看分区相关的查询。
5.0.37后支持。
select @@have_profiling;//查看是否支持
select @@profiling;//查看是否开启
set @@profiling = 1;//开启
1,select count(*) from temp;
2,show profiles;
3,show profile for query 2;
4,show profile cpu for query 2;//只查询cup的耗时。all,cpu,block io,context switch,page faults的更明细类型。
以下语句未明确执行:
select state,sum(duration) as total_r,
round(100*sum(duration)/
(select (sum(duration)
from information_schema.profiling
where query_id = 2
),2) as pct_r,
count(*) as calls,
sum(duration) / count(*) as "r/Call"
from information_schema.profiling
where query_id = 2
group by state
order by tatal_r desc;
trace:(5.6)
打开并设置格式:当前session有效:
set optimizer_trace="enabled=on",end_markers_in_json=on;
设置最大能够使用的内存:(默认较小)
set optimizer_trace_max_mem_size=1000000;
select * from information_schema.optimizer_trace\G
索引:
b-tree:
hash:只有memory支持
full-text:5.6之后innodb开始支持。之前只有MyISAM支持。
前缀索引:create index idx_title on temp(name(10));
b-tree 不是二叉树(binary) 是平衡树(balanced)
创建索引:
alter table temp drop index index_name;
alter table temp add index index_name(id,name,age);
使用索引的典型场景:
1,match the full value:索引的所有值进行等值匹配
2,match a range of valu
4000
e;
3,match a leftmost prefix:针对复合索引的左起索引。B-Tred使用的首要原则
4,index only query:覆盖索引扫描
5,match a column prefix:列前缀
6,match one part exactly and match a range on another part:范围索引查数据+覆盖索引取数据。extra:using where;using index;
7,column is null;-->type:ref;
8,5.6以后,index condition pushdown(ICP)索引下放:where dat1 < xxx1 and dat1 > xxx2 and age < 30;extra:using index condition
存在索引但不能使用:
1,%开头的like语句。
一:fullText 全文索引
二:Innodb 聚簇索引(需要在like字段创建索引):explain select * from (select actor_id from actor where last_name like '%NI%')a,
actor b where a.actor_id = b.actor_id \G
2,数据类型隐式转换的时候:字符串,一定加引号
如:name = 1 (不使用索引) ;name = '1':(使用索引)
3,复合索引,不符合leftmost规则。index_name(name,age):name ok;age ok; name age ok; age name no;
4,mysql估计使用索引比全表扫描更慢,则不使用索引,如like 'S%',选择率比较低。通过trace可以查看cost代价。
5,用or分割的条件:or前有索引,or后无索引,则不会使用索引。因为有一个无索引,所以肯定走全表扫面,另一个走索引也意义了。
查看索引使用情况:
show status like 'handler_read%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Handler_read_first | 2 |
| Handler_read_key | 4 |如索引正在工作,该值高。一个行被索引值读到的次数。低表明增加索引得到的性能改善不高,因为索引并不经常用。
| Handler_read_last | 0 |
| Handler_read_next | 0 |值高说明表索引不正确或写入的查询没有利用索引。
| Handler_read_prev | 0 |
| Handler_read_rnd | 0 |
| Handler_read_rnd_next | 8 |高代表查询运行低效,应建索引补救。数据文件中,读下一行的请求数。
+-----------------------+-------+
两个简单实用的优化方法:
1,定期分析和检查表:
analyze table payment;用户分析和存储表的关键字分布,使得系统得到准确的统计信息,达到sql生成正确的执行计划的目的。
如用户感觉实际执行计划不是预期执行计划,执行一次表分析可能会解决问题。
check table temp;对innodb和myisam用用。myisam中,关键字统计数据会被更新。
check table还可以检查视图是否有错误,如依赖的表不存在,则报错。
2,定期优化表
optimize table temp;
如表已删除大部分,或变长字段varchar,blob,text进行了很多修改,则应使用,消除空间浪费。对innodeb,myisam,dbd起作用。
对于innodb,可以设置innodb_file_per_table参数,设置独立表空间模式,减轻innodb表的空间回收问题。
在删除大量数据后,可以通过alter table temp engine=innodb来回收空间,实际存储引擎没有改变。
以上命令执行期间进行行锁定,一定注意在数据库不繁忙的时候执行。
常用sql优化:
1,大批量插入数据
对于myisam的非空表:
alter table tbl_name disable keys;
load data infile '/home/mysql/film_test.txt' into tble film_test2;
alter table tbl_name enable keys;//打开非唯一索引更新
如果是空表,默认是先导入,后建非唯一索引,无影响
对于innodb:
1,按照主键顺序存储,所以导入数据按主键顺序,可有效提高导入数据的效率。(提高效果有限)
2,临时关闭唯一索引:
set unique_checks=0/1;(提高效果有限)
3,set autocommit=0/1;
临时关闭自动提交。(提高效果有限)
insert语句:
1,insert into table1 values(1,2),(2,3);
2,load tata infile 装载表比insert快20倍。
order by
mysql排序两种方式:
1,通过有序索引,顺序扫描,直接返回有序数据。
explain:extra: using index;
2,通过对返回的数据进行排序。不代表通过磁盘文件排序,只是说进行了一个排序操作,是否使用磁盘文件或临时表,取决于参数和数据大小。
sort_buffer_size 内存排序区中进行排序。独占的,同一时刻可有多个。
以下会使用索引:
select * from tabname order by key_part,key_part2 关键字顺序正确。
select * from tabname where key_part1=1 order by key_part1 desc,key_part2 desc; where 关键字与排序关键字相同
select * from tabname order by key_part1 desc,key_part2 desc;排序方向一样,都是desc
以下不会使用索引:
order by key_part1 desc,key_part2 asc;熟悉怒混乱
where key1=constant order by key2 ;where 与 order不同
order by eky1,key2 不同的关键字排序
filesort的优化:
对于filesort 的两种排序算法:
两次扫描算法:1,查询排序字段,主键id,排序,2;根据id查询数据
一次扫描算法:查询所有字段,内存中排序。适当加大排序内存。因为内存一致,所以select id,name,age 优于 select * 。
group by
默认对group by col1,col2 的字段进行排序,同ordey col1,col2 .因此,显示包括order by 对性能无影响。
order by null 禁止排序,减少filesort,提高性能。
优化嵌套查询:
select * from customer where customer_id not in (select customer_id from payment) \G 需要临时表,逻辑上需要两步。
select * from customer a left join payment b on a.customer_id = b.customer_id and b.customer_id is null 一步查询完成。如果payment 表的customer_id 有索引,效率更高。
OR条件的优化:
where name = 'lisi' or age = 23 ;//name和age都有单独的索引的时候才能使用索引。是两个select的查询进行union操作。
name和age的复合索引不能使用(排序操作可以)。
分页优化:
第一种(推荐):select name,age from temp order by name limit 50,5\G不用索引
select a.name,a.age from temp a inner join (select id from temp order by name linit 50,5) b on a.id = b.id //用索引排序
第二种(只适用于排序字段不重复的字段,如主键,否则数据不准确):和前天商榷,出入上一页最后一条数据的id。
select * from temp where id < 3343 order by id desc limit 5\G // 讲limit n,m 转化成limit n 查询
使用sql提示
explain select count(*) from rental use index(idx+rental_date)\G 参考索引,不考虑其他可用索引。但如果全表扫描效率高,则会使用全表扫描。
ingnre index(xxx) :忽略一个或多个索引
force index (xxx) :强制使用某个索引
常用sql技巧:
1,regular expression
regexp
2,rand()取随机行
order by rand();
3,group by 的with rollup 进行统计。与order by互斥,在limit之前。
4,big_or(xxx) and big_and(xxx) 做统计。
select big_or(kind) group by user_id;//统计用户买过商品的种类。
select big_and(king) group by user_id;//统计用户每次都会购买的商品。
相关文章推荐
- 今天开始学习oracle
- SQLiteDatabase
- 第17章 Mysql分区表,已有表变更分区表
- 第16章 SQL Mode及相关问题
- PLSQL Developer报“动态执行表不可访问,本会话的自动统计被禁止”的解决方案
- 第15章 SQL中的安全问题
- oracle11g客户端如何完全卸载(转)
- Oracle 学习笔记 17 -- 异常处理(PL/SQL)
- sqlite3常用命令&语法
- oracle修改表空间
- MariaDB 二进制安装步骤
- Html5本地存储和本地数据库
- 关于CoreData和SQLite多线程访问时的线程安全问题
- 建分区表索引优化SQL
- 将mysql数据库中的数据转入sql server中
- 复制分发数据库
- MongoDB正则表达式及应用
- SQL SERVER 2014 安装图解教程(含SQL SERVER 2014下载)
- mac系统OS X10.10版本安装最新5.7.9mysql的方法
- Oracle归档日志写满(ora-00257)了怎么办