SlideShare una empresa de Scribd logo
1 de 30
MySQL 高级优化之—

理解查询执行

上海二三四五网络科技股份有限公司
互联网研发中心
王德玖
2013-10-11

www.2345.com
议程
•
•
•
•

Mysql 实例数据库安装
Explain介绍
举例
问答

2

www.2345.com
实例数据库安装
• 本ppt使用 sakila 数据库为事例;
• 下载地址:
http://downloads.mysql.com/docs/sakila-db.tar.gz
• 安装事例数据库:
• [root@locahost]# tar -xzvf sakila.sql.tar.gz
• mysql> source /opt/src/sakila/ sakila-schema.sql
• mysql> source /opt/src/sakila/ sakila-data.sql
• 内网ip:172.16.0.230 已经安装此测试库
3

www.2345.com
Explain 输出介绍
•
•
•
•
•
•
•
•
•
•

id :表的序列号标识
select_type: SELECT 的类型
table: table 或者 alias 的名称
type :连接的查询类型(本次重点)
possible_keys: 有哪些mysql可用的索引
keys : MySQL 执行时实际使用的索引
key_len: 使用到的索引长度
Ref:哪些字段被用来和 key配合从表中获取结果集
Rows:查询需要扫描的估计行数
extra: 其他的附加信息
4 www.2345.com
Explain 输出 type
• SELECT 查询的访问类型
• 各种方法:
•
system/const
好
•
eq_ref
•
ref
•
ref_or_null
•
index_merge
•
range
•
index
•
ALL
坏
5

www.2345.com
Explain实例
root@localhost: >EXPLAIN SELECT * FROM rental INNER JOIN inventory ON
> rental.inventory_id = inventory.inventory_id WHERE rental_date BETWEEN '2006-03-01' AND '2006-08-01'G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: rental
type: range
possible_keys: rental_date,idx_fk_inventory_id
key: rental_date
key_len: 8
查询Tpye
ref: NULL
rows: 1
range
Extra: Using where
eq_ref
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: inventory
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 3
ref: sakila.rental.inventory_id
rows: 1
Extra:
2 rows in set (0.00 sec)

6

类型:

www.2345.com
查询类型 – 避免 “ALL”
• Type这一列是explain 输出的最重要的信息
• 它告诉我们mysql选择怎么样访问策略来获
取特定的结果
– Type 为“ALL”意味着什么呢?
– 这一提示表示mysql获取结果需要进行一次全
表扫描
– 下页为一个全表扫描的实例 ...

www.2345.com
全表扫描type:ALL
root@localhost: sakila 01:21:19>EXPLAIN SELECT * FROM rental G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: rental
这里,我们看到了一个全表扫
type: ALL
描的的执行计划。在这个场景
possible_keys: NULL
中,没有给定where子句,查
key: NULL
key_len: NULL
询优化器没有使用索引来过滤
ref: NULL
行。因此,注意, SELECT *
rows: 16451
FROM rental 和下面我们将要
Extra:
1 row in set (0.00 sec)
给出的 ‘ SELECT rental_date

from rental ’ ,仅仅选择一列的
效率是不一样的 …
www.2345.com
查询类型 – ’INDEX’ 扫描
• ‘INDEX’ 扫描并不是很好的查询类型
– 它提示在表的索引上进行了一次全索引扫描
– 当然它比全表扫描来说性能要好,但是依然需
要消耗大量资源
– 下页为一个全索引扫描的实例 ...

www.2345.com
全索引扫描type:INDEX
root@localhost: sakila 01:21:23>EXPLAIN SELECT rental_date FROM rental G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: rental
type: index
这里,我们看到了一个全索引扫
possible_keys: NULL
描的执行计划。通过指定我们仅
key: rental_date
key_len: 13
想要的列,其实这就是告诉
ref: NULL
mysql查询优化器,如果查询的
rows: 16451
列( rental_date )上包含有索引,
Extra: Using index
1 row in set (0.00 sec)
那么就不需要表上的其他列,通

过索引自身就可以提供我们需要
的数据 …
www.2345.com
原来如此 ”SELECT * …”

www.2345.com
范围扫描类型:”RANGE”扫描
范围扫描 “range” 类型特点
指定 WHERE (or ON) 作为范围范围过滤
使用 BETWEEN 操作符
使用 IN() 操作符
带有 >, >=, <, <= 操作符
MySQL 有很多优化范围扫描的操作符,它们
一般访问比较快速
• 但是必须保证在操作的列上有索引
• 下页为一个范围扫描的实例 ...
•
•
•
•
•
•

www.2345.com
范围扫描type:RANGE
root@localhost: sakila 02:53:19>EXPLAIN SELECT * FROM rental
->WHERE rental_date BETWEEN '2006-01-01' AND '2006-07-01'G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
这里我们看到一个范围扫描的
table: rental
type: range
查询计划。 BETWEEN 操作符
possible_keys: rental_date
表示我们想要的数据在rental
key: rental_date
date 的某一范围之间。注意
key_len: 8
ref: NULL
possible_keys 列提示有一个索
rows: 2614
引在 rental_date上,可以 为
Extra: Using where
优化器提供范围扫描匹配,如
1 row in set (0.00 sec)

果没有这个索引,情况又将如
果何呢?
www.2345.com
怎么样?回到了 ’ALL’
root@localhost: sakila 02:53:19> DROP INDEX rental_date ON rental;
Query OK, 16044 rows affected (1.20 sec)
Records: 16044 Duplicates: 0 Warnings: 0
mysql> EXPLAIN SELECT * FROM rental
-> WHERE rental_date BETWEEN '2006-01-01' AND '2006-07-01' G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: rental
type: ALL
因为rental_date 列没
possible_keys: NULL
有了索引,查询优化
key: NULL
key_len: NULL
器不再使用范围扫描,
ref: NULL
而回到了全表扫描,
rows: 16462
可见恰当的索引是多
Extra: Using where
1 row in set (0.01 sec)
么重要
www.2345.com
合并索引类型 - ”index_merge”
• 合并索引扫描 “index_merge” 类型特点
– 这一特性在mysql5.0以上版本才有
– 它的优势是在一张表上可以同时使用多个索引
• 在mysql5.0之前一张表上的查询近能使用一个索引

– 在or 类型的操作中很有帮助
– 下页看一个index_merge实例 ...

www.2345.com
合并索引扫描 :index_merge
root@localhost: sakila 03:27:44>EXPLAIN SELECT * FROM rental
-> WHERE rental_id IN (10,11,12)
-> OR rental_date = '2006-02-01' G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: rental
type: index_merge
possible_keys: PRIMARY,rental_date
key: rental_date,PRIMARY
key_len: 8,4
ref: NULL
rows: 4
Extra: Using sort_union(rental_date,PRIMARY); Using where
1 row in set (0.02 sec)

这里使用了和并
索引扫描,优化
器使用到了连个
索引,在
mysql5.0之前之
能使用一个索引
www.2345.com
合并索引index_mereg 续…
• 它可以在用于
– sort_union
• 如前例子,或者是条件使用范围的非主键的列

– Union
• OR 条件使用常量或范围条件是主键列并且是innodb表

– Intersection
• AND 条件使用常量或范围条件是主键列且是innodb表

• 不能在全文索引上使用
• 可以使用下面的参数来关闭之
– optimizer_switch =
index_merge=on,index_merge_union=on,index_merge_sort_u
nion=on,index_merge_intersection=on
www.2345.com
Ref类型扫描
• 根据键值返回的结果集不大的情况
• 在索引列上有一个常量的时候(见下例)
• 通过连接表的索引来访问另一个连接表的
时候(见后例)
• 通过索引搜索或者多连接单独扫描时

www.2345.com
Ref类型扫描实例( on indexed 列 )
root@localhost: sakila 04:40:44>EXPLAIN SELECT * FROM rental
->WHERE rental_id IN (10,11,12)
-> AND rental_date = '2006-02-01'G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: rental
type: ref
这里有两个可选索引供优化
possible_keys: PRIMARY,rental_date
器过滤记录选用,但是优化
key: rental_date
key_len: 8
器选用rental_date,先从此
ref: const
索引中搜索出符合条件的记
rows: 1
录,根据索引再找出基于in()
Extra: Using where
1 row in set (0.00 sec)
表达式中相应记录过滤出结

果集
www.2345.com
Ref类型扫描实例( on join )
root@localhost: : sakila >EXPLAIN SELECT * FROM rental

-> INNER JOIN inventory ON inventory.inventory_id=rental.inventory_id G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: inventory
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 4645
Extra:
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: rental
type: ref
possible_keys: idx_fk_inventory_id
key: idx_fk_inventory_id
key_len: 3
ref: sakila.inventory.inventory_id
rows: 1
Extra:
2 rows in set (0.00 sec)

这是一个ref扫描的的实例,
它通过外表(inventory)连
接到(rental)表索引列来
查询。值得注意的是,虽然
我们把rental 表作为第一个
from 子句,但是执行计划依
然挑选inventory作为第一张
表进入,这是为什么呢?因
为行数少 …
www.2345.com
eq_ref类型扫描
• 从一表中读出一行记录以和前一个表中读
取出来的记录做联合
• Where条件用于做连接的列是一个primary
key 或 unique 类型
• 直接看实例 …

www.2345.com
eq_ref类型扫描实例
root@localhost: sakila 09:48:41> EXPLAIN SELECT f.film_id, f.title, c.name
> FROM film f INNER JOIN film_category fc
> ON f.film_id=fc.film_id INNER JOIN category c
> ON fc.category_id=c.category_id WHERE f.title LIKE 'T%' G
*************************** 1. row ***************************
select_type: SIMPLE
table: c
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 16
Extra:
*************************** 2. row ***************************
select_type: SIMPLE
table: fc
type: ref
possible_keys: PRIMARY,fk_film_category_category
key: fk_film_category_category
key_len: 1
ref: sakila.c.category_id
rows: 1
Extra: Using index
*************************** 3. row ***************************
select_type: SIMPLE
table: f
type: eq_ref
possible_keys: PRIMARY,idx_title
key: PRIMARY
key_len: 2
ref: sakila.fc.film_id
rows: 1
Extra: Using where

我们注意到,第三行显示使用
了eq_ref访问,即使在作为
where条件的„film.title „有一可
用索引,但是优化器选择使用
primary key,这是为什么呢?
其实我们可以看到在表
category中有16行,通过
film_category表的链接列能够
快速获取数据,16列比通过
tittle索引过滤得到的结果集46
行要少。
www.2345.com
一个重要的分割索引列
mysql> EXPLAIN SELECT * FROM film WHERE title LIKE 'Tr%'G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: film
得到一个不错的范围查询,tittle上的
type: range
索引得到使用
possible_keys: idx_title
key: idx_title
key_len: 767
ref: NULL
rows: 15
Extra: Using where
mysql> EXPLAIN SELECT * FROM film WHERE LEFT(title,2) = 'Tr' G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: film
情况就不乐观了,索引没有得以使用,
type: ALL
导致全表扫描为什么呢?
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 951
Extra: Using where

www.2345.com
index_subquery 和 unique_subquery
• 它们出现在SELECT 的子查询中
• 子查询出现唯一结果集的时候为
unique_subquery,否则是index_subquery
– unique_subquery的性能稍好,因为优化器可以
把子查询替换成常量集
– 因此,它变成了一个范围条件
• 通常,连接会有更好的性能
• 下面将展示它们的具体情况
www.2345.com
unique_subquery访问实例
root@localhost: sakila > EXPLAIN SELECT * FROM rental r WHERE r.customer_id IN (
-> SELECT customer_id FROM customer WHERE last_name LIKE 'S%') G
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: r
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 15646
Extra: Using where
*************************** 2. row ***************************
id: 2
select_type: DEPENDENT SUBQUERY
table: customer
type: unique_subquery
possible_keys: PRIMARY,idx_last_name
key: PRIMARY
key_len: 2
ref: func
rows: 1
Extra: Using index; Using where

外表(rental)通过一个全表扫描,
并通过customer_id 常量集,where过
滤后,把此结果集应用到子查询中的
select,逐个进行自查询。注意,这里
的查询类型提示为依赖子查询
(DEPENDENT SUBQUERY),从技
术上说,这是不正确的,因为这里的
子查询不是相关子查询,而应该返回
一个常量列表。因此,这个查询的
“customer.last_name”上的索引没有仸
何价值 …
www.2345.com
重写子查询为标准join
root@localhost: sakila> EXPLAIN SELECT * FROM rental r
-> INNER JOIN customer c ON r.customer_id=c.customer_id WHERE last_name LIKE 'S%' G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: c
type: range
possible_keys: PRIMARY,idx_last_name
key: idx_last_name
key_len: 137
ref: NULL
rows: 54
Extra: Using where
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: r
type: ref
possible_keys: idx_fk_customer_id
key: idx_fk_customer_id
key_len: 2
ref: sakila.c.customer_id
rows: 13
Extra:

优化器为标准连接给
了一个更好的执行计
划,并且有相同的查
询结果。这一方法值
得推荐-把相关子查询
重写为标准连接查询

www.2345.com
下讲引题
mysql> EXPLAIN SELECT r.staff_id, COUNT(*)
-> FROM rental r GROUP BY r.staff_id G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: r
type: index
possible_keys: NULL
key: idx_fk_staff_id
key_len: 1
ref: NULL
rows: 15646
Extra: Using index
mysql> EXPLAIN SELECT r.return_date, COUNT(*)
-> FROM rental r GROUP BY r.return_date G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: r
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 15646
Extra: Using temporary; Using filesort

我们注意到
Extra:的信息
完全不一样,这
是为什么呢? …

www.2345.com
总结
•
•
•
•

上面我们看了一系列explain输出的type
这是mysql执行计划里非常总要的信息
还有其他列的含义如何
尤其Extra: , key:

www.2345.com
结束

Q&A
29

www.2345.com
谢谢

30

www.2345.com

Más contenido relacionado

La actualidad más candente

Oracle10g高级安全特性列加密技术
Oracle10g高级安全特性列加密技术Oracle10g高级安全特性列加密技术
Oracle10g高级安全特性列加密技术maclean liu
 
Advanced heap exploitaion
Advanced heap exploitaionAdvanced heap exploitaion
Advanced heap exploitaionAngel Boy
 
Mongo db技术分享
Mongo db技术分享Mongo db技术分享
Mongo db技术分享晓锋 陈
 
Sql语句大全大全(经典珍藏版)
Sql语句大全大全(经典珍藏版)Sql语句大全大全(经典珍藏版)
Sql语句大全大全(经典珍藏版)totaleather2009
 
Oracle中比对2张表之间数据是否一致的几种方法
Oracle中比对2张表之间数据是否一致的几种方法Oracle中比对2张表之间数据是否一致的几种方法
Oracle中比对2张表之间数据是否一致的几种方法maclean liu
 
【Maclean liu技术分享】深入理解oracle中mutex的内部原理
【Maclean liu技术分享】深入理解oracle中mutex的内部原理【Maclean liu技术分享】深入理解oracle中mutex的内部原理
【Maclean liu技术分享】深入理解oracle中mutex的内部原理maclean liu
 
Row Set初步学习V1.1
Row Set初步学习V1.1Row Set初步学习V1.1
Row Set初步学习V1.1Zianed Hou
 
Mysql开发与优化
Mysql开发与优化Mysql开发与优化
Mysql开发与优化isnull
 
揭秘家用路由器Ch10 sharing
揭秘家用路由器Ch10 sharing揭秘家用路由器Ch10 sharing
揭秘家用路由器Ch10 sharingYi-Jun Zheng
 
那些年,我們一起看的例外
那些年,我們一起看的例外那些年,我們一起看的例外
那些年,我們一起看的例外kao kuo-tung
 
MySQL 6.0 下的cluster + replicate - 20080220
MySQL 6.0 下的cluster + replicate - 20080220MySQL 6.0 下的cluster + replicate - 20080220
MySQL 6.0 下的cluster + replicate - 20080220Jinrong Ye
 
基于Innodb开发的最佳实践
基于Innodb开发的最佳实践基于Innodb开发的最佳实践
基于Innodb开发的最佳实践wubx
 
SQL Loader & Bulk Insert 大量資料匯入工具
SQL Loader & Bulk Insert 大量資料匯入工具SQL Loader & Bulk Insert 大量資料匯入工具
SQL Loader & Bulk Insert 大量資料匯入工具HO-HSUN LIN
 
twMVC#27 | C# 7.0 新功能介紹
twMVC#27 | C# 7.0 新功能介紹twMVC#27 | C# 7.0 新功能介紹
twMVC#27 | C# 7.0 新功能介紹twMVC
 
Essential oracle security internal for dba
Essential oracle security internal for dbaEssential oracle security internal for dba
Essential oracle security internal for dbamaclean liu
 

La actualidad más candente (20)

Ch8 教學
Ch8 教學Ch8 教學
Ch8 教學
 
Oracle10g高级安全特性列加密技术
Oracle10g高级安全特性列加密技术Oracle10g高级安全特性列加密技术
Oracle10g高级安全特性列加密技术
 
Advanced heap exploitaion
Advanced heap exploitaionAdvanced heap exploitaion
Advanced heap exploitaion
 
Ch8
Ch8Ch8
Ch8
 
Mongo db技术分享
Mongo db技术分享Mongo db技术分享
Mongo db技术分享
 
Sql语句大全大全(经典珍藏版)
Sql语句大全大全(经典珍藏版)Sql语句大全大全(经典珍藏版)
Sql语句大全大全(经典珍藏版)
 
Oracle中比对2张表之间数据是否一致的几种方法
Oracle中比对2张表之间数据是否一致的几种方法Oracle中比对2张表之间数据是否一致的几种方法
Oracle中比对2张表之间数据是否一致的几种方法
 
【Maclean liu技术分享】深入理解oracle中mutex的内部原理
【Maclean liu技术分享】深入理解oracle中mutex的内部原理【Maclean liu技术分享】深入理解oracle中mutex的内部原理
【Maclean liu技术分享】深入理解oracle中mutex的内部原理
 
Ch10 教學
Ch10 教學Ch10 教學
Ch10 教學
 
Row Set初步学习V1.1
Row Set初步学习V1.1Row Set初步学习V1.1
Row Set初步学习V1.1
 
Mysql开发与优化
Mysql开发与优化Mysql开发与优化
Mysql开发与优化
 
揭秘家用路由器Ch10 sharing
揭秘家用路由器Ch10 sharing揭秘家用路由器Ch10 sharing
揭秘家用路由器Ch10 sharing
 
Ch12
Ch12Ch12
Ch12
 
那些年,我們一起看的例外
那些年,我們一起看的例外那些年,我們一起看的例外
那些年,我們一起看的例外
 
MySQL 6.0 下的cluster + replicate - 20080220
MySQL 6.0 下的cluster + replicate - 20080220MySQL 6.0 下的cluster + replicate - 20080220
MySQL 6.0 下的cluster + replicate - 20080220
 
基于Innodb开发的最佳实践
基于Innodb开发的最佳实践基于Innodb开发的最佳实践
基于Innodb开发的最佳实践
 
SQL Loader & Bulk Insert 大量資料匯入工具
SQL Loader & Bulk Insert 大量資料匯入工具SQL Loader & Bulk Insert 大量資料匯入工具
SQL Loader & Bulk Insert 大量資料匯入工具
 
twMVC#27 | C# 7.0 新功能介紹
twMVC#27 | C# 7.0 新功能介紹twMVC#27 | C# 7.0 新功能介紹
twMVC#27 | C# 7.0 新功能介紹
 
Zoo keeper
Zoo keeperZoo keeper
Zoo keeper
 
Essential oracle security internal for dba
Essential oracle security internal for dbaEssential oracle security internal for dba
Essential oracle security internal for dba
 

Similar a Mysql 高级优化之 理解查询执行

Sql调优clustering factor影响数据删除速度一例
Sql调优clustering factor影响数据删除速度一例Sql调优clustering factor影响数据删除速度一例
Sql调优clustering factor影响数据删除速度一例maclean liu
 
Oracle10g Rac Configuration For Linux X86
Oracle10g Rac Configuration For Linux X86Oracle10g Rac Configuration For Linux X86
Oracle10g Rac Configuration For Linux X86dbabc
 
oracle优化器星型转换
oracle优化器星型转换oracle优化器星型转换
oracle优化器星型转换maclean liu
 
Mysql handlersocket
Mysql handlersocketMysql handlersocket
Mysql handlersocketpwesh
 
Osc scott linux下的数据库优化for_postgresql
Osc scott linux下的数据库优化for_postgresqlOsc scott linux下的数据库优化for_postgresql
Osc scott linux下的数据库优化for_postgresqlOpenSourceCamp
 
Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期yiditushe
 
C++工程实践
C++工程实践C++工程实践
C++工程实践Shuo Chen
 
My sql explain & select
My sql explain & selectMy sql explain & select
My sql explain & selectMing-Ying Wu
 
A.oracle 数据字典与脚本初步
A.oracle 数据字典与脚本初步A.oracle 数据字典与脚本初步
A.oracle 数据字典与脚本初步WASecurity
 
Sql语句的优化
Sql语句的优化Sql语句的优化
Sql语句的优化abszhanghe
 
Mysql introduction-and-performance-optimization
Mysql introduction-and-performance-optimizationMysql introduction-and-performance-optimization
Mysql introduction-and-performance-optimizationisnull
 
Mysql fast share
Mysql fast shareMysql fast share
Mysql fast sharerfyiamcool
 
Avm2虚拟机浅析与as3性能优化
Avm2虚拟机浅析与as3性能优化Avm2虚拟机浅析与as3性能优化
Avm2虚拟机浅析与as3性能优化Harvey Zhang
 
110824 knoss-windows系统机制浅析
110824 knoss-windows系统机制浅析110824 knoss-windows系统机制浅析
110824 knoss-windows系统机制浅析Zoom Quiet
 
【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410
【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410
【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410maclean liu
 
MySQL InnoDB 源码实现分析(一)
MySQL InnoDB 源码实现分析(一)MySQL InnoDB 源码实现分析(一)
MySQL InnoDB 源码实现分析(一)frogd
 
Free Marker中文文档
Free Marker中文文档Free Marker中文文档
Free Marker中文文档yiditushe
 
美团点评技术沙龙010-美团Atlas实践
美团点评技术沙龙010-美团Atlas实践美团点评技术沙龙010-美团Atlas实践
美团点评技术沙龙010-美团Atlas实践美团点评技术团队
 

Similar a Mysql 高级优化之 理解查询执行 (20)

Sql调优clustering factor影响数据删除速度一例
Sql调优clustering factor影响数据删除速度一例Sql调优clustering factor影响数据删除速度一例
Sql调优clustering factor影响数据删除速度一例
 
Oracle10g Rac Configuration For Linux X86
Oracle10g Rac Configuration For Linux X86Oracle10g Rac Configuration For Linux X86
Oracle10g Rac Configuration For Linux X86
 
oracle优化器星型转换
oracle优化器星型转换oracle优化器星型转换
oracle优化器星型转换
 
Mysql handlersocket
Mysql handlersocketMysql handlersocket
Mysql handlersocket
 
Osc scott linux下的数据库优化for_postgresql
Osc scott linux下的数据库优化for_postgresqlOsc scott linux下的数据库优化for_postgresql
Osc scott linux下的数据库优化for_postgresql
 
MySQL進階介紹
MySQL進階介紹MySQL進階介紹
MySQL進階介紹
 
Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期
 
C++工程实践
C++工程实践C++工程实践
C++工程实践
 
My sql explain & select
My sql explain & selectMy sql explain & select
My sql explain & select
 
A.oracle 数据字典与脚本初步
A.oracle 数据字典与脚本初步A.oracle 数据字典与脚本初步
A.oracle 数据字典与脚本初步
 
Sql语句的优化
Sql语句的优化Sql语句的优化
Sql语句的优化
 
Mysql introduction-and-performance-optimization
Mysql introduction-and-performance-optimizationMysql introduction-and-performance-optimization
Mysql introduction-and-performance-optimization
 
Mysql fast share
Mysql fast shareMysql fast share
Mysql fast share
 
Avm2虚拟机浅析与as3性能优化
Avm2虚拟机浅析与as3性能优化Avm2虚拟机浅析与as3性能优化
Avm2虚拟机浅析与as3性能优化
 
110824 knoss-windows系统机制浅析
110824 knoss-windows系统机制浅析110824 knoss-windows系统机制浅析
110824 knoss-windows系统机制浅析
 
【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410
【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410
【Maclean liu技术分享】开oracle调优鹰眼,深入理解awr性能报告 第二讲 正式版 20130410
 
MySQL InnoDB 源码实现分析(一)
MySQL InnoDB 源码实现分析(一)MySQL InnoDB 源码实现分析(一)
MySQL InnoDB 源码实现分析(一)
 
Enterprise Data Lake in Action
Enterprise Data Lake in ActionEnterprise Data Lake in Action
Enterprise Data Lake in Action
 
Free Marker中文文档
Free Marker中文文档Free Marker中文文档
Free Marker中文文档
 
美团点评技术沙龙010-美团Atlas实践
美团点评技术沙龙010-美团Atlas实践美团点评技术沙龙010-美团Atlas实践
美团点评技术沙龙010-美团Atlas实践
 

Mysql 高级优化之 理解查询执行

  • 3. 实例数据库安装 • 本ppt使用 sakila 数据库为事例; • 下载地址: http://downloads.mysql.com/docs/sakila-db.tar.gz • 安装事例数据库: • [root@locahost]# tar -xzvf sakila.sql.tar.gz • mysql> source /opt/src/sakila/ sakila-schema.sql • mysql> source /opt/src/sakila/ sakila-data.sql • 内网ip:172.16.0.230 已经安装此测试库 3 www.2345.com
  • 4. Explain 输出介绍 • • • • • • • • • • id :表的序列号标识 select_type: SELECT 的类型 table: table 或者 alias 的名称 type :连接的查询类型(本次重点) possible_keys: 有哪些mysql可用的索引 keys : MySQL 执行时实际使用的索引 key_len: 使用到的索引长度 Ref:哪些字段被用来和 key配合从表中获取结果集 Rows:查询需要扫描的估计行数 extra: 其他的附加信息 4 www.2345.com
  • 5. Explain 输出 type • SELECT 查询的访问类型 • 各种方法: • system/const 好 • eq_ref • ref • ref_or_null • index_merge • range • index • ALL 坏 5 www.2345.com
  • 6. Explain实例 root@localhost: >EXPLAIN SELECT * FROM rental INNER JOIN inventory ON > rental.inventory_id = inventory.inventory_id WHERE rental_date BETWEEN '2006-03-01' AND '2006-08-01'G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: rental type: range possible_keys: rental_date,idx_fk_inventory_id key: rental_date key_len: 8 查询Tpye ref: NULL rows: 1 range Extra: Using where eq_ref *************************** 2. row *************************** id: 1 select_type: SIMPLE table: inventory type: eq_ref possible_keys: PRIMARY key: PRIMARY key_len: 3 ref: sakila.rental.inventory_id rows: 1 Extra: 2 rows in set (0.00 sec) 6 类型: www.2345.com
  • 7. 查询类型 – 避免 “ALL” • Type这一列是explain 输出的最重要的信息 • 它告诉我们mysql选择怎么样访问策略来获 取特定的结果 – Type 为“ALL”意味着什么呢? – 这一提示表示mysql获取结果需要进行一次全 表扫描 – 下页为一个全表扫描的实例 ... www.2345.com
  • 8. 全表扫描type:ALL root@localhost: sakila 01:21:19>EXPLAIN SELECT * FROM rental G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: rental 这里,我们看到了一个全表扫 type: ALL 描的的执行计划。在这个场景 possible_keys: NULL 中,没有给定where子句,查 key: NULL key_len: NULL 询优化器没有使用索引来过滤 ref: NULL 行。因此,注意, SELECT * rows: 16451 FROM rental 和下面我们将要 Extra: 1 row in set (0.00 sec) 给出的 ‘ SELECT rental_date from rental ’ ,仅仅选择一列的 效率是不一样的 … www.2345.com
  • 9. 查询类型 – ’INDEX’ 扫描 • ‘INDEX’ 扫描并不是很好的查询类型 – 它提示在表的索引上进行了一次全索引扫描 – 当然它比全表扫描来说性能要好,但是依然需 要消耗大量资源 – 下页为一个全索引扫描的实例 ... www.2345.com
  • 10. 全索引扫描type:INDEX root@localhost: sakila 01:21:23>EXPLAIN SELECT rental_date FROM rental G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: rental type: index 这里,我们看到了一个全索引扫 possible_keys: NULL 描的执行计划。通过指定我们仅 key: rental_date key_len: 13 想要的列,其实这就是告诉 ref: NULL mysql查询优化器,如果查询的 rows: 16451 列( rental_date )上包含有索引, Extra: Using index 1 row in set (0.00 sec) 那么就不需要表上的其他列,通 过索引自身就可以提供我们需要 的数据 … www.2345.com
  • 11. 原来如此 ”SELECT * …” www.2345.com
  • 12. 范围扫描类型:”RANGE”扫描 范围扫描 “range” 类型特点 指定 WHERE (or ON) 作为范围范围过滤 使用 BETWEEN 操作符 使用 IN() 操作符 带有 >, >=, <, <= 操作符 MySQL 有很多优化范围扫描的操作符,它们 一般访问比较快速 • 但是必须保证在操作的列上有索引 • 下页为一个范围扫描的实例 ... • • • • • • www.2345.com
  • 13. 范围扫描type:RANGE root@localhost: sakila 02:53:19>EXPLAIN SELECT * FROM rental ->WHERE rental_date BETWEEN '2006-01-01' AND '2006-07-01'G *************************** 1. row *************************** id: 1 select_type: SIMPLE 这里我们看到一个范围扫描的 table: rental type: range 查询计划。 BETWEEN 操作符 possible_keys: rental_date 表示我们想要的数据在rental key: rental_date date 的某一范围之间。注意 key_len: 8 ref: NULL possible_keys 列提示有一个索 rows: 2614 引在 rental_date上,可以 为 Extra: Using where 优化器提供范围扫描匹配,如 1 row in set (0.00 sec) 果没有这个索引,情况又将如 果何呢? www.2345.com
  • 14. 怎么样?回到了 ’ALL’ root@localhost: sakila 02:53:19> DROP INDEX rental_date ON rental; Query OK, 16044 rows affected (1.20 sec) Records: 16044 Duplicates: 0 Warnings: 0 mysql> EXPLAIN SELECT * FROM rental -> WHERE rental_date BETWEEN '2006-01-01' AND '2006-07-01' G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: rental type: ALL 因为rental_date 列没 possible_keys: NULL 有了索引,查询优化 key: NULL key_len: NULL 器不再使用范围扫描, ref: NULL 而回到了全表扫描, rows: 16462 可见恰当的索引是多 Extra: Using where 1 row in set (0.01 sec) 么重要 www.2345.com
  • 15. 合并索引类型 - ”index_merge” • 合并索引扫描 “index_merge” 类型特点 – 这一特性在mysql5.0以上版本才有 – 它的优势是在一张表上可以同时使用多个索引 • 在mysql5.0之前一张表上的查询近能使用一个索引 – 在or 类型的操作中很有帮助 – 下页看一个index_merge实例 ... www.2345.com
  • 16. 合并索引扫描 :index_merge root@localhost: sakila 03:27:44>EXPLAIN SELECT * FROM rental -> WHERE rental_id IN (10,11,12) -> OR rental_date = '2006-02-01' G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: rental type: index_merge possible_keys: PRIMARY,rental_date key: rental_date,PRIMARY key_len: 8,4 ref: NULL rows: 4 Extra: Using sort_union(rental_date,PRIMARY); Using where 1 row in set (0.02 sec) 这里使用了和并 索引扫描,优化 器使用到了连个 索引,在 mysql5.0之前之 能使用一个索引 www.2345.com
  • 17. 合并索引index_mereg 续… • 它可以在用于 – sort_union • 如前例子,或者是条件使用范围的非主键的列 – Union • OR 条件使用常量或范围条件是主键列并且是innodb表 – Intersection • AND 条件使用常量或范围条件是主键列且是innodb表 • 不能在全文索引上使用 • 可以使用下面的参数来关闭之 – optimizer_switch = index_merge=on,index_merge_union=on,index_merge_sort_u nion=on,index_merge_intersection=on www.2345.com
  • 18. Ref类型扫描 • 根据键值返回的结果集不大的情况 • 在索引列上有一个常量的时候(见下例) • 通过连接表的索引来访问另一个连接表的 时候(见后例) • 通过索引搜索或者多连接单独扫描时 www.2345.com
  • 19. Ref类型扫描实例( on indexed 列 ) root@localhost: sakila 04:40:44>EXPLAIN SELECT * FROM rental ->WHERE rental_id IN (10,11,12) -> AND rental_date = '2006-02-01'G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: rental type: ref 这里有两个可选索引供优化 possible_keys: PRIMARY,rental_date 器过滤记录选用,但是优化 key: rental_date key_len: 8 器选用rental_date,先从此 ref: const 索引中搜索出符合条件的记 rows: 1 录,根据索引再找出基于in() Extra: Using where 1 row in set (0.00 sec) 表达式中相应记录过滤出结 果集 www.2345.com
  • 20. Ref类型扫描实例( on join ) root@localhost: : sakila >EXPLAIN SELECT * FROM rental -> INNER JOIN inventory ON inventory.inventory_id=rental.inventory_id G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: inventory type: ALL possible_keys: PRIMARY key: NULL key_len: NULL ref: NULL rows: 4645 Extra: *************************** 2. row *************************** id: 1 select_type: SIMPLE table: rental type: ref possible_keys: idx_fk_inventory_id key: idx_fk_inventory_id key_len: 3 ref: sakila.inventory.inventory_id rows: 1 Extra: 2 rows in set (0.00 sec) 这是一个ref扫描的的实例, 它通过外表(inventory)连 接到(rental)表索引列来 查询。值得注意的是,虽然 我们把rental 表作为第一个 from 子句,但是执行计划依 然挑选inventory作为第一张 表进入,这是为什么呢?因 为行数少 … www.2345.com
  • 22. eq_ref类型扫描实例 root@localhost: sakila 09:48:41> EXPLAIN SELECT f.film_id, f.title, c.name > FROM film f INNER JOIN film_category fc > ON f.film_id=fc.film_id INNER JOIN category c > ON fc.category_id=c.category_id WHERE f.title LIKE 'T%' G *************************** 1. row *************************** select_type: SIMPLE table: c type: ALL possible_keys: PRIMARY key: NULL key_len: NULL ref: NULL rows: 16 Extra: *************************** 2. row *************************** select_type: SIMPLE table: fc type: ref possible_keys: PRIMARY,fk_film_category_category key: fk_film_category_category key_len: 1 ref: sakila.c.category_id rows: 1 Extra: Using index *************************** 3. row *************************** select_type: SIMPLE table: f type: eq_ref possible_keys: PRIMARY,idx_title key: PRIMARY key_len: 2 ref: sakila.fc.film_id rows: 1 Extra: Using where 我们注意到,第三行显示使用 了eq_ref访问,即使在作为 where条件的„film.title „有一可 用索引,但是优化器选择使用 primary key,这是为什么呢? 其实我们可以看到在表 category中有16行,通过 film_category表的链接列能够 快速获取数据,16列比通过 tittle索引过滤得到的结果集46 行要少。 www.2345.com
  • 23. 一个重要的分割索引列 mysql> EXPLAIN SELECT * FROM film WHERE title LIKE 'Tr%'G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: film 得到一个不错的范围查询,tittle上的 type: range 索引得到使用 possible_keys: idx_title key: idx_title key_len: 767 ref: NULL rows: 15 Extra: Using where mysql> EXPLAIN SELECT * FROM film WHERE LEFT(title,2) = 'Tr' G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: film 情况就不乐观了,索引没有得以使用, type: ALL 导致全表扫描为什么呢? possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 951 Extra: Using where www.2345.com
  • 24. index_subquery 和 unique_subquery • 它们出现在SELECT 的子查询中 • 子查询出现唯一结果集的时候为 unique_subquery,否则是index_subquery – unique_subquery的性能稍好,因为优化器可以 把子查询替换成常量集 – 因此,它变成了一个范围条件 • 通常,连接会有更好的性能 • 下面将展示它们的具体情况 www.2345.com
  • 25. unique_subquery访问实例 root@localhost: sakila > EXPLAIN SELECT * FROM rental r WHERE r.customer_id IN ( -> SELECT customer_id FROM customer WHERE last_name LIKE 'S%') G *************************** 1. row *************************** id: 1 select_type: PRIMARY table: r type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 15646 Extra: Using where *************************** 2. row *************************** id: 2 select_type: DEPENDENT SUBQUERY table: customer type: unique_subquery possible_keys: PRIMARY,idx_last_name key: PRIMARY key_len: 2 ref: func rows: 1 Extra: Using index; Using where 外表(rental)通过一个全表扫描, 并通过customer_id 常量集,where过 滤后,把此结果集应用到子查询中的 select,逐个进行自查询。注意,这里 的查询类型提示为依赖子查询 (DEPENDENT SUBQUERY),从技 术上说,这是不正确的,因为这里的 子查询不是相关子查询,而应该返回 一个常量列表。因此,这个查询的 “customer.last_name”上的索引没有仸 何价值 … www.2345.com
  • 26. 重写子查询为标准join root@localhost: sakila> EXPLAIN SELECT * FROM rental r -> INNER JOIN customer c ON r.customer_id=c.customer_id WHERE last_name LIKE 'S%' G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: c type: range possible_keys: PRIMARY,idx_last_name key: idx_last_name key_len: 137 ref: NULL rows: 54 Extra: Using where *************************** 2. row *************************** id: 1 select_type: SIMPLE table: r type: ref possible_keys: idx_fk_customer_id key: idx_fk_customer_id key_len: 2 ref: sakila.c.customer_id rows: 13 Extra: 优化器为标准连接给 了一个更好的执行计 划,并且有相同的查 询结果。这一方法值 得推荐-把相关子查询 重写为标准连接查询 www.2345.com
  • 27. 下讲引题 mysql> EXPLAIN SELECT r.staff_id, COUNT(*) -> FROM rental r GROUP BY r.staff_id G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: r type: index possible_keys: NULL key: idx_fk_staff_id key_len: 1 ref: NULL rows: 15646 Extra: Using index mysql> EXPLAIN SELECT r.return_date, COUNT(*) -> FROM rental r GROUP BY r.return_date G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: r type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 15646 Extra: Using temporary; Using filesort 我们注意到 Extra:的信息 完全不一样,这 是为什么呢? … www.2345.com