分页联盟 ALL 结果 - 最佳性能



我们遇到这样一种情况,我们需要将 4 个不同表的结果组合成一个列表,并通过 OFFSET/FETCH 对其进行分页。

想要从表 a、b、c 和 d 中选择记录,按 CreatedDatetime 排序,然后按偏移量 X、获取 Y 排序。 表非常大(就行数而言(,只做 UNION ALL 然后分页听起来很可怕,因为这意味着可能编译整个记录列表,然后进行分页部分。

问题是没有一个表可以作为提取开始/结束日期时间窗口的参考,因为每个集合都可能包含但也可能不包含任何表中的记录。例如,最终结果可能包含来自a; a/b; a/b/c; a/b/c/d; b; b/c;....表的任意组合的记录,我们需要返回固定大小的数字(例如,分页大小为 20(。

关于如何最有效地解决这个问题的任何想法?

更新

基于@HABO的问题 不幸的是,没有关于查询的特殊线索。我们正在显示系统中的用户活动。它有不同种类的(我们选择的表格(。现在,查询会为查看活动的管理员弹出数据。管理员查看数据的方式可能会有很大差异:某些用户在过去几个小时内将有数千个活动,管理员希望查看所有活动。在其他情况下,用户一天将有 3 个操作,管理员只会看到第一页数据。

附言。它不是一个纯粹的日志表,因为活动随着时间的推移充当状态机,每个状态都有自己的状态,我们也在这些查询中寻找。

如果您知道页面大小(例如 100(,那么您只需编写 4 个前 100 个查询(按创建日期排序( - 然后在结果上做一个联合 ALL。 这样,即使所有前 100 条记录都来自 1 个表,您也被覆盖。

对于后续分页查询 - 您需要记录每个表中最后显示的行,并将其用作下次提取的高水位标记 - (从 RowID> @HighWater的表中选择前 100 个(

应该相当高效...

这就是缓存有用的地方。您可以将查询结果缓存在应用程序层中,如果查询不是太大,则可以在那里进行分页,或者如果查询结果很大,则可以将查询结果缓存在表(或临时表(中。

我想会有过滤器。从你说的来看,这些可能会有很大差异。因此,在最坏的情况下,所有列都可以是筛选器。 我的建议是使用 5 个视图,每个表一个,最后一个将它们合并。只需确保所有筛选器列都尽可能直接地进入物理表。 最后,选择主视图并获取,但要注意顺序依据子句。确保排序依据具有唯一的数据组合,否则您可能会遇到行在简单的普通刷新中更改页面的情况。如果按定义用户顺序,则强制在末尾添加一些键列。

如何安全地确保顺序为 100% 安全获取/偏移量提供不同的值:

在 4 个视图中创建一个新列,其中包含一个简单的常量作为值,例如 1、2、3、4 AS [表源] 请确保选择每个表的 PK。如果没有,则必须在视图中创建一个,可能使用 ROW_NUMBER 或 NEWID,例如 [Pk]。 最后,从主视图中进行选择时,您可以按创建日期、Pk、TableSource 进行排序。这样,您 100% 安全,在同一组数据中,任何行都将精确地放置在相同的位置,从而产生正确的分页。

按 CreateDate 安全隔离 30 行顺序的页面的示例:

SELECT * FROM (
SELECT src, id, ROW_NUMBER() OVER(ORDER BY dt DESC,src,id)rn FROM (
SELECT 1 src, id, dt FROM table1 /*WHERE x=y*/ UNION ALL 
SELECT 2 src, id, dt FROM table2 /*WHERE x=y*/ UNION ALL 
SELECT 3 src, id, dt FROM table3 /*WHERE x=y*/ UNION ALL 
SELECT 4 src, id, dt FROM table4 /*WHERE x=y*/)alltables
)data WHERE data.rn BETWEEN 3001 AND 3030

最新更新