【发布时间】:2020-03-29 09:01:14
【问题描述】:
我已经为此苦苦挣扎了一段时间。
我有一个包含三个表的数据库(每个表都有数百万条记录),如下所示(为简单起见,删除了一些列):
1.[Entity]
[Id] UNIQUEIDENTIFIER PK,
[EntityLevel_Id] UNIQUEIDENTIFIER NOT NULL FK [EntityLevel] ([Id])
2.[EntityData]
[Id] UNIQUEIDENTIFIER PK,
[Entity_Id] UNIQUEIDENTIFIER NOT NULL FK [Entity] ([Id]),
[DataLanguage_Id] UNIQUEIDENTIFIER NOT NULL FK [Language] ([Id]),
[Code] NVARCHAR (250) NOT NULL
3.[EntityLevel]
[Id] UNIQUEIDENTIFIER PK,
[Sort] INT NOT NULL
存在索引如下
[IX_Entity_EntityLevelId] ON [Entity] ([EntityLevel_Id])
[IX_EntityData_EntityId] ON [EntityData] ([Entity_Id])
[IX_EntityData_DataLanguageId_Code] ON [EntityData] ([DataLanguage_Id], [Code])
[IX_EntityLevel_Sort] ON [EntityLevel] ([Sort])
为了排除速度慢是因为选择的列的可能性,我只选择了一个固定值
以下查询运行速度非常快(不到 1 秒):
SELECT TOP 20
1
FROM
[Entity]
INNER JOIN [EntityData] ON [Entity].[Id] = [EntityData].[Entity_Id]
INNER JOIN [EntityLevel] ON [Entity].[EntityLevel_Id] = [EntityLevel].[Id]
WHERE
[EntityData].[DataLanguage_Id] = 'B6930015-F177-4ED3-97B0-AAEF401F9265'
以下查询也运行得非常快:
SELECT TOP 20
1
FROM
[Entity]
INNER JOIN [EntityData] ON [Entity].[Id] = [EntityData].[Entity_Id]
INNER JOIN [EntityLevel] ON [Entity].[EntityLevel_Id] = [EntityLevel].[Id]
WHERE
[EntityData].[DataLanguage_Id] = 'B6930015-F177-4ED3-97B0-AAEF401F9265'
ORDER BY
[EntityData].[Code] ASC
以下内容也运行得很快:
SELECT TOP 20
1
FROM
[Entity]
INNER JOIN [EntityData] ON [Entity].[Id] = [EntityData].[Entity_Id]
INNER JOIN [EntityLevel] ON [Entity].[EntityLevel_Id] = [EntityLevel].[Id]
WHERE
[EntityLevel].[Sort] = 1
但是,以下查询运行非常慢(大约 10 秒):
SELECT TOP 20
1
FROM
[Entity]
INNER JOIN [EntityData] ON [Entity].[Id] = [EntityData].[Entity_Id]
INNER JOIN [EntityLevel] ON [Entity].[EntityLevel_Id] = [EntityLevel].[Id]
WHERE
[EntityData].[DataLanguage_Id] = 'B6930015-F177-4ED3-97B0-AAEF401F9265'
AND
[EntityLevel].[Sort] = 1
ORDER BY
[EntityData].[Code]
我不知道原因,也找不到任何方法来应用更多索引以使查询运行得更快
感谢任何帮助!
编辑: 以下查询也运行得很快:
SELECT TOP 20
1
FROM
[Entity]
INNER JOIN [EntityData] ON [Entity].[Id] = [EntityData].[Entity_Id]
INNER JOIN [EntityLevel] ON [Entity].[EntityLevel_Id] = [EntityLevel].[Id]
WHERE
[EntityData].[DataLanguage_Id] = 'B6930015-F177-4ED3-97B0-AAEF401F9265'
AND
[EntityLevel].[Sort] = 1
和
SELECT TOP 20
1
FROM
[Entity]
INNER JOIN [EntityData] ON [Entity].[Id] = [EntityData].[Entity_Id]
INNER JOIN [EntityLevel] ON [Entity].[EntityLevel_Id] = [EntityLevel].[Id]
WHERE
[EntityLevel].[Sort] = 1
ORDER BY
[EntityData].[Code]
只有 order by 和两个过滤器才会出现问题
【问题讨论】:
-
sort=1是普通过滤器吗?过滤索引将对此有所帮助。请注意,您在这里使用的 EAV 数据库以性能和可伸缩性问题而闻名 -
sort=1 不是常用过滤器,按排序过滤很常见,但值不常见,我不明白的是它只是普通连接,查询运行速度非常快,有几个条件但使用 order by 和两个过滤器会减慢速度
-
它使用了不同的查询计划。当您观察它们并尝试找出它为什么这样做时,您通常可以修复它。通常只是更新统计数据就可以解决问题。有时问题是参数嗅探
-
好的,只是重读,它已缩小到
order by code?代码不是任何索引中的前导列,所以我猜顺序(总是一个昂贵的操作)是问题所在。聚集索引通常会按性能问题修复顺序,但您只会得到一个。 -
我必须再次评论 EAV 设计和 guid pk。对于开发人员来说,这似乎是一个绝妙的想法,但对于 DBA 来说却不是。
标签: sql sql-server indexing query-performance