一位同事在一家使用Microsoft SQL Server的公司工作。他们的团队创建了每天执行的存储过程,以创建数据提取。基础表非常庞大(有些表有数十亿行),因此大多数存储过程的设计都是这样的:首先,它们只将这些巨大表中的相关行提取到临时表中,然后临时表相互连接并与其他更小的表连接以创建最终的提取。类似于:
SELECT COL1, COL2, COL3
INTO #TABLE1
FROM HUGETABLE1
WHERE COL4 IN ('foo', 'bar');
SELECT COL1, COL102, COL103
INTO #TABLE2
FROM HUGETABLE2
WHERE COL14 = 'blah';
SELECT COL1, COL103, COL306
FROM #TABLE1 AS T1
JOIN #TABLE2 AS T2
ON T1.COL1 = T2.COL1
LEFT JOIN SMALLTABLE AS ST
ON T1.COL3 = ST.COL3
ORDER BY T1.COL1;
通常,临时表在创建后不会被修改(因此没有后续的ALTER、UPDATE或INSERT操作)。为了便于讨论,我们假设临时表以后只使用一次(因此只有一个SELECT查询会依赖于它们)。
问题是:在创建这些临时表之后和在后续查询中使用它们之前对它们进行索引是否是一个好主意?
我的同事认为创建索引会使连接和排序操作更快。然而,我认为总的时间会更长,因为创建索引需要时间。换句话说,我假设除了边缘情况之外(例如,临时表本身非常大,或者最终的SELECT查询非常复杂),SQL Server将使用它在临时表上拥有的统计信息来优化最终查询,并且在这样做的过程中,它将有效地为它认为合适的临时表建立索引。
换句话说,我习惯于认为,创建索引只有在您知道经常使用表的情况下才有用;一旦存储过程完成就被删除的一次性临时表不值得索引。
我们对SQL Server优化器的了解都不够,无法确定我们在哪些方面是对的,哪些方面是错的。您能帮助我们更好地了解我们的哪些假设更接近事实吗?
2条答案
按热度按时间lymnna711#
您的朋友可能是正确的,因为即使要在单个查询中使用一个表,在没有看到查询的情况下(即使看到了,我们仍然不知道它的执行计划是什么样子的),我们也不知道SQL Server需要在每个表的各个列中查找数据多少次,以便进行联接、排序等。
然而,我们永远不会知道确切的,直到它实际上做了两种方式,并测量和比较的结果。
9rbhqvlz2#
如果您每天都要提取数十亿行的数据,我建议您使用临时表而不是临时表。这样可以将您的提取与使用tempdb的其他资源隔离开来。
问题是:在创建这些临时表之后和在后续查询中使用它们之前对它们进行索引是否是一个好主意?
***在将数据加载到临时表后创建索引。***这将消除碎片并创建统计信息。
优化器将使用统计信息来生成最佳计划。因此,如果没有统计信息,可能会显著影响查询性能,尤其是对于大型数据集。
下面的示例查询临时表中索引创建前后的比较:
您需要测试索引是否对您有帮助。您需要平衡可以拥有的索引数量,因为如果索引太多,也会影响性能。