优化 Report 的 SQL 查询

Posted

技术标签:

【中文标题】优化 Report 的 SQL 查询【英文标题】:Optimize the SQL query for Report 【发布时间】:2019-05-07 09:49:15 【问题描述】:

我必须为火车站的大门生成一个简单的正常运行时间报告。如果任何门有任何错误,则它在数据库中,具有特定原因以及中断的 startTime 和 EndTime。需要处理的场景很少:

    如果一个车站有 2 个闸门,一个在每月的前 15 天工作,第二个在接下来的 15 天工作,因此两个闸门中的一个都在工作。所以这个站的价值应该是100%。如果两个门都关闭了任何天数,则不会出现在这个百分比中。

我已经写下了一个查询,但是执行几十万条记录需要 5-6 分钟。所以它会阻塞系统。

declare @dt_start datetime, @dt_end datetime
set @dt_start = '2019-04-01 00:00';
set @dt_end = '2019-04-30 23:59';
DROP TABLE IF EXISTS #minutesTime;
with cte_Dates as (
        SELECT @dt_start as uptimeMinute
        UNION ALL
        SELECT DATEADD(MINUTE,1,uptimeMinute)
        FROM cte_Dates
        WHERE DATEADD(MINUTE,1,uptimeMinute) < @dt_end
    )

SELECT * 
INTO #minutesTime FROM cte_Dates
WHERE CAST(uptimeMinute as time) >= '05:00:00'
or CAST(uptimeMinute as time) < '02:00:00'
OPTION(MAXRECURSION 0);

SELECT
uptimeMinute,
count(DISTINCT o.ReaderID) as numOfflineReaders
FROM #minutesTime m
CROSS JOIN Readers r 
JOIN Outages o
ON r.ReaderId = o.ReaderId
WHERE 
uptimeMinute BETWEEN o.OutageStart AND o.OutageEnd
GROUP BY 
uptimeMinute having count(DISTINCT o.ReaderID)=3
ORDER BY 
uptimeMinute;

表定义为:

读者:

ReaderId NotificationsDisabled
1        0
2        1

中断:

OutageId    SourceType  SourceId    OutageStart                     OutageEnd                       OutageSeconds   ReaderId
1           Faults          1       2019-03-28 10:13:35.6700000     2019-03-31 00:21:45.5900000     223690          24      

【问题讨论】:

您是否还包括查询的执行计划 @ARr0w,请检查问题 @RamSingh 。 . .我建议你问一个新问题。专注于您引用的两个或三个表中的数据。显示您想要的结果——全部作为文本表格。清楚地解释逻辑并设置一个 db 小提琴。然后解释你有一个查询似乎需要很长时间。我可以阅读您的第一段,但我不知道解释与您的数据有何关系,因此我不会阅读第一段之外的内容。 请参阅paste the plan 了解在您的问题中包含执行计划的更好方法。 与其在几分钟内打破一个月并四处寻找,找到与该月重叠的所有中断行并处理它们以确定该月的总停机时间和任何重叠的停机时间会更有效。从您的表格中不清楚如何判断哪些读者被分配到给定的站点。重叠范围的一般检查是Start1 &lt;= End2 and Start2 &lt;= End1。请参阅 overlap 标签 wiki 了解说明。 【参考方案1】:

您的日期生成器(使用递归)可能有点低效。 你可以试试这个:

DECLARE @StartDate DATETIME = '2019-04-01 00:00'  , @EndDate DATETIME= '2019-04-30 23:59';



WITH dates as (
SELECT  DATEADD(MINUTE, nbr - 1, @StartDate) as uptimeMinute
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY c.object_id , c.a ) AS Nbr
          FROM      
          (SELECT c.object_id, 1 as a FROM sys.columns c
          UNION ALL 
          SELECT c.object_id, 0 as a FROM sys.columns c) c
        ) nbrs
WHERE   nbr - 1 <= DATEDIFF(MINUTE, @StartDate, @EndDate)
)
SELECT uptimeMinute into #minute
from dates
WHERE CAST(uptimeMinute as time) >= '05:00:00'
or CAST(uptimeMinute as time) < '02:00:00'

【讨论】:

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

MySQL 查询优化以获得月度报告

SQL查询优化

SQL 数据库查询的优化工具及实用

数据库牛人是如何进行SQL优化的?

sql查询优化 索引优化

如何做SQL优化?优化SQL语句,提高SQL查询效率。Effective MySQL之SQL语句最优化