SQL 检测导致锁定/长查询的原因的策略
SQL Strategies for detecting what is causing a lock / long query
我有一个针对 Azure SQL 数据库的查询,偶尔会产生以下结果:
如果用户不多,就不会发生这种情况。但如果有,这种情况经常发生——查询需要很长时间才能完成,而且我的 DTU 百分比几乎超出了图表。
如何确定造成这种情况的原因?
一些一般信息:
- 我在应用程序的某些部分使用 dapper 作为 ORM
- 我在其他领域使用 EF
- 当它挂起时,它会挂起 >30 秒。很少是 1s < time < 30s
- 下面是挂起的小巧查询,其中
XXXX
是两种情况下大约 2,500 个项目 ID 的列表:
- 拥有一小部分
XXXX
ID 的用户似乎从来没有遇到过这个问题。 XXXX
的检索从来都不是问题 - 但使用大的 XXXX
有时似乎会降低性能。
- [User] 在 UserId (PK) 上建立索引,而 LastOnline
代码:
select USERID, USERNAME, NICKNAME, BIRTHDATE, LASTONLINE
from [User]
where AccountDisabled <> 1 and Banned <> 1 and
(ABOUTME <> '' OR ProvidedPhoto = 1) and
USERID <> @userId and ProvidedPhoto = 1 AND
USERID IN (-1) AND USERID NOT IN (-1)
AND USERID NOT IN (XXXX) UNION ALL
select * from (select USERID, USERNAME, NICKNAME, BIRTHDATE, LASTONLINE from [User] where
AccountDisabled <> 1 and
Banned <> 1 and (ABOUTME <> '' OR ProvidedPhoto = 1) and
USERID <> @userId and ProvidedPhoto = 1 AND USERID NOT IN (-1)
AND USERID NOT IN (XXXX) AND USERID NOT IN (-1)
order by LastOnline asc offset 0 rows fetch next + 20 rows only)
as dt
我对性能取证的世界有点陌生...任何建议都很棒。
更新 - 执行计划:
以下是您可以尝试的一些方法:
- 看看您是否可以通过将@UserID 作为参数传递来为return 您所需的列表创建一个存储过程。调用此存储过程而不是每次都生成查询。
将 NOT IN 替换为 NOT EXISTS,如下所示。首先检查这是否有帮助。这在很大程度上取决于 USERID 列中的值。
SELECT USERID,USERNAME,NICKNAME,BIRTHDATE,LASTONLINE
FROM [User]
WHERE AccountDisabled <> 1
AND Banned <> 1
AND (
ABOUTME <> ''
OR ProvidedPhoto = 1
)
AND USERID <> @userId
AND ProvidedPhoto = 1
AND USERID IN (- 1) --How will these two conditions ever be true together?
AND USERID NOT IN (- 1) --Be sure about your conditions
AND NOT EXISTS (SELECT USERID FROM [USER] U2 WHERE U1.USERID = U2.USERID)
UNION ALL
SELECT *
FROM ( SELECT USERID,USERNAME,NICKNAME,BIRTHDATE,LASTONLINE
FROM [User] U1
WHERE AccountDisabled <> 1
AND Banned <> 1
AND (
ABOUTME <> ''
OR ProvidedPhoto = 1
)
AND USERID <> @userId
AND ProvidedPhoto = 1
AND USERID NOT IN (- 1)
AND NOT EXISTS (SELECT USERID FROM [USER] U2 WHERE U1.USERID = U2.USERID)
-- AND USERID NOT IN (- 1) WHY AGAIN??
ORDER BY LastOnline ASC offset 0 rows FETCH NEXT + 20 rows ONLY
) AS dt
您可能还考虑在 WHERE 子句中的其他列上创建非聚集索引。您能否也显示查询的执行计划? (方法:在 SQL 查询编辑器中,按 CTRL+M,然后执行您的查询。您将获得一个执行计划以及结果。)
我有一个针对 Azure SQL 数据库的查询,偶尔会产生以下结果:
如果用户不多,就不会发生这种情况。但如果有,这种情况经常发生——查询需要很长时间才能完成,而且我的 DTU 百分比几乎超出了图表。
如何确定造成这种情况的原因?
一些一般信息:
- 我在应用程序的某些部分使用 dapper 作为 ORM
- 我在其他领域使用 EF
- 当它挂起时,它会挂起 >30 秒。很少是 1s < time < 30s
- 下面是挂起的小巧查询,其中
XXXX
是两种情况下大约 2,500 个项目 ID 的列表: - 拥有一小部分
XXXX
ID 的用户似乎从来没有遇到过这个问题。XXXX
的检索从来都不是问题 - 但使用大的XXXX
有时似乎会降低性能。 - [User] 在 UserId (PK) 上建立索引,而 LastOnline
代码:
select USERID, USERNAME, NICKNAME, BIRTHDATE, LASTONLINE
from [User]
where AccountDisabled <> 1 and Banned <> 1 and
(ABOUTME <> '' OR ProvidedPhoto = 1) and
USERID <> @userId and ProvidedPhoto = 1 AND
USERID IN (-1) AND USERID NOT IN (-1)
AND USERID NOT IN (XXXX) UNION ALL
select * from (select USERID, USERNAME, NICKNAME, BIRTHDATE, LASTONLINE from [User] where
AccountDisabled <> 1 and
Banned <> 1 and (ABOUTME <> '' OR ProvidedPhoto = 1) and
USERID <> @userId and ProvidedPhoto = 1 AND USERID NOT IN (-1)
AND USERID NOT IN (XXXX) AND USERID NOT IN (-1)
order by LastOnline asc offset 0 rows fetch next + 20 rows only)
as dt
我对性能取证的世界有点陌生...任何建议都很棒。
更新 - 执行计划:
以下是您可以尝试的一些方法:
- 看看您是否可以通过将@UserID 作为参数传递来为return 您所需的列表创建一个存储过程。调用此存储过程而不是每次都生成查询。
将 NOT IN 替换为 NOT EXISTS,如下所示。首先检查这是否有帮助。这在很大程度上取决于 USERID 列中的值。
SELECT USERID,USERNAME,NICKNAME,BIRTHDATE,LASTONLINE FROM [User] WHERE AccountDisabled <> 1 AND Banned <> 1 AND ( ABOUTME <> '' OR ProvidedPhoto = 1 ) AND USERID <> @userId AND ProvidedPhoto = 1 AND USERID IN (- 1) --How will these two conditions ever be true together? AND USERID NOT IN (- 1) --Be sure about your conditions AND NOT EXISTS (SELECT USERID FROM [USER] U2 WHERE U1.USERID = U2.USERID) UNION ALL SELECT * FROM ( SELECT USERID,USERNAME,NICKNAME,BIRTHDATE,LASTONLINE FROM [User] U1 WHERE AccountDisabled <> 1 AND Banned <> 1 AND ( ABOUTME <> '' OR ProvidedPhoto = 1 ) AND USERID <> @userId AND ProvidedPhoto = 1 AND USERID NOT IN (- 1) AND NOT EXISTS (SELECT USERID FROM [USER] U2 WHERE U1.USERID = U2.USERID) -- AND USERID NOT IN (- 1) WHY AGAIN?? ORDER BY LastOnline ASC offset 0 rows FETCH NEXT + 20 rows ONLY ) AS dt
您可能还考虑在 WHERE 子句中的其他列上创建非聚集索引。您能否也显示查询的执行计划? (方法:在 SQL 查询编辑器中,按 CTRL+M,然后执行您的查询。您将获得一个执行计划以及结果。)