您的位置:首页 > 数据库

第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;//统计用户每次都会购买的商品。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: