我拼命想要更快地看到我的观点。我正在查看的数据是位置表。每个位置(根节点除外)都有一个ParentID,这是一个自连接。
该表有40K行。我试图添加一个好的覆盖索引。但是当选择单行时,我得到250ms的响应。我已经检查了查询计划,除了很多2%的项目(100%的时间加入)之外,没有任何突出的东西。
为了获得帮助,我创建了一个脚本,用于创建一个非常相似的表格(由于隐私,仅限'描述'更改)。它具有相同的索引和表结构。它也有我使用的相同视图。
视图为每个唯一位置返回一行。 该视图还具有正在查看的位置名称。
该文件包含所有数据 - 所以40K行......并且是4.5Meg。运行时需要4分钟才能插入确切的数据。
我在这里托管了SQL脚本。它是40K线,所以......我认为这是最好的。 https://1drv.ms/u/s!Avhw2DacCYPugsJckaO-Mo9cwNTLpA
无论如何都要让这个观点更快。我真的看着50ms以下 - 希望更少。
我已经想到了一个索引视图,但是当我使用UNION时,我无法做到。如果我使用递归CTE,那就是UNION,所以再一次,不能。我认为我的索引是合适的,但不能提供我需要的性能。
我还有其他方法可以提高视图效果吗?
全部在SQL文件中,但这是主要结构。
folderIdFromCalendar = new FolderId(WellKnownFolderName.Calendar, username);
CalendarFolder calendar = CalendarFolder.Bind(service, folderIdFromCalendar , new PropertySet());
我尝试了这样的CTE,但响应时间似乎已经衰退了。
CREATE TABLE MyLocations
(
Id INT NOT NULL PRIMARY KEY,
ParentId INT NULL,
Description VARCHAR(100) NOT NULL,
IsDeleted BIT NOT NULL,
LocationLevel INT NOT NULL
)
ALTER TABLE MyLocations ADD CONSTRAINT fk_Loop FOREIGN KEY (ParentId) REFERENCES MyLocations(Id)
CREATE NONCLUSTERED INDEX [IX_Location_LocationType] ON [dbo].[MyLocations]
(
[LocationLevel] 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_Location_ParentLocationId_INCLUDES] ON [dbo].[MyLocations]
(
[ParentId] ASC
)
INCLUDE ( [Id],
[Description],
[LocationLevel],
[IsDeleted]) 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
SET NOCOUNT ON
GO
CREATE VIEW [dbo].[vwMyLocations]
WITH SchemaBinding
AS
/*
SELECT * FROM vwMyLocations
*/
WITH cte AS
(
SELECT
l1.Id as LocationId,
l1.LocationLevel,
l1.ParentId,
l1.Description AS thisLocationName,
l1.IsDeleted,
l1.Description AS Level1,
NULL AS Level2,
NULL AS Level3,
NULL AS Level4,
NULL AS Level5,
NULL AS Level6,
NULL AS Level7,
NULL AS Level8,
NULL AS Level9,
NULL AS Level10
FROM [dbo].MyLocations l1
WHERE l1.LocationLevel = 1
UNION ALL
SELECT
l2.Id AS LocationId,
l2.LocationLevel,
l2.ParentId,
l2.Description AS thisLocationName,
l1.IsDeleted | l2.IsDeleted,
l1.Description AS Level1,
l2.Description AS Level2,
NULL AS Level3,
NULL AS Level4,
NULL AS Level5,
NULL AS Level6,
NULL AS Level7,
NULL AS Level8,
NULL AS Level9,
NULL AS Level10
FROM [dbo].MyLocations l1
INNER JOIN [dbo].MyLocations l2
ON l2.ParentId = l1.Id
WHERE l2.LocationLevel = 2
UNION ALL
SELECT
l3.Id AS LocationId,
l3.LocationLevel,
l3.ParentId,
l3.Description AS thisLocationName,
l1.IsDeleted | l2.IsDeleted | l3.IsDeleted,
l1.Description AS Level1,
l2.Description AS Level2,
l3.Description AS Level3,
NULL AS Level4,
NULL AS Level5,
NULL AS Level6,
NULL AS Level7,
NULL AS Level8,
NULL AS Level9,
NULL AS Level10
FROM [dbo].MyLocations l1
INNER JOIN [dbo].MyLocations l2
ON l2.ParentId = l1.Id
INNER JOIN [dbo].MyLocations l3
ON l3.ParentId = l2.Id
WHERE l3.LocationLevel = 3
UNION ALL
SELECT
l4.Id AS LocationId,
l4.LocationLevel,
l4.ParentId,
l4.Description AS thisLocationName,
l1.IsDeleted | l2.IsDeleted | l3.IsDeleted | l4.IsDeleted,
l1.Description AS Level1,
l2.Description AS Level2,
l3.Description AS Level3,
l4.Description AS Level4,
NULL AS Level5,
NULL AS Level6,
NULL AS Level7,
NULL AS Level8,
NULL AS Level9,
NULL AS Level10
FROM [dbo].MyLocations l1
INNER JOIN [dbo].MyLocations l2
ON l2.ParentId = l1.Id
INNER JOIN [dbo].MyLocations l3
ON l3.ParentId = l2.Id
INNER JOIN [dbo].MyLocations l4
ON l4.ParentId = l3.Id
WHERE l4.LocationLevel = 4
UNION ALL
SELECT
l5.Id AS LocationId,
l5.LocationLevel,
l5.ParentId,
l5.Description AS thisLocationName,
l1.IsDeleted | l2.IsDeleted | l3.IsDeleted | l4.IsDeleted | l5.IsDeleted,
l1.Description AS Level1,
l2.Description AS Level2,
l3.Description AS Level3,
l4.Description AS Level4,
l5.Description AS Level5,
NULL AS Level6,
NULL AS Level7,
NULL AS Level8,
NULL AS Level9,
NULL AS Level10
FROM [dbo].MyLocations l1
INNER JOIN [dbo].MyLocations l2
ON l2.ParentId = l1.Id
INNER JOIN [dbo].MyLocations l3
ON l3.ParentId = l2.Id
INNER JOIN [dbo].MyLocations l4
ON l4.ParentId = l3.Id
INNER JOIN [dbo].MyLocations l5
ON l5.ParentId = l4.Id
WHERE l5.LocationLevel = 5
UNION ALL
SELECT
l6.Id AS LocationId,
l6.LocationLevel,
l6.ParentId,
l6.Description AS thisLocationName,
l1.IsDeleted | l2.IsDeleted | l3.IsDeleted | l4.IsDeleted | l5.IsDeleted | l6.IsDeleted,
l1.Description AS Level1,
l2.Description AS Level2,
l3.Description AS Level3,
l4.Description AS Level4,
l5.Description AS Level5,
l6.Description AS Level6,
NULL AS Level7,
NULL AS Level8,
NULL AS Level9,
NULL AS Level10
FROM [dbo].MyLocations l1
INNER JOIN [dbo].MyLocations l2
ON l2.ParentId = l1.Id
INNER JOIN [dbo].MyLocations l3
ON l3.ParentId = l2.Id
INNER JOIN [dbo].MyLocations l4
ON l4.ParentId = l3.Id
INNER JOIN [dbo].MyLocations l5
ON l5.ParentId = l4.Id
INNER JOIN [dbo].MyLocations l6
ON l6.ParentId = l5.Id
WHERE l6.LocationLevel = 6
UNION ALL
SELECT
l7.Id AS LocationId,
l7.LocationLevel,
l7.ParentId,
l7.Description AS thisLocationName,
l1.IsDeleted | l2.IsDeleted | l3.IsDeleted | l4.IsDeleted | l5.IsDeleted | l6.IsDeleted | l7.IsDeleted,
l1.Description AS Level1,
l2.Description AS Level2,
l3.Description AS Level3,
l4.Description AS Level4,
l5.Description AS Level5,
l6.Description AS Level6,
l7.Description AS Level7,
NULL AS Level8,
NULL AS Level9,
NULL AS Level10
FROM [dbo].MyLocations l1
INNER JOIN [dbo].MyLocations l2
ON l2.ParentId = l1.Id
INNER JOIN [dbo].MyLocations l3
ON l3.ParentId = l2.Id
INNER JOIN [dbo].MyLocations l4
ON l4.ParentId = l3.Id
INNER JOIN [dbo].MyLocations l5
ON l5.ParentId = l4.Id
INNER JOIN [dbo].MyLocations l6
ON l6.ParentId = l5.Id
INNER JOIN [dbo].MyLocations l7
ON l7.ParentId = l6.Id
AND l7.LocationLevel = 7
UNION ALL
SELECT
l8.Id AS LocationId,
l8.LocationLevel,
l8.ParentId,
l8.Description AS thisLocationName,
l1.IsDeleted | l2.IsDeleted | l3.IsDeleted | l4.IsDeleted | l5.IsDeleted | l6.IsDeleted | l7.IsDeleted | l8.IsDeleted,
l1.Description AS Level1,
l2.Description AS Level2,
l3.Description AS Level3,
l4.Description AS Level4,
l5.Description AS Level5,
l6.Description AS Level6,
l7.Description AS Level7,
l8.Description AS Level8,
NULL AS Level9,
NULL AS Level10
FROM [dbo].MyLocations l1
INNER JOIN [dbo].MyLocations l2
ON l2.ParentId = l1.Id
INNER JOIN [dbo].MyLocations l3
ON l3.ParentId = l2.Id
INNER JOIN [dbo].MyLocations l4
ON l4.ParentId = l3.Id
INNER JOIN [dbo].MyLocations l5
ON l5.ParentId = l4.Id
INNER JOIN [dbo].MyLocations l6
ON l6.ParentId = l5.Id
INNER JOIN [dbo].MyLocations l7
ON l7.ParentId = l6.Id
INNER JOIN [dbo].MyLocations l8
ON l8.ParentId = l7.Id
WHERE l8.LocationLevel = 8
UNION ALL
SELECT
l9.Id AS LocationId,
l9.LocationLevel,
l9.ParentId,
l9.Description AS thisLocationName,
l1.IsDeleted | l2.IsDeleted | l3.IsDeleted | l4.IsDeleted | l5.IsDeleted | l6.IsDeleted | l7.IsDeleted | l8.IsDeleted | l9.IsDeleted,
l1.Description AS Level1,
l2.Description AS Level2,
l3.Description AS Level3,
l4.Description AS Level4,
l5.Description AS Level5,
l6.Description AS Level6,
l7.Description AS Level7,
l8.Description AS Level8,
l9.Description AS Level9,
NULL AS Level10
FROM [dbo].MyLocations l1
INNER JOIN [dbo].MyLocations l2
ON l2.ParentId = l1.Id
INNER JOIN [dbo].MyLocations l3
ON l3.ParentId = l2.Id
INNER JOIN [dbo].MyLocations l4
ON l4.ParentId = l3.Id
INNER JOIN [dbo].MyLocations l5
ON l5.ParentId = l4.Id
INNER JOIN [dbo].MyLocations l6
ON l6.ParentId = l5.Id
INNER JOIN [dbo].MyLocations l7
ON l7.ParentId = l6.Id
INNER JOIN [dbo].MyLocations l8
ON l8.ParentId = l7.Id
INNER JOIN [dbo].MyLocations l9
ON l9.ParentId = l8.Id
WHERE l9.LocationLevel = 9
UNION ALL
SELECT
l10.Id AS LocationId,
l10.LocationLevel,
l10.ParentId,
l10.Description AS thisLocationName,
l1.IsDeleted | l2.IsDeleted | l3.IsDeleted | l4.IsDeleted | l5.IsDeleted | l6.IsDeleted | l7.IsDeleted | l8.IsDeleted | l9.IsDeleted | l10.IsDeleted,
l1.Description AS Level1,
l2.Description AS Level2,
l3.Description AS Level3,
l4.Description AS Level4,
l5.Description AS Level5,
l6.Description AS Level6,
l7.Description AS Level7,
l8.Description AS Level8,
l9.Description AS Level9,
l10.Description AS Level10
FROM [dbo].MyLocations l1
INNER JOIN [dbo].MyLocations l2
ON l2.ParentId = l1.Id
INNER JOIN [dbo].MyLocations l3
ON l3.ParentId = l2.Id
INNER JOIN [dbo].MyLocations l4
ON l4.ParentId = l3.Id
INNER JOIN [dbo].MyLocations l5
ON l5.ParentId = l4.Id
INNER JOIN [dbo].MyLocations l6
ON l6.ParentId = l5.Id
INNER JOIN [dbo].MyLocations l7
ON l7.ParentId = l6.Id
INNER JOIN [dbo].MyLocations l8
ON l8.ParentId = l7.Id
INNER JOIN [dbo].MyLocations l9
ON l9.ParentId = l8.Id
INNER JOIN [dbo].MyLocations l10
ON l10.ParentId = l9.Id
WHERE l10.LocationLevel = 10
)
SELECT
cte.LocationId,
cte.LocationLevel,
cte.IsDeleted,
lt.DisplayName,
cte.ParentId,
cte.thisLocationName,
cte.Level1,
cte.Level2,
cte.Level3,
cte.Level4,
cte.Level5,
cte.Level6,
cte.Level7,
cte.Level8,
cte.Level9,
cte.Level10
FROM cte
INNER JOIN ref.LocationType lt
ON lt.Id = cte.LocationLevel
GO
答案 0 :(得分:1)
我认为此处不需要CTE
,因此您可以使用INTO
子句将所有数据存储在临时中,并从中选择最终查询。我相信它会最大限度地减少时间:但你必须管理它以保持某个地方,最终的查询只会写在视图中。
SELECT
l1.Id as LocationId,
l1.LocationLevel,
l1.ParentId,
l1.Description AS thisLocationName,
l1.IsDeleted,
l1.Description AS Level1,
NULL AS Level2,
NULL AS Level3,
NULL AS Level4,
NULL AS Level5,
NULL AS Level6,
NULL AS Level7,
NULL AS Level8,
NULL AS Level9,
NULL AS Level10
INTO #tmpLocation
FROM [dbo].MyLocations l1
WHERE l1.LocationLevel = 1
UNION ALL
---------
---------
UNION ALL
--------
--------
最终查询将是:
SELECT
cte.LocationId,
cte.LocationLevel,
cte.IsDeleted,
lt.DisplayName,
cte.ParentId,
cte.thisLocationName,
cte.Level1,
cte.Level2,
cte.Level3,
cte.Level4,
cte.Level5,
cte.Level6,
cte.Level7,
cte.Level8,
cte.Level9,
cte.Level10
FROM #tmpLocation cte
INNER JOIN ref.LocationType lt ON lt.Id = cte.LocationLevel
注意:您还可以在临时表的LocationLevel
列上添加索引
答案 1 :(得分:1)
由于你的等级有限,这可能会有所帮助
select LocationId = lc1.Id,
LocationLevel = lc1.LocationLevel,
IsDeleted = lc1.IsDeleted,
DisplayName = lt.DisplayName,
ParentId = lc1.ParentId,
thisLocationName = lc1.Description,
Level1 = coalesce( case when lc5.LocationLevel = 1 then lc5.Description end,
case when lc4.LocationLevel = 1 then lc4.Description end,
case when lc3.LocationLevel = 1 then lc3.Description end,
case when lc2.LocationLevel = 1 then lc2.Description end,
case when lc1.LocationLevel = 1 then lc1.Description end
),
Level2 = coalesce( case when lc5.LocationLevel = 2 then lc5.Description end,
case when lc4.LocationLevel = 2 then lc4.Description end,
case when lc3.LocationLevel = 2 then lc3.Description end,
case when lc2.LocationLevel = 2 then lc2.Description end,
case when lc1.LocationLevel = 2 then lc1.Description end
),
Level3 = coalesce( case when lc5.LocationLevel = 3 then lc5.Description end,
case when lc4.LocationLevel = 3 then lc4.Description end,
case when lc3.LocationLevel = 3 then lc3.Description end,
case when lc2.LocationLevel = 3 then lc2.Description end,
case when lc1.LocationLevel = 3 then lc1.Description end
),
Level4 = coalesce( case when lc5.LocationLevel = 4 then lc5.Description end,
case when lc4.LocationLevel = 4 then lc4.Description end,
case when lc3.LocationLevel = 4 then lc3.Description end,
case when lc2.LocationLevel = 4 then lc2.Description end,
case when lc1.LocationLevel = 4 then lc1.Description end
),
Level5 = coalesce( case when lc5.LocationLevel = 5 then lc5.Description end,
case when lc4.LocationLevel = 5 then lc4.Description end,
case when lc3.LocationLevel = 5 then lc3.Description end,
case when lc2.LocationLevel = 5 then lc2.Description end,
case when lc1.LocationLevel = 5 then lc1.Description end
)
from MyLocations lc1
left join MyLocations lc2 on lc1.ParentId = lc2.Id
left join MyLocations lc3 on lc2.ParentId = lc3.Id
left join MyLocations lc4 on lc3.ParentId = lc4.Id
left join MyLocations lc5 on lc4.ParentId = lc5.Id
left join MyLocations lc6 on lc5.ParentId = lc6.Id
left join MyLocations lc7 on lc6.ParentId = lc7.Id
left join MyLocations lc8 on lc7.ParentId = lc8.Id
left join MyLocations lc9 on lc8.ParentId = lc9.Id
left join MyLocations lc10 on lc9.ParentId = lc10.Id
inner join LocationType lt on lc1.LocationLevel = lt.Id