ORACLE sql在WHERE子句中显式提供值,与使用子查询相比,显示出更好的性能

问题描述 投票:2回答:2

我是oracle的新手

我有两个表加入huge_table包含大约10亿行big_table包含大约1亿行,小表包含999行提供过滤条件

small_table.num_id匹配huge_table.num_id列

我注意到的问题是,如果我在where子句中明确提供值,那么使用子查询将比它快得多。

特别是在查看解释计划结果时,此查询的基数为100,成本为6,速度更快

SELECT h.col_required, b.col_required, h.num_id
FROM  huge_table h,
      big_table b
WHERE h.row_id = b.xx_id
  AND b.status = 'up'
  AND h.num_id in ('num1', 'num2',... 'num100')  -- Explicitly providing the values that in 
                                                 -- small_table`

带有子查询的查询速度要慢得多,基数为1445704,成本为660293

SELECT h.col_required, b.col_required, h.num_id
FROM huge_table h, big_table b
WHERE h.row_id = b.xx_id
  AND b.status = 'up'
  AND h.num_id in ('SELECT num_id FROM small_table)  -- Using sub query 
                                                     -- provide the values

我也尝试过使用WHERE exists或INNER JOIN,small_table都提供与子查询类似的结果。

我的问题是,如果没有明确提供where子句中的值,是否可以获得良好的性能?

谢谢

我终于找出了造成这个问题的原因。

在small_table中,num_id的数据类型是NVARCHAR2(255)。虽然在huge_table中,num_id的数据类型是VARCHAR2(255)。

基本上在我转换数据类型后,查询时间减少了。

sql subquery where
2个回答
0
投票

这个答案是推测性的,但是您所看到的性能的一个可能解释是Oracle在第二个查询中多次在WHERE子句中执行子查询。也就是说,不是执行一次并缓存结果集,而是多次完成工作。如果使用显式连接重写查询,则可能会解决此问题:

SELECT h.col_required, b.col_required, h.num_id
FROM huge_table h
INNER JOIN big_table b
    ON h.row_id = b.xx_id
INNER JOIN small_table s
    ON h.num_id = s.num_id
WHERE
    b.status = 'up';

您还可以在num_id上添加以下索引到small_table

CREATE INDEX idx ON small_table (num_id);

这可能有助于Oracle更快地完成第二次加入/查找。


0
投票

你可以试试exists

SELECT h.col_required, b.col_required, h.num_id
FROM huge_table h join
     big_table b
     on h.row_id = b.xx_id
WHERE b.status = 'up' AND
      EXISTS (SELECT 1
              FROM small_table st
              WHERE h.num_id = st.num_id
             );

特别是,这可以利用small_table(num_id)上的索引,以及其他表上的其他索引。

© www.soinside.com 2019 - 2024. All rights reserved.