简体   繁体   中英

PL/SQL Query Optimization

I have this query that executes 100,000s of times. It currently runs pretty fast. I was just wondering if there was a better way to run it for even faster response times.

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)

Avoid TRIM functions in WHERE and JOIN clauses - > TRIM (A.SHORT_DESC) = TRIM (var1)

Just creating indexes on JOIN, WHERE and GROUP clause columns doesn't mean that your query will always return your required results quickly. It is query optimizer which selects proper index for a query to give you an optimum performance but query optimizer can only suggest optimum query plan by using proper indexes WHEN your are helping it by writing good query syntax.

Using any type of function (system or user defined) in WHERE or JOIN clause can dramatically decrease query performance because this practice create hurdles in query optimizer work of proper index selection. One common example is TRIM functions, which are commonly used by developers in WHERE clause.

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'

在此处输入图片说明

Though outputs of both queries are same but first query took almost 99% of total execution time. This huge difference is just because of these trim functions so on production databases we must avoid these TRIM and other functions in both JOIN and WHERE clauses.

Taken from AASIM ABDULLAH blog

So what you could/should do is run an update on your data to trim it once and for all, and start triming it while its being added to the table, so no new data will ever require trimming. Or if that for some reason is not possible, look for Function-Based indexes as suggested by Maurice Reeves in comments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM