方法步骤
查看SQL执行频率(Mysql|Oracle)
1 |
-- Mysql 查看当前session中所有统计参数的值 |
定位低效SQL语句(Mysql|Oracle)
- 查询慢查询日志
1 |
-- Mysql |
explain分析执行计划(Mysql|Oracle)
mysql使用
1 |
EXPLAIN SELECT * FROM jg_cust JOIN jg_zp ON jg_cust.id = jg_zp.cust; |
字段 | 含义 |
---|---|
id | 序列号, 执行select子句或者操作表顺序 |
select_type | 表示SELECT类型: SIMPLE(简单表, 不使用表连接或者子查询)、PARMARY(主查询、即外层的查询)、UNION(UNION中第二个或者后面的查询语句)、SUBQUERY(子查询中第一个SELECT) |
table | 输出的表 |
partitions | |
type | 类型 |
possible_keys | 可能用到的索引 |
key | 实际用到的索引 |
key_len | 索引长度 |
ref | 引用 |
rows | 扫描的行数 |
filtered | |
Extra | 执行情况的说明和描述 |
oracle使用
默认情况下,Oracle会将执行计划插入如到一张名为PLAN_TABLE的表中。可以使用脚本
utlexplain.sql
来创建自己的计划表。这个脚本位于Oracle软件安装目录的子目录$ORACLE_HMOE/rmdbs/admin/中。从Oracle 10g开始,Oracle会创建一个全局临时表PLAN_TABLE供所有用户使用,所以通常情况下不需要创建自己的计划表。由于此默认的计划表是一个全局临时表,所以你无法看到其他会话插入的执行计划,你的执行计划也会随着自己会话的结束而自动消失。
1 |
EXPLAIN PLAN FOR SELECT * FROM DUAL ; |
列名 | 类型 | 描述 |
---|---|---|
STATEMENT_ID | VARCHAR2(30) | 在EXPLAIN PLAN的SET STATEMENT_ID子句提供的SQL语句的唯一标志符。 |
PLAN_ID | NUMBER | 执行计划的在全局表plan_table中的唯一标识符 |
TIMESTAMP | DATE | EXPLAN PLAN语句执行的日期和时间 |
REMARKS | VARCHAR2(80) | 注释 |
OPERATION | VARCHAR2(30) | 执行的操作类型。如TABLE ACCESS,SORT或HASH JOIN |
OPTIONS | VARCHAR2(225) | 操作的附加信息,例如,以TABLE SCAN为例,选项可能是FULL或BY ROWID |
OBJECT_NODE | VARCHAR2(128) | 如果是分布式查询,这一列表示用于引用对象的数据库链接名称。如果并行查询,它的值可能对应一个临时的结果集。 |
OBJECT_OWNER | VARCHAR2(30) | 对象的名字 |
OBJECT_NAME | VARCHAR2(30) | 对象名称 |
OBJECT_ALIAS | VARCHAR2(65) | 对象的别名 |
OBJECT_INSTANCE | NUMERIC | 对象在SQL语句中的位置 |
OBJECT_TYPE | VARCHAR2(30) | 对象的类型(表,索引等) |
OPTIMIZER | VARCHAR2(255) | 解释SQL语句时生效的优化器 |
SEARCH_COLUMNS | NUMBERIC | 未使用 |
ID | NUMERIC | 执行计划的ID号 |
PARENT_ID | NUMERIC | 上一个步骤的ID号 |
DEPTH | NUMERIC | 操作的深度 |
POSITION | NUMERIC | 如果两个步骤有相同的父步骤,有更低POSITION值的步骤将被先执行 |
COST | NUMERIC | 优化器估算出来的此操作的相对成本 |
CARDINALITY | NUMERIC | 优化器预期这一步将饭后的记录数 |
BYTES | NUMERIC | 预计这一步将返回的字节数 |
OTHER_TAG | VARCHAR2(255) | 标识OTHER列中的值的类型。 |
PARTITION_START | VARCHAR2(255) | 访问的分区范围的起始分区 |
PARTITION_STOP | VARCHAR2(255) | 访问的分区范围的结束分区 |
PARTITION_ID | NUMERIC | 计算PARTITION_START和PARTITION_STOP列的值对的ID |
OTHER | LONG | 对于分布式查询,这列可能是包含发往远程数据库的SQL语句的文本。对于并行查询,它比啊是并行从属进程执行的SQL语句。 |
DISTRIBUTION | VARCHAR2(30) | 描述记录是如何从一组并行查询从属进程分配到后续的“消费者”从属进程的。 |
CPU_COST | NUMERIC | 估算出来的操作的CPU成本 |
IO_COST | NUMERIC | 估算出来的的操作的IO成本 |
TEMP_SPACE | NUMERIC | 估算出来的这一步操作所使用的临时存储的空间大小 |
ACCESS_PREDICATES | VARCHAR2(4000) | SQL语句中,确定如何在当前步骤中提取记录的子句。 |
FILTER_PREDICATES | VARCHAR2(4000) | SQL语句中确定对见记录进行过滤的子句路,如WHERE子句在非索引列上的条件。 |
PROJECTION | VARCHAR2(4000) | 决定将返回的记录的子句,通常是SELECT后面的字段列表 |
TIME | NUMBER(20,2) | 优化器为这一步执行估算的时间消耗 |
QBLOCK_NAME | VARCHAR2(30) | 查询块的唯一标识符。 |
#什么影响
全表扫描
-
表上的索引失效或无法被使用的情形(如对谓词使用函数、计算、NULL值、不等运算符、类型转换)
1
select * from t where t.id + 1 = 3
-
查询条件返回了整个表的大部分数据
当表上所返回的数据行数接近于表上的30%时,Oracle 倾向于使用全表扫描
1
select count(pad) from t where n<=990; -- 表数量为 991 条
-
使用了并行方式访问表(parallel 强行启用Oracle的多线程处理功能)
1
select /*+ parallel(3) */ count(pad) from t where n<=10;
-
使用full 提示
1
select /*+ full(t) */ count(pad) from t where n<=10;
-
统计信息缺失时使得Oracle认为全表扫描比索引扫描更高效
-
表上的数据块小于DB_FILE_MULTIBLOCK_READ_COUNT值的情形可能产生全表扫描