与自动收缩 TempDB 作为 SQL 代理作业相关的风险?

Cen*_*rze 0 sql-server shrink tempdb sql-server-2016

我有一种情况,我对 TempDB 的大小有限制,不能超过 350 GB。我autogrowth 10在 TempDB 上使用(百分比),因为我读到它应该是超过 500 MB 的数据库的最佳实践。

当我使用

 dbcc checkdb with estimateonly 
Run Code Online (Sandbox Code Playgroud)

在每个数据库上,我注意到 TempDB 的估计需求比我目前的需求低得多。将 返回的值相加dbcc checkdb with estimateonly得到大约 75 GB 的值。

TempDB 的大小目前为 300 GB。我无法进一步增加 TempDB 的允许大小。

我听说我们公司以前有一个 SQL 作业,如果它超过某个值,它会自动缩小 TempDB,但它没有在我们的新环境中使用。然而,我很矛盾,对缩小 TempDB 过于宽松可能会导致问题。

使用这篇文章中的信息,如果当前大小超过 200 GB 左右,将 TempDB 自动收缩到 200 GB 大小是否存在任何重大风险,看到dbcc checkdb with estimateonly返回的估计最小大小为 75 GB,这将导致这一个相当高的相对缓冲?

我读过这不是缩小 TempDB 的最佳做法,但在这种情况下,参考 TempDB 的估计最小大小,它可能更“合法”吗?

编辑

我做了以下查询,例如,internal object MB space, internal object dealloc MB space, statement text(查询), total elapsed time, is_user_process

WITH task_space_usage AS (
    SELECT dmv_tsu.session_id,
           dmv_tsu.request_id,
           SUM(dmv_tsu.internal_objects_alloc_page_count) AS alloc_pages,
           SUM(dmv_tsu.internal_objects_dealloc_page_count) AS dealloc_pages,
           dmv_es.login_name,
           dmv_es.host_name,
           dmv_es.program_name,
           dmv_es.is_user_process,
           dmv_es.total_elapsed_time,
           er.start_time,
           er.estimated_completion_time,
           er.command
    FROM sys.dm_db_task_space_usage dmv_tsu WITH (NOLOCK)
    INNER JOIN sys.dm_exec_sessions dmv_es
ON (dmv_tsu.session_id = dmv_es.session_id)
    INNER JOIN sys.dm_exec_requests er ON dmv_tsu.session_id = er.session_id and dmv_tsu.request_id = er.request_id 
    WHERE dmv_tsu.session_id <> @@SPID
    GROUP BY dmv_tsu.session_id, dmv_tsu.request_id,dmv_es.login_name,dmv_es.host_name,dmv_es.program_name,dmv_es.is_user_process,
           dmv_es.total_elapsed_time,er.start_time,
           er.estimated_completion_time,
           er.command
)
SELECT TSU.session_id,
       TSU.alloc_pages * 1.0 / 128 AS [internal object MB space],
       TSU.dealloc_pages * 1.0 / 128 AS [internal object dealloc MB space],
       EST.text,
       ISNULL(
           NULLIF(
               SUBSTRING(
                 EST.text, 
                 ERQ.statement_start_offset / 2, 
                 CASE WHEN ERQ.statement_end_offset < ERQ.statement_start_offset 
                  THEN 0 
                 ELSE( ERQ.statement_end_offset - ERQ.statement_start_offset ) / 2 END
               ), ''
           ), EST.text
       ) AS [statement text],
       EQP.query_plan,
       TSU.host_name,
       TSU.login_name,
       TSU.program_name,
       TSU.is_user_process,
       TSU.total_elapsed_time,
       TSU.start_time,
           TSU.estimated_completion_time,
           TSU.command
FROM task_space_usage AS TSU
INNER JOIN sys.dm_exec_requests ERQ WITH (NOLOCK)
    ON  TSU.session_id = ERQ.session_id
    AND TSU.request_id = ERQ.request_id
OUTER APPLY sys.dm_exec_sql_text(ERQ.sql_handle) AS EST
OUTER APPLY sys.dm_exec_query_plan(ERQ.plan_handle) AS EQP
WHERE EST.text IS NOT NULL OR EQP.query_plan IS NOT NULL
ORDER BY 10 DESC;
Run Code Online (Sandbox Code Playgroud)

我的问题是:

将这样的查询与 SQL 代理作业结合使用是否更有益,该作业表示:`

If TempDB > maxSize then CheckTheQueryPosted, terminate all queries which is a user process
Run Code Online (Sandbox Code Playgroud)

我知道这不是代码,但我的意思是在这个概念的行中?

Dan*_*her 6

当谈到 tempdb 和收缩数据库时,有很多常见的误解。

首先,如果 tempdb 增长超过 350 GB,那是因为它需要。随着这种规模的增长,我会说 ETL 工作或手动批处理表现不佳。您可以通过多种方式解决此问题,其中最好的是(我认为)

  • 修复占用 tempdb 的查询:如果您正在执行 Read Committed Snapshot Isolation,则寻找没有适当索引的大型哈希匹配或排序操作,甚至行版本控制。
  • 添加更多磁盘空间。在大多数环境中,这只是给您的 SAN 管理员打电话的问题。

通常,我会建议将 tempdb 放在自己的磁盘上并从一开始就调整数据库的大小,这样您就可以完全避免自动增长。自动增长 10% 通常是非常糟糕的做法,原因有两个:

  • 当数据库很小时,自动增长可能非常频繁,并且与您的物理存储扇区不对齐
  • 对于更大的数据库,文件一旦增加就会增长很多。

收缩 tempdb 的另一个问题是 SQL Server 在其中保留了大量内容,以防止其收缩。您会发现即使您尝试缩小 tempdb,它也不会,除非您几乎重新启动服务器(无论是从字面上还是通过清除各种缓冲区,这两者都会对您的生产环境产生巨大影响) .

总之

  • 不要自动收缩,确保从一开始就有足够的空间。
  • 从一开始就考虑调整 tempdb 的大小,这样它就不必自动增长。
  • 看看您是否可以调整那些填充您的 tempdb 的查询。它们也可能是运行时间最长的那些。