gpt4 book ai didi

SQL CTE 与临时表

转载 作者:行者123 更新时间:2023-12-02 23:01:44 37 4
gpt4 key购买 nike

我在这里遇到了一点困难。我的主要目标是能够在 C# 和 Entity Framework 中使用它,而我们的高层指令是远离存储过程。

我有 2 个表:一个外部参照和一个 (Celko) 树表。

/**
** Table [dbo].[EntityXref]
**/
IF EXISTS(SELECT * FROM sys.tables WHERE name = N'EntityXref' AND type = N'U')
DROP TABLE [dbo].[EntityXref]
GO
CREATE TABLE dbo.[EntityXref]
( Id BIGINT IDENTITY(1,1) NOT NULL
, EntityId INT NOT NULL
, EntityTypeId INT NOT NULL
, ChildEntityId INT NOT NULL
, ChildEntityTypeId INT NOT NULL
, CONSTRAINT [PK_EntityXref] PRIMARY KEY NONCLUSTERED ([Id] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
, CONSTRAINT [UQ_EntityXref] UNIQUE CLUSTERED (EntityId, EntityTypeId, ChildEntityId, ChildEntityTypeId)
)


/**
** Table [dbo].[EntityTree]
**/
IF EXISTS(SELECT * FROM sys.tables WHERE name = N'EntityTree' AND type = N'U')
DROP TABLE dbo.EntityTree
GO
CREATE TABLE dbo.EntityTree
( Id BIGINT IDENTITY(1,1) NOT NULL
, SystemId INT NOT NULL DEFAULT 1
, EntityId INT NOT NULL -- could be an AgencyId, UserId, ClientId, VendorId, etc
, EntityTypeId INT NOT NULL -- Defines the entity type
, isActive BIT NOT NULL
, lft BIGINT NOT NULL
, rgt BIGINT NOT NULL
, CONSTRAINT [PK_EntityTree] PRIMARY KEY CLUSTERED ([Id] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
, CONSTRAINT [UQ_Entity] UNIQUE NONCLUSTERED (EntityId, EntityTypeId)
, CONSTRAINT [UQ_Left] UNIQUE NONCLUSTERED ([lft])
, CONSTRAINT [UQ_LeftRight] UNIQUE NONCLUSTERED ([lft], [rgt])
)
GO

基本树数据如下所示:

Customer -> Agencies -> Users -> Clients

我们还有管理多个机构的用户,因此有外部引用(不良名称)表。我正在对一个拥有 98% 代理机构概览的用户进行测试,我需要所有客户。所以,我的难题是:

注意:

  • EntityTypeId = 7 --> 用于生成报告的用户帐户
  • EntityTypeId = 4 --> 客户帐户

这需要 4 秒才能运行,但无法表示为 View :

DECLARE @t TABLE
( childentityid INT
, childentitytypeid INT
)

INSERT INTO @t
SELECT et.RootEntityId, et.RootEntityTypeId
FROM dbo.EntityXref et
WHERE et.EntityId = 17088 AND et.EntityTypeId = 7

SELECT *
FROM @t a
INNER JOIN dbo.GetMyCaseLoad b ON a.RootEntityId = b.ParentEntityId AND a.RootEntityTypeId = b.ParentEntityTypeId
GO

这需要 36-40 秒才能运行(此连接有几种不同的排列!)

WITH xrefParent (parentEntityId, parentEntityTypeId)    --, rootEntityId, rootEntityTypeId)
AS (SELECT ChildEntityId, ChildEntityTypeId /*, EntityId, EntityTypeId */ FROM dbo.EntityXref WHERE EntityId = 17088 AND EntityTypeId = 7)
SELECT *
FROM GetMyCaseLoad cl
INNER JOIN xrefParent p ON cl.ParentEntityId = p.parentEntityId AND cl.ParentEntityTypeId = p.parentEntityTypeId
-- WHERE p.rootEntityId = 17088 AND p.rootEntityTypeId = 7
GO

关于如何将临时表的好处放入 View 中以供 Entity Framework 使用,有什么想法吗?

<小时/>

添加定义:

CREATE VIEW GetMyCaseLoad AS
SELECT Parent.Id [ParentRecordId]
, Parent.EntityId [ParentEntityId]
, Parent.EntityTypeId [ParentEntityTypeId]
, Child.SystemId [ChildSystemId]
, Child.Id [ChildRecordId]
, Child.EntityId [ChildEntityId]
, Child.EntityTypeId [ChildEntityTypeId]
, Child.isActive [ChildIsActive]
, Child.lft [ChildLeft]
, Child.rgt [ChildRight]
FROM dbo.EntityTree Parent
, dbo.EntityTree Child
WHERE Child.lft > Parent.lft
AND Child.rgt < Parent.rgt
AND Child.EntityTypeId = 4
GO


CREATE VIEW GetMyFullCaseLoad AS
SELECT x.Id [XrefRecordId]
, x.EntityId [XrefParentEntityId]
, x.EntityTypeId [XrefParentEntityTypeId]
, c.ParentRecordId
, c.ParentEntityId
, c.ParentEntityTypeId
, c.ChildRecordId
, c.ChildEntityId
, c.ChildEntityTypeId
, c.ChildIsActive
, c.ChildLeft
, c.ChildRight
, x.CanRead
, x.CanWrite
FROM EntityXref x
INNER JOIN dbo.GetMyCaseLoad c ON x.ChildEntityId = c.ParentEntityId AND x.ChildEntityTypeId = c.ParentEntityTypeId
GO

第二个 View 是我们正在努力加快的速度。

旁注:当前系统大约需要 2-3 分钟才能恢复记录。第二个 View 或 CTE 基于新的数据结构(邻接树与集合树)在 40 秒内完成。使用临时表 4 秒。

最佳答案

CTE 的问题是它们没有具体化,它们没有专用的统计信息(它们依赖于底层对象的统计信息),它们没有索引(尽管在某些情况下它们可以在引用的表上使用索引) .

临时表的优点是它们本质上是物化的(在 tempdb 中),它们可以有索引(如果您定义它们)并且绝对有专用的统计信息。

在很多情况下,这意味着使用临时表而不是 CTE 可以产生更好的执行计划。使用 CTE 几乎永远不会加快速度,而在很多情况下使用临时表却可以。

我会服从比我更高的权威,并给你留下他的引言:

A CTE should never be used for performance. You will almost never speed things up by using a CTE because it's just a disposable view. You can do some neat things with them but speeding up a query isn't really one of them.

这句话来自accepted answer问题“CTE 和临时表有什么区别?”

PS:我发现您在第一个查询中使用了 TABLE 变量。这与临时表不同。就性能而言,临时表几乎总是优于 TABLE 变量。有关 TABLE 变量和临时表之间差异的好文章,请阅读此 accepted answer关于问题“SQL Server 中的临时表和表变量有什么区别?”。

关于SQL CTE 与临时表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35020883/

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