【问题标题】:Oracle Full HintOracle 完整提示
【发布时间】:2011-05-29 15:30:05
【问题描述】:

如果我理解documentation correctly;完整的提示应该强制进行全表扫描。在下面的场景中,它的表现不一样;

在其上创建的索引中的编号。

SQL> desc test;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 NUM                                       NOT NULL NUMBER
 NUM2                                               NUMBER(10)
 NUM3                                               NUMBER

查询:

select num from test;

结果:

       NUM
----------
         1
         2

执行计划

Plan hash value: 410557223

-------------------------------------------------------------------------
| Id  | Operation        | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT |      |     2 |     4 |     1   (0)| 00:00:01 |
|   1 |  INDEX FULL SCAN | ID   |     2 |     4 |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------

查询:

select /* +full(test) */ num from test;

结果:

       NUM
----------
         1
         2

执行计划

Plan hash value: 410557223

-------------------------------------------------------------------------
| Id  | Operation        | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT |      |     2 |     4 |     1   (0)| 00:00:01 |
|   1 |  INDEX FULL SCAN | ID   |     2 |     4 |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------

我知道我正在选择一个存储在索引中的值。添加任何其他列会使扫描完整。因此,我不得不问显而易见的问题。提示是请求还是对优化器的命令?

在旁注中,统计计算与优化有什么关系。索引的统计信息是自动更新还是显式操作?

【问题讨论】:

    标签: sql oracle query-optimization


    【解决方案1】:

    我没有对此进行测试,但是使用提示的正确语法是:

    select /*+ full(test) */ num from test;
    

    这是斜线加空格。

    【讨论】:

    • 天哪,这太尴尬了。干杯!
    • 另外 - 我不知道您是如何准确执行查询的,但是如果您从另一种语言的程序中调用它,请注意编译器不会吞下 /* 之间的内容*/.例如,假设您使用 C,queryString = "select /*+ full(test) */ num from test"; 将编译为与 queryString = "select num from test"; 相同...
    • @slothrop:很抱歉让这个复活......但没有理智的编译器会吞下嵌入在双引号字符串中的/* ... */。唯一的问题可能是当您用周围的 /* ... */ 评论这样一行时。
    【解决方案2】:

    “顺便说一句,统计计算必须做什么 与优化。是否统计 自动更新的索引或 这是显式操作吗?”

    可能本身就值得提出一个问题(它肯定比您的主要问题更相关:-D)。

    Oracle 不会自动为我们的所有对象维护 100% 的统计信息。在 10g 之前,我们必须使用 DBMS_STATS.GATHER_%_STATISTICS 显式地安排后台作业来执行此操作。

    自 11g 以来,Oracle 更改了默认行为。它监视针对模式发布的 DML,并在现有统计信息过时时运行作业以收集对象的统计信息。即使这样,它也只计算一定百分比的行的统计信息。这通常已经足够了,特别是对于检查所有行会很昂贵的大型表。

    这种默认行为本身通常是足够好的。如果您遇到错误查询计划的问题,则可能值得收集新的统计信息,也许针对更大的行样本。但是不要觉得有必要定期收集针对您的整个架构的完整统计信息,因为许多地方仍然这样做。大多数时候,您可能只是在浪费 CPU 周期,并且冒着破坏现有计划的风险。

    数据库统计是一个很大的话题。 Performance Tuning Guide 有一整章的内容。 Find out more. 另外,请阅读 PL/SQL Packages guide for more on DBMS_STATS 本身。

    【讨论】:

    • +1 - 处理工业规模数据库查询时非常重要的一点
    • +1,但稍作修正:10g 也自动收集统计数据,开箱即用:download.oracle.com/docs/cd/B19306_01/server.102/b14211/…
    • @DCookie - 谢谢,我直接从 9i 升级到 11g。我会更正我的答案。
    • 我直接从 8i 到 10g :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-11
    • 2018-12-03
    • 2023-03-15
    • 2021-06-22
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    相关资源
    最近更新 更多