从PL/SQL插入临时表GTT的速度非常慢
我有一个从SQL执行的查询,它的性能非常好 它是表和查询之间的连接。这两个表都有接近4 mn的记录。 在doc表上有一些位图索引,我试图提供一些提示。当我从蟾蜍身上看到的时候,解释计划确实表明他们在帮助他们很好地加入 我还提供了另外两个提示,看看它们是否有帮助。一个用于直接路径追加,另一个用于利用pda上现有的BTree索引 当对SQL中的替换变量运行此查询时,结果是即时的,但过程中的同一查询需要8秒或更长时间 除了DBA尚未让步的程序计划之外,如果有任何明显的遗漏,您会怎么想?提前谢谢从PL/SQL插入临时表GTT的速度非常慢,sql,performance,oracle,sql-tuning,Sql,Performance,Oracle,Sql Tuning,我有一个从SQL执行的查询,它的性能非常好 它是表和查询之间的连接。这两个表都有接近4 mn的记录。 在doc表上有一些位图索引,我试图提供一些提示。当我从蟾蜍身上看到的时候,解释计划确实表明他们在帮助他们很好地加入 我还提供了另外两个提示,看看它们是否有帮助。一个用于直接路径追加,另一个用于利用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语句ALL_ROWSCost:1086010字节:15309420基数:36451011加载为选择TMP\u搜索\u总文档
10按索引ROWID表访问表PDA成本:3字节:20基数:1
9个嵌套循环成本:1086010字节:15309420基数:364510
7按索引进行的表访问ROWID表属性成本:23893字节:8019220基数:364510
6位图到行ID的转换
5位图或
2位图合并
1位图索引范围扫描索引(位图)IDX\u BMP\u搜索\u FN 4位图合并
3位图索引范围扫描索引(位图)IDX\U BMP\U搜索\U LN 8索引范围扫描索引IDX\U PDA\U EXP\U文档成本:2基数:1 基数364510似乎不正确,因为表中包含3738562行,其中列的替换值的计数仅为8892 但是,这个计划至少告诉我,正确的索引正在使用中,并且在toad编辑器中运行得非常快 PL/SQL中的实际计划仍然不可用
不确定这是否增加了一些有价值的信息。但是思想还是会改变的。谢谢你可能会关注的几件事
首先,我认为用append插入GTT没有任何逻辑。我可能错了,但据我所知,append绕过缓冲区缓存并直接写入文件,它写入的数据超过了最高水位线,并且在提交之前不允许查询。 GTT不在常规数据文件上-它在临时文件上,并且在提交时被截断(默认设置)
我认为,如果您不需要在查询之后操作数据,可以考虑将REF游标返回给应用程序。这基本上是一样的——许多DAL层都是以这种方式实现的
如果您仍然需要GTT,我会检查我的临时文件分配,包括大小和实际磁盘-您的DBA可能已将它们放在不同的设备上。 如果您的过程是首先使用参数执行的,例如%
,Oracle无法对谓词使用某些索引访问方法。Oracle无法听从您的暗示,并制定了一个计划,该计划对%
来说相当不错,但对其他一切都很糟糕
一种可能的解决方案是强制Oracle始终硬解析您的查询。我已经使用了这个解决方案,正如Dion Cho在
:
硬解析将使用额外的CPU资源,但希望有更好的计划能够弥补这一差异。此解决方案将导致其他不相关的查询需要硬解析。您可能想看看参考线程中提到的一些其他解决方案
此外,您的提示可能不正确。索引之间不应该有逗号。然而,提示语法的文档很少,提示解析器通常“部分”工作。您的提示可能被评估为
/*+INDEX\u COMBINE(attr)*/
,它可能按您希望的方式工作,也可能不按您希望的方式工作。没有计划你永远不会知道
有充分的理由避免提示,特别是如果您无法方便地访问解释计划。在#2上,是的,查询返回600多行与我比较性能的相关参数。我已经到了最后一张记录的结果是的。3号。是的,我已经确定这是造成延误的原因。来自独立SQL的计划看起来不错,这就是我如何进行调优并将其带到过程中的。没有运行跟踪的权限,也没有过程的实际执行计划。不过,感谢您重申这些要点。您在该过程中还做了什么?不确定这是否有帮助,但最终它将建立一个记录集,然后由应用程序读取。我应该指出,我确实在同一个SQL上使用集合尝试了大容量收集,这也是同样的性能。不知何故,您觉得SELECT没有采用从编辑器执行时的最佳路径..+1您对使用GTT和append持怀疑态度是正确的。GTT的优点是它应该总是被缓存;为第一个w绕过缓存
dbms_stats.set_table_stats('schema','DOC',num_rows=>null,no_invalidate=>false);