优化 SQL 查询以减少执行时间

Posted

技术标签:

【中文标题】优化 SQL 查询以减少执行时间【英文标题】:Optimize SQL Query to reduce execution time 【发布时间】:2013-05-30 13:19:17 【问题描述】:

我有一个用 MS SQL Server R2 编写的查询。请帮助优化它。它返回超过 60 万的数据字符串结构。返回结果大约需要 5-6 分钟。有什么办法可以改善吗?

以下是我的查询:

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

【问题讨论】:

【参考方案1】:

试试这个 -

CREATE PROC [dbo].[Test] 
(
    @UserTypeID INT,
    @UserID INT,
    @CityID INT,
    @OperatorID INT,
    @ParameterID INT
)
AS BEGIN

    SELECT data = '[' + STUFF((
        SELECT
            ',"latitude":"' + A.lat + '","longitude":"' + A.long + '","value":"' + CONVERT(VARCHAR(20), A.value) + '","image":"' + temp.IMAGE + '"'
        FROM (
            SELECT
                  sd.lat
                , sd.long
                , sd.value
            FROM dbo.tbl_Survey_Details sd
            JOIN dbo.tbl_Survey s ON sd.tbl_survey_id = s.id
            JOIN dbo.tbl_Location l ON s.tbl_location_id = l.id
            JOIN dbo.tbl_Area a ON l.tbl_area_id = a.id
            JOIN dbo.tbl_City c ON a.tbl_city_id = c.id
            WHERE sd.tbl_parameter_id = @ParameterID
                AND s.tbl_mobile_operator_id = @OperatorID
                AND a.tbl_city_id = @CityID
        ) a
        JOIN (
            SELECT  
                  [range] = CASE WHEN symbol = '<' THEN t.range2 ELSE t.[range] END
                , range2 = CASE WHEN symbol = '<' THEN t.[range] ELSE t.range2 END
                , [image] = t.[image]
            FROM dbo.tbl_Legend_ViewNetwork_Dtls t
            JOIN dbo.tbl_Legend_ViewNetwork n ON t.tbl_legend_view_network_id = n.id
            WHERE n.parameter_id = @ParameterID
                AND n.user_type_id = @UserTypeID
                AND n.is_default = 1
                AND (
                        (
                              n.[user_id] = @UserID 
                            AND 
                              @UserID > 0
                        ) 
                        OR 
                          @UserID <= 0
                )
        ) temp ON A.value BETWEEN temp.[range] AND temp.range2
        FOR XML PATH ('')
    ), 1, 1, '') + ']'

END

【讨论】:

很抱歉,与我发布的相比,这个花费了更多时间。 :( 有什么其他方法可以尽快得到响应。【参考方案2】:

如果您在 MS SQL Management Studio 查询分析器中运行此查询并单击菜单查询,在数据库优化顾问中分析此查询,它将告诉您需要添加哪些索引来优化查询...

对于我们这些在南亚以外的人来说,十万是 100, 000

【讨论】:

我试过了,它给了我一些建议(在survey_details 表上建立索引),我全部应用了,我只得到了几秒钟的差异。还有其他可能的解决方案吗?? 大部分时间都花在了哪里?好吧,如果数据有很大的变化,这些事情通常需要很长时间。您确实希望一次定位 1-10 000 行,因此使用您递增的变量拆分工作范围。我不知道是否最好在用户 ID 或范围上进行拆分,攻击在查询分析器中给出最大百分比的位。 帖子已转移到this link

以上是关于优化 SQL 查询以减少执行时间的主要内容,如果未能解决你的问题,请参考以下文章

数据库查询优化技术

减少查询响应时间,需要优化查询

如何优化 sql 查询以避免在没有 php.ini 或设置时间限制的情况下执行最长时间 [关闭]

MySQL 查询优化

sql 优化

如何在 spark-submit 之前触发催化剂优化器以减少执行时间?