为什么相同的select语句在Oracle中有不同的成本?

时间:2015-05-27 03:23:41

标签: oracle performance query-optimization

最近我使用Oracle 11g数据库来完成我的作业。我有12个表,比如trip_data_11和trip_data_12。 它们具有相同的结构,并且记录的数量几乎相同。我在每个表上创建了相同的索引。 所以对于trip_data_11表:

create index pick_add_11 on trip_data_11(pickup_longitude,pickup_latitude);
create index drop_add_11 on trip_data_11(dropoff_longitude,dropoff_latitude);

与trip_data_12相同的操作。

然后我使用以下select语句来选择每天的出租车号码。

SELECT
   COUNT(DISTINCT(td.medallion)) AS taxi_num
FROM
   SYS.TRIP_DATA_11 td
WHERE 
    (td.pickup_longitude >= -74.2593 AND td.pickup_longitude <= -73.7011
     AND td.pickup_latitude >= 40.4770 AND td.pickup_latitude <= 40.9171
    )
    AND
    (td.dropoff_longitude >= -74.2593 AND td.dropoff_longitude <=    -73.7011
    AND td.dropoff_latitude >= 40.4770 AND td.dropoff_latitude <=  40.9171
  )
 AND
     td.trip_distance > 0
 AND
     td.passenger_count > 0
  GROUP BY 
      regexp_substr(td.pickup_datetime,'\d{4}-\d{2}-\d{2}')
  ORDER BY
      regexp_substr(td.pickup_datetime,'\d{4}-\d{2}-\d{2}');

它花费38秒。当我将表名更改为SYS.TRIP_DATA_12时,问题就出现了,它的成本超过2小时。 更重要的是,它没有结束。我不知道为什么。

今天我问我的同学,他说:清除缓存。所以我使用以下语句来做到这一点。

alter system flush shared_pool;
alter system flush buffer_cache;
alter system flush global context;

现在,当我对SYS.TRIP_DATA_11使用相同的select语句时,我得到的结果与SYS.TRIP_DATA_12相同。为什么?

1 个答案:

答案 0 :(得分:3)

好像你的同学开玩笑了。

显然,您的查询只是表现良好,因为您有一个温暖的缓冲区缓存,其中包含TRIP_DATA_11所需的所有数据。通过刷新缓存,你已经破坏了所有这些,现在你对所有表都有相同的糟糕表现。

调整查询很难,因为有很多可能性。 Please read the documentation on it

只选择一件事:您正在搜索范围,这是有问题的。填充-74.2593 to -73.7011的行数是多少?它可能比-71.00 to -68.59更多,尽管它的范围更广。了解您的数据 - 其数量,分布和偏差 - 至关重要。

作为第一步,学习如何使用EXPLAIN PLAN。 Find out more。要获得更好的计划,请使用DBMS_STATS包收集有关表及其索引的统计信息。 Find out more

一个提示。 Oracle仅使用一个索引来访问表。因此,它会选择pick_add_11 drop_add_11,但不能同时选择两者。然后,它将读取表中的所有匹配记录,并按其他条件对其进行过滤。您可以从旨在为此查询提供服务的索引中获得更好的性能:

create  index add_11 on trip_data_11
   (pickup_longitude
    , pickup_latitude
    , dropoff_longitude
    , dropoff_latitude
    , trip_distance 
    , passenger_count )
;

select语句将针对此索引执行整个过滤器,只触摸该表以获取MEDALLION值。 (您也可以将medallion添加到索引中)。试验列顺序。由于纬度范围比经度窄,可能应该先行;也许在提货之前应该出现下降值。您需要一个索引,其中最大数量的相关记录聚集在一起。

像这样的索引可能是一个开销,所以我们不想在现实生活中维护太多这样的索引。但它们是用于调整频繁运行的昂贵查询的有价值技术。

哦,@ Justin是对的:不要使用SYS进行应用程序工作。即使对于学校作业,您也应该创建一个新的架构并在其中创建表格等。