我使用以下查询返回rowcount进行分页,它工作正常但需要很长时间才能返回,因为所有表都有数百万条记录。 目前它需要7秒才能返回rowcount,任何人都可以帮助我快速返回它。
我也尝试过与#table和@table相同的查询都很慢。 查询是
WITH cte_rowcount
AS (SELECT p.policyid
FROM resident (nolock) r
INNER JOIN resident_policy (nolock) rp
ON r.residentid = rp.residentid
INNER JOIN policy (nolock) p
ON p.policyid = rp.policyid
--INNER JOIN PolicySource (NOLOCK) psourse ON p.PolicySourceID = psourse.PolicySourceId
INNER JOIN policy_locations (nolock) pl
ON pl.policyid = p.policyid
INNER JOIN location (nolock) l
ON pl.locationid = l.locationid
--INNER JOIN Policy_Status (NOLOCK) ps ON ps.PolicyStatusId = p.PolicyStatusId
INNER JOIN property (nolock) pr
ON pr.propertyid = l.propertyid
--INNER JOIN dbo.States (NOLOCK) s ON s.StateId = pr.StateId
WHERE r.primary_resident = 0x1
AND ( ( @ResidentFirstName IS NULL )
OR R.firstname LIKE @ResidentFirstName + '%' )
AND ( ( @ResidentLastName IS NULL )
OR R.firstname LIKE @ResidentLastName + '%' )
AND ( @PropertyAddress IS NULL
OR pr.address LIKE @PropertyAddress + '%' )
AND ( @Policynumber IS NULL
OR p.policynumber LIKE @Policynumber + '%' )
AND ( @LocationAddress IS NULL
OR l.address2 LIKE @LocationAddress + '%' )
AND ( @City IS NULL
OR pr.city LIKE @City + '%' )
AND ( @ZipCode IS NULL
OR pr.zipcode = @ZipCode )
AND ( @StateId IS NULL
OR pr.stateid = @StateId )
AND ( @PolicyStatusId IS NULL
OR p.policystatusid = @PolicyStatusId ))
SELECT @rowcount = Count(*)
FROM cte_rowcount
答案 0 :(得分:1)
这很难回答,因为有大量数据可能会发生很多事情。
在加入方面,这应该表现良好。
如果此查询仅用于执行计数,那么我建议您直接SELECT count('x')
执行此操作而不使用CTE
且不使用(nolock)
。
SELECT @rowcount = count('x') as rc
FROM
resident r
INNER JOIN resident_policy rp
ON r.residentid = rp.residentid
INNER JOIN policy p
ON p.policyid = rp.policyid
INNER JOIN policy_locations pl
ON pl.policyid = p.policyid
INNER JOIN location l
ON pl.locationid = l.locationid
INNER JOIN property pr
ON pr.propertyid = l.propertyid
WHERE
r.primary_resident = 0x1
AND ( ( @ResidentFirstName IS NULL )
OR R.firstname LIKE @ResidentFirstName + '%' )
AND ( ( @ResidentLastName IS NULL )
OR R.firstname LIKE @ResidentLastName + '%' )
AND ( @PropertyAddress IS NULL
OR pr.address LIKE @PropertyAddress + '%' )
AND ( @Policynumber IS NULL
OR p.policynumber LIKE @Policynumber + '%' )
AND ( @LocationAddress IS NULL
OR l.address2 LIKE @LocationAddress + '%' )
AND ( @City IS NULL
OR pr.city LIKE @City + '%' )
AND ( @ZipCode IS NULL
OR pr.zipcode = @ZipCode )
AND ( @StateId IS NULL
OR pr.stateid = @StateId )
AND ( @PolicyStatusId IS NULL
OR p.policystatusid = @PolicyStatusId )
如果此CTE同时用于行计数并从CTE
检索数据,请确保您仅检索相关网页的数据(仅包含ROWCOUNT() as RC
和RC > 0 AND RC <= 20
的20个元素)
在数据库方面,您可以检查是否有所有join子句的索引。看起来只有PK,所以他们已经有了索引。请确保您在已连接的列上有索引。
如果您仍然遇到问题,请使用“实时执行计划”功能,看看到底发生了什么。
LIKE
条件可以是性能杀手,具体取决于文本大小和数据库内容。您可以考虑使用COLLECTION来存储您的文本,并在文本比较方面获得一些收益。
答案 1 :(得分:1)
我说要查看索引,但它可能不会有多大帮助,因为a)你可能已经做过了,并且b)你不能在这种查询中找到它,只扫描。
想法是摆脱这些OR并允许优化器产生合理的计划。
有两种选择。
不知道哪个版本的SQL Server存在问题,但如果它是SQL 2008 SP1 CU5(10.0.2746)或更高版本,或SQL 2008 R2 CU1(10.50.1702)或更高版本,或者比这更新的东西,在查询中添加option (recompile)
。这应该会产生更好的计划,使用相关指数的搜索。
但是,这会为每次执行添加一些重新编译开销,所以第二个选项可能更好。
您可以将查询重写为动态查询,并在优化程序甚至查看查询之前消除NULL参数。我试图重写您的查询,没有您的数据,因此无法对其进行测试,并且可能存在一些错误,但您仍会得到我的意图。我不得不猜测数据类型。 (顺便说一下,有SELECT p.policyid
的具体原因吗?)
这是:
declare @qry nvarchar(4000), @prms nvarchar(4000);
set @qry = N'
SELECT count(*)
FROM resident (nolock) r
INNER JOIN resident_policy (nolock) rp
ON r.residentid = rp.residentid
INNER JOIN policy (nolock) p
ON p.policyid = rp.policyid
INNER JOIN policy_locations (nolock) pl
ON pl.policyid = p.policyid
INNER JOIN location (nolock) l
ON pl.locationid = l.locationid
INNER JOIN property (nolock) pr
ON pr.propertyid = l.propertyid
WHERE r.primary_resident = 0x1 '
if @ResidentFirstName IS NOT NULL
set @qry = @qry + ' AND R.firstname LIKE @ResidentFirstName + ''%'''
if @ResidentLastName IS NOT NULL
set @qry = @qry + ' AND R.firstname LIKE @ResidentLastName + ''%'''
if @PropertyAddress IS NOT NULL
set @qry = @qry + ' AND pr.address LIKE @PropertyAddress + ''%'''
if @Policynumber IS NOT NULL
set @qry = @qry + ' AND p.policynumber LIKE @Policynumber + ''%'''
if @LocationAddress IS NOT NULL
set @qry = @qry + ' AND l.address2 LIKE @LocationAddress + ''%'''
if @City IS NOT NULL
set @qry = @qry + ' AND pr.city LIKE @City + ''%'''
if @ZipCode IS NOT NULL
set @qry = @qry + ' AND pr.zipcode = @ZipCode'
if @StateId IS NOT NULL
set @qry = @qry + ' AND pr.stateid = @StateId'
if @PolicyStatusId IS NOT NULL
set @qry = @qry + ' AND p.policystatusid = @PolicyStatusId'
set @prms = N'@PolicyStatusId int, @StateId int, @ZipCode int,
@City varchar(50), @LocationAddress varchar(50), @Policynumber varchar(50),
@PropertyAddress varchar(50), @ResidentLastName varchar(50), @ResidentFirstName varchar(50)'
exec sp_executesql
@qry,
@prms,
@PolicyStatusId = @PolicyStatusId, @StateId = @StateId, @ZipCode = @ZipCode,
@City = @City, @LocationAddress = @LocationAddress,
@Policynumber = @Policynumber, @PropertyAddress = @PropertyAddress,
@ResidentLastName = @ResidentLastName, @ResidentFirstName = @ResidentFirstName
如果您对执行计划有所影响,只要在WHERE和JOIN列上有非聚簇索引,您就会看到索引搜索。
此外,计划将被缓存,每个参数组合一个。
答案 2 :(得分:0)
有一些一般性指示:
false
的语句