SQL : Weird query performance after "select into" a new table

标签 sql sql-server sql-server-2008

我遇到了如下奇怪的情况:

我在名为“Table1”的数据库中有一个巨大的表。 然后,我使用以下代码复制完全相同的表。

选择* 代入表2 来自表1

之后, 我发现查询性能有显着差异。

选择计数(不同 ID) 来自表1 大约需要 2 分钟才能完成。 (旧表)

同时, 选择计数(不同 ID) 来自表2 只需大约 10 秒即可完成(新表)

顺便说一句,我发现在“select into”之后,newtable 中的数据已重新排序。 此外,在“选择”新表之前,在 Table1(旧表)中添加了一列 (即更改表格,将 col1 添加为 col2。)

那么,这是怎么发生的呢?

(NB: The original version of the question stated that the new table was the slow one. This was an error. Also, it didn't mention about the data manipulation on Table1)

<小时/>

对更多信息请求的回复

这是 Sebastian 代码的结果。

SELECT  QUOTENAME(OBJECT_SCHEMA_NAME(t.object_id)) + '.' + QUOTENAME(t.name) tbl,
        s.name stats_name,
        cols.cols,
        t.create_date table_date,
        STATS_DATE(s.object_id, s.stats_id) AS statistics_date,
        s.auto_created,
        s.user_created,
        s.no_recompute,
        s.has_filter,
        s.filter_definition
FROM    sys.tables t
LEFT OUTER JOIN sys.stats s
        ON s.object_id = t.object_id
OUTER APPLY (
              SELECT  STUFF((SELECT ',' + c.name
                             FROM   sys.stats_columns sc
                             JOIN   sys.columns c
                                    ON sc.column_id = c.column_id
                                       AND sc.object_id = c.object_id
                             WHERE  sc.object_id = s.object_id
                                    AND sc.stats_id = s.stats_id
                             ORDER BY sc.stats_column_id
                      FOR   XML PATH(''),
                                TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '') cols
            ) cols
--Update Table Name(s) here:      
WHERE   t.OBJECT_ID IN ( OBJECT_ID('[Sales].[SpecialOffer]'),
        OBJECT_ID('[Sales].[SalesOrderDetail]') );

SELECT  name,
        compatibility_level,
        is_auto_close_on,
        is_auto_shrink_on,
        state_desc,
        is_auto_create_stats_on,
        is_auto_update_stats_on,
        is_auto_update_stats_async_on
FROM sys.databases
WHERE database_id = DB_ID();

实际上,我将新表复制到另一个数据库。 而表名实际上命名为ID2000

上图引用“Table1”(数据库1) 下图引用“Table2”(数据库2)

"Table1"

"Table2"

<小时/>

好吧,由于 XML 代码太长,这里是遵循哈姆雷特建议的替代打印输出。 我用 SET SHOWPLAN_ALL ON GO 而不是粘贴所有 XML 代码。希望对您有所帮助。

红色代表“表1”计划,黑色代表“表2”计划。 图像中的文字有点小,但是通过增加此页面尺寸来放大只会放大它。

非常感谢!! Figure 1

<小时/>

SELECT * FROM sys.dm_db_index_physical_stats(db_id(),object_id('YourTable'),NULL,NULL,'Detaile‌​d') 的结果

确实,两个表之间存在巨大差异。 同样,红色代表“表1”,红色代表“表2”

这个问题很烦人,它让我发疯,因为我一直问自己是否应该重建所有表。 :( enter image description here

实际上这很奇怪,请注意 record_count 是不同的。 但是,当我重新检查时 select COUNT (ID) from id2000 ,(即计算该表上的总数据行数) 两个结果都是2324798,即Table_2的record_count

此外,“Table2”是由“select * into”语句创建的,我想两者应该是相同的,但现在我很困惑。

enter image description here 上表是 Sebastian 代码(运行统计)的结果

<小时/>

SELECT * FROM sys.dm_db_index_physical_stats(db_id(),object_id('YourTable'),NULL,NULL,'Detaile‌​d') 的结果

确实,两个表之间存在巨大差异。 同样,红色代表“表1”,红色代表“表2”

这个问题很烦人,它让我发疯,因为我一直问自己是否应该重建所有表。 :( enter image description here

实际上这很奇怪,请注意 record_count 是不同的。 但是,当我重新检查时 select COUNT (ID) from id2000 ,(即计算该表上的总数据行数) 两个结果都是2324798,即Table_2的record_count

此外,“Table2”是由“select * into”语句创建的,我想两者应该是相同的,但现在我很困惑。

最佳答案

好吧,既然我们已经弄清楚旧表是慢表而不是新表,一切都表明转发记录量极高是罪魁祸首。

要删除转发的记录,您可以使用以下查询:

ALTER TABLE dbo.Table2 REBUILD;

向堆中添加列很可能会导致每行频繁移动,从而导致大量转发记录。 sys.dm_db_index_physical_stats DMV 返回的 forwarded_records_count 列显示转发数量 - 几乎您案例中的所有行。

SELECT * INTO 不会复制转发指针,而是对其进行重新组织。因此您确实看到了性能差异。

当我们谈论转发时,在大多数情况下,在表上拥有聚集索引是一个非常好的主意。这样就避免了类似的问题。

在您的情况下,ID 列似乎是聚集主键的候选者(如果它是唯一的),但我需要了解有关该模型的更多信息才能在此处为您提供建议。

关于SQL : Weird query performance after "select into" a new table,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14031665/

相关文章:

mysql - 通过 MySQL 中的 bool 值查找 JSON 对象路径

sql - PgSQL 上的累积值和有界总和

mysql - 查询一个人一年内购买了多少次

sql-server - SQL - 从合并查询过滤器获取数据库名称

sql-server - 无法根据 View 的存在使用 IF 创建或更改 View

c# - 如何在 lambda 中执行 sql 连接?

c# - 如何使用 Dapper 将字符串作为 NULL 发送到 SQLServer?

.net - SQL Server 2008 - HashBytes 计算列

java - beans.xml 中的 ms sql 配置

SQL Server - 如何在我的表上查找依赖表?