【问题标题】:How to optimize SQL query with MIN MAX function如何使用 MIN MAX 函数优化 SQL 查询
【发布时间】:2017-09-19 13:33:50
【问题描述】:

这是我的查询

SELECT
    [Car].CarId AS Id,
    CAST(MIN(ISNULL([Dates].StartDate, [Reco].InsStartDate)) AS date) AS StartDate,
    CAST(MAX(ISNULL([Dates].EndDate, [Reco].InsEndDate)) AS date) AS EndDate
FROM
    dbo.TabReco [Reco]
    INNER JOIN dbo.Insurance [INS] ON [INS].InsId = [Reco].InsId
    INNER JOIN dbo.InsuranceCar [Details] ON [Details].INSCarId = [INS].INSCarId
    INNER JOIN dbo.CarHistory [Car] ON [Car].CarHistId = [Details].CarHistId
    INNER JOIN dbo.InsuranceRiskDates [Dates] ON [Dates].INSId = [INS].INSId
GROUP BY
    [Reco].Number,
    [Car].CarId

当我运行这个查询时,它需要很长时间。问题在于日期的 MIN/MAX 部分。

CAST(MIN(ISNULL([Dates].StartDate, [Reco].InsStartDate)) AS date) AS StartDate,
CAST(MAX(ISNULL([Dates].EndDate, [Reco].InsEndDate)) AS date) AS EndDate

如果我删除该部分,那么查询会更快。有没有办法优化这样的查询?或者这是不可能的。

【问题讨论】:

  • 可以发一下执行计划吗?没有一些细节,我们只是猜测。
  • 如果您在用于join 的键上有索引,那么您无能为力。
  • 如果您的日期被存储为作为 DATE,那么您也许可以添加一些巧妙的索引来解决这个问题。因为它们不是,所以你能做的最好的可能是一个覆盖索引,这可能有帮助,也可能没有帮助。无论哪种方式,我们仍然需要查看查询计划。

标签: sql sql-server performance database-performance


【解决方案1】:

看起来你在使用 INNER JOIN 时不需要 ISNULL。

别管那个了,把那部分去掉就行了。

除非您在 [Dates].StartDate 和 [Dates].EndDate 上允许 null 或者如果您使用 LEFT JOIN :

SELECT
    [Car].CarId AS Id,
    CAST(MIN(ISNULL([Dates].StartDate, [Reco].InsStartDate)) AS date) AS StartDate,
    CAST(MAX(ISNULL([Dates].EndDate, [Reco].InsEndDate)) AS date) AS EndDate
FROM
    dbo.TabReco [Reco]
    INNER JOIN dbo.Insurance [INS] ON [INS].InsId = [Reco].InsId
    INNER JOIN dbo.InsuranceCar [Details] ON [Details].INSCarId = [INS].INSCarId
    INNER JOIN dbo.CarHistory [Car] ON [Car].CarHistId = [Details].CarHistId
    LEFT JOIN dbo.InsuranceRiskDates [Dates] ON [Dates].INSId = [INS].INSId
GROUP BY
    [Reco].Number,
    [Car].CarId

您可能需要为连接区域中不是主键的每一列建立索引。

已编辑:除了索引之外,我还有一个想法,试试这个:

SELECT Id,
CAST(MIN(StartDate) AS date) AS StartDate,
CAST(MIN(EndDate) AS date) AS EndDate
FROM
( 
    SELECT [Reco].Number,
    [Car].CarId AS Id,
    [Dates].StartDate, [Dates].EndDate
    FROM
    dbo.TabReco [Reco]
    INNER JOIN dbo.Insurance [INS] ON [INS].InsId = [Reco].InsId
    INNER JOIN dbo.InsuranceCar [Details] ON [Details].INSCarId = [INS].INSCarId
    INNER JOIN dbo.CarHistory [Car] ON [Car].CarHistId = [Details].CarHistId
    INNER JOIN dbo.InsuranceRiskDates [Dates] ON [Dates].INSId = [INS].INSId
    WHERE [Dates].StartDate IS NOT NULL

    UNION ALL

    SELECT [Reco].Number,
    [Car].CarId AS Id,
    [Reco].InsStartDate AS StartDate, 
    [Reco].InsEndDate AS EndDate
    FROM
    dbo.TabReco [Reco]
    INNER JOIN dbo.Insurance [INS] ON [INS].InsId = [Reco].InsId
    INNER JOIN dbo.InsuranceCar [Details] ON [Details].INSCarId = [INS].INSCarId
    INNER JOIN dbo.CarHistory [Car] ON [Car].CarHistId = [Details].CarHistId
    LEFT JOIN dbo.InsuranceRiskDates [Dates] ON [Dates].INSId = [INS].INSId
    WHERE [Dates].StartDate IS NULL
) x
GROUP BY Number, Id

【讨论】:

  • ISNULL 不是问题,问题在于 MIN MAX,因为有数千条记录
猜你喜欢
  • 2017-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-01
  • 2020-03-11
  • 2018-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多