提高Oracle中的查询性能Postgres的

时间:2016-04-05 16:52:53

标签: sql oracle postgresql

我需要进行多次连接,如下面的查询。大约有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)

5 个答案:

答案 0 :(得分:1)

在oracle中,您可以unpivot使用prim表并使用结果连接到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

答案 1 :(得分:1)

如果可能的话,你绝不应该在语句的select组件中嵌入sql查询。

你可以重写它,以便它适当地反对​​所有表。

选择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中的一个类别为nu​​ll,在这种情况下,针对test_lov的连接必须是外连接。

如果test_lov.column_lkup列上有索引,这也有使用索引的好处。

大声笑 - 这正在变成一个偶然的。您在select子句中的选择基本上会导致全表扫描,然后在PGA中发生分辨率,这很慢。另一种方法在每次成功时停止,因此速度要快得多。

答案 2 :(得分:0)

我的oracle不是很好,但我过去在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

答案 3 :(得分:0)

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
  3. 定义了表格

答案 4 :(得分:0)

拥有CATEGORY的索引,COLUMN_LKP将避免全表扫描,并在您拥有庞大的数据集时更快地获取结果。