Oracle 在 IN 子句中使用子查询降低性能
Posted
技术标签:
【中文标题】Oracle 在 IN 子句中使用子查询降低性能【英文标题】:Oracle slow performance using subquery inside IN clause 【发布时间】:2016-02-22 15:39:08 【问题描述】:我有这样的查询:
SELECT
xmlelement("objects",
xmlagg(
xmlelement("object",
xmlelement("accountId", ACCOUNTS.accountId),
xmlelement("address", ACCOUNTS.ADDRESS)
)
)
INTO obj_info_xml
FROM
ACCOUNTS
WHERE account_code IN (SELECT EXTRACTVALUE(VALUE(accountCodes), '/accountCode/text()') as accountCode
FROM TABLE(XMLSEQUENCE(EXTRACT(X, '//accountCodes/accountCode'))) accountCodes);
当我在IN
子句中硬编码值时,查询执行得很快,但是当我使用子查询从 xml 中选择时,我无法获得结果,因为它执行得非常慢。你有什么建议吗?
【问题讨论】:
一些建议...有些人发誓用 EXISTS 替换 IN 将提供性能优势,但您将获得多少改进是值得怀疑的 - 仍然很容易尝试更改。但是,我认为可能更有帮助的是对子查询使用子查询分解(使用 WITH 语句)。然后解析器将决定是否要将您的查询视为内联视图,或者是否要创建一个临时表来存储值。无论哪种方式,您都应该看到性能提升。在此处阅读有关子查询分解的信息:oracle-base.com/articles/misc/with-clause 当 RDBMS 被用作 XML 而不是 RDBMS 的数据存储时会发生这种情况。 不确定您使用的是哪个版本,但您是否使用XML indexes查看过。如果 XPATH 查找是瓶颈,这应该有助于加快速度。 我的直觉是放弃 xmlsequence,提取和提取值,转而使用 xmltable。但是,如果没有示例数据和您的帐户表的 ddl,您将很难为您提供帮助。请更新您的问题以包含额外信息。 Dank 你能提供一些例子,我如何用 WITH 子句更改 IN 子句,因为我不知道。 【参考方案1】:假设 x
是一个 PL/SQL 变量,其中包含您的帐户代码列表,这样的事情应该会加快速度:
select xmlelement("objects",
xmlagg(xmlelement("object",
xmlelement("accountId", accounts.accountid),
xmlelement("address", accounts.address))
)
) account_xml
into obj_info_xml
from accounts a
inner join xmltable('//accountCodes/accountCode'
passing x
columns account_code varchar2(30) path '.') xdata -- amend datatype as appropriate
on a.account_code = xdata.account_code;
注意由于缺乏样本数据,未经测试。
好的,下面给你什么?
select xmlelement("objects",
xmlagg(xmlelement("object",
xmlelement("accountId", accounts.accountid),
xmlelement("address", accounts.address))
)
) account_xml
into obj_info_xml
from accounts a
where a.account_code in (select /*+ dynamic_sampling(xdata 10) */
account_code
from xmltable('//accountCodes/accountCode'
passing x
columns account_code varchar2(30) path '.') xdata); -- amend datatype as appropriate
另一个建议是将/*+ dynamic_sampling(xdata 10) */
替换为/* cardinality(xdata <roughly expected number of rows>) */
(当然,用相关号码覆盖)。
另外,您能否编辑您的问题以提供带有和不带有硬编码变量的查询的执行计划?
【讨论】:
感谢您的建议,但这也和我原来的查询一样慢 我已经用一些可能有用的建议更新了我的答案。以上是关于Oracle 在 IN 子句中使用子查询降低性能的主要内容,如果未能解决你的问题,请参考以下文章