我有一个包含系统事件的大(几百万行)表。我必须得到最近的事件计数,而且我不知道如何以正确的方式做到这一点。
我创建了这个视图:
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
此视图返回:
现在我的代码在所有大表上运行了4次,我想优化它。我不能使用预聚集,因为这取决于执行时间。由于同样的原因,我无法使用索引视图。
我想我可以在Timestamp列上添加非聚集索引,但代码仍然需要读取整个表得到这个计数,对吗?
您能否建议如何优化我的查询?
P.S。 last15minEventCount,from15to30EventCount,from30to60EventCount - 所有事件的很小一部分。
答案 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