Let we have a table of payments having 35 columns with a primary key (autoinc bigint) and 3 non-clustered, non-unique indeces (each on one int column).
讓我們有一個支付表,其中35列包含主鍵(autoinc bigint)和3個非聚集,非唯一的indeces(每個在一個int列上)。
Among the table's columns we have two datetime fields:
在表的列中,我們有兩個datetime字段:
payment_date datetime NOT NULL
payment_date datetime NOT NULL
edit_date datetime NULL
edit_date datetime NULL
The table has about 1 200 000 rows. Only ~1000 of rows have edit_date column = null. 9000 of rows have edit_date not null and not equal to payment_date Others have edit_date=payment_date
該表有大約1 200 000行。只有~1000行有edit_date column = null。 9000行的edit_date不為null且不等於payment_date其他行有edit_date = payment_date
When we run the following query 1:
當我們運行以下查詢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
server needs a couple of seconds to do it. But if we run query 2:
服務器需要幾秒鍾才能完成。但是如果我們運行查詢2:
select top 1 *
from payments
where edit_date is not null
order by payment_date desc
the execution ends up with The log file for database 'tempdb' is full. Back up the transaction log for the database to free up some log space.
執行結束於數據庫'tempdb'的日志文件已滿。備份數據庫的事務日志以釋放一些日志空間。
If we replace * with some certain column, see query 3
如果我們用某些列替換*,請參閱查詢3
select top 1 payment_date
from payments
where edit_date is not null
order by payment_date desc
it also finishes in a couple of seconds.
它也會在幾秒鍾內完成。
Where is the magic?
魔術在哪里?
EDIT I've changed query 1 so that it operates over exactly the same number of rows as the 2nd query. And still it returns in a second, while query 2 fills tempdb.
編輯我已經更改了查詢1,以便它在與第二個查詢完全相同的行數上運行。並且它仍然在一秒鍾內返回,而查詢2填充tempdb。
ANSWER I followed the advice to add an index, did this for both date fields - everything started working quick, as expected. Though, the question was - why in this exact situation sql server behave differently on similar queries (query 1 vs query 2); I wanted to understand the logic of the server optimization. I would agree if both queries did used tempdb similarly, but they didn't....
答案我按照建議添加索引,在兩個日期字段中都這樣做 - 一切都按預期開始快速運行。雖然,問題是 - 為什么在這種情況下,sql server在類似的查詢上表現不同(查詢1與查詢2);我想了解服務器優化的邏輯。我同意,如果兩個查詢都使用了類似的tempdb,但他們沒有....
In the end I mark as the answer the first one, where I saw the must-be symptoms of my problem and the first, as well, thoughts on how to avoid this (i.e. indeces)
最后我標記為第一個答案,在那里我看到了我的問題的必然症狀,第一個,以及關於如何避免這種情況的想法(即凹痕)
5
This is happening cause certain steps in an execution plan can trigger writes to tempdb
in particular certain sorts
and joins
involving lots of data.
發生這種情況會導致執行計划中的某些步驟觸發對tempdb的寫入,特別是涉及大量數據的某些排序和連接。
Since you are sorting a table with a boat load of columns, SQL decides it would be crazy to perform the sort alone in temp db without the associated data. If it did that it would need to do a gazzilion inefficient bookmark lookups on the underlying table.
由於您正在使用列加載列對表進行排序,因此SQL決定在沒有關聯數據的情況下在temp db中單獨執行排序會很瘋狂。如果它這樣做,它將需要在基礎表上進行一個低效的書簽查找。
Follow these rules:
遵循以下規則:
4
Usually, tempdb fills up when you are low on disk space, or when you have set an unreasonably low maximum size for database growth. Many people think that tempdb is only used for #temp tables. When in fact, you can easily fill up tempdb without ever creating a single temp table. Some other scenarios that can cause tempdb to fill up:
通常,當磁盤空間不足時,或者為數據庫增長設置了不合理的低最大大小時,tempdb會填滿。許多人認為tempdb僅用於#temp表。實際上,您可以輕松填充tempdb而無需創建單個臨時表。其他一些可能導致tempdb填滿的場景:
use of an ODBC DSN with the option 'create temporary stored procedures' set can leave objects there for the life of the connection.
使用帶有“創建臨時存儲過程”選項的ODBC DSN可以在連接的生命周期中保留對象。
USE tempdb GO
使用tempdb GO
SELECT name
FROM tempdb..sysobjects
SELECT OBJECT_NAME(id), rowcnt
FROM tempdb..sysindexes
WHERE OBJECT_NAME(id) LIKE '#%'
ORDER BY rowcnt DESC
The higher rowcount, values will likely indicate the biggest temporary tables that are consuming space.
行數越高,值可能表示占用空間的最大臨時表。
Short-term fix
短期修復
DBCC OPENTRAN -- or DBCC OPENTRAN('tempdb')
DBCC INPUTBUFFER(<number>)
KILL <number>
Long-term prevention
長期預防
-- 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
Reference : http://sqlserver2000.databases.aspfaq.com/why-is-tempdb-full-and-how-can-i-prevent-this-from-happening.html
Other references : http://social.msdn.microsoft.com/Forums/is/transactsql/thread/af493428-2062-4445-88e4-07ac65fedb76
參考:http://sqlserver2000.databases.aspfaq.com/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
本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2012/08/09/cf89c5a81c767d6f94337a8220c929b5.html。