3

我有一个从 SQL 执行时执行出色的查询。

它是表和查询之间的连接。这两个表都有近 400 万条记录。我试图提供提示的文档表上有位图索引。当我从蟾蜍看到时,解释计划确实表明他们正在帮助加入。

我提供了 2 个其他提示,看看它们是否有帮助。一种是直接路径 APPEND,另一种是利用 pda 上现有的 BTree 索引。

当对 SQL 中的替换变量运行此查询时,结果是即时的,但过程中的相同查询需要 8 秒或更长时间。

除了 DBA 尚未屈服的程序计划之外,如果有任何明显的遗漏,我可能会让您想到什么?提前致谢。

 
     INSERT                                                           /*+ APPEND */
          INTO  tmp_search_gross_docs (document_id,
                                       last_name,
                                       first_name,
                                       person_doc_association_id,
                                       association_date)
       SELECT                 /*+INDEX(pda IDX_DOC_PDOC_DOCID ) USE_NL(pda doc) */
             pda.document_id,
              last_name,
              first_name,
              person_doc_association_id,
              association_date
         FROM   pda,
              (SELECT /*+INDEX_COMBINE(attr IDX_BMP_SEARCH_FN,IDX_BMP_SEARCH_LN)*/
                      document_id, last_name, first_name
                 FROM doc attr
                WHERE first_name LIKE l_first_name OR last_name LIKE l_last_name) doc
        WHERE pda.document_id = doc.document_id;
                         ) doc
                 WHERE pda.document_id = doc.document_id;

  

解释计划(来自 Toad 的绑定变量)

INSERT STATEMENT ALL_ROWSCost: 1,086,010 Bytes: 15,309,420 Cardinality: 364,510
11 LOAD AS SELECT TMP_SEARCH_GROSS_DOCS
10 TABLE ACCESS BY INDEX ROWID TABLE PDA Cost: 3 Bytes: 20 Cardinality: 1
9 NESTED LOOPS Cost: 1,086,010 Bytes: 15,309,420 Cardinality: 364,510
7 TABLE ACCESS BY INDEX ROWID TABLE ATTR 成本:23,893 字节:8,019,220 基数:364,510
6 位图转换为行 5 位图

2位图合并
1 位图索引范围扫描索引(位图) IDX_BMP_SEARCH_FN 4 位图合并
3 BITMAP INDEX RANGE SCAN INDEX (BITMAP) IDX_BMP_SEARCH_LN 8 INDEX RANGE SCAN INDEX IDX_PDA_EXP_DOC 成本:2 基数:1

基数 364,510 似乎关闭,因为该表包含 3738562 行,而对于 WHERE 中列的替换值,计数仅为 8892。

但同样,这个计划至少告诉我正在使用正确的索引,并且从 toad 编辑器运行得非常快。

PL/SQL 的实际计划仍然不可用。

不确定这是否会增加一些有价值的信息。但思想还是会编辑。谢谢

4

3 回答 3

2

首先,我认为使用 append 插入 GTT 没有任何逻辑。我可能是错的,但据我所知,附加绕过缓冲区缓存并直接写入文件,它写在高水位线之上,并且在提交之前不允许查询。GTT 不在常规数据文件上 - 它在临时文件上,并且在提交时被截断(默认设置)。

我认为,如果您不需要在查询后操作数据,请考虑将 ref 游标返回给应用程序。基本上是一样的——很多 DAL 层都是这样实现的。

如果您仍然想要 GTT,我会检查我的临时文件分配,包括大小和实际磁盘 - 您的 DBA 可能已将它们放在不同的设备上。

于 2013-04-13T07:04:01.587 回答
1

您可能会研究的几件事。

  1. 与 GTT 表无关。就像您说的那样,在 nologging 中创建更多表,并且在插入时使用插入附加提示进行直接路径加载。

  2. 此外,如果您查看 Toad 的结果,可能会对查询速度产生误解。像 toad 这样的软件会自动添加提示以获取前 50/100/200 行,因此查询可能看起来运行得更快。您是否尝试过转到最后一条记录(网格中的“>”图标)并查看获取最后一行需要多少时间?

  3. 如果无法查看计划,就不可能调整查询甚至编写好的代码。如果它是一个更大的过程,您可以查看 DBMS_PROFILER 之类的东西。如果您确定这是导致问题的语句,您可以从 SQL 跟踪或解释计划开始。

于 2013-04-12T18:45:46.567 回答
0

自适应游标共享不适用于 LIKE 谓词。

如果您的过程首先使用诸如 之类的参数执行%,则 Oracle 不能对谓词使用某些索引访问方法。甲骨文无法听从你的暗示,并制定了一个对其他一切都很好%但对其他一切都很糟糕的计划。

一种可能的解决方案是强制 Oracle 始终硬解析您的查询。我已经使用了这个解决方案,正如 Dion Cho 在 这个 OTN 线程中所解释的那样:

dbms_stats.set_table_stats('schema','DOC',num_rows=>null,no_invalidate=>false);

硬解析将使用额外的 CPU 资源,但希望更好的计划能够弥补差异。此解决方案将导致其他不相关的查询需要硬解析。您可能想查看引用线程中提到的其他一些解决方案。

此外,您的INDEX_COMBINE提示可能不正确。索引之间不应有逗号。但是,提示语法的文档记录很差,提示解析器通常会“部分”工作。您的提示可能被评估为 的等价物 /*+INDEX_COMBINE(attr)*/,它可能会或可能不会按您希望的方式工作。没有计划你永远不会知道。

避免提示是有充分理由的,尤其是当您无法方便地访问解释计划时。

于 2013-04-15T18:55:02.363 回答