还有另一种变体:选择客户端,然后使用 CROSS APPLY (.. TOP (1) ... ORDER BY ...) 获取相关条目。
SELECT c.ClientName,r.LogEntryId, r.FileId, r.CreatedOn, r.EventTypeId
FROM (
SELECT DISTINCT ClientName
FROM LogEntries
WHERE EventTypeId IN (2,4)) as c
CROSS APPLY (
SELECT TOP (1) a.LogEntryId, a.FileId, a.CreatedOn, a.EventTypeId
FROM LogEntries as a
WHERE a.ClientName = c.ClientName
AND a.EventTypeId IN (2,4)
ORDER BY a.CreatedOn DESC) as r;
Update
在不了解架构的情况下谈论 T-SQL 查询的性能是没有意义的。该查询在正确设计的架构上满足其需求是完美的最佳选择。由于访问是通过 ClientName 和 CreatedOn 进行的,因此即使是简单的模式也需要考虑到这一点:
CREATE TABLE LogEntries (
LogEntryId int identity(1,1),
FileID int,
CreatedOn datetime,
EventTypeID int,
ClientName varchar(30)
);
create clustered index cdxLogEntries on LogEntries (
ClientName, CreatedOn DESC);
go
让我们加载包含 240 万行的表:
declare @i int;
set @i = 0;
while @i < 1000
begin
insert into LogEntries (FileId, CreatedOn, EventTypeId, ClientName)
select cast(rand()*100 as int),
dateadd(minute, -rand()*10000, getdate()),
cast(rand() * 5 as int),
'Client' + cast(@i as varchar(10))
from master..spt_values;
set @i = @i+1;
end
我们的时间和 IO 是多少set statistics io on; set statistics time on;
在预热的缓存上?
(410 row(s) affected)
Table 'LogEntries'. Scan count 411, logical reads 14354, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 1219 ms, elapsed time = 1932 ms.
1.9 秒即可从我的笔记本电脑(已使用 4 年且具有 1Gb RAM)上的 240 万个条目中获取数据。而且模式设计仍有很大的改进空间。将 ClientName 分离到规范化表中,并使用来自 LogEntries 的可信外键将其显着减少时间。 EntryTypeId IN (2,4) 上正确的过滤索引也会有所帮助。我们甚至没有开始探索并行可能性。
这就是 SQL,性能是在架构的绘图板上获得的,而不是在查询的文本编辑器中获得的。