Pie*_*erk 3 performance oracle-11g-r2 query-performance
我有一个MERGE
语句需要永远执行选择,因为它从 ( SUB_DATA
)运行的表相当大(读取 1.4 Tb,7 亿行)。我的SELECT
看起来像这样。
SELECT MIN(TRUNC(DATETIME,'DD')) AS FIRST_ACTIVITY,
MAX(TRUNC(DATETIME,'DD')) AS LAST_ACTIVITY,
NVL(PHONE_NUMBER, '-1') AS PHONE_NUMBER,
MAX(NVL(PHONE_ID, '-1')) KEEP (DENSE_RANK LAST ORDER BY DATETIME) AS LAST_PHONE_ID,
MAX(TYPE_ID) KEEP (DENSE_RANK LAST ORDER BY DATETIME) AS TYPE_ID
FROM SUB_DATA AD,
SUB_PROF ICP
WHERE DATETIME BETWEEN minDate AND maxDate
AND PROFILE_ID = ICP.ICP_SEQID
AND REF_RT_ID in (13, 63)
AND DURATION > 3
AND PHONE_NUMBER like '123%'
GROUP BY NVL(PHONE_NUMBER, '-1')
Run Code Online (Sandbox Code Playgroud)
INDEXES
桌子上有两个PHONE_NUMBER
,一个在另一列上,一个在此处未使用的列上。
我努力让查询运行得更快,工作中的一位资深人士建议我强制使用FULL TABLE SCAN
. 我这样做了,它产生了奇迹。
即使它有效,它也违背了全表扫描不好的一般概念。
有人可以解释为什么会这样吗?
[...] 它违背了全表扫描不好的一般概念。
这有例外,就像所有一般概念一样。全表扫描可能比索引扫描然后按 rowid 访问表便宜 - 有时便宜得多。
请记住:
我发现这篇文章中的数字Oracle clustering_factor 提示很好地解释了这个问题。
从本质上讲,如果通过索引扫描使数据块 I/O 请求跳过整个表,则总体成本将高于执行大型顺序读取的成本。FTS 更有可能使用多块直接路径读取,完全绕过 SGA,这也有潜在的好处——没有“缓存颠簸”,锁存更少。
如果你有一个覆盖索引,很有可能它会一直击败全表扫描。如果不是,它将取决于需要处理的实际块(数据 + 索引)的百分比(该查询的索引选择性),以及它们相对于彼此的“物理排序”程度。
至于为什么优化器在这里为您选择了“错误”的路径:很难说。索引或表上的陈旧统计数据可能是一个问题,根据LIKE
某些模式计算的估计值可能会关闭,实例参数可能有点偏爱索引,......如果这是唯一一个行为不端的查询,并且您的统计数据是最新的,使用/*+ full */
提示听起来还不错。