Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 查询所有表的不同计数时Tempdb Full_Database_Sql Server 2012_Tempdb - Fatal编程技术网

Database 查询所有表的不同计数时Tempdb Full

Database 查询所有表的不同计数时Tempdb Full,database,sql-server-2012,tempdb,Database,Sql Server 2012,Tempdb,原始问题 我创建了一个自定义脚本,用于将数据从远程SQL server检索到办公室的本地副本中。我在脚本中遇到了一些问题,其中选定的表插入了两次某些数据,从而创建了重复项。我知道所有数据库中的所有表都不应该有重复项 这个问题让我产生了一种妄想,其他表可能在历史上有过这个问题,因此我想验证一下 解决方案 我创建了一个SQL脚本,用于将所有列的计数和不同计数插入到服务器上所有数据库(不包括4个系统数据库)的表中: 表变量@AllTables使用带有信息的sp_msforeachdb_SCHEMA.T

原始问题

我创建了一个自定义脚本,用于将数据从远程SQL server检索到办公室的本地副本中。我在脚本中遇到了一些问题,其中选定的表插入了两次某些数据,从而创建了重复项。我知道所有数据库中的所有表都不应该有重复项

这个问题让我产生了一种妄想,其他表可能在历史上有过这个问题,因此我想验证一下

解决方案

我创建了一个SQL脚本,用于将所有列的计数和不同计数插入到服务器上所有数据库(不包括4个系统数据库)的表中:

表变量@AllTables使用带有信息的sp_msforeachdb_SCHEMA.TABLES列出所有数据库中的所有表(共16537个表)。表游标用于存储所有非系统项,然后我使用动态SQL进行计数和不同的计数,该计数存储在另一个表变量@ResultsTable中

此解决方案的问题

当我运行此查询时,它将运行大约3分钟,然后抛出一个错误,指出tempdb主文件组已满:

我是我自己的DBA,我习惯于设置我的SQL server实例,我的tempdb设置了8 x 3GB mdf/ndf文件(服务器有8个核心):

这些文件在“常规”属性下显示为有23997MB可用空间

我的问题

  • 如果我有大约24GB的tempdb可用空间,为什么这个相对简单的查询会耗尽tempdb空间
  • 是否有更好/更有效的方法获取所有数据库中所有表的计数和不同计数

  • 在添加TEMPDB文件之前,应该始终考虑争用。添加7个额外的TempDb文件并没有真正的帮助

    如果我有大约24GB的tempdb可用空间,为什么这是相对的 简单查询是否耗尽了tempdb空间

    不,不应该。但是,您确定您没有处理大量的数据,或者您没有在SQL上运行其他进程吗?游标、临时表甚至表变量广泛使用TempDb。检查哪个对象占用更多的TempDb空间:

    SELECT
        SUM (user_object_reserved_page_count)*8 as usr_obj_kb,
        SUM (internal_object_reserved_page_count)*8 as internal_obj_kb,
        SUM (version_store_reserved_page_count)*8  as version_store_kb,
        SUM (unallocated_extent_page_count)*8 as freespace_kb,
        SUM (mixed_extent_page_count)*8 as mixedextent_kb
    FROM sys.dm_db_file_space_usage
    
    因此,如果您的用户和内部对象更多,那么这显然意味着由于游标和SQL Server内部使用(例如:中间表、散列联接、散列聚合等),您的TempDb空间较低

    是否有更好/更有效的方法来获取计数和区分 所有数据库中所有表的计数

    您可以使用下面的代码获取所有数据库中所有表的计数

      DECLARE @Stats TABLE (DBNAME VARCHAR(40), NAME varchar(200), Rows INT)
    INSERT INTO @Stats
    EXECUTE sp_MSForEachDB 
            'USE ?; SELECT DB_NAME()AS DBName, 
            sysobjects.Name
        , sysindexes.Rows
    FROM
        sysobjects
        INNER JOIN sysindexes
        ON sysobjects.id = sysindexes.id 
    WHERE
        type = ''U''
        AND sysindexes.IndId < 2'
    
        SELECT * FROM @Stats
    
    同样,您可以使用下面的查询在所有数据库的所有表中使用distinct

        DECLARE @ServerStatsDistinct TABLE (DatabaseName varchar(200), TableName varchar(200), RowsCount INT)
    INSERT INTO @ServerStatsDistinct
    exec sp_msforeachdb @command1='
    use #;
    if ''#''  NOT IN (''master'', ''model'', ''msdb'', ''tempdb'',''ReportServer'')
    begin
    print ''#''
    exec sp_MSforeachtable @command1=''
    SELECT ''''#'''' AS DATABASENAME, ''''?'''' AS TABLENAME, COUNT(*)  FROM  (
        SELECT DISTINCT *
        FROM ?
    ) a  ;
    ''
    end 
    ', @replacechar = '#'
    
    SELECT * FROM @ServerStatsDistinct
    

    正在处理多少数据?如果对具有许多不同值的不同数据进行区分,则所有这些值最终都会出现在临时工作表中。解决这一问题的办法并非微不足道。您需要分块处理该表。感谢回复usr。您是指子查询:从“+@TableFullName”中选择DISTINCT*?是否已将其放入tempdb中?显然,它处理数千个表,因此如果它缓存所有这些表(我本以为每次循环都会清除缓存?),那么它将有数百GB的数据。子查询在循环的每次迭代中都不会从缓存中删除吗?我会在上面搜索一下。你在说什么缓存?每次查询结束时,tempdb的使用结束。一定有一些大的查询。我承认我对查询缓存的了解非常有限,但是为什么SQL server会为循环中运行的每个子查询缓存所有的表(以及整个表)?谢谢回答Anuj。虽然我并不自称是专家,但我对tempdb的了解足以让我了解争用,并且我已经按照微软的指导为8个处理器内核设置了8个tempdb文件。在这种情况下,问题是由SELECT DISTINCT导致的,SELECT DISTINCT每次都在tempdb中缓存。由于我正在对服务器实例中的每个数据库执行此查询,因此任何tempdb重新配置都不足以完成此操作。但是,我的另一个经验领域是VB,因此我将编写一个VBA程序来实现这一点,并在这里发布答案。我还想指出,您提供的用于检查哪些对象用于消耗tempdb空间的代码非常有用,谢谢您(我将在稍后提供的答案中使用此代码)。但是,您提供的用于获取每个表中的行的代码没有太大帮助,因为(1)它没有为我提供不同的计数,这是我的问题的一个要求,(2)它基于统计数据,没有计数(*)那么准确。@quarcheck我已经用更新的查询库编辑了我的答案,以继续支持Anuj。最后,事实证明,使用您在原始答案中给我的查询帮助我找到了问题的根源。我真的很喜欢你独特的查询实际上,它比我自己的要简洁得多。我不知道我可以将sp_msforeachdb执行到这样的表中,或者您可以将sp_msforeachtable嵌套到sp_msforeachdb中。非常聪明!用光标救了我!最后,问题是一个大表(唯一一个大于24GB的表)接近结果的开始,这导致tempdb抛出错误。在对结果进行排序后,我发现了这个问题。在我排除此表后,它目前正在运行最后几个数据库,因此再次感谢您的帮助。自编辑以来,我已将您的答案标记为已接受答案,因为您已成功回答了我的两个问题。:)
        DECLARE @ServerStats TABLE (DatabaseName varchar(200), TableName varchar(200), RowsCount INT)
    INSERT INTO @ServerStats
    exec sp_msforeachdb @command1='
    use #;
    if ''#'' NOT IN (''master'', ''model'', ''msdb'', ''tempdb'',''ReportServer'')
    begin
    print ''#''
    exec sp_MSforeachtable @command1=''
    SELECT ''''#'''' AS DATABASENAME, ''''?'''' AS TABLENAME, COUNT(*)  FROM ? ;
    ''
    end 
    ', @replacechar = '#'
    
    SELECT * FROM @ServerStats
    
        DECLARE @ServerStatsDistinct TABLE (DatabaseName varchar(200), TableName varchar(200), RowsCount INT)
    INSERT INTO @ServerStatsDistinct
    exec sp_msforeachdb @command1='
    use #;
    if ''#''  NOT IN (''master'', ''model'', ''msdb'', ''tempdb'',''ReportServer'')
    begin
    print ''#''
    exec sp_MSforeachtable @command1=''
    SELECT ''''#'''' AS DATABASENAME, ''''?'''' AS TABLENAME, COUNT(*)  FROM  (
        SELECT DISTINCT *
        FROM ?
    ) a  ;
    ''
    end 
    ', @replacechar = '#'
    
    SELECT * FROM @ServerStatsDistinct