AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题

问题[execution-plan](dba)

Martin Hope
Mike Petrak
Asked: 2024-05-23 21:28:47 +0800 CST

Azure SQL 托管实例:1. 初始编译时间过长导致应用程序超时和 2. 分区维护:长时间运行,导致数据文件膨胀

  • 7

我们遇到了一些问题,导致我们无法将本地 SQL 2016 Std Ed 迁移到 Azure SQL 托管实例业务关键层,我想知道是否有人遇到过类似的问题并能为我们提供建议。我们的问题是:

  1. 最令人头疼的问题是,至少有十几个存储过程和其他查询的查询计划初始编译时间过长(40 秒到 174 秒……我甚至见过长达 725 秒的例子!)。这导致应用程序频繁且随机超时,因为大多数都设置为默认的 30 秒。需要澄清的是,这不是过多的重新编译,而是查询计划中的编译时间非常长。

https://erikdarling.com/are-long-compile-times-bringing-you-down/中的查询和信息对于识别这些查询非常有帮助(我也读过https://littlekendra.com/2024/03/05/long-compilers-who-time-out-not-in-query-store/)。我们也看到了一些编译超时:https://www.brentozar.com/blitzcache/compilation-timeout/。

我们正在尝试调整这些查询并降低其复杂性,因为我们被告知这应该会减少编译时间。几个月来,我们还尝试将 AZ MI 层升级到业务关键层,添加 vCores,并调整实例和数据库设置。

我们已经与 Microsoft 合作了几个星期的 Sev B 案例,并收到了一些提示,但仍然没有解决方案。3 级支持建议确保编译超时查询没有强制计划,因为计划强制允许 SQL 优化器花费比正常时间长 3 倍的时间进行编译,这会增加超时的可能性。唯一强制计划的是自动调整,它仅适用于 MI 的 FORCE_LAST_GOOD_PLAN 选项,请参阅https://learn.microsoft.com/en-us/sql/relational-databases/automatic-tuning/automatic-tuning?view=sql-server-ver16和https://learn.microsoft.com/en-us/azure/azure-sql/database/automatic-tuning-overview?view=azuresql。我们根据他们的建议关闭了 FORCE_LAST_GOOD_PLAN,这有助于解决一些较长的编译时间问题,但不是全部。我们不会使用计划指南 (USE PLAN N'<xml_plan>') 强制执行计划,也不会在查询存储中手动强制执行。他们建议调整查询以降低其复杂性,如果关闭 FORCE_LAST_GOOD_PLAN 不起作用,则运行 DUMP。我希望安排与他们的性能团队进行工作会议来解决这些问题。

更新:在 5 月 28 日与 3 级支持人员通话期间,我们注意到,即使是 SELECT COUNT(*) FROM Table 等一些简单查询也使用了 OptimizationLevel = FULL 而不是 TRIVIAL。3 级支持人员表示,我们无法更改任何设置来影响这一点,但会向产品团队提及此事。

  1. 与 SQL 2016 Std Ed 中的相同代码相比,我们的分区维护作业(执行 ALTER PARTITION SPLIT)在 MI BusCrit 中的运行时间更长(几天到几周) 。它还会在处理过程中占用数据(和日志)文件中大量额外的使用空间,而这在 SQL 2016 中不会发生,例如在作业运行时,52 GB 的数据库增长到 588 GB!膨胀(和性能?)可能部分与加速数据库恢复 (ADR) 有关,因为它在 SQL 2019+ 和 AZ MI 中:Azure SQL 托管实例与本地 SQL Server 中的表大小(另请参阅https://learn.microsoft.com/en-us/sql/relational-databases/accelerated-database-recovery-concepts?view=sql-server-ver16)。

我们正在审查我们继承的算法,因为它似乎没有遵循https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-partition-function-transact-sql?view=sql-server-ver16中的最佳实践“始终在分区范围的两端保留空分区。保留两端的分区以确保分区拆分和分区合并不会引起任何数据移动。分区拆分发生在开始时,分区合并发生在结束时。避免拆分或合并已填充的分区。拆分或合并已填充的分区可能效率低下。它们效率低下,因为拆分或合并可能会导致多达四倍的日志生成,也可能导致严重的锁定。”但我们很困惑,为什么相同的代码在 MI 中运行时间更长,并且过度膨胀数据文件,而在 SQL 2016 Std Ed 中却没有。

我们考虑的另一个建议是使用 SQL 迁移到 Azure VM,但这将使我们的重新平台启动时间增加数月,以设置、测试和运行此环境,因为我们现在没有任何 Azure VM。我们还必须运行修补、备份等。

非常感谢你的帮助!Mike

execution-plan
  • 3 个回答
  • 305 Views
Martin Hope
supervisor
Asked: 2022-09-14 14:04:19 +0800 CST

为什么 SQL Server 在更新位列时扫描所有行,即使是通过链接服务器的主键

  • 9

我正在为 SQL 链接服务器的特定主键使用简单的更新语句,如下所示

UPDATE t
SET
    processed = 1,
    processed_on = GETDATE()
FROM [LINKED\SERVER].DATABASE.dbo.FileQueue t
WHERE t.FileId = '3b33eff6-fde1-4e8c-9c23-2dbd45f50222'

两台服务器都是 SQL Server 2019。表定义是

CREATE TABLE dbo.FileQueue
(
    FileId UNIQUEIDENTIFIER NOT NULL,
    Processed BIT NOT NULL,
    Processed_on DATETIME NULL
 CONSTRAINT PK_FileQueue PRIMARY KEY CLUSTERED 
 (
    FileId ASC
 )
)

Processed 列具有位类型。由于全表扫描,查询速度很慢。

查询计划

为什么会这样?当我从语句中删除位列时,一切正常,读取和更新单个远程行。

该Id列是聚集的主键。我有很多具有相似键的表。

我尝试了CONVERTorCAST函数,结果是一样的。

对于没有位列的查询,执行计划非常好。

UPDATE t
SET
    --processed = 1,
    -- any other columns can be added to be updated except bit
    processed_on = GETDATE()
FROM [LINKED\SERVER].DATABASE.dbo.FileQueue t
WHERE t.FileId = 'ABD4442F-8560-43B5-8B04-000000B2A626'

查询计划

sql-server execution-plan
  • 2 个回答
  • 550 Views
Martin Hope
Geezer
Asked: 2022-08-08 07:51:04 +0800 CST

SQL 所有的 Procs 都有 WITH RECOMPLILE 所以如何维护一个臃肿的计划缓存

  • 0

我正在使用在 Azure SQL 数据库中创建的星型模式数据仓库,其中最后一个开发人员包含WITH RECOMPILE在所有 Procs 中。

我认为这是因为 ETL 每天只执行这些 Procs 两次,因此重新编译的开销很小。

但是,是否存在缓存因所有这些计划而变得臃肿的风险,如果是这样,维护计划缓存以使其保持精简和尽可能高效的最佳方法是什么?

azure-sql-database execution-plan
  • 1 个回答
  • 33 Views
Martin Hope
Erik Darling
Asked: 2022-07-18 09:32:23 +0800 CST

为什么 SQL Server 可以准确地跟踪某些多语句表值函数查询计划而不是其他的时间?

  • 11

设置

对于这个演示,我使用的是2013 版本的 Stack Overflow 数据库和 SQL Server 2022 CTP2,但它可以追溯到 SQL Server 2017,这是我想检查的。

功能一

对于此函数,SQL Server 跟踪函数中花费的执行时间:

CREATE OR ALTER FUNCTION
    dbo.ScoreStats
(
    @UserId int
)
RETURNS
    @out table
    (
        TotalScore bigint
    )
WITH SCHEMABINDING
AS 
BEGIN

    INSERT
        @out
    (
        TotalScore
    )
    SELECT
        TotalScore = 
            SUM(x.Score)
    FROM 
    (
        SELECT
            Score = 
                SUM(p.Score)
        FROM dbo.Posts AS p
        WHERE p.OwnerUserId = @UserId

        UNION ALL

        SELECT
            Score = 
                SUM(c.Score)
        FROM dbo.Comments AS c
        WHERE c.UserId = @UserId    
    ) AS x;

    RETURN;

END;

这是查询和执行计划:

SELECT
    u.DisplayName,
    TotalScore = 
        (
            SELECT
                ss.TotalScore
            FROM dbo.ScoreStats(u.Id) AS ss
        )
FROM dbo.Users AS u
WHERE u.Reputation >= 1000000;

坚果

您可以看到,在查询计划和 Query Time Stats 属性中都准确地跟踪了时间。

功能二

这是第二个功能,它不会发生:

CREATE OR ALTER FUNCTION
    dbo.VoteStats()
RETURNS
    @out table
    (
        PostId int,
        UpVotes int,
        DownVotes int,
        UpMultipier AS 
             UpVotes * 2
    )
WITH SCHEMABINDING
AS 
BEGIN

    INSERT
        @out
    (
        PostId,
        UpVotes,
        DownVotes
    )
    SELECT
        v.PostId,
        UpVotes = 
            SUM
            (
                CASE v.VoteTypeId
                     WHEN 2
                     THEN 1
                     ELSE 0
                END
            ),
        DownVotes = 
            SUM
            (
                CASE v.VoteTypeId
                     WHEN 3
                     THEN 1
                     ELSE 0
                END
            )
    FROM dbo.Votes AS v
    GROUP BY 
        v.PostId;

    RETURN;

END;

这是查询和执行计划:

SELECT TOP (100)
     p.Id,
     vs.UpVotes,
     vs.DownVotes
FROM dbo.VoteStats() AS vs
JOIN dbo.Posts AS p
    ON vs.PostId = p.Id
WHERE vs.DownVotes > vs.UpMultipier
AND   p.CommunityOwnedDate IS NULL
AND   p.ClosedDate IS NULL
ORDER BY vs.UpVotes DESC;

坚果

在此查询中,时间没有在图形执行计划中准确跟踪,而是在 Query Time Stats 属性中进行跟踪。

MAXDOP 1 处的功能二

即使是强制连载,也无法准确跟踪时间:

SELECT TOP (100)
     p.Id,
     vs.UpVotes,
     vs.DownVotes
FROM dbo.VoteStats() AS vs
JOIN dbo.Posts AS p
    ON vs.PostId = p.Id
WHERE vs.DownVotes > vs.UpMultipier
AND   p.CommunityOwnedDate IS NULL
AND   p.ClosedDate IS NULL
ORDER BY vs.UpVotes DESC
OPTION(MAXDOP 1);

坚果

问题

回到手头的问题:为什么在一个查询计划中可以准确地跟踪时间,而在另一个查询计划中却没有?

sql-server execution-plan
  • 2 个回答
  • 773 Views
Martin Hope
Sylvia
Asked: 2022-06-07 08:01:11 +0800 CST

在我的查询计划中 - 多个节点说他们的成本是 100%

  • 0

在此查询计划中:

https://www.brentozar.com/pastetheplan/?id=HydtQjsO5

...多个节点的成本为 100%。这是怎么发生的?当如此多的节点具有一定是错误的成本时,您如何确定从哪里开始优化?是否有其他东西可以代替成本百分比?

sql-server execution-plan
  • 2 个回答
  • 82 Views
Martin Hope
Data Dill
Asked: 2022-06-03 10:22:21 +0800 CST

在并行位图哈希匹配计划中读取可能不正确的行数

  • 1

我正在尝试确定这是报告错误的执行计划还是按预期工作的实际功能。

在我的执行计划中,当使用 MAXDOP 1 时,我看到整个表正在被扫描(https://www.brentozar.com/pastetheplan/?id=HkPFquLdc - 计划对象 11 的最底部显示读取了大约 250 万行整个表)。

但是,当我让引擎在没有提示的情况下选择它自己的计划时,它会并行(https://www.brentozar.com/pastetheplan/?id=r12p5OUdc)并进行位图/哈希匹配,并且相同的 Object11 只显示〜尽管进行了索引扫描并且在不在聚集索引中的其他列上有一堆谓词,但仍读取了 534k 行。

我希望 SQL 必须读取表中的每一行来评估每个谓词,但也许并行计划中对象 11 上的 PROBE IN(您在粘贴计划中看不到这一点)能够“过滤掉页面" 因为探头在 PK/CX 上。

sql-server execution-plan
  • 1 个回答
  • 44 Views
Martin Hope
ahmed elbarbary
Asked: 2022-02-28 16:46:44 +0800 CST

何时从表中选择前 5 行需要太多时间?

  • 2

我在 sql server 2019 上工作,我在选择top 5 行时遇到问题,它需要太多时间。

表上的行数Z2DataCore.parts.SourcingNotMappedParts70 百万行。

当运行语句选择top 5它需要太多时间超过15 minutes。

那么如何让它更快

选择有问题的语句

SELECT top 5 GivenPartNumber_Non,vcompanyid
into #GetSupplierAndOther
FROM Z2DataCore.parts.SourcingNotMappedParts with(nolock)
Where  PriorityLevel in ('A3','A4') and vcompanyid is not null and sourcetypeid=484456
group by GivenPartNumber_Non,vcompanyid
having count(distinct sourcetypeid)=2

我估计的执行计划

https://www.brentozar.com/pastetheplan/?id=r1EPmqFx5

注意:我尝试在不使用的情况下选择上面的列,select into但仍然很慢。

示例表脚本和索引

CREATE TABLE [Parts].[SourcingNotMappedParts](
    [SourcingNotMappedPartsID] [int] IDENTITY(1,1) NOT NULL,
    [SearchPart] [nvarchar](200) NULL,
    [GivenManufacture] [nvarchar](200) NULL,
    [CompanyId] [int] NULL,
    [SourceTypeID] [int] NULL,
    [RevisionId] [bigint] NULL,
    [ExtractionDate] [date] NULL,
    [Taxonomy] [nvarchar](250) NULL,
    [PartStatus] [nvarchar](50) NULL,
    [Datasheet] [nvarchar](2000) NULL,
    [ROHS] [nvarchar](250) NULL,
    [StockId] [int] NULL,
    [SourceUrl] [nvarchar](2000) NULL,
    [Description] [nvarchar](2000) NULL,
    [CreatedBy] [int] NULL,
    [ModifiedBy] [int] NULL,
    [CreatedDate] [datetime] NULL,
    [ModifiedDate] [datetime] NULL,
    [Comment] [nvarchar](2000) NULL,
    [Reason] [nvarchar](2000) NULL,
    [PartId] [int] NULL,
    [GroupID] [int] NULL,
    [PartStatusID] [int] NULL,
    [ManufactureStatus] [int] NULL,
    [EditStatus] [int] NULL,
    [FamilyID] [int] NULL,
    [LookupId] [int] NULL,
    [ValidationReasonId] [int] NULL,
    [MatchStatus] [nvarchar](200) NULL,
    [GivenPartNumber_Non] [nvarchar](200) NULL,
    [GivenManufacturer_Non] [nvarchar](200) NULL,
    [signatureID] [int] NULL,
    [VCompanyId] [int] NULL,
    [PriorityLevel] [nvarchar](10) NULL,
    [NotMappedCode] [int] NULL,
    [PCPartStatus] [nvarchar](50) NULL,
 CONSTRAINT [PK_Parts.SourcingNotMappedParts] PRIMARY KEY CLUSTERED 
(
    [SourcingNotMappedPartsID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [Parts].[SourcingNotMappedParts] ADD  CONSTRAINT [DF_SourcingNotMappedParts_CreatedDate]  DEFAULT (getdate()) FOR [CreatedDate]
GO

ALTER TABLE [Parts].[SourcingNotMappedParts] ADD  CONSTRAINT [DF_SourcingNotMappedParts_ModifiedDate]  DEFAULT (getdate()) FOR [ModifiedDate]
GO

ALTER TABLE [Parts].[SourcingNotMappedParts] ADD  CONSTRAINT [PK_Parts.SourcingNotMappedParts] PRIMARY KEY CLUSTERED 
(
    [SourcingNotMappedPartsID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_NotMapped_SourceType] ON [Parts].[SourcingNotMappedParts]
(
    [SourceTypeID] ASC,
    [CompanyId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_NotMapped_PriorityLevel] ON [Parts].[SourcingNotMappedParts]
(
    [PriorityLevel] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_NotMapped_NonalphaPartCompany] ON [Parts].[SourcingNotMappedParts]
(
    [GivenPartNumber_Non] ASC,
    [VCompanyId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IDX_SourcingNotMappedParts_VCompanyId] ON [Parts].[SourcingNotMappedParts]
(
    [VCompanyId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
stored-procedures execution-plan
  • 2 个回答
  • 45 Views
Martin Hope
SEarle1986
Asked: 2022-01-28 15:11:23 +0800 CST

执行计划中的位图创建导致聚集索引扫描的错误估计

  • 6

鉴于 StackOverflow2010 数据库上的以下简单查询:

SELECT  u.DisplayName,
        u.Reputation
FROM    Users u
        JOIN Posts p
            ON u.id = p.OwnerUserId
WHERE   u.DisplayName = 'alex' AND
        p.CreationDate >= '2010-01-01' AND
        p.CreationDate <= '2010-03-01'

我试图理解为什么要创建索引

CREATE INDEX IX_CreationDate ON Posts
(
    CreationDate
)
INCLUDE (OwnerUserId)

产生更好的估计Posts.CreationDate

当我运行没有索引的查询时,我得到Plan 1。在这个计划中,SQL Server 估计有 298,910 行来自对 Posts 的 CI 扫描,实际上有 552 行回来了——这个估计还有很长的路要走。

添加索引后,我会得到Plan 2,这会导致索引搜索和更准确的估计。

我很好奇为什么添加索引会导致更好的估计,因为在谓词中使用列时会创建统计信息WHERE,无论它是否被索引。

进一步检查,我可以看到Posts.CreationDate计划 1 和计划 2 的谓词不同:

计划 1 谓词

[StackOverflow2010].[dbo].[Posts].[CreationDate] as [p].[CreationDate]>='2010-01-01 00:00:00.000' AND [StackOverflow2010].[dbo].[Posts].[CreationDate] as [p].[CreationDate]<='2010-03-01 00:00:00.000' AND PROBE([Bitmap1002],[StackOverflow2010].[dbo].[Posts].[OwnerUserId] as [p].[OwnerUserId],N'[IN ROW]')

计划 2 谓词

Seek Keys[1]: Start: [StackOverflow2010].[dbo].[Posts].CreationDate >= Scalar Operator('2010-01-01 00:00:00.000'), End: [StackOverflow2010].[dbo].[Posts].CreationDate <= Scalar Operator('2010-03-01 00:00:00.000')

所以我可以看到计划 2 只是要使用直方图来查找两个日期之间的行数,但计划 1 有一个稍微复杂的谓词,涉及位图探测。

这(我认为)解释了为什么对搜索的估计更准确,但我现在想知道什么是位图探测?我可以在计划中看到创建了一个与 Alex 谓词匹配的用户 ID 的位图,这就是正在调查的内容。

我想知道“没有索引,为什么计划 1 与计划 2 不同,唯一的区别是 CI 扫描而不是 CreationDate 上的索引搜索?”

我做了一些进一步的测试,发现如果我在没有索引的情况下运行查询但强制计划进入串行,使用OPTION (MAXDOP 1)我得到计划 3,尽管现在对 Posts 进行 CI 扫描,但它对 CreationDate 的估计更好。如果我查看谓词,我可以看到探针现在已经消失并且位图不再在计划中,因此这使我相信位图与计划并行有关。

所以我的问题是 - 为什么在计划并行时会创建位图,为什么会导致对 的估计如此糟糕Posts.CreationDate?

sql-server execution-plan
  • 1 个回答
  • 529 Views
Martin Hope
Vadim Samokhin
Asked: 2022-01-24 03:57:59 +0800 CST

Postgresql 10:具有精确堆块的位图堆扫描

  • 2

我有以下查询:

select ro.*
from courier c1
    join courier c2 on c2.real_physical_courier_1c_id = c1.real_physical_courier_1c_id
    join restaurant_order ro on ro.courier_id = c2.id
    left join jsonb_array_elements(items) jae on true
    left join jsonb_array_elements(jae->'options') ji on true
    inner join catalogue c on c.id in ((jae->'id')::int, (ji->'id')::int)
    join restaurant r on r.id = ro.restaurant_id
where c1.id = '7b35cdab-b423-472a-bde1-d6699f6cefd3' and ro.status in (70, 73)
group by ro.order_id, r.id ;

这是查询计划的一部分,它需要大约 95% 的时间:

->  Parallel Bitmap Heap Scan on restaurant_order ro  (cost=23.87..2357.58 rows=1244 width=1257) (actual time=11.931..38.163 rows=98 loops=2)"
      Recheck Cond: (status = ANY ('{70,73}'::integer[]))"
      Heap Blocks: exact=28755"
      ->  Bitmap Index Scan on ro__status  (cost=0.00..23.34 rows=2115 width=0) (actual time=9.168..9.168 rows=51540 loops=1)"
            Index Cond: (status = ANY ('{70,73}'::integer[]))"

我有一些问题。

  1. 首先是位图索引扫描部分。Postgres 遍历 51540 条 ro__status 索引记录,Index Cond: (status = ANY ('{70,73}'::integer[]))"并创建一个包含 28755 个元素的位图。它的键是对应表行的物理位置(exact在Heap Blocks节中表示)。这个对吗?
  2. 其次,这张图被传递到 Bitmap Heap Scan 阶段。Recheck Cond实际上并没有执行,因为堆块不是有损样式。位图堆扫描按元组的物理位置对位图进行排序,以启用顺序访问。然后它分两次依次读取表数据 ( loops=2) 并获得不超过 196 个表行。那是对的吗?
  3. 线中反映的位图大小Heap Blocks: exact=28755随时间变化很大。差异是两个数量级。比如昨天是500左右,为什么会这样?
  4. 现在,为什么在位图索引扫描阶段创建的位图有这么多键?有 ro__status 索引可以表明只有大约 200 条状态为 70 和 73 的记录。我想不出任何原因阻止 postgres 只保留那些实际满足index cond. 开销似乎很大:而不是约 200 个键,而是 28755 个!
  5. 为什么位图堆扫描需要这么长时间?据我所知,有两次顺序读取(loops=2),它应该花费更少的时间,不是吗?或者,按元组的物理位置排序的位图是罪魁祸首吗?
  6. 我应该担心估计不佳吗?如果是这样,增加 default_statistics_target 应该会有所帮助,对吧?现在默认为 100。

以防万一,这是一个完整的计划:

"Group  (cost=51297.15..52767.65 rows=19998 width=1261) (actual time=42.555..42.555 rows=0 loops=1)"
"  Group Key: ro.order_id, r.id"
"  ->  Gather Merge  (cost=51297.15..52708.83 rows=11764 width=1261) (actual time=42.554..45.459 rows=0 loops=1)"
"        Workers Planned: 1"
"        Workers Launched: 1"
"        ->  Group  (cost=50297.14..50385.37 rows=11764 width=1261) (actual time=38.850..38.850 rows=0 loops=2)"
"              Group Key: ro.order_id, r.id"
"              ->  Sort  (cost=50297.14..50326.55 rows=11764 width=1261) (actual time=38.850..38.850 rows=0 loops=2)"
"                    Sort Key: ro.order_id, r.id"
"                    Sort Method: quicksort  Memory: 25kB"
"                    Worker 0:  Sort Method: quicksort  Memory: 25kB"
"                    ->  Nested Loop  (cost=31.84..45709.27 rows=11764 width=1261) (actual time=38.819..38.819 rows=0 loops=2)"
"                          ->  Nested Loop Left Join  (cost=27.21..5194.50 rows=5882 width=1325) (actual time=38.819..38.819 rows=0 loops=2)"
"                                ->  Nested Loop Left Join  (cost=27.20..5076.49 rows=59 width=1293) (actual time=38.818..38.818 rows=0 loops=2)"
"                                      ->  Nested Loop  (cost=27.20..5074.49 rows=1 width=1261) (actual time=38.818..38.818 rows=0 loops=2)"
"                                            ->  Hash Join  (cost=26.93..5073.59 rows=1 width=1257) (actual time=38.817..38.818 rows=0 loops=2)"
"                                                  Hash Cond: (c2.real_physical_courier_1c_id = c1.real_physical_courier_1c_id)"
"                                                  ->  Nested Loop  (cost=24.28..5068.22 rows=1038 width=1267) (actual time=11.960..38.732 rows=98 loops=2)"
"                                                        ->  Parallel Bitmap Heap Scan on restaurant_order ro  (cost=23.87..2357.58 rows=1244 width=1257) (actual time=11.931..38.163 rows=98 loops=2)"
"                                                              Recheck Cond: (status = ANY ('{70,73}'::integer[]))"
"                                                              Heap Blocks: exact=28755"
"                                                              ->  Bitmap Index Scan on ro__status  (cost=0.00..23.34 rows=2115 width=0) (actual time=9.168..9.168 rows=51540 loops=1)"
"                                                                    Index Cond: (status = ANY ('{70,73}'::integer[]))"
"                                                        ->  Index Scan using courier_pkey on courier c2  (cost=0.41..2.18 rows=1 width=26) (actual time=0.005..0.005 rows=1 loops=195)"
"                                                              Index Cond: (id = ro.courier_id)"
"                                                  ->  Hash  (cost=2.63..2.63 rows=1 width=10) (actual time=0.039..0.039 rows=1 loops=2)"
"                                                        Buckets: 1024  Batches: 1  Memory Usage: 9kB"
"                                                        ->  Index Scan using courier_pkey on courier c1  (cost=0.41..2.63 rows=1 width=10) (actual time=0.034..0.034 rows=1 loops=2)"
"                                                              Index Cond: (id = '7b35cdab-b423-472a-bde1-d6699f6cefd3'::uuid)"
"                                            ->  Index Only Scan using restaurant_pkey on restaurant r  (cost=0.27..0.89 rows=1 width=4) (never executed)"
"                                                  Index Cond: (id = ro.restaurant_id)"
"                                                  Heap Fetches: 0"
"                                      ->  Function Scan on jsonb_array_elements jae  (cost=0.00..1.00 rows=100 width=32) (never executed)"
"                                ->  Function Scan on jsonb_array_elements ji  (cost=0.01..1.00 rows=100 width=32) (never executed)"
"                          ->  Bitmap Heap Scan on catalogue c  (cost=4.63..6.87 rows=2 width=4) (never executed)"
"                                Recheck Cond: ((id = ((jae.value -> 'id'::text))::integer) OR (id = ((ji.value -> 'id'::text))::integer))"
"                                ->  BitmapOr  (cost=4.63..4.63 rows=2 width=0) (never executed)"
"                                      ->  Bitmap Index Scan on catalogue_pkey  (cost=0.00..0.97 rows=1 width=0) (never executed)"
"                                            Index Cond: (id = ((jae.value -> 'id'::text))::integer)"
"                                      ->  Bitmap Index Scan on catalogue_pkey  (cost=0.00..0.97 rows=1 width=0) (never executed)"
"                                            Index Cond: (id = ((ji.value -> 'id'::text))::integer)"
"Planning Time: 1.113 ms"
"Execution Time: 45.588 ms"
postgresql execution-plan
  • 1 个回答
  • 307 Views
Martin Hope
mj_
Asked: 2021-11-06 12:56:25 +0800 CST

postgres 实际上是如何获得一些列的?执行计划问题

  • 0

我有一张有一堆列的桌子。其中facility_id和po_date。我正在编写一个复杂的查询,并且我在这两列上有一个索引。您可以从下面的计划器输出中看到 Postgres 在加入我的facility表时使用该索引作为索引条件。

我的问题实际上是关于Filter:下面一行中列举的列的存在。exclude, verified, 并且deleted不在顶部引用的索引中,那么 Postgres 是如何实际获取这些列中的数据的呢?我本来希望明确引用全表扫描,但是在任何地方都看不到。全表扫描可以悄悄地隐藏在一个中Filter吗?

该表大小为 50M 行,我使用的是 Postgres 10。此外,这部分查询位于 CTE 中。

->  Index Scan using clustered_table_facility_id_po_date_idx on clustered_table cp  (cost=0.56..1401.08 rows=31929 width=37) (actual time=0.021..5.331 rows=9572 loops=3640)
      Index Cond: (facility_id = af.id)
      Filter: ((NOT exclude) AND (verified IS NULL) AND (deleted IS NULL))
      Rows Removed by Filter: 2819
postgresql execution-plan
  • 1 个回答
  • 47 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve