[英]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
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
;
TEST_LOV
和TEST_PRIM
,但您的问题分别将它们分别标记为LOV
和PRIM
。 CATEGRY
,但是您的问题使用字段CATEGORY
定义了表 在CATEGORY上具有索引,COLUMN_LKP将避免全表扫描,并在您拥有巨大数据集的情况下更快地获取结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.