Dee*_*k D 4 sql-server-2008 sql-server
我正在运行一个查询,它有数十万条记录,获取数据需要 20 多分钟。运行执行计划后,我注意到聚集索引查找成本可能是原因。如何减少下面提到的查询的聚集索引查找成本?
外键的成本约为 13% 到 23%。
CREATE PROC [dbo].[Test] (@UserTypeID INT,
@UserID INT,
@CityID INT,
@OperatorID INT,
@ParameterID INT)
AS
BEGIN
DECLARE @temp TABLE (
range DECIMAL(18, 2),
range2 DECIMAL(18, 2),
image VARCHAR(50),
symbol VARCHAR(20))
IF( @UserID > 0 )
BEGIN
--print 'hii'
INSERT INTO @temp
(range,
range2,
image,
symbol)
SELECT tbl_Legend_ViewNetwork_Dtls.range,
tbl_Legend_ViewNetwork_Dtls.range2,
tbl_Legend_ViewNetwork_Dtls.image,
tbl_Legend_ViewNetwork_Dtls.symbol
FROM tbl_Legend_ViewNetwork_Dtls
INNER JOIN tbl_Legend_ViewNetwork
ON tbl_Legend_ViewNetwork_Dtls.tbl_legend_view_network_id = tbl_Legend_ViewNetwork.id
WHERE tbl_Legend_ViewNetwork.parameter_id = @ParameterID
AND tbl_Legend_ViewNetwork.user_type_id = @UserTypeID
AND tbl_Legend_ViewNetwork.is_default = 1
AND tbl_Legend_ViewNetwork.user_id = @UserID
UPDATE @temp
SET range = range2,
range2 = range
WHERE symbol = '<'
END
ELSE
BEGIN
INSERT INTO @temp
(range,
range2,
image,
symbol)
SELECT tbl_Legend_ViewNetwork_Dtls.range,
tbl_Legend_ViewNetwork_Dtls.range2,
tbl_Legend_ViewNetwork_Dtls.image,
tbl_Legend_ViewNetwork_Dtls.symbol
FROM tbl_Legend_ViewNetwork_Dtls
INNER JOIN tbl_Legend_ViewNetwork
ON tbl_Legend_ViewNetwork_Dtls.tbl_legend_view_network_id = tbl_Legend_ViewNetwork.id
WHERE tbl_Legend_ViewNetwork.parameter_id = @ParameterID
AND tbl_Legend_ViewNetwork.user_type_id = @UserTypeID
AND tbl_Legend_ViewNetwork.is_default = 1
UPDATE @temp
SET range = range2,
range2 = range
WHERE symbol = '<'
END
--select * from @temp
SELECT '[' + STUFF((SELECT ',{"latitude":"' + a.lat + '","longitude":"' + a.long + '","value":"' + CONVERT(VARCHAR(20), a.value) + '","image":"' + temp.image + '"}'
FROM (SELECT tbl_Survey_Details.lat,
tbl_Survey_Details.long,
tbl_Survey_Details.value
FROM tbl_Survey_Details
INNER JOIN tbl_Survey
ON tbl_Survey_Details.tbl_survey_id = tbl_Survey.id
INNER JOIN tbl_Location
ON tbl_Survey.tbl_location_id = tbl_Location.id
INNER JOIN tbl_Area
ON tbl_Location.tbl_area_id = tbl_Area.id
INNER JOIN tbl_City
ON tbl_Area.tbl_city_id = tbl_City.id
WHERE tbl_Survey_Details.tbl_parameter_id = @ParameterID
AND tbl_Survey.tbl_mobile_operator_id = @OperatorID
AND tbl_Area.tbl_city_id = @CityID) AS a
INNER JOIN @temp temp
ON a.value BETWEEN temp.range AND temp.range2
FOR XML Path ('')), 1, 1, '') + ']' AS data
END
Run Code Online (Sandbox Code Playgroud)
修订查询:
CREATE PROC [dbo].[Test] (@UserTypeID INT,
@UserID INT,
@CityID INT,
@OperatorID INT,
@ParameterID INT)
AS
BEGIN
DECLARE @temp TABLE (
range DECIMAL(18, 2),
range2 DECIMAL(18, 2),
image VARCHAR(50),
symbol VARCHAR(20))
IF( @UserID > 0 )
BEGIN
--print 'hii'
INSERT INTO @temp
(range,
range2,
image,
symbol)
SELECT tbl_Legend_ViewNetwork_Dtls.range,
tbl_Legend_ViewNetwork_Dtls.range2,
tbl_Legend_ViewNetwork_Dtls.image,
tbl_Legend_ViewNetwork_Dtls.symbol
FROM tbl_Legend_ViewNetwork_Dtls
INNER JOIN tbl_Legend_ViewNetwork
ON tbl_Legend_ViewNetwork_Dtls.tbl_legend_view_network_id = tbl_Legend_ViewNetwork.id
WHERE tbl_Legend_ViewNetwork.parameter_id = @ParameterID
AND tbl_Legend_ViewNetwork.user_type_id = @UserTypeID
AND tbl_Legend_ViewNetwork.is_default = 1
AND tbl_Legend_ViewNetwork.user_id = @UserID
UPDATE @temp
SET range = range2,
range2 = range
WHERE symbol = '<'
END
ELSE
BEGIN
INSERT INTO @temp
(range,
range2,
image,
symbol)
SELECT tbl_Legend_ViewNetwork_Dtls.range,
tbl_Legend_ViewNetwork_Dtls.range2,
tbl_Legend_ViewNetwork_Dtls.image,
tbl_Legend_ViewNetwork_Dtls.symbol
FROM tbl_Legend_ViewNetwork_Dtls
INNER JOIN tbl_Legend_ViewNetwork
ON tbl_Legend_ViewNetwork_Dtls.tbl_legend_view_network_id = tbl_Legend_ViewNetwork.id
WHERE tbl_Legend_ViewNetwork.parameter_id = @ParameterID
AND tbl_Legend_ViewNetwork.user_type_id = @UserTypeID
AND tbl_Legend_ViewNetwork.is_default = 1
UPDATE @temp
SET range = range2,
range2 = range
WHERE symbol = '<'
END
SELECT a.lat, a.long,a.value, temp.image
FROM (SELECT tbl_Survey_Details.lat,
tbl_Survey_Details.long,
tbl_Survey_Details.value
FROM tbl_Survey_Details
INNER JOIN tbl_Survey
ON tbl_Survey_Details.tbl_survey_id = tbl_Survey.id
INNER JOIN tbl_Location
ON tbl_Survey.tbl_location_id = tbl_Location.id
INNER JOIN tbl_Area
ON tbl_Location.tbl_area_id = tbl_Area.id
INNER JOIN tbl_City
ON tbl_Area.tbl_city_id = tbl_City.id
WHERE tbl_Survey_Details.tbl_parameter_id = @ParameterID
AND tbl_Survey.tbl_mobile_operator_id = @OperatorID
AND tbl_Area.tbl_city_id = @CityID) AS a
INNER JOIN @temp temp
ON a.value BETWEEN temp.range AND temp.range2
END
Run Code Online (Sandbox Code Playgroud)
修订后的执行计划:
链接到 XML 执行计划文件:单击此处
由于使用非常简单的查询获取 300,000 行所需的时间大致相同,因此我建议您暂时停止查看查询调整并确定您当前正在测试的特定场景是否现实。
您正在本地工作站上运行 Management Studio,连接到某个 Godaddy 服务器上的 SQL Server 实例。因此,除了 SQL Server 中的查询成本之外,您还受到以下因素的限制:
您正在检索结果中的 300,000 行。通常这不是你做的 - 哪个用户会消耗 300,000 行?考虑在每次拉取时聚合或仅返回一个子集(Google 不会在单个页面中返回 300,000 个结果,他们一次显示 10 个结果),并考虑此查询的实际用途。
由于这不太可能是您的数据库在现实中产生结果的方式,我建议您稍微改变您的测试方法。要么在Godaddy 基础设施中的某个服务器上安装 Management Studio ,将带宽和一般 Internet 波动排除在外,要么使用 Management Studio 的本地副本测试您的查询逻辑,但不要使用它来计时结果。相反,使用godaddy 基础设施中的应用程序来测试时间(毕竟,这就是您的应用程序最终将如何工作,对吗?)。
如果在您将带宽/Internet 排除在外时查询也很慢,那么您可以开始考虑从 Godaddy 的服务器获得的 I/O 是否足够(或者您是否真的需要在无论如何,任何时候,所以也许这一点没有实际意义)。
归档时间: |
|
查看次数: |
12939 次 |
最近记录: |