我有以下查询,它在执行后从 100000000 返回 20000 条记录..
SELECT *
FROM (SELECT a.*, ROWNUM rnum
FROM (select TIME,url,bytes
FROM (SELECT TO_CHAR ("5mintime",'YYYY-MM-DD HH24:MI:SS') AS TIME, url, BYTES
FROM available_web_details
WHERE "5mintime" >= TIMESTAMP '2012-02-10 00:00:00'
AND "5mintime" <= TIMESTAMP '2012-02-13 23:59:59'
AND username = 'asha1328874833'
AND CATEGORY = 'None240001'AND domain = '1328874833.vmware.com.'
AND (appid IN ('216.198.204.192id','216.198.207.0id','216.198.211.64id','216.198.211.128id','216.198.212.0id', '216.198.214.128id','216.198.214.192id','216.198.218.0id','216.198.220.192id','216.198.222.0id','216.198.223.32id','216.198.228.128id','216.198.229.128id',.....)))
ORDER BY TIME DESC) a
WHERE ROWNUM <= 10)
WHERE rnum > 0
执行它大约需要 5 分钟。但是当我删除 order by 子句时,它会在 4 秒内执行。你能建议我如何提高性能吗?
available_web_details 的 架构:
Name Null Type
------------ ---- --------------
5mintime TIMESTAMP(6)
USERNAME VARCHAR2(64)
HOST NUMBER
SRC_ZONE VARCHAR2(32)
DOMAIN VARCHAR2(512)
DST_ZONE VARCHAR2(32)
CONTENT VARCHAR2(64)
CATEGORY VARCHAR2(64)
URL VARCHAR2(1024)
HITS NUMBER
BYTES NUMBER
APPID VARCHAR2(32)
APPLICATION VARCHAR2(64)
CATEGORYTYPE VARCHAR2(64)
USERGROUP VARCHAR2(384)
我在 appid 上有索引,“5mintime” 带有本地分区。
available_web_details
是 1 个月的范围分区表。
最佳答案
让我们从免责声明开始:如果你不删除那个 order by
或开始使用临时表,执行时间是 永远不会 减少到 4s。第二个免责声明:我犯了一个大错误,现在正在纠正;我花了太长时间才意识到这一点。谢谢 Alex Poole 。
我的观点(我总是有几个)。
where
子句中的所有 和 select
中的所有内容,您 保证 是 table access by index rowid
。这意味着对于您从最里面的 select
返回的每一行,您都从索引中提取,您还可以重新访问该表。我承认这将是您当前表上的一个可笑的大索引。 select
中下订单。您还在别名上方的两个级别引用别名 a
。虽然这可能不会导致任何问题,但它有点令人困惑,最终会出现两次 rnum
列。 url
是否需要为 1024 个字符? 这些要点实际上归结为我的主要建议;减小表的大小。 然后,尽一切可能去除 Oracle 需要做的任何额外工作;甚至将大部分表格变成索引。
所以,步骤是:
where, group by, order by and select clauses
中的所有列 按照 和 的顺序降低选择性。这将使您的索引类似于 "5mintime", username, category, domain, appid, url, bytes
。 SELECT time, url, bytes, rownum as rnum
FROM ( SELECT time, url, bytes, rowum as rnum
FROM ( SELECT TO_CHAR ("5mintime",'YYYY-MM-DD HH24:MI:SS') AS time
, url
, bytes
FROM available_web_details
WHERE "5mintime" BETWEEN to_timestamp('2012-02-10 00:00:00','YYYY-MM-DD HH24:MI:SS')
AND to_timestamp('2012-02-13 23:59:59','YYYY-MM-DD HH24:MI:SS')
AND username = 'asha1328874833'
AND category = 'None240001'
AND domain = '1328874833.vmware.com.'
AND appid IN ('216.198.204.192id',...)
ORDER BY "5mintime" DESC
)
WHERE rownum <= 10)
WHERE rnum > 0
希望这一切都有意义;在一天结束时,您的报告在服务器上完成的工作量以及您希望它们运行的速度将决定您想要做什么。
关于sql - order by 子句的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9441649/