PL / SQL查询优化

时间:2015-10-28 13:00:11

标签: sql oracle plsql oracle11g

我有这个执行100,000次的查询。它目前运行得非常快。我只是想知道是否有更好的方法来运行它以获得更快的响应时间。

CODES TABLE = 160KB

INDEXES: INSTANCE(UNIQUE) SHORT)DESC 

CODE_VALUES=10MB

INDEXES: INSTANCE(UNIQUE), INTFC_INST, CODE_INST,SHORT_DESC

INTERFACES=160KB

INDEXES: INSTANCE (UNIQUE), SHORT_DESC
id="0" operation="SELECT STATEMENT" optimizer="ALL_ROWS" search_columns="0" cost="7">
  id="1" operation="NESTED LOOPS" search_columns="0" cost="7" cardinality="1" bytes="102" cpu_cost="54,820" io_cost="7" qblock_name="SEL$1" time="1">
      id="2" operation="MERGE JOIN" option="CARTESIAN" search_columns="0" cost="3" cardinality="1" bytes="33" cpu_cost="23,764" io_cost="3" time="1">
          object_ID="0" id="3" operation="TABLE ACCESS" option="BY INDEX ROWID" object_name="CODES" object_type="TABLE" search_columns="0" cost="2" cardinality="1" bytes="19" cpu_cost="15,443" io_cost="2" qblock_name="SEL$1" time="1">
              object_ID="1" id="4" operation="INDEX" option="RANGE SCAN" object_name="CODES_SHORT_DESC_FINDX" object_type="INDEX" search_columns="1" cost="1" cardinality="1" cpu_cost="8,171" io_cost="1" qblock_name="SEL$1" access_predicates=""A"."SYS_NC00010$"='MANAGER_GROUP'" time="1"/>
          id="5" operation="BUFFER" option="SORT" search_columns="0" cost="1" cardinality="1" bytes="14" cpu_cost="8,321" io_cost="1" time="1">
              object_ID="2" id="6" operation="TABLE ACCESS" option="BY INDEX ROWID" object_name="INTERFACES" object_type="TABLE" search_columns="0" cost="1" cardinality="1" bytes="14" cpu_cost="8,321" io_cost="1" qblock_name="SEL$1" time="1">
                  object_ID="3" id="7" operation="INDEX" option="RANGE SCAN" object_name="INTERFACES_SHORT_DESC_FINDX" object_type="INDEX" search_columns="1" cost="0" cardinality="1" cpu_cost="1,050" io_cost="0" qblock_name="SEL$1" access_predicates=""C"."SYS_NC00007>
      object_ID="4" id="8" operation="TABLE ACCESS" option="BY INDEX ROWID" object_name="CODE_VALUES" object_type="TABLE" search_columns="0" cost="4" cardinality="1" bytes="69" cpu_cost="31,056" io_cost="4" qblock_name="SEL$1" filter_predicates="("A"."INSTANCE"="B"."CODE_INST" AND "B"."INTFC_INST"="C"."INSTANCE")" time="1">
          object_ID="5" id="9" operation="INDEX" option="RANGE SCAN" object_name="CODE_VALUES_FUN_IDX" object_type="INDEX" search_columns="1" cost="1" cardinality="4" cpu_cost="8,771" io_cost="1" qblock_name="SEL$1" access_predicates=""B"."SYS_NC00010$"='150'" time="1"/>


SELECT A.INSTANCE, C.INSTANCE, B.LONG_DESC
  FROM CODES A,
   CODE_VALUES B,
   INTERFACES C
 WHERE A.INSTANCE = B.CODE_INST
   AND B.INTFC_INST = C.INSTANCE
   AND TRIM (A.SHORT_DESC) = TRIM (var1)
   AND TRIM (B.SHORT_DESC) = TRIM (var2)
   AND TRIM (C.SHORT_DESC) = TRIM (var3)

1 个答案:

答案 0 :(得分:2)

在WHERE和JOIN子句中避免使用TRIM函数 - > TRIM (A.SHORT_DESC) = TRIM (var1)

仅在JOIN,WHERE和GROUP子句列上创建索引并不意味着您的查询将始终快速返回所需的结果。 它是查询优化器,它为查询选择适当的索引以提供最佳性能,但查询优化器只能通过使用适当的索引来建议最佳查询计划。当您通过编写良好的查询语法来帮助它时。

在WHERE或JOIN子句中使用任何类型的函数(系统或用户定义)可以极大地降低查询性能,因为这种做法在查询优化器工作中创建了正确索引选择的障碍。 一个常见的例子是TRIM函数,它们通常由开发人员在WHERE子句中使用。

USE AdventureWorks
GO
SELECT pr.ProductID,pr.Name,pr.ProductNumber,wo.*  fROM Production.WorkOrder wo
INNER JOIN Production.Product pr
ON PR.ProductID = wo.ProductID
WHERE LTRIM(RTRIM(pr.name)) = 'HL Mountain Handlebars'
GO
SELECT pr.ProductID,pr.Name,pr.ProductNumber,wo.*  fROM Production.WorkOrder wo
INNER JOIN Production.Product pr
ON PR.ProductID = wo.ProductID
WHERE pr.name = 'HL Mountain Handlebars'

enter image description here

虽然两个查询的输出相同,但第一次查询占用了总执行时间的近99%。这个巨大的差异只是因为这些修剪函数,所以在生产数据库中我们必须避免JOIN和WHERE子句中的这些TRIM和其他函数。

取自AASIM ABDULLAH blog

所以您可以/应该做的是对数据进行更新以一劳永逸地修剪它,并在将其添加到表中时开始对其进行修剪,因此不需要修改新数据。 或者,如果由于某种原因无法实现,请查看Maurice Reeves在评论中建议的基于函数的索引。