我们已经在COMPATIBILITY_LEVEL <120中运行数据库已有一段时间了,因为我们无法查明为什么某些查询的运行速度非常慢。我不是觉得这是解决covid-19无聊问题的完美方法,因此我尝试解决新的CE(嗯...不再那么新)的问题。
因此,我得到了一个相当简单的查询,其中涉及3个表和2个表值参数
declare @spIDs as table (id int not null primary key); INSERT INTO @spIDs values(1),(2); -- 169 in my sql script DECLARE @subscriptionProductGroupMapping AS table ( subscriptionProductID int not null, groupID int not null, primary key(subscriptionProductID, groupID) ); INSERT INTO @subscriptionProductGroupMapping (subscriptionProductID, groupID) VALUES(101,101); -- 168 in my script SELECT [dbo].[User].[userID] FROM [dbo].[User] LEFT JOIN ( SELECT DISTINCT [UserValidThrough].userID FROM [dbo].[UserValidThrough] INNER JOIN @spIDs spIDs on(spIDs.id = [dbo].[UserValidThrough].subscriptionProductID) ) AS [uvt] ON [uvt].[userID] = [User].userID INNER JOIN ( SELECT DISTINCT userID FROM GroupMembership INNER JOIN @subscriptionProductGroupMapping as SPIAndGroup ON(GroupMembership.groupID = SPIAndGroup.groupID) ) gms ON(gms.userID = [User].userID) WHERE [User].permissionType NOT IN(8, 16, 32, 64, 128) AND [User].deleteDate IS NULL AND [User].userTypeID IN(@userTypeID_0) AND [uvt].[userID] IS NULL
当以兼容级别110运行此查询时,查询速度很快,少于0.3秒。当更改为兼容性级别120时,查询大约需要8-9秒才能执行! :(
[调查实际执行计划时,我发现有一个聚集索引查找分配了大约7秒的时间,因此我专注于该部分
我已经尝试将此查询分解为另一个Table值参数,然后该查询又很快了。但是,这意味着我必须在许多地方重写我的应用程序,我真的很想知道为什么这样做很慢以及如何处理。
任何人都可以阐明这个问题吗?
编辑2020-04-15 12:57 CET这是一个调试脚本,它复制了一个简化的方案:1.创建调试表和调试数据
create table temp_User ( userID int not null, -- Additional columns ommited for readability primary key (useriD) ); create table temp_UserValidThrough ( userID int not null, subscriptionProductID int not null, -- Additional columns ommited for readability primary key(userID, subscriptionProductID) ); create table temp_GroupMembership ( userID int not null, groupID int not null, primary key(userID, groupID) ); CREATE NONCLUSTERED INDEX temp_GroupMembership_GroupIDWithUserID ON [dbo].[temp_GroupMembership] ([groupID]) INCLUDE ([userID]) -- populate User -- populate UserValidThrough -- populate GroupMembership declare @noUsers as int = 120000; declare @noGroups as int = 400; SET NOCOUNT ON; declare @n as int = 0; while @n < @noUsers begin insert into temp_User values(@n); declare @rand as int = rand() * @noGroups; insert into temp_UserValidThrough VALUES(@n, @rand); insert into temp_GroupMembership VALUES(@n, @rand); SET @n = @n + 1; end;
- 此查询可以使用不同的COMPATIBILITY_LEVEL设置执行,并且性能会有很大差异。
DECLARE @userTypeID_0 AS Int;
SET @userTypeID_0 = '1';
declare @spIDs as table (id int not null primary key);
insert into @spIDs
select distinct groupID from temp_GroupMembership;
DECLARE @subscriptionProductGroupMapping AS table
(
subscriptionProductID int not null,
groupID int not null,
primary key(subscriptionProductID, groupID)
);
insert into @subscriptionProductGroupMapping
SELECT
T.groupID as subscriptionProductID,
T.groupID
FROM
(select distinct groupID from temp_GroupMembership) AS T;
SELECT
[User].[userID]
FROM
[dbo].[temp_User] AS [User]
--LEFT JOIN
--(
-- SELECT DISTINCT [UserValidThrough].userID
-- FROM
-- [dbo].[UserValidThrough]
-- INNER JOIN @spIDs spIDs on(spIDs.id = [dbo].[UserValidThrough].subscriptionProductID)
--) AS [uvt] ON [uvt].[userID] = [User].userID
INNER JOIN
(
SELECT DISTINCT userID
FROM
temp_GroupMembership as GroupMembership
INNER JOIN
@subscriptionProductGroupMapping as SPIAndGroup ON(GroupMembership.groupID = SPIAndGroup.groupID)
) gms ON(gms.userID = [User].userID)
WHERE
--[User].permissionType NOT IN(8, 16, 32, 64, 128) AND
--[User].deleteDate IS NULL AND
--[User].userTypeID IN(@userTypeID_0) AND
NOT EXISTS
(
SELECT DISTINCT [UserValidThrough].userID
FROM
[dbo].[UserValidThrough]
--INNER JOIN @spIDs spIDs on(spIDs.id = [dbo].[UserValidThrough].subscriptionProductID)
WHERE
[UserValidThrough].userID = [User].userID
AND
[UserValidThrough].subscriptionProductID IN(SELECT id from @spIDs)
)
--[uvt].[userID] IS NULL
declare @lvl as varchar (10) = (SELECT compatibility_level FROM sys.databases WHERE name = DB_NAME());
print 'COMPATIBILITY_LEVEL: ' + @lvl
-- COMPATIBILITY_LEVEL 110 time: average 242 ms
-- COMPATIBILITY_LEVEL 120 time: average 40 s! (200 times slower!)
我们已经在COMPATIBILITY_LEVEL <120中运行数据库已有一段时间了,因为我们无法查明为什么某些查询的运行速度非常慢。不,我觉得这是对covid-19的完美治疗方法...
尝试一下: