在已经对选定表进行排序时优化联合所有订单

Posted

技术标签:

【中文标题】在已经对选定表进行排序时优化联合所有订单【英文标题】:Optimizing a union all order by when selected tables are already sorted 【发布时间】:2013-11-25 14:51:41 【问题描述】:

我说 3+ 个表,每个表包含 10+ 百万行,每个表的结构如下:

Table1:    ColName | Type
           --------------
              cDT  | DateTime2(7)
              cID  | int
              c3   | ...
            ...    | ...

(cDT,cID) 上有一个聚集索引,因此每个单独的表都已按 cDT 进行物理排序。使用 cID 是因为我通常只想要包含特定 cID 的行。

从这些表中,我想为我的应用程序创建一个按时间排序的“流”(即 cDT)。目前由以下人员完成:

SELECT t.cDT AS cDT, t.cID AS cID, t.c3 AS c3, t.cTAB as cTab
FROM
(
SELECT cDT AS cDT, cID AS cID, c3 AS c3, 'tab1' as cTAB FROM TABLE1
UNION ALL
SELECT cDT AS cDT, cID AS cID, c3 AS c3, 'tab2' as cTAB FROM TABLE2
UNION ALL
SELECT cDT AS cDT, cID AS cID, c3 AS c3, 'tab3' as cTAB FROM TABLE3
)
WHERE t.cID IN (SELECT ID FROM TABLEIDs)
ORDER BY t.cDT

看到我的表已经使用聚集索引正确排序,我正在尝试寻找提高此查询性能的方法。我尝试使用视图,但这不起作用(无法在视图上创建索引)。我还尝试使用单独的唯一 cDT 列并使用连接,但这很麻烦(也许有人可以使用连接提供一个不错的解决方案?)。

显而易见的答案就是把所有东西都放在一张桌子上。我不介意即时执行此操作,但我不想静态执行此操作。

对于如何优化所有传入表都单独排序并且您想要全局排序的联合所有查询有什么想法吗?

提前致谢。

附:优化 where 语句并不重要,因此任何忽略我的 where 语句的解决方案仍然非常感谢。

查询计划:

【问题讨论】:

查询是否使用了您的聚集索引? 保证行返回顺序的唯一方法是在最外层的查询上有一个ORDER BY。如果幸运的话,优化器可以利用您拥有的索引,ORDER BY 实际上并不昂贵。 向我们展示查询计划。 您能否将WHERE 从外部查询移至 3 个内部查询 - 并为此添加执行计划? (如果它与你所拥有的不同) 【参考方案1】:

SQL Server 生成的计划似乎不太好。最好将三个表合并并连接到 IDs 表一次。也许我们可以欺骗 SQL Server 这样做:

SELECT t.cDT AS cDT, t.cID AS cID, t.c3 AS c3, t.cTAB as cTab
FROM
(
SELECT TOP 1000000000 *
FROM (
 SELECT cDT AS cDT, cID AS cID, c3 AS c3, 'tab1' as cTAB FROM TABLE1
 UNION ALL
 SELECT cDT AS cDT, cID AS cID, c3 AS c3, 'tab2' as cTAB FROM TABLE2
 UNION ALL
 SELECT cDT AS cDT, cID AS cID, c3 AS c3, 'tab3' as cTAB FROM TABLE3
) x
ORDER BY cDT,cID --CI order
)
WHERE t.cID IN (SELECT ID FROM TABLEIDs)
ORDER BY t.cDT

这个几乎不受限制的 TOP 子句可能会导致它在进行连接之前评估联合。 order-by 应该有助于维护基表的 CI 顺序,这样就不需要排序操作。

如果这不能立即奏效,请尝试一下这个想法。

【讨论】:

或者有一个OPTION (MERGE UNION) 提示可用于评估性能并查看是否有充分的理由未选择该计划。 最终使用与上述答案类似的东西,使用 top xxx,有帮助。

以上是关于在已经对选定表进行排序时优化联合所有订单的主要内容,如果未能解决你的问题,请参考以下文章

SQL 将索引(订单值)设置为列

SQL的一些查询语句

如何对access中两个数据库中表进行联合查询

PHP Mysql Logic 循环遍历表并优化输出

如何按月顺序对我的数据进行排序?我希望我的月订单是 4 月到 4 月(即财政年度)

订单分库分表实践总结