Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何减少大数据表的查询执行时间_Sql_Database_Performance_Oracle - Fatal编程技术网

Sql 如何减少大数据表的查询执行时间

Sql 如何减少大数据表的查询执行时间,sql,database,performance,oracle,Sql,Database,Performance,Oracle,我正在生产(Oracle)中运行此查询,需要3分钟以上的时间。有没有办法缩短执行时间?svc_顺序和事件表都包含近100万条记录 select 0 test_section, count(1) count, 'DD' test_section_value from svc_order so, event e where so.svc_order_id = e.svc_order_id and so.entered_date >= to_date('01/01/2012',

我正在生产(Oracle)中运行此查询,需要3分钟以上的时间。有没有办法缩短执行时间?svc_顺序和事件表都包含近100万条记录

select 0 test_section, count(1) count, 'DD' test_section_value  
from svc_order so, event e  
where so.svc_order_id = e.svc_order_id  
  and so.entered_date >= to_date('01/01/2012', 'MM/DD/YYYY')  
  and e.event_type = 230 and e.event_level = 'O'  
  and e.current_sched_date between 
      to_date( '09/01/2010 00:00:00', 'MM/DD/YYYY HH24:MI:SS')
      and to_date('09/29/2013 23:59:59', 'MM/DD/YYYY HH24:MI:SS')  
  and (((so.sots_ta = 'N') and (so.action_type = 0)) 
       or  ((so.sots_ta is null) and (so.action_type = 0)) 
       or  ((so.sots_ta = 'N') and (so.action_type is null)))
  and so.company_code = 'LL'
您至少可以通过使用
COALESCE()
(或其oracle等价物
IFNULL()
)来避免三元组和/或列表注意:这不适用于sots和action类型都为NULL的情况

SELECT 0 test_section, count(1) count, 'DD' test_section_value
FROM svc_order so 
JOIN event e  ON so.svc_order_id = e.svc_order_id
WHERE e.event_type = 230 and e.event_level = 'O'  
  AND so.entered_date >= to_date('01/01/2012', 'MM/DD/YYYY')
  AND e.current_sched_date >= to_date('09/01/2010 00:00:00', 'MM/DD/YYYY HH24:MI:SS')
  AND e.current_sched_date  < to_date('10/01/2013 00:00:00', 'MM/DD/YYYY HH24:MI:SS') 
  AND  COALESCE(so.sots_ta, 'N') = 'N'
  AND  COALESCE(so.action_type, 0) = 0   
  AND so.company_code = 'LL'
选择0测试部分、计数(1)计数、“DD”测试部分值
从svc_订单so
在so.svc\u order\u id=e.svc\u order\u id上加入事件e
其中e.event_type=230,e.event_level='O'
因此,输入日期>=截止日期('2012年1月1日','MM/DD/YYYY')
和e.当前日程日期>=截止日期('09/01/2010 00:00:00','MM/DD/YYYY HH24:MI:SS')
和e.当前日程日期<截止日期('2013年1月10日00:00:00','MM/DD/YYYY HH24:MI:SS')
并结合(so.sots_ta,'N')='N'
和合并(so.action_type,0)=0
因此,company_code='LL'
我用一个普通的
t>=low和t<高)
测试,因为我不喜欢
之间的
语义。我将kommalist中的
替换为
连接,因为我更喜欢连接。

您至少可以使用
COALESCE()
(或其oracle等价物
IFNULL()
)来避免三元组和/或列表。注意:这不适用于sots和action类型都为NULL的情况

SELECT 0 test_section, count(1) count, 'DD' test_section_value
FROM svc_order so 
JOIN event e  ON so.svc_order_id = e.svc_order_id
WHERE e.event_type = 230 and e.event_level = 'O'  
  AND so.entered_date >= to_date('01/01/2012', 'MM/DD/YYYY')
  AND e.current_sched_date >= to_date('09/01/2010 00:00:00', 'MM/DD/YYYY HH24:MI:SS')
  AND e.current_sched_date  < to_date('10/01/2013 00:00:00', 'MM/DD/YYYY HH24:MI:SS') 
  AND  COALESCE(so.sots_ta, 'N') = 'N'
  AND  COALESCE(so.action_type, 0) = 0   
  AND so.company_code = 'LL'
选择0测试部分、计数(1)计数、“DD”测试部分值
从svc_订单so
在so.svc\u order\u id=e.svc\u order\u id上加入事件e
其中e.event_type=230,e.event_level='O'
因此,输入日期>=截止日期('2012年1月1日','MM/DD/YYYY')
和e.当前日程日期>=截止日期('09/01/2010 00:00:00','MM/DD/YYYY HH24:MI:SS')
和e.当前日程日期<截止日期('2013年1月10日00:00:00','MM/DD/YYYY HH24:MI:SS')
并结合(so.sots_ta,'N')='N'
和合并(so.action_type,0)=0
因此,company_code='LL'

我用一个普通的
t>=low和t<高)
测试,因为我不喜欢
之间的
语义。我将kommalist的
替换为
连接,因为我更喜欢连接。

我们不能有额外的索引,但表必须至少有完整的主键,对吗?这至少会产生索引、非/聚集的任何结果。 看看它,试着利用它

若表是一个堆,我们希望按原样处理它,那个么我们应该通过应用各自的where过滤器来分别减少每个表中的行数,然后合并该结果集。 在查询中,唯一表示整个结果列依赖于基表的是count(1)。其他两列是常量。 因为还加入了/笛卡尔积等…。。将引导DB引擎查找索引,所以使用INTERSECT,我觉得在您的情况下应该更好。 您可以执行的其他一些更改: 避免使用WHERE条件列右侧的TO_DATE或任何类型的函数。在局部变量中准备数据,并在查询中使用局部变量。 此外,您还需要检查使用>=是否有任何良好的性能提升

我修改了查询,还合并了一个冗余where条件。 记住,如果这些改变现在对你有效,并不意味着它会一直有效。当您的表开始命中更多的数据时,这些数据将再次以慢查询的形式返回。所以短期内这可能有效,但长期而言,你必须考虑其他选择

    1)  for example Indexed Views on top of this tables
    2)  Create same tables with different name and sync data 
        between new and original table using  “Insert/Update/Delete Trigger”.




    SELECT COUNT(1) AS [COUNT], 'DD' test_section_value  ,0 test_section
    FROM
    (
        SELECT  so.svc_order_id
        FROM    svc_order so
        WHERE   so.entered_date >= to_date('01/01/2012', 'MM/DD/YYYY')
                AND so.company_code = 'LL'

        INTERSECT

        SELECT  e.svc_order_id
        FROM    event e
        WHERE   e.event_type = 230
                AND e.event_level = 'O'
                AND e.current_sched_date BETWEEN
                    to_date('09/01/2010 00:00:00','MM/DD/YYYY HH24:MI:SS')
                    AND to_date('09/29/2013 23:59:59','MM/DD/YYYY HH24:MI:SS')
                AND ( 
                        (( so.sots_ta = 'N' ) AND ( so.action_type IS NULL OR so.action_type = 0))
                        OR 
                        (( so.sots_ta IS NULL ) AND ( so.action_type = 0 )) 
                        --or ((so.sots_ta = 'N') and (so.action_type is null))
                    )
    )qry1

我们不能有额外的索引,但表必须至少有完整的主键,对吗?这至少会产生索引、非/聚集的任何结果。 看看它,试着利用它

若表是一个堆,我们希望按原样处理它,那个么我们应该通过应用各自的where过滤器来分别减少每个表中的行数,然后合并该结果集。 在查询中,唯一表示整个结果列依赖于基表的是count(1)。其他两列是常量。 因为还加入了/笛卡尔积等…。。将引导DB引擎查找索引,所以使用INTERSECT,我觉得在您的情况下应该更好。 您可以执行的其他一些更改: 避免使用WHERE条件列右侧的TO_DATE或任何类型的函数。在局部变量中准备数据,并在查询中使用局部变量。 此外,您还需要检查使用>=是否有任何良好的性能提升

我修改了查询,还合并了一个冗余where条件。 记住,如果这些改变现在对你有效,并不意味着它会一直有效。当您的表开始命中更多的数据时,这些数据将再次以慢查询的形式返回。所以短期内这可能有效,但长期而言,你必须考虑其他选择

    1)  for example Indexed Views on top of this tables
    2)  Create same tables with different name and sync data 
        between new and original table using  “Insert/Update/Delete Trigger”.




    SELECT COUNT(1) AS [COUNT], 'DD' test_section_value  ,0 test_section
    FROM
    (
        SELECT  so.svc_order_id
        FROM    svc_order so
        WHERE   so.entered_date >= to_date('01/01/2012', 'MM/DD/YYYY')
                AND so.company_code = 'LL'

        INTERSECT

        SELECT  e.svc_order_id
        FROM    event e
        WHERE   e.event_type = 230
                AND e.event_level = 'O'
                AND e.current_sched_date BETWEEN
                    to_date('09/01/2010 00:00:00','MM/DD/YYYY HH24:MI:SS')
                    AND to_date('09/29/2013 23:59:59','MM/DD/YYYY HH24:MI:SS')
                AND ( 
                        (( so.sots_ta = 'N' ) AND ( so.action_type IS NULL OR so.action_type = 0))
                        OR 
                        (( so.sots_ta IS NULL ) AND ( so.action_type = 0 )) 
                        --or ((so.sots_ta = 'N') and (so.action_type is null))
                    )
    )qry1

首先,确保统计数据是最新的

begin
    dbms_stats.gather_table_stats('[schema]', 'svc_order');
    dbms_stats.gather_table_stats('[schema]', 'event');
end;
/
此查询是两个小表之间的一个非常简单的联接,但具有复杂的谓词。 几乎可以肯定的是,您不希望为了搜索一些神奇的语法而显著地重写所有查询,这些语法将使所有查询都运行得很快。是的,在一些罕见的情况下,
BETWEEN
不起作用,或者将谓词移动到内联视图中会有帮助,或者用
INTERSECT
替换连接可能会有帮助。但我觉得这很像。扪心自问,为什么这些变化会有什么不同?如果这些类型的更改总是能提高性能,为什么Oracle不在内部转换查询呢

通常,您应该尝试向优化器提供更好的信息,以便优化器能够做出更好的决策。通常,这与使用默认设置收集统计数据一样简单。有些谓词太复杂了,因此您应该尝试使用 ,例如
/*+动态_采样(6)*/
。或许 加一些。