最近我使用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相同。为什么?
答案 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进行应用程序工作。即使对于学校作业,您也应该创建一个新的架构并在其中创建表格等。