当前位置: 首页 > 知识库问答 >
问题:

索引一次性临时表

壤驷英叡
2023-03-14

一位同事在一家使用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个答案

艾心远
2023-03-14

如果您正在执行包含数十亿行的日常数据提取,我建议您使用临时表而不是临时表。这将使用 tempdb 将数据提取与其他资源隔离开来。

问题是:在创建这些临时表之后,在随后的查询中使用它们之前,索引这些临时表是一个好主意吗?

将数据加载到临时表后创建索引。这将消除碎片并创建统计数据。

优化器将使用统计数据生成最佳计划。因此,如果您没有统计数据,它可能会极大地影响查询性能,特别是对于大型数据集。

下面示例查询临时表中索引创建前后的比较:

/* Create index after data load into temp table -- stats is created */
CREATE TABLE #temp ( [text] varchar(50), [num] int);
INSERT INTO #temp([text], [num]) VALUES ('aaa', 1), ('bbb', 2) , ('ccc',3);
CREATE UNIQUE CLUSTERED INDEX [IX_num] ON #temp (num);
DBCC SHOW_STATISTICS ('tempdb..#temp', 'IX_num');

/* Create index before data load into temp table -- stats is not created */
CREATE TABLE #temp_nostats ( [text] varchar(50), [num] int);
CREATE UNIQUE CLUSTERED INDEX [IX_num] ON #temp_nostats (num);
INSERT INTO #temp_nostats([text], [num]) VALUES ('aaa', 1), ('bbb', 2) , ('ccc',3);
DBCC SHOW_STATISTICS ('tempdb..#temp_nostats', 'IX_num');

您需要测试索引是否对您有帮助。您需要平衡可以拥有的索引数,因为如果索引太多,它也会影响性能。

宋稳
2023-03-14

您的朋友可能是正确的,因为即使一个表将在一个查询中使用,在没有看到该查询的情况下(即使我们看到了,我们仍然不知道它的执行计划是什么样子的),我们也不知道SQL Server将需要多少次在这些表的各个列中查找数据以进行连接、排序等。

然而,我们永远无法确定,直到它实际以两种方式完成,并测量和比较结果。

 类似资料:
  • 我正在学习弹性搜索,还有很多东西我没有得到,但有一件事我不知道(或发现所有的)是什么时候使用一个索引,什么时候使用更多的索引。部分原因是我不知道弹性搜索索引到底是什么。 您能解释一下什么是弹性搜索索引吗?什么时候应该只对所有数据使用一个索引?什么时候应该将数据拆分为多个索引? 奖励点/或者,我如何判断何时需要将我的数据拆分为多个索引,然后,我应该如何决定如何将数据拆分为新的索引?

  • 问题内容: 有没有一种方法可以从ElasticSearch中检索有关特定索引的最新更新时间的信息?我的目标是能够知道什么时候是最后一次在索引中插入/更新/删除任何文档。如果无法做到这一点,是否可以在索引修改请求中添加一些内容,以便稍后提供此信息? 问题答案: 您可以从_timestamp获取修改时间 为了更轻松地返回时间戳,您可以设置Elasticsearch来存储它: 如果插入文档然后对其进行查

  • 问题内容: 数百万条记录的哪个更快:永久表 还是 临时表? 我只需要将其用于1500万条记录。处理完成后,我们将删除这些记录。 问题答案: 在您的情况下,我们使用称为临时表的永久表。这是大量进口的常用方法。实际上,我们通常使用两个登台表,一个带有原始数据,另一个带有清理后的数据,这使得研究提要中的问题变得更加容易(它们几乎总是我们客户发现向我们发送垃圾数​​据的新方式和多种方式的结果,但是我们必须

  • 主要内容:1 独立的列,2 前缀索引和索引选择性,3 多列(组合、联合)索引,3.1 多个单列索引的问题,3.2 使用多列索引,4 选择适合的索引列顺序,5 聚簇(聚集)索引,6 覆盖索引详细介绍了各种高性能的索引使用策略,比如联合索引、索引顺序、聚簇索引、覆盖索引等等,以及常见索引失效的情况。 前面我们已经介绍了各种类型的索引结构及其对应的优缺点: BTREE索引的数据结构以及具体实现原理深入解析 哈希索引的数据结构以及索引的优缺点 正确的创建和使用索引是实现高性能查询的基础。我们通常会看到一

  • 问题: 主键为复合哈希范围键的DynamoDB表是唯一的。这是否也延伸到二级指数? 示例: 我有一个带有post_id主键和comment_id范围键的comments DynamoDB表。此外,还有一个带有date-user_id范围键的本地辅助索引。 每个条目都是用户在发布时留下的评论。二级索引的目的是统计在特定的一天,有多少唯一的用户在一个帖子上留下了评论。 条目1:post_id:1 co

  • 我是弹性搜索的新手,我正在尝试使用下面的映射创建索引,我在网上找到了这些映射,并使用kibana作为我的客户机,它抛出错误。 “类型”:“映射程序解析异常”,“原因”:“根映射定义有不受支持的参数:[local_test:{u all={enabled=false},properties={amount={type=long},user_id={type=keyword},recurtive={t