【问题标题】:Oracle SQL query performanceOracle SQL 查询性能
【发布时间】:2013-05-28 18:20:08
【问题描述】:

我有 3 个表 trader,city_state,city_present。

我在交易者表中有 400 万行,我的查询至少需要 20 秒。 city_present 和城市表中的记录很少。

以下是我的查询。

select t.trader_id, t.name, t.city, t.state from ( SELECT distinct c.city, c.state FROM city_present p,city_state c WHERE p.name = 'TEST_TEST' AND c.city = p.city AND c.state = p.state ) cs, trader t where AND t.city = cs.city AND t.state = cs.state AND t.name = 'john test' AND t.is_valid= 1

我有客户索引(城市、州、姓名、valid_customer) 子查询耗时不到一秒.. 外部查询耗时约 20 秒。

谁能帮我减少查询时间。

【问题讨论】:

  • 对于初学者来说,显示解释计划会有所帮助。
  • 您的查询返回了多少行?

标签: oracle


【解决方案1】:

我假设你有一个关于 trader.name 的索引,可能还包括 trader.is_valid?

真的需要不同吗?这真的需要一个内联视图,还是可以是一个常规连接?

【讨论】:

  • 大约返回 35 行。
  • 我需要交易商名称、is_valid、城市、州列的索引还是只需要名称和 is_valid 列?
  • 您几乎可以肯定至少需要一个关于 trader.name 的索引。是否需要 is_valid 取决于能够在不去表的情况下从索引中仅找到 is_valid=1 将节省多少时间。对于 is_valid 的每个值,您有多少行?您可能不需要索引中的所有交易者列——先尝试一下。
  • 几乎所有行都有 is_valid=1
  • 使用常规连接重写不带内联视图的查询。将 distinct 应用于新查询。在问题中发布新查询,如果仍然存在问题,则发布带有和不带有区别的执行计划。
【解决方案2】:

有些事情您可以在不向架构中添加任何内容的情况下尝试:在您的子查询中,您永远不会从 city_present 中选择任何内容,因此您可以将其转换为 IN / EXISTS

 select t.trader_id, t.name, t.city, t.state from 
 (
 SELECT c.city, c.state
 FROM city_state c
 WHERE EXISTS (
     select null
     from city_present p
     where
     p.name = 'TEST_TEST'  
     AND c.city = p.city  
     AND c.state = p.state)
 ) 
cs, trader t
where 
AND t.city = cs.city
AND t.state = cs.state
AND t.name = 'john test'
AND t.is_valid= 1

那么,同样的事情也适用于 cs。所以你可以重写为:

select t.trader_id, t.name, t.city, t.state from 
trader t
where 
exists (
    SELECT null
    FROM city_state c
    WHERE EXISTS (
         select null
         from city_present p
         where
         p.name = 'TEST_TEST'  
         AND c.city = p.city  
         AND c.state = p.state)
    AND t.city = c.city
    AND t.state = c.state
) 
AND t.name = 'john test'
AND t.is_valid= 1

您也可以尝试展平子查询:

select t.trader_id, t.name, t.city, t.state from 
trader t
where 
exists (
     SELECT null
     FROM city_present p,city_state c
     WHERE p.name = 'TEST_TEST'  
     AND c.city = p.city  
     AND c.state = p.state  
     AND t.city = c.city
     AND t.state = c.state
) 
AND t.name = 'john test'
AND t.is_valid= 1

从这里开始,您应该调查一下索引:

  • trader.name 和/或 trader.id
  • (city_state.city,city_state.state)和(city_present.city,city_present.state)

【讨论】:

    猜你喜欢
    • 2018-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-03
    • 2015-01-17
    • 1970-01-01
    • 2013-01-16
    相关资源
    最近更新 更多