首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >为什么我的查询在强制全表扫描后运行得更快?

为什么我的查询在强制全表扫描后运行得更快?
EN

Database Administration用户
提问于 2012-10-30 09:23:58
回答 2查看 3.2K关注 0票数 3

我有一个MERGE语句,它花费了很长时间来执行select,因为它正在运行的表(SUB_DATA)相当大(阅读1.4TB,7亿行)。我的SELECT看起来像这样。

代码语言:javascript
代码运行次数:0
运行
复制
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')

表上有两个INDEXES,一个在PHONE_NUMBER上,另一个在没有在这里使用的列上。

我很难让查询运行得更快,工作中一个更资深的人建议我强制使用FULL TABLE SCAN。我做了这件事,效果很好。

尽管它有效,但它违背了一般的概念,即全表扫描是不好的。

有人能解释一下为什么会这样吗?

EN

回答 2

Database Administration用户

回答已采纳

发布于 2012-10-30 13:17:07

... --它违背了一般的概念,即全表扫描是不好的。

这有例外,就像所有的一般概念一样。一个完整的表扫描可以比索引扫描后跟rowid的表访问更便宜--有时要便宜得多。

记住:

  • 除了表的块之外,还需要读取索引块。如果索引很大(表大小的相当大的百分比),SGA (和关联锁)的压力可能是显而易见的。
  • 如果索引的排序顺序与实际表中存储数据的方式不匹配,则完成查询所需的逻辑I/O的数量可能比完成整个表扫描所需的LIOs数多(可能更多)。(索引的聚类因子是可以用来估计这一点的指标之一。)

我发现本文中的数字Oracle聚类_因素提示很好地解释了这个问题。

本质上,如果通过索引进行扫描使数据块I/O请求跳转到整个表中,则总体成本将高于可以进行大规模顺序读取的成本。FTS更可能使用多块直接路径读取,完全绕过SGA,这也是潜在的好-没有“高速缓存冲击”,更少的锁存。

如果你有一个覆盖指数,这很可能会击败一个完整的表扫描所有时间。如果不是,这将取决于实际块(数据+索引)中需要处理的百分比(索引对该查询的选择性),以及它们之间的“物理排序”情况。

至于为什么优化器在这里为您选择“错误”的路径:很难说。索引或表上的陈旧统计数据可能是一个问题,通常情况下,基于LIKE计算的估计值对于某些模式来说可能是不正确的,实例参数可能对索引有太大的偏爱,……如果这是唯一有问题的查询,并且您的统计数据是最新的,那么使用/*+ full */提示听起来并不太糟糕。

票数 5
EN

Database Administration用户

发布于 2012-10-30 16:32:39

编辑马特指出,这是一个Oracle问题,我认为这是针对的。我不确定这个答案是否适用于,但如果可以的话,我将把它放在一边,以防它确实适用,并且它是否可以帮助其他人。MODS,如果这是不应该在这里,请删除或让我知道如何!谢谢。结束编辑

根据您的问题,您缺少一个覆盖索引。这意味着SQL服务器正在进行书签查找,这可能会非常慢。

有趣的是,Server没有使用查询优化器进行表扫描。你的统计数据最新吗?这是一个非常有选择性的查询吗?

此外,“包括”列在本例中可能非常有用。所包含的列在索引b树的非叶节点中没有指针,但是列值包含在索引叶页上,从而避免了昂贵的书签查找操作的需要,这些操作需要大量的物理IO。

我不喜欢为每个查询创建索引,但是如果您有两个单列索引,那么将这两个列合并到一个索引中,那么从select语句中添加包含的列应该是非常有用的。

票数 0
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/27874

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档