【问题标题】:Speeding up MSSQL SELECT DISTINCT statement加快 MSSQL SELECT DISTINCT 语句
【发布时间】:2014-04-02 10:25:42
【问题描述】:

在我将DISTINCT 添加到SELECT 语句之前,我已经让这个查询正常工作并且不到1 秒。我试过GROUP BY,也试过MAX 每列。所有这些仍然提供相同的时间 5+ 秒。如果有人对如何加快运行速度有任何建议,我将不胜感激。

这是post here的后续内容

  SET @query = N'SELECT * FROM (  
  SELECT
        ROW_NUMBER() OVER (ORDER BY ' + @SORTBY + ') AS [rownum],  *  
  FROM (
        SELECT DISTINCT  
              dbo.funcSellIdByPropId(T0.id) as SellerId,  
              dbo.funcDefaultImage(T0.id, 1) as propImage,  
              dbo.funcDefaultImage(T0.id, 2) as propImage2,  
              dbo.funcDefaultImage(T0.id, 3) as propImage3,  
              dbo.funcDefaultImage(T0.id, 4) as propImage4,  
              dbo.funcCountPropertyImages(T0.id) as imageCount,  
              dbo.funcGetPropertyTypeListGB(T0.id) as TypeGB,  
              dbo.funcGetPropertyTypeListFR(T0.id) as TypeFR,  
              dbo.funcGetPropertyEnviListGB(T0.id) as EnviGB,  
              dbo.funcGetPropertyEnviListFR(T0.id) as EnviFR,  
              dbo.funcGetDepartmentByTown(T0.Town) as Department,  
              dbo.funcCheckFeaturedProperty(T0.id) as Featured,  
              T0.id, T0.Price, T0.BedRooms, T0.Town, T0.Postcode,
              T0.Mandate, T0.MinLandArea, T0.Rooms, T0.HabitableSurface, 
              T0.Active, T0.Budget,  
              T1.TitleFR, T1.TitleGB, SUBSTRING(T1.DescFR, 0, 300) as DescFR,
              SUBSTRING(T1.DescGB, 0, 300) as DescGB  
          FROM  
              PROPERTIES T0
              INNER JOIN PROPERTYTRANSLATIONS T1 ON T1.PropertyId = T0.id  
              INNER JOIN MATRIXPROPENVIRONMENT T2 ON T2.PropertyId = T0.id
              INNER JOIN ENVIRONMENT T3 ON T3.id = T2.EnvironmentId  
          WHERE  
              T0.Deleted = 0    
              AND T0.Active = 1   
              AND T3.GB IN (' + @FILTERBY + ')  
    ) T ) TT  
  WHERE  rownum BETWEEN (' + CONVERT(varchar(4), @PERPAGE * @PAGENUM) + ') AND (' + CONVERT(varchar(4), @PERPAGE * (@PAGENUM + 1)) + ')'

传递的参数

@PAGENUM = 0
@PERPAGE = 20
@SORTBY = N'Price DESC'
@FILTERBY = N'''City'', ''Village'', ''Coastal'''

结果

Download csv

【问题讨论】:

  • Distinct、Max 和 Group 会尝试按您的结果集进行比较或排序。如果你有一个大的结果集,CPU 将很难对行进行排序,甚至为每一行创建一个散列。由于您的值来自函数而不是列索引,因此无济于事。也许您可以将该数据集“存储”在临时表中并创建索引或哈希列或两者并使用它进行排序,甚至快进游标也可以进行插入排序。都是长镜头,也许您只是获得了一个太大的数据集,无法及时处理它
  • 如果您无法通过加快查询速度来解决问题,您可以尝试另一种方法,例如 argh! 非规范化或创建 SearchFromThisTable 并分别更新(在此处输入时间段)
  • 为什么需要DISTINCT?也许您只需要在与 T1 或 T2 或 T3 的 JOIN 上添加补充条件。这些重复的行是从哪里来的?
  • 你能发布一个查询计划来看看吗?
  • 添加一个 CTE,您可以在其中区分真正需要区分的列。然后使用 INNER JOIN 获取其他字段。

标签: sql sql-server database tsql relational-database


【解决方案1】:

在这里,正如 cmets 中所述,不会在所有内容上运行函数,只在您要返回的内容上运行:

更好的是,摆脱这些功能。 SQL 中的函数总是带有 DBA 的不良代码气味,他们还没有在集合中思考。我确信有一种更快的方法来获取这些值。

SELECT 
  [rownum],
  dbo.funcSellIdByPropId(T0.id) as SellerId,  
  dbo.funcDefaultImage(T0.id, 1) as propImage,  
  dbo.funcDefaultImage(T0.id, 2) as propImage2,  
  dbo.funcDefaultImage(T0.id, 3) as propImage3,  
  dbo.funcDefaultImage(T0.id, 4) as propImage4,  
  dbo.funcCountPropertyImages(T0.id) as imageCount,  
  dbo.funcGetPropertyTypeListGB(T0.id) as TypeGB,  
  dbo.funcGetPropertyTypeListFR(T0.id) as TypeFR,  
  dbo.funcGetPropertyEnviListGB(T0.id) as EnviGB,  
  dbo.funcGetPropertyEnviListFR(T0.id) as EnviFR,  
  dbo.funcGetDepartmentByTown(T0.Town) as Department,  
  dbo.funcCheckFeaturedProperty(T0.id) as Featured,  
  T0.id, T0.Price, T0.BedRooms, T0.Town, T0.Postcode,
  T0.Mandate, T0.MinLandArea, T0.Rooms, T0.HabitableSurface, 
  T0.Active, T0.Budget,  
  T1.TitleFR, T1.TitleGB, SUBSTRING(T1.DescFR, 0, 300) as DescFR,
  SUBSTRING(T1.DescGB, 0, 300) as DescGB  
  FROM  
(
 SELECT
        ROW_NUMBER() OVER (ORDER BY ' + @SORTBY + ') AS [rownum],  *  
 FROM (
        SELECT DISTINCT  
              T0.id

          FROM  
              PROPERTIES T0
              INNER JOIN PROPERTYTRANSLATIONS T1 ON T1.PropertyId = T0.id  
              INNER JOIN MATRIXPROPENVIRONMENT T2 ON T2.PropertyId = T0.id
              INNER JOIN ENVIRONMENT T3 ON T3.id = T2.EnvironmentId  
          WHERE  
              T0.Deleted = 0    
              AND T0.Active = 1   
              AND T3.GB IN (' + @FILTERBY + ')  
    ) T ) TT  
  WHERE  rownum BETWEEN (' + CONVERT(varchar(4), @PERPAGE * @PAGENUM) + ') 
    AND (' +   CONVERT(varchar(4), @PERPAGE * (@PAGENUM + 1)) + ')'
) TTT
JOIN PROPERTIES T0 ON T0.id = TTT.id
JOIN PROPERTYTRANSLATIONS T1 ON T1.PropertyId = T0.id  

【讨论】:

  • 当您不返回它们时,关于不对所有行运行 func 的好答案。另外:尽可能不要使用动态 SQL 语句。如果您将其设为 TVF 或存储过程,则 SQL Server 可以更轻松地为其缓存计划。
  • @jhilden - 如果此查询使用参数化查询,它将被编译和缓存。第一次调用后它应该具有与 SP 相同的性能。
  • 范太棒了。我不得不稍微改变你放在那里的东西,但它现在又运行不到一秒钟,并且拥有所有相同的功能!神送。非常感谢!
  • @TheAngrySaxon - 很高兴听到它,祝你好运,摆脱所有这些功能!
  • 当你说在集合中思考是什么意思?只是出于好奇?我非常喜欢 LINQ,所以任何类型的 SQL SP 技巧都会大有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-12
相关资源
最近更新 更多