2012-08-09 145 views
5

讓我們有一個包含35個主鍵(autoinc bigint)和3個非集羣非唯一索引(每個索引一個int列)。爲什麼我會得到「數據庫'tempdb'的日誌文件已滿'

在表列有兩個日期時間字段:

  1. PAYMENT_DATEdatetime NOT NULL

  2. EDIT_DATEdatetime NULL

表大約有1 200 000行。 只有〜1000行具有edit_date column = null。 9000行有EDIT_DATE不空,不等於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 

enter image description here

服務器需要一對夫婦幾秒鐘就可以做到。但是,如果我們運行查詢2

select top 1 * 
from payments 
where edit_date is not null 
order by payment_date desc 

enter image description here

執行與結束了對tempdb數據庫中的日誌文件已滿。備份數據庫的事務日誌以釋放一些日誌空間。

如果我們更換*與某些特定的列,見查詢3

select top 1 payment_date 
from payments 
where edit_date is not null 
order by payment_date desc 

enter image description here

也完成在幾秒鐘。

魔法在哪裏?

編輯 我已經更改了查詢1,以便它的操作與第二個查詢的行數完全相同。並且它仍然在一秒鐘內返回,而查詢2填充tempdb。

ANSWER 我跟着建議添加一個索引,這樣做兩個日期字段 - 一切都開始工作快速,符合市場預期。雖然,問題是 - 爲什麼在這種情況下,sql server在類似的查詢(查詢1對查詢2)上表現不同?我想了解服務器優化的邏輯。我同意,如果兩個查詢都使用tempdb類似,但他們沒有......

最後,我標記爲第一個答案,在那裏我看到了我的問題和第一個問題的必然症狀,以及如何避免這種想法(即的indeces)

+1

你有沒有考慮以下錯誤消息的建議嗎?某些查詢將需要使用tempdb,並且如果日誌文件已滿,則不能執行其他事務。 – 2012-08-09 03:11:58

+1

@AndrewBarber我didn't..but什麼,我試圖找出是爲什麼幾乎相似的查詢,完全不同執行...和我怎麼有望建成查詢來避免這種behaivour的.. – horgh 2012-08-09 03:46:15

+2

不要使用* *選擇所有列,對於初學者。並備份該事務日誌。 – 2012-08-09 03:47:51

回答

5

這是發生原因某些步驟在執行計劃可以觸發特別是某些sortsjoins涉及大量的數據寫入到tempdb

因爲你是一個排序表列的船載,SQL決定這將是瘋狂的臨時數據庫沒有相關的數據單獨執行排序。如果這樣做,就需要做一個gazzilion基礎表低效書籤查找。

遵循以下規則:

  1. 儘量選擇只有你適當地需要
  2. 大小tempdb中,如果你需要做瘋狂的查詢,一個gazzilion行進行排序的數據,你最好有一個適當大小的tempdb
+0

但爲什麼沒有做同樣「瘋狂」的操作,當我嘗試執行第一個問題(見)查詢......如果再算上從第一和第二查詢,他們幾乎相等造成的行數(大約一百萬)......但是,在第一個中使用'TOP 1'效果不錯,但在第二個中 - 它失敗了......第二個查詢中的什麼會導致日誌使用率? – horgh 2012-08-09 04:24:40

+0

@horgh *所有事務*會導致日誌使用。你應該問的問題是「什麼導致tempdb使用」。 – 2012-08-09 04:45:24

+0

對不起,我的意思正是... – horgh 2012-08-09 04:50:10

4

通常情況下,tempdb中填滿了,當你的磁盤空間不足,或者當您已設置了數據庫的增長不合理的低最大尺寸。 很多人認爲tempdb中僅用於#TEMP表。實際上,您可以輕鬆填充tempdb,而無需創建單個臨時表。這可能會導致tempdb中的其他場景來填補:

  • ,需要更多的內存比已分配給SQL服務器 將被迫做的工作在tempdb任何排序;
  • 如果排序需要比分配給tempdb更多的空間, 將會發生上述錯誤之一;
  • DBCC CheckDB('任何數據庫')將在tempdb中執行其工作 - 在 較大的數據庫上,這會佔用相當多的空間;
  • DBCC DBREINDEX或類似DBCC與「排序在tempdb」選項 集也將潛在地填滿tempdb的命令;
  • 大結果集的笛卡爾 連接,外連接,遊標,臨時表,表變量和 散列常常需要從tempdb中幫助涉及工會,以便通過/組;
  • 任何未提交併未回滾的事務可能會使 對象在tempdb中孤立;
  • 使用具有「創建臨時存儲的 過程」選項的ODBC DSN可以在該連接的生命期間留下對象。

    使用tempdb GO

    SELECT name 
         FROM tempdb..sysobjects 
    
        SELECT OBJECT_NAME(id), rowcnt 
         FROM tempdb..sysindexes 
         WHERE OBJECT_NAME(id) LIKE '#%' 
         ORDER BY rowcnt DESC 
    

較高的行數,值可能會表明,在消費空間最大的臨時表。

短期修復

DBCC OPENTRAN -- or DBCC OPENTRAN('tempdb') 
DBCC INPUTBUFFER(<number>) 
KILL <number> 

長期的預防

-- 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 

參考: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

+0

你試過這個嗎? select top 1 payment_date from payments 其中edit_date不爲空並且payment_date = edit_date order by payment_date desc – 2012-08-09 06:12:39

+0

我測試了問題中提供的所有查詢。或者你在問什麼? – horgh 2012-08-09 06:27:30

+0

我想知道,多少時間做這個查詢需要執行 – 2012-08-09 06:36:10

相關問題