如何优化依赖于执行时间的T-SQL查询?

时间:2018-03-13 05:41:24

标签: sql sql-server indexing query-optimization non-clustered-index

我有一个包含系统事件的大(几百万行)表。我必须得到最近的事件计数,而且我不知道如何以正确的方式做到这一点。

我创建了这个视图:

CREATE VIEW [dbo].[EventCounts] 
AS
  SELECT  
      (SELECT COUNT(1)
       FROM dbo.SystemEvents r
       WHERE r.Timestamp > DATEADD(MINUTE, -15, GETDATE())
         AND r.Timestamp <= GETDATE()) AS last15minEventCount,
      (SELECT COUNT(1)
       FROM dbo.SystemEvents r
       WHERE r.Timestamp > DATEADD(MINUTE, -30, GETDATE())
         AND r.Timestamp <= DATEADD(MINUTE, -15, GETDATE())) AS from15to30EventCount,
      (SELECT COUNT(1)
       FROM dbo.SystemEvents r
       WHERE r.Timestamp > DATEADD(MINUTE, -60, GETDATE())
         AND r.Timestamp <= DATEADD(MINUTE, -30, GETDATE())) AS from30to60EventCount,
     (SELECT COUNT(1)
      FROM dbo.SystemEvents r
      WHERE r.Timestamp <= DATEADD(MINUTE, -60, GETDATE())) AS olderThan60minEventCount

此视图返回:

  1. &LT; 15分钟事件计数;
  2. 15 - 30分钟事件计数;
  3. 30 - 60分钟事件计数;
  4. 超过60分钟的事件计数。
  5. 现在我的代码在所有大表上运行了4次,我想优化它。我不能使用预聚集,因为这取决于执行时间。由于同样的原因,我无法使用索引视图。

    我想我可以在Timestamp列上添加非聚集索引,但代码仍然需要读取整个表得到这个计数,对吗?

    您能否建议如何优化我的查询?

    P.S。 last15minEventCount,from15to30EventCount,from30to60EventCount - 所有事件的很小一部分。

3 个答案:

答案 0 :(得分:2)

尝试这样的事情:

 SELECT COUNT(1),
        SUM(case when r.Timestamp > DATEADD(MINUTE, -15, GETDATE()) AND r.Timestamp <= GETDATE() 
                 then 1
                 else 0
            end) as last15minEventCount,
        sum(case when r.Timestamp > DATEADD(MINUTE, -30, GETDATE())AND r.Timestamp <= DATEADD(MINUTE, -15, GETDATE())
                 then 1
                 else 0 
                 end) as from15to30EventCount,
        sum(case when  r.Timestamp > DATEADD(MINUTE, -60, GETDATE()) AND r.Timestamp <= DATEADD(MINUTE, -30, GETDATE())
                 then 1
                 else 0 
                 end) as from30to60EventCount,
        sum(case when r.Timestamp <= DATEADD(MINUTE, -60, GETDATE()
                 then 1
                 else 0 
                 end) as olderThan60minEventCount,

 FROM dbo.SystemEvents r

答案 1 :(得分:1)

一个建议是,您可以更改方法并编写查询,如下所示。

CREATE VIEW [dbo].[EventCounts] 
AS 
  WITH Boundary AS (
           SELECT Dateadd(MINUTE, -15, Getdate()) AS LOW, 
                  Getdate()                       AS HIGH, 
                  'last15minEventCount'           AS Label 
           UNION 
           SELECT Dateadd(MINUTE, -30, Getdate()) AS LOW, 
                  Dateadd(MINUTE, -15, Getdate()) AS HIGH, 
                  'from15to30EventCount'          as Label 
          --Additional Conditions 
          ) 
  SELECT Count(*), 
         B.Label 
  FROM   SystemEvents R 
         INNER JOIN Boundary B 
                 ON R.TimeStamp BETWEEN LOW AND HIGH 
  GROUP  BY B.Label 

通过这个你可以将输出变成行,你需要转换成列,我觉得这应该是直截了当的。

这应该很快,因为查询现在是SARGable,你需要在TimpeStamp列上放置非聚集索引。

答案 2 :(得分:1)

要避免每个间隔进行一次扫描,您可以使用<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorgrey" android:orientation="vertical" tools:context="com.example.karthi.nestaway.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <android.support.v7.widget.RecyclerView android:id="@+id/recycle" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="10dp" android:outlineProvider="bounds" android:background="@color/colorwhite android:clipToPadding="false" android:elevation="2dp" android:layout_marginBottom="10dp" /> </LinearLayout> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" android:elevation="6dp" app:srcCompat="@drawable/ic_add_black_24dp" tools:ignore="VectorDrawableCompat" /> </android.support.design.widget.CoordinatorLayout> 。但是为了使查询非常快,您应该维护一个包含总计数的表,并在SUM(CASE ... END)列上创建索引:

TimeStamp