hor*_*rgh 5 sql sql-server sql-server-2000 sql-execution-plan
让我们有一个支付表,其中35列包含主键(autoinc bigint)和3个非聚集的非唯一indeces(每个在一个int列上).
在表的列中,我们有两个日期时间字段:
付款日期 datetime NOT NULL
EDIT_DATE datetime NULL
该表有大约1 200 000行.只有~1000行有edit_date column = null.9000行的edit_date不为null且不等于payment_date其他行有edit_date = payment_date
当我们运行以下查询1时:
select top 1 *
from payments
where edit_date is not null and (payment_date=edit_date or payment_date<>edit_date)
order by payment_date desc
Run Code Online (Sandbox Code Playgroud)

服务器需要几秒钟才能完成.但是如果我们运行查询2:
select top 1 *
from payments
where edit_date is not null
order by payment_date desc
Run Code Online (Sandbox Code Playgroud)

执行结束于数据库'tempdb'的日志文件已满.备份数据库的事务日志以释放一些日志空间.
如果我们用某些列替换*,请参阅查询3
select top 1 payment_date
from payments
where edit_date is not null
order by payment_date desc
Run Code Online (Sandbox Code Playgroud)

它也会在几秒钟内完成.
魔术在哪里?
编辑 我已经更改了查询1,以便它在与第二个查询完全相同的行数上运行.并且它仍然在一秒钟内返回,而查询2填充tempdb.
答案 我按照建议添加了一个索引,为两个日期字段做了这个 - 一切都按预期开始快速运行.虽然,问题是 - 为什么在这种情况下,sql server在类似的查询上表现不同(查询1与查询2); 我想了解服务器优化的逻辑.我同意如果两个查询都使用了类似的tempdb,但他们没有....
最后我将答案标记为第一个,在那里我看到了问题的必然症状,第一个,以及关于如何避免这种情况的想法(即凹痕)
发生这种情况是因为执行计划中的某些步骤可能会触发tempdb特定的写入sorts并joins涉及大量数据.
由于您正在使用列加载列对表进行排序,因此SQL决定在没有关联数据的情况下在temp db中单独执行排序会很疯狂.如果它这样做,它将需要在底层表上执行gazzilion低效的书签查找.
遵循以下规则:
通常,当磁盘空间不足或为数据库增长设置了不合理的低最大大小时,tempdb 会填满。许多人认为 tempdb 仅用于 #temp 表。事实上,您可以轻松地填充 tempdb,而无需创建单个临时表。其他一些可能导致 tempdb 填满的场景:
使用带有“创建临时存储过程”选项的 ODBC DSN 可以在连接的生命周期内将对象留在那里。
使用 tempdb 去
SELECT name
FROM tempdb..sysobjects
SELECT OBJECT_NAME(id), rowcnt
FROM tempdb..sysindexes
WHERE OBJECT_NAME(id) LIKE '#%'
ORDER BY rowcnt DESC
Run Code Online (Sandbox Code Playgroud)较高的行数值可能表示消耗空间的最大临时表。
短期修复
DBCC OPENTRAN -- or DBCC OPENTRAN('tempdb')
DBCC INPUTBUFFER(<number>)
KILL <number>
Run Code Online (Sandbox Code Playgroud)
长期预防
-- SQL Server 7.0, should show 'trunc. log on chkpt.'
-- or 'recovery=SIMPLE' as part of status column:
EXEC sp_helpdb 'tempdb'
-- SQL Server 2000, should yield 'SIMPLE':
SELECT DATABASEPROPERTYEX('tempdb', 'recovery')
ALTER DATABASE tempdb SET RECOVERY SIMPLE
Run Code Online (Sandbox Code Playgroud)
参考:https : //web.archive.org/web/20080509095429/http : //sqlserver2000.databases.aspfaq.com : 80/why-is-tempdb-full-and-how-can-i-prevent-this- from-happening.html
其他参考资料:http : //social.msdn.microsoft.com/Forums/is/transactsql/thread/af493428-2062-4445-88e4-07ac65fedb76