我有一个一千万的数据库。客户端需要读取数据并执行计算。由于数据量大,如果将其保存在应用程序缓存中,则会导致内存溢出并发生崩溃。如果使用select语句实时查询数据库中的数据,则时间可能太长,数据库上的操作次数可能太频繁。是否有更好的方法读取数据库数据?我使用C++和C#访问Server数据库。
我的数据库语句类似于以下内容:
SELECT TOP 10 y.SourceName, MAX(y.EndTimeStamp - y.StartTimeStamp) AS ProcessTimeStamp
FROM
(
SELECT x.SourceName, x.StartTimeStamp, IIF(x.EndTimeStamp IS NOT NULL, x.EndTimeStamp, 134165256277210658) AS EndTimeStamp
FROM
(
SELECT
SourceName,
Active,
LEAD(Active) OVER(PARTITION BY SourceName ORDER BY TicksTimeStamp) NextActive,
TicksTimeStamp AS StartTimeStamp,
LEAD(TicksTimeStamp) OVER(PARTITION BY SourceName ORDER BY TicksTimeStamp) EndTimeStamp
FROM Table1
WHERE Path = N'App1' and TicksTimeStamp >= 132165256277210658 and TicksTimeStamp < 134165256277210658
) x
WHERE (x.Active = 1 and x.NextActive = 0) OR (x.Active = 1 and x.NextActive = null)
) y
GROUP BY y.SourceName
ORDER BY ProcessTimeStamp DESC, y.SourceName数据库结构大致如下:
ID Path SourceName TicksTimeStamp Active
1 App1 Pipe1 132165256277210658 1
2 App1 Pipe1 132165256297210658 0
3 App1 Pipe1 132165956277210658 1
4 App2 Pipe2 132165956277210658 1
5 App2 Pipe2 132165956277210658 0我使用C #的ExecuteReader。相同的SQL语句在statement上运行4s,但是ExecuteReader返回的时间是8-9秒。慢时间和这个界面有什么关系吗?
发布于 2022-09-08 11:18:46
我并不真正“理解”整个查询,但我想知道这个部分:
WHERE (x.Active = 1 and x.NextActive = 0) OR (x.Active = 1 and x.NextActive = null)SQL不太喜欢OR,所以为什么不将其转换为
WHERE x.Active = 1 and ISNULL(x.NextActive, 0) = 0这可能会导致完全不同的查询计划。(或否)
正如CharlieFace所提到的,最好共享查询计划,这样我们就可以了解正在发生的事情了。
PS:我也不知道那些'ticksTimestamps‘代表什么,但是看起来你在那里得到了一个相当大的范围,更大的容量也会导致更长的处理时间。即使你只返回前10名,它仍然要通过整个范围来计算那些持续时间。
发布于 2022-09-07 20:56:28
我同意@Charlieface。我认为你想要的索引如下:
CREATE INDEX idx ON Table1 (Path, TicksTimeStamp) INCLUDE (SourceName, Active);您可以添加两个索引(当然名称不同),并查看执行引擎选择哪个索引。
发布于 2022-09-07 14:20:53
我可以建议添加以下索引,这将有助于使用LEAD进行内部查询
CREATE INDEX idx ON Table1 (SourceName, TicksTimeStamp, Path) INCLUDE (Active);上述指标的关键点在于,它应允许快速计算铅值。它还有一个用于INCLUDE的Active子句,用于覆盖整个select。
https://stackoverflow.com/questions/73636920
复制相似问题