簡體   English   中英

提高Oracle和Postgres中的查詢性能

[英]Improve Query performance in Oracle & Postgres

我需要像下面的查詢一樣進行多個聯接。大約有200個CAT_CODE。

主表(PRIM):

NUM     CAT1_CODE   CAT2_CODE   CAT3_CODE
A          1           y           q     
B          2           e           a     
C          3           s           z  

輔助表(LOV):

CATEGORY    COLUMN_LKP        EXT_CODE
CAT1_CODE       1                AB
CAT1_CODE       2                CD
CAT1_CODE       3                HI
CAT2_CODE       y                JL
CAT2_CODE       e                QD
CAT2_CODE       s                AH
CAT3_CODE       q                CD
CAT3_CODE       a                MS
CAT3_CODE       z                EJ

所需的輸出:

NUM CAT1    CAT2    CAT3
A    AB      JL      CD
B    CD      QD      MS
C    HI      AH      EJ

SQL:

我已經編寫了一個簡單的查詢來完成此任務。 您認為這是正確的方法嗎? 還有其他方法可以改善此查詢嗎? 現在,我同時使用Oracle和Postgres。

SELECT 
NUM,
(SELECT EXT_CODE FROM TEST_LOV 
WHERE CATEGRY='CAT1_CODE' AND COLUMN_LKP=A.CAT1_CODE) CAT1,
(SELECT EXT_CODE FROM TEST_LOV 
WHERE CATEGRY='CAT2_CODE' AND COLUMN_LKP=A.CAT2_CODE) CAT2,
(SELECT EXT_CODE FROM TEST_LOV 
WHERE CATEGRY='CAT3_CODE' AND COLUMN_LKP=A.CAT3_CODE) CAT3 
FROM 
TEST_PRIM A

TEST_LOV被掃描了多次。

查詢計划:

-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |     3 |    24 |    17   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TEST_LOV  |     1 |    15 |     3   (0)| 00:00:01 |
|*  2 |  TABLE ACCESS FULL| TEST_LOV  |     1 |    15 |     3   (0)| 00:00:01 |
|*  3 |  TABLE ACCESS FULL| TEST_LOV  |     1 |    15 |     3   (0)| 00:00:01 |
|   4 |  TABLE ACCESS FULL| TEST_PRIM |     3 |    24 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------

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

   1 - filter("CATEGRY"='CAT1_CODE' AND "COLUMN_LKP"=:B1)
   2 - filter("CATEGRY"='CAT2_CODE' AND "COLUMN_LKP"=:B1)
   3 - filter("CATEGRY"='CAT3_CODE' AND "COLUMN_LKP"=:B1)

在oracle中,可以unpivot透視表,然后使用結果聯接到lov表。

with primunpiv as 
(select * from test_prim
 unpivot
 (code for category in (CAT1_CODE,CAT2_CODE,CAT3_CODE))
)
select p.num
,max(case when p.category = 'CAT1_CODE' then l.ext_code end) cat1
,max(case when p.category = 'CAT2_CODE' then l.ext_code end) cat2
,max(case when p.category = 'CAT3_CODE' then l.ext_code end) cat3
from primunpiv p
join testlov l on p.code = l.column_lkp and p.category = l.category
group by p.num

絕對不要將sql查詢嵌入到語句的select組件中。

您可以重寫它,使其與所有表正確對應。

選擇num,...從test_prim a,test_lov b,test_lov c,test_lov d其中a.cat1_code = b.column_lkup和b.catgry ='CAT1_CODE'並...

這種方法的唯一問題是在test_prim中的類別之一為null的情況下,在這種情況下,您對test_lov的聯接必須是外部聯接。

如果test_lov.column_lkup列上有索引,則這也具有使用索引的好處。

大聲笑-這變成了磨合。 您在select子句中進行的選擇基本上會引起全表掃描,然后在PGA中進行解析,這很慢。 另一種方法是每次成功都會停止,因此速度更快。

我的甲骨文不是很好,但是過去我在SQL Server中做過類似的事情。 我認為這應該可行,並且可以改善您的效果。 如果每個不同的CAT代碼始終有對應的記錄,則可以將其更改為INNER JOIN。

SELECT 
NUM,
B.EXT_CODE CAT1, 
C.EXT_CODE CAT2, 
D.EXT_CODE CAT3
FROM TEST_PRIM A
LEFT JOIN TEST_LOV B ON B.CATEGRY='CAT1_CODE' AND B.COLUMN_LKP = A.CAT1_CODE
LEFT JOIN TEST_LOV C ON C.CATEGRY='CAT2_CODE' AND C.COLUMN_LKP = A.CAT2_CODE
LEFT JOIN TEST_LOV D ON D.CATEGRY='CAT3_CODE' AND C.COLUMN_LKP = A.CAT3_CODE

SQLFiddle:Postgres

WITH
cat1 AS ( SELECT EXT_CODE, COLUMN_LKP FROM LOV WHERE CATEGORY='CAT1_CODE' ),
cat2 AS ( SELECT EXT_CODE, COLUMN_LKP FROM LOV WHERE CATEGORY='CAT2_CODE' ),
cat3 AS ( SELECT EXT_CODE, COLUMN_LKP FROM LOV WHERE CATEGORY='CAT3_CODE' )

SELECT num, cat1.ext_code CAT1, cat2.ext_code CAT2, cat3.ext_code CAT3
FROM prim
LEFT JOIN cat1 ON prim.cat1_code::varchar(1) = cat1.column_lkp
LEFT JOIN cat2 ON prim.cat2_code = cat2.column_lkp
LEFT JOIN cat3 ON prim.cat3_code = cat3.column_lkp
;

有您的問題的問題

  1. 您的查詢使用TEST_LOVTEST_PRIM ,但您的問題分別將它們分別標記為LOVPRIM
  2. 您的查詢使用CATEGRY ,但是您的問題使用字段CATEGORY定義了表

在CATEGORY上具有索引,COLUMN_LKP將避免全表掃描,並在您擁有巨大數據集的情況下更快地獲取結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM