1.2. Verwenden Sie Tools von Drittanbietern, wie z. B. das Erklärungsfenster von PL/SQL Develop , aber ich habe es noch nicht herausgefunden, füge
Beispiel später hinzu: SQL> EXPLAIN PLAN FOR SELECT * FROM EMP;
Nach dem Login kopieren
wurde erklärt. SQL> SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE'));
Nach dem Login kopieren
Oder:
SQL> select * from table(dbms_xplan.display);
Nach dem Login kopieren
2. Leeren Sie den SGA-Cache Denn wenn SQL ausgeführt wird, werden der SQL-Ausführungsplan, die von der Festplatte gelesene Datenbank und andere Informationen für einen bestimmten Zeitraum in einigen Caches von SGA gespeichert. Um die Anweisungsnummer anzuzeigen. Die Auswirkung einer Ausführung erfordert das Löschen dieser Caches.
ALTER SYSTEM FLUSH SHARED_POOL;
ALTER SYSTEM FLUSH BUFFER_CACHE;
ALTER SYSTEM FLUSH GLOBAL CONTEXT;
Nach dem Login kopieren
3. Analysieren Sie den Ausführungsplan
3.1. Erstellen Sie zwei neue Tabellen, cust_info und cst_tran (nur zum Testen, keine praktische Bedeutung)
CREATE TABLE CUST_INFO
(CST_NO NUMBER,
CST_NAME VARCHAR2(50),
AGE SMALLINT);
CREATE TABLE CST_TRAN
(
CST_NO NUMBER,
TRAN_DATE VARCHAR2(8),
TRAN_AMT NUMBER(19,3)
);
Nach dem Login kopieren
Fügen Sie einige Daten ein, CUST_INFO-Tabelle 10.000, CST_TRAN-Tabelle 1 Million .
INSERT INTO CUST_INFO
SELECT 100000+LEVEL,
'test'||LEVEL,
ROUND(DBMS_RANDOM.VALUE(1,100))
FROM DUAL
CONNECT BY LEVEL<=10000;
INSERT INTO CST_TRAN
WITH AA AS
(SELECT LEVEL FROM DUAL CONNECT BY LEVEL<=100)
SELECT T.CST_NO,
TO_CHAR(SYSDATE - DBMS_RANDOM.VALUE(1,1000),'yyyymmdd'),
ROUND(DBMS_RANDOM.VALUE(1,999999999),3)
FROM CUST_INFO T
INNER JOIN AA
ON 1=1;
Nach dem Login kopieren
3.2. Sehen Sie sich den Ausführungsplan an, der diesen beiden Tabellen zugeordnet ist im Ausführungsplan:
ID: Eine Seriennummer, aber nicht die Reihenfolge der Ausführung. Die Reihenfolge der Ausführung wird anhand der Einrückung beurteilt. Vorgang: Der Inhalt des aktuellen Vorgangs. Zeilen: Kardinalität der aktuellen Operation, Oracle schätzt die Rückgabeergebnismenge der aktuellen Operation. Kosten (CPU): Ein von Oracle berechneter numerischer Wert (Kosten), um die Kosten der SQL-Ausführung zu veranschaulichen. Zeit: Oracle schätzt die Zeit des aktuellen Vorgangs. Anweisungen: 1. VorgangNotieren Sie die Vorgänge jedes Schritts und beurteilen Sie die Ausführungsreihenfolge entsprechend dem Grad der Einkerbung. In OLAP-Datenbanken gibt es viele HASH JOIN-Verbindungen, insbesondere wenn der zurückgegebene Datensatz groß ist, handelt es sich im Grunde genommen um HASH JOIN.
2. ZeilenDer Zeilenwert gibt die Anzahl der Datensätze an, die CBO voraussichtlich von einer Zeilenquelle zurückgeben wird. Diese Zeilenquelle kann eine Tabelle, ein Index oder eine Unterabfrage sein. Im Ausführungsplan in Oracle 9i wird Kardinalität als Karte abgekürzt. In 10g werden Kartenwerte durch Reihen ersetzt. Der - rows
- value ist für CBO
- von entscheidender Bedeutung, um den richtigen Ausführungsplan zu erstellen.
Wenn der von CBO erhaltene Zeilenwert nicht genau genug ist (normalerweise aufgrund mangelnder Analyse oder veralteter Analysedaten), kommt es zu Abweichungen in der Kostenberechnung des Ausführungsplans, die dazu führen, dass CBO einen Ausführungsplan falsch formuliert.
Wenn es in SQL eine auf mehrere Tabellen bezogene Abfrage oder eine Unterabfrage gibt, hat der Zeilenwert jeder zugehörigen Tabelle oder Unterabfrage einen großen Einfluss auf die Hauptabfrage. Man kann sogar sagen, dass CBO von den Zeilen jeder zugehörigen Tabelle abhängt oder Unterabfragewert, um den endgültigen Ausführungsplan zu berechnen. Bei Abfragen mit mehreren Tabellen verwendet CBO die Anzahl der Zeilen (Zeilen), die von jeder zugehörigen Tabelle zurückgegeben werden, um zu bestimmen, welche Zugriffsmethode für die Tabellenzuordnung verwendet werden soll (z. B. Nested-Loops-Join oder Hash-Join)
3, Kosten (CPU) und Zeit Es ist ein wichtiger Referenzwert für den Ausführungsplan. 3.2.2. Prädikatsbeschreibung: -----------------------------------------------------------
1 - Zugriff ("G"."CST_NO"="T"." CST_NO")
Hinweis
----- – für diese Anweisung verwendetes dynamisches Sampling (Stufe=2)
Zugriff: Gibt den Wert dieses Prädikats an Bedingung wirkt sich auf den Zugriffspfad der Daten (Tabelle oder Index) aus.
Filter: Zeigt an, dass der Wert der Prädikatbedingung keinen Einfluss auf den Zugriffspfad der Daten hat und nur eine Filterrolle spielt. (Nicht in diesem Beispiel) Hinweis: Achten Sie auf Zugriff
im Prädikat. Sie müssen die Bedingungen des Prädikats berücksichtigen und prüfen, ob der verwendete Zugriffspfad korrekt ist. 3.2.3、统计信息
Statistics
----------------------------------------------------------
561 recursive calls
0 db block gets
70483 consistent gets
4389 physical reads
0 redo size
45078003 bytes sent via SQL*Net to client
733845 bytes received via SQL*Net from client
66668 SQL*Net roundtrips to/from client
10 sorts (memory)
0 sorts (disk)
1000000 rows processed
Nach dem Login kopieren
参数说明:
- recursive calls :递归调用。一般原因:dictionary cache未命中;动态存储扩展;PL/SQL语句
- db block gets :bufer中读取的block数量,用于insert,update,delete,selectfor update
- consistent gets :这里是一致读次数(一个block可能会被读多次),bufer中读取的用于查询(除掉select forupdate)的block数量。
- physical reads :从磁盘上读取的block数量,敬请关注每周五晚免费网络公开课。
- redo size :bytes,写到redo logs的数据量
- bytes sent via SQL*Net to client :发送给客户端的字节数
- bytes received via SQL*Net from client :从客户端接收的字节数
- SQL*Net roundtrips to/from client :与客户端的交互次数(个人理解接收一条SQL语句,执行结果分多次发送给客户端,如有问题请指正)
- sorts (memory) :内存排序次数
- sorts (disk) :磁盘排序次数;与sort_area_size有关
- rows processed :执行完SQL后返回结果集的行数
四、部分信息解释
4.1、SQL*Net roundtrips to/from client的计算方式
这个指标的计算方式和一个参数息息相关,arraysize。
arraysize是什么呢?
请查阅大牛博文:Oracle arraysize 和 fetch size 参数 与 性能优化 说明
arraysize定义了一次返回到客户端的行数,取值范围【1-5000】,默认15。
使用命令在数据库中查看arraysize的值。
show arraysize
还可以修改这个值
set arraysize 5000;
明白了arraysize这个参数就可以计算SQL*Net roundtrips to/from client的值了。上例中,返回客户端结果集的行数是1000000,默认arraysize值是15,1000000/15向上取整等于66667。
为啥要向上取整?
举个栗子,如果有10个苹果,一个只能拿3个,几次可以拿完,3次可以拿9个,还剩1个,所以还需要再拿一次,共4次。
统计分析中的值是66668,为什么我们计算的值是66667?
就要看这个指标本身了,再粘贴一次:SQL*Net roundtrips to/from client 重点看from,意思是我们还要接受一次客户端发来的SQL语句,因此是:66667+1,本问题纯属个人臆断,无真凭实据,受限于本人的知识水平,如有误,请指出。
将arraysize的值修改为5000后,再观察SQL*Net roundtrips to/from client的变化,结果为201。
前面提到 arraysize的取值范围是【1-5000】,我们可以试一下改为不在这个区间的值,比如改为0,结果报错了
SQL> set arraysize 0;
SP2-0267: arraysize option 0 out of range (1 through 5000)
Nach dem Login kopieren
4.2、consistent gets
译为中文就是:一致性读, 好抽象的一个指标,啥叫一致性读,心中无数羊驼驼在大海中狂奔。
官网对consistent gets 的解释:
consistent gets:Number of times a consistent read wasrequested for a block.
通常我们执行SQL查询时涉及的每一block都是Consistent Read, 只是有些CR(Consistent Read)需要使用undo 来进行构造, 大部分CR(Consistent Read)并不涉及到undo block的读.
还有就是每次读这个block都是一次CR(可能每个block上有多个数据row), 也就是如果某个block被读了10次, 系统会记录10个Consistent Read.
如果想深入学习,请参考大佬博文:Oracle 有关 Consistent gets 的测试 -- cnDBA.cn_中国DBA社区
接来下测试下, consistent gets是从哪来的,需要使用有sysdba权限的用户,因为oradebug工具需要sysdba权限。
oradebug工具介绍:oracle实用工具:oradebug
使用10046对同一条数据跟踪两次,注意观察 consistent gets的不同
为了不影响测试结果,首先清空缓存
SQL> ALTER SYSTEM FLUSH SHARED_POOL;
System altered.
SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;
System altered.
SQL> ALTER SYSTEM FLUSH GLOBAL CONTEXT;
System altered.
Nach dem Login kopieren
第一次执行
SQL> set tim on timing on
00:42:30 SQL> set autot trace stat
00:42:36 SQL> oradebug setmypid
Statement processed.
00:42:42 SQL> alter session set tracefile_identifier='chf1';
Session altered.
Elapsed: 00:00:00.01
00:42:50 SQL> oradebug event 10046 trace name context forever,level 12;
Statement processed.
00:42:57 SQL> SELECT T.CST_NO, T.CST_NAME, G.TRAN_DATE, G.TRAN_AMT FROM CHF.CUST_INFO T INNER JOIN CHF.CST_TRAN G ON G.CST_NO = T.CST_NO;
1000000 rows selected.
Elapsed: 00:00:22.71
Statistics
----------------------------------------------------------
547 recursive calls
0 db block gets
70368 consistent gets
3898 physical reads
0 redo size
45078003 bytes sent via SQL*Net to client
733845 bytes received via SQL*Net from client
66668 SQL*Net roundtrips to/from client
10 sorts (memory)
0 sorts (disk)
1000000 rows processed
00:44:24 SQL> oradebug event 10046 trace name context off;
Statement processed.
00:45:54 SQL> oradebug tracefile_name
/u01/app/oracle/diag/rdbms/orcl/bpas/trace/bpas_ora_7715_chf1.trc
Nach dem Login kopieren
第二次执行
00:46:04 SQL> alter session set tracefile_identifier='chf2';
Session altered.
Elapsed: 00:00:00.00
00:46:35 SQL> oradebug event 10046 trace name context forever,level 12;
Statement processed.
00:46:43 SQL> SELECT T.CST_NO, T.CST_NAME, G.TRAN_DATE, G.TRAN_AMT FROM CHF.CUST_INFO T INNER JOIN CHF.CST_TRAN G ON G.CST_NO = T.CST_NO;
1000000 rows selected.
Elapsed: 00:00:21.62
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
70301 consistent gets
3850 physical reads
0 redo size
45078003 bytes sent via SQL*Net to client
733845 bytes received via SQL*Net from client
66668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1000000 rows processed
00:47:11 SQL> oradebug event 10046 trace name context off;
Statement processed.
00:49:03 SQL> oradebug tracefile_name
/u01/app/oracle/diag/rdbms/orcl/bpas/trace/bpas_ora_7715_chf2.trc
Nach dem Login kopieren
通过对比两次执行,发现consistent gets、physical reads、sorts (memory)都有变化,这是因为SGA中已经缓存了部分数据块。
再对比下我们刚才生产的两个跟踪日志,为方便查看,先将其格式转换以下
[oracle@localhost ~]$ tkprof /u01/app/oracle/diag/rdbms/orcl/bpas/trace/bpas_ora_7715_chf1.trc /u01/chf1.trc
TKPROF: Release 11.2.0.1.0 - Development on Wed Dec 8 00:53:37 2021
Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
[oracle@localhost ~]$ tkprof /u01/app/oracle/diag/rdbms/orcl/bpas/trace/bpas_ora_7715_chf2.trc /u01/chf2.trc
TKPROF: Release 11.2.0.1.0 - Development on Wed Dec 8 00:53:48 2021
Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
Nach dem Login kopieren
打开 /u01/chf1.trc,下面贴出部分重要信息
OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.03 0.03 8 67 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 66668 0.76 3.24 3890 70301 0 1000000
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 66670 0.79 3.28 3898 70368 0 1000000
Misses in library cache during parse: 1
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 66670 0.01 0.14
SQL*Net message from client 66670 64.54 79.11
db file sequential read 5 0.00 0.00
Disk file operations I/O 1 0.00 0.00
db file scattered read 5 0.00 0.00
asynch descriptor resize 4 0.00 0.00
direct path read 69 0.00 0.02
OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 12 0.00 0.00 0 0 0 0
Execute 24 0.01 0.01 0 0 0 0
Fetch 30 0.00 0.00 8 67 0 18
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 66 0.02 0.02 8 67 0 18
Nach dem Login kopieren
打开 /u01/chf2.trc,下面贴出部分重要信息
OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 66668 1.57 3.73 3850 70301 0 1000000
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 66670 1.57 3.73 3850 70301 0 1000000
Misses in library cache during parse: 0
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 66670 0.00 0.10
SQL*Net message from client 66670 6.83 19.93
asynch descriptor resize 4 0.00 0.00
direct path read 69 0.00 0.01
OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 0 0.00 0.00 0 0 0 0
Execute 0 0.00 0.00 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 0 0.00 0.00 0 0 0 0
Nach dem Login kopieren
比较发现,第一次执行解析SQL语句,生产执行计划时,consistent gets发生67次,执行SQL语句时发生70301。第一次执行解析SQL语句,生产执行计划时,因已经有缓存,所以consistent gets发生0次,执行SQL语句时发生70301。
推荐教程:《Oracle视频教程》