gpt4 book ai didi

sql - 使用 in (select ...) 子句进行查询优化

转载 作者:行者123 更新时间:2023-12-04 19:40:37 24 4
gpt4 key购买 nike

我在 Windows 上使用 Firebird WI-V3.0.4.33054。

我在优化此查询时遇到问题,它使用带有选择的 in 子句:

update CADPC p set p.STA = 'L'
where p.COD in (select distinct CODPC from CADPCI_Rec where IDNfr = 27)
and not exists (select * from CADPCI where CODPC = p.COD)

此查询的计划是(明显的问题是 P NATURAL 部分):

PLAN SORT (CADPCI_REC INDEX (PK_CADPCI_REC))
PLAN (CADPCI INDEX (FK_CADPCI_CODPC))
PLAN (P NATURAL)

Select Expression
-> Filter
-> Unique Sort (record length: 36, key length: 8)
-> Filter
-> Table "CADPCI_REC" Access By ID
-> Bitmap
-> Index "PK_CADPCI_REC" Range Scan (partial match: 1/3)
Select Expression
-> Filter
-> Table "CADPCI" Access By ID
-> Bitmap
-> Index "FK_CADPCI_CODPC" Range Scan (full match)
Select Expression
-> Filter
-> Table "CADPC" as "P" Full Scan

另一方面,如果我手动运行 select distinct,复制结果并粘贴到查询中,如下所示:

update CADPC p set p.STA = 'L'
where p.COD in (5699, 5877, 5985)
and not exists (select * from CADPCI where CODPC = p.COD)

现在优化器为 P 表选择了一个合理的计划,查询运行得非常快:

PLAN (CADPCI INDEX (FK_CADPCI_CODPC))
PLAN (P INDEX (PK_CADPC, PK_CADPC, PK_CADPC))

Select Expression
-> Filter
-> Table "CADPCI" Access By ID
-> Bitmap
-> Index "FK_CADPCI_CODPC" Range Scan (full match)
Select Expression
-> Filter
-> Table "CADPC" as "P" Access By ID
-> Bitmap Or
-> Bitmap Or
-> Bitmap
-> Index "PK_CADPC" Unique Scan
-> Bitmap
-> Index "PK_CADPC" Unique Scan
-> Bitmap
-> Index "PK_CADPC" Unique Scan

我也尝试过在这两种情况下都存在,但结果是一样的:子查询对每一行都重新求值。

update CADPC p set p.STA = 'L'
where exists (select * from CADPCI_Rec where IDNfr = 27 and CODPC = p.COD)
and not exists (select * from CADPCI where CODPC = p.COD)

计划:

PLAN (CADPCI_REC INDEX (PK_CADPCI_REC))
PLAN (CADPCI INDEX (FK_CADPCI_CODPC))
PLAN (P NATURAL)

Select Expression
-> Filter
-> Table "CADPCI_REC" Access By ID
-> Bitmap
-> Index "PK_CADPCI_REC" Range Scan (partial match: 1/3)
Select Expression
-> Filter
-> Table "CADPCI" Access By ID
-> Bitmap
-> Index "FK_CADPCI_CODPC" Range Scan (full match)
Select Expression
-> Filter
-> Table "CADPC" as "P" Full Scan

因此,问题是:当 in 子句包含选择(通常只有几条记录)时,我能否以某种方式让引擎选择索引计划?

最佳答案

您可以尝试EXECUTE BLOCK 和“反转控制”

本质上是发布一个匿名的临时存储过程

EXECUTE BLOCK AS
declare id INTEGER;
BEGIN
for select distinct t1.CODPC from CADPCI_Rec t1
left join CADPCI t2 on where t2.CODPC = t1.CODPC
where t2.CODPC is NULL and t1.IDNfr = 27
into :id
do
update CADPC p set p.STA = 'L' where p.COD = :ID and p.STA <> 'L';
END

您还可以使用全局临时表 (GTT)

然后在实际删除之前创建 ID 列表。

数据库准备(创建无主体表):

CREATE GLOBAL TEMPORARY TABLE CADPC_mark_IDs
( ID integer )
ON COMMIT DELETE ROWS

然后命令就像

insert into CADPC_mark_IDs(ID)
select distinct t1.CODPC from CADPCI_Rec t1
left join CADPCI t2 on where t2.CODPC = t1.CODPC
where t2.CODPC is NULL and t1.IDNfr = 27

然后

update CADPC p set p.STA = 'L'
where p.COD in (select * from CADPC_mark_IDs) and p.STA <> 'L'

然后

commit; -- clear the in-memory table for next uses

在将“不存在的地方”转换为“左连接”(已在上面完成,希望是正确的)之后,还有一个选项,如 Mark 所建议的那样,将使用 MERGE

一些东西

merge into CADPC p
using (
select distinct t1.CODPC as id from CADPCI_Rec t1
left join CADPCI t2 on where t2.CODPC = t1.CODPC
where t2.CODPC is NULL and t1.IDNfr = 27
) t
on (t.id = p.COD) and (p.STA <> 'L')
when matched then update set p.STA = 'L'

关于sql - 使用 in (select ...) 子句进行查询优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57399622/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com