如何描述关系数据库中的性能问题?

Mar*_*ber 8 oracle performance query-optimization relational-database

我有一个在关系数据库中运行的查询,它不能满足用户的期望.

我应该提供哪些信息以及应该避免哪些信息,以便我能够在本网站上获得有效的帮助?

Mar*_*ber 13

对于Oracle数据库,提供以下信息:

描述问题的症状

描述导致问题的行为.查询的行为是稳定的还是仅在有时使用特定参数或简单随机发生问题.你能在IDE(例如SQL Developer)中重现这种行为吗?

描述环境

定义Oracle的确切版本

 select * from v$version
Run Code Online (Sandbox Code Playgroud)

描述如何连接数据库:driver,ORM,编程语言.提供名称和/或版本号.

描述查询

发布查询文本.尽量简化 - 展示一个可重复性最小的例子.

示例 - 您有问题的查询连接10个表.检查在具有9或8个连接的查询中是否看到相同的症状.退一步直到看到问题并仅显示减少的查询.

是的,这是昂贵的,但它大大增加了你获得支持的机会!查询越小,它吸引支持者的程度就越高.

描述执行计划

要获取执行计划,请运行此语句(替换查询文本)

 EXPLAIN PLAN  SET STATEMENT_ID = '<some_id>' into   plan_table  FOR
     select * from ....   -- your query here 
 ;
Run Code Online (Sandbox Code Playgroud)

执行计划存储在PLAN_TABLE,以查看它运行此查询

 SELECT * FROM table(DBMS_XPLAN.DISPLAY('plan_table', '<some_id>','ALL')); 
Run Code Online (Sandbox Code Playgroud)

显示完整的结果(不仅是包含执行计划的表).极端重要的可能是谓词部分和下面的注释.

示例 select * from dual where dummy = :1;

Plan hash value: 272002086

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     2 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| DUAL |     1 |     2 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1 / DUAL@SEL$1

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("DUMMY"=:1)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - "DUMMY"[VARCHAR2,1]
Run Code Online (Sandbox Code Playgroud)

不要剪切和粘贴 IDE解释计划的图形结果.

这个执行计划是真正的执行计划吗?

不幸的是并不总是 有几个原因的解释执行计划可能从真正的不同.

如果您有疑问(特别是当您看到一个好的计划,但查询运行不好时),您可以从数据库缓存中提取计划SQL_ID.

 SELECT t.* FROM  table(DBMS_XPLAN.DISPLAY_CURSOR('<SQL_ID>',null,'ALL')) t; 
Run Code Online (Sandbox Code Playgroud)

可以使用文本匹配和/或数据库用户找到当前正在运行(或者正在运行并且仍在缓存)的查询的SQL_ID:

select sql_id, sql_fulltext from v$sql a where 
 lower(sql_text) like lower('%<some identifying part of the query text>%') 
  and parsing_schema_name = '<user running the query>';
Run Code Online (Sandbox Code Playgroud)

如果您拥有AWR许可证,您可以从那里获得执行计划,即使是在历史记录中运行的查询也是如此.

SELECT t.*
FROM  table(DBMS_XPLAN.DISPLAY_AWR('10u2rj016s96k'  )) t;
Run Code Online (Sandbox Code Playgroud)

可以使用找到SQL_ID

select sql_id, sql_text 
from dba_hist_sqltext a 
where lower(sql_text) like lower('%<some identifying part of the query text>%')
Run Code Online (Sandbox Code Playgroud)

描述数据

显示这些表上的表和索引的DDL.

提及最近是否收集优化程序统计信息并显示已使用的dbms_stats收集语句.

对于关键表,提供有关段大小,行号,分区,...的信息.

对于访问或联接中使用的列,提供有关不同值的数量的信息.值是均匀分布还是倾斜(例如,经常出现的少量值和大量稀有值).你定义直方图吗?

还要别的吗?

当然,这只是基础知识,可能仍然需要其他信息,例如系统统计信息或优化器参数.但是再次尝试提供(你的东西)可以识别问题的最小信息.根据要求发布其他信息.

祝好运!