gpt4 book ai didi

performance - T-SQL - 错误的查询执行计划行为

转载 作者:行者123 更新时间:2023-12-04 04:46:05 25 4
gpt4 key购买 nike

我们的一个查询在数据库上产生负载后降级。

我们的查询是 3 个表之间的连接:

  • Base包含 10 M 行的表。
  • EventPerson包含 5000 行的表。
  • EventPerson788这是空的。

  • 似乎优化器扫描了 EventPerson 上的索引而不是寻求,这是复制问题的脚本:
    --Create Tables 
    CREATE TABLE [dbo].[BASE](
    [ID] [bigint] NOT NULL,
    [IsActive] BIT
    PRIMARY KEY CLUSTERED ([ID] ASC)
    )ON [PRIMARY]
    GO

    CREATE TABLE [dbo].[EventPerson](
    [DUID] [bigint] NOT NULL,
    [PersonInvolvedID] [bigint] NULL,

    PRIMARY KEY CLUSTERED ([DUID] ASC)
    ) ON [PRIMARY]
    GO

    CREATE NONCLUSTERED INDEX [EventPerson_IDX] ON [dbo].[EventPerson]
    (
    [PersonInvolvedID] ASC
    )

    CREATE TABLE [dbo].[EventPerson788](
    [EntryID] [bigint] NOT NULL,
    [LinkedSuspectID] [bigint] NULL,
    [sourceid] [bigint] NULL,

    PRIMARY KEY CLUSTERED ([EntryID] ASC)
    ) ON [PRIMARY]
    GO

    ALTER TABLE [dbo].[EventPerson788] WITH CHECK
    ADD CONSTRAINT [FK7A34153D3720F84A]
    FOREIGN KEY([sourceid]) REFERENCES [dbo].[EventPerson] ([DUID])
    GO

    ALTER TABLE [dbo].[EventPerson788] CHECK CONSTRAINT [FK7A34153D3720F84A]
    GO

    CREATE NONCLUSTERED INDEX [EventPerson788_IDX]
    ON [dbo].[EventPerson788] ([LinkedSuspectID] ASC)
    GO

    --POPOLATE BASE TABLE
    DECLARE @I BIGINT=1
    WHILE (@I<10000000)
    BEGIN
    begin transaction
    INSERT INTO BASE(ID) VALUES(@I)
    SET @I+=1
    if (@I%10000=0 )
    begin
    commit;
    end;

    END
    go

    --POPOLATE EventPerson TABLE
    DECLARE @I BIGINT=1
    WHILE (@I<5000)
    BEGIN
    BEGIN TRANSACTION
    INSERT INTO EventPerson(DUID,PersonInvolvedID) VALUES(@I,(SELECT TOP 1 ID FROM BASE ORDER BY NEWID()))
    SET @I+=1
    IF(@I%10000=0 )
    COMMIT TRANSACTION ;
    END

    GO

    这是查询:
    select 
    count(EventPerson.DUID)
    from
    EventPerson
    inner loop join
    Base on EventPerson.DUID = base.ID
    left outer join
    EventPerson788 on EventPerson.DUID = EventPerson788.sourceid
    where
    (EventPerson.PersonInvolvedID = 37909 or
    EventPerson788.LinkedSuspectID = 37909)
    AND BASE.IsActive = 1

    你知道优化器为什么决定使用索引扫描而不是索引查找吗?

    已经完成的解决方法:
  • 分析表并构建统计信息。
  • 重建索引。
  • 尝试 FORCESEEK 提示

  • 以上都没有说服优化器在 EventPerson 上运行索引查找。并在基表上查找。

    谢谢你的帮助。

    最佳答案

    由于 or,扫描在那里条件和外部联接反对 EventPerson788 .

    要么它会从 EventPerson 返回行当EventPerson.PersonInvolvedID = 37909 EventPerson788 中存在行时哪里EventPerson788.LinkedSuspectID = 37909 .最后一部分表示 EventPerson 中的每一行必须根据连接进行检查。

    事实EventPerson788 is empty 不能被查询优化器使用,因为查询计划被保存以便以后在 EventPerson788 中可能有匹配的行时重用.

    更新:

    您可以使用 union all 来重写您的查询,而不是使用或在 EventPerson 中查找。 .

    select count(EventPerson.DUID) 
    from
    (
    select EventPerson.DUID
    from EventPerson
    where EventPerson.PersonInvolvedID = 1556 and
    not exists (select *
    from EventPerson788
    where EventPerson788.LinkedSuspectID = 1556)
    union all
    select EventPerson788.sourceid
    from EventPerson788
    where EventPerson788.LinkedSuspectID = 1556
    ) as EventPerson
    inner join BASE
    on EventPerson.DUID=base.ID
    where
    BASE.IsActive=1

    enter image description here

    关于performance - T-SQL - 错误的查询执行计划行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18171975/

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