2011-04-26 69 views
8

包銷公司剛給我們送來引線的數據提取。有900萬行。這些行由LeadID(guid),RawLeadXML(xml - 最大可能爲3-4kb)和LeadStatusID(int)組成。巨大的表(9萬條記錄)

我第一次嘗試添加一個自動編號整數,並使其此表的主鍵。那麼,它添加了該字段,但無法使其成爲主鍵(緩衝池中沒有足夠的可用內存)。

我需要做的是將每個記錄逐一取出並獲取XML,將其放入.Net中的XmlDocument對象中,去掉所有我想要的字段(名字,姓氏等),並將解析的信息存儲到另一個表中。

我甚至無法獲得此聲明運行:SELECT * FROM信息,其中編號1和1000

之間

如果我只是在一個時間選擇1000條記錄(前1000 *從信息中選擇),這樣的作品,但是我怎麼會選擇沒有某種參考點的下一個1000條記錄呢?

我的機器有4個處理器(2.53GHz的)和12 GB的RAM。它不是一臺服務器,但它是一臺強健的機器。老實說,我不知道下一步該怎麼嘗試。

編輯:我離開了原來的文件實際上是一箇中密度纖維板(以及相關的LDF)文件,所以我重視他們在SQL Server中。

編輯2:我搞砸了,並表示,RawLeadXML列是XML - 它不是,它只是爲nvarchar(最大)。我真的不知道那裏是一個XML數據類型。

編輯3:我甚至不能出具該表DELETE語句: 「從引線刪去leadid = '100a7927-5311-4f12-8fe3-95c079d32dd4'」 與炸燬:

Msg 802, Level 17, State 20, Line 2 
There is insufficient memory available in the buffer pool. 

我不知道下一步該怎麼做。這到底是怎麼回事?世界上有成千上萬的數據庫比我有更多的記錄。

編輯4:如果有人關心,沒有下面的解決方案的工作。我確信這是我機器的限制,絕對不是對我在下面收到的好答案的譴責。目前,我傳送壓縮DB(2.6 GB)到我們的服務器在Rackspace公司,然後我將嘗試在該硬件上增加一個索引,希望不採取了我們的生產服務器。一旦添加了索引,我希望我可以壓縮數據庫並將其重新下載到本地計算機,然後實際上可以對其進行操作。

編輯5:我的機器字面上無法處理這種大小的表格。我的機器有12 GB RAM,64位Windows 7 Professional,四核2.53Ghz處理器,SSD驅動器等。這對於開發機器來說非常有用。它無法處理這個問題。

所以,我搬到了DB我們在Rackspace公司在倫敦的服務器。 48 GB或內存中,並能夠添加我需要的索引。即使在那之後,我的機器在這裏無法做任何事情都那麼有用了下來,所以我寫了在倫敦運行的撲救記錄1000的時間,把它解析爲另一個表,然後一個.net程序將原始記錄標記爲已處理。

一旦我這樣做,我將不得不離開數據庫在倫敦,因爲我懷疑我可以在本地寫出任何有意義的報告來對付這個怪物。這會讓開發變得有趣。

摘要:我相信沒有好的方法來處理這個大的數據集,而不使用具有至少48 GB的RAM(在我的情況下)的服務器級硬件。

+0

做了沒有where子句的select,開始返回行嗎?如果是這樣,那似乎是一種選擇。如果沒有,你是否還有原始文本文件?直接處理該文件會更容易,而不必使用數據庫? – forsvarir 2011-04-26 18:17:52

+0

對不起,只是編輯了這個問題。沒有CSV或任何東西,他們是mdf和ldf文件。 – 2011-04-26 18:43:10

+0

但是rawlead列,在nvarchar max中是否存在xml? – Ivo 2011-04-26 18:51:56

回答

4

900萬行不是那麼大,您可能沒有LeadId列上的索引。首先創建一個,但它需要一些時間(不必是唯一的或主鍵)。 對於第一個查詢,比使用 「SELECT TOP 1000 LeadId,RawXML ORDER BY LeadId」。 記錄最後LeadId(MaxLeadId)值,使用 「SELECT TOP 1000 LeadId,RawXML凡LeadId> MaxLeadId ORDER BY LeadId」 等等...

+0

如果導出到平面文件然後導入到目標表格方法不起作用,我可能會嘗試此操作。 – 2011-04-26 19:00:50

+0

選擇top 1000 * from lead by leadid也會導致緩衝存儲器錯誤。我會嘗試重新啓動我的機器並嘗試它,但是我將165k條記錄導出到一個平面文件,以便先嚐試不同的方法。 – 2011-04-26 19:46:09

+0

現在我正在添加一把鑰匙(30分鐘內只有200k條記錄出口,所以,雖然我仍然可以嘗試這條路線,但我不會這樣做,直到我可以啓動並回家)。 – 2011-04-26 20:00:30

0

如果這是一個平面文件,你可能會得到前1000行,加載它們,然後返回並從文件中刪除基於GUID的行,然後重複? (當然首先備份文件)

另外,您可以嘗試通過Integration Services包加載此文件,該包應該能夠跟蹤導入的位置,並且應該能夠對它們進行批處理並保留在你的記憶力限制內。

1

你有磁盤空間嗎? 也許在「舞臺造型」,但與Autonumeric編號從平面文件創建相同的表結構,然後做從表中插入...

導入到你的舞臺造型(第一導出它,如果它不是一個平面文件) ,這是另一種方式。

獲取您的寄存器的ID是與他們合作的優先事項。

+0

而不是插入的,他可以利用合併,這就是快 – Ivo 2011-04-26 18:25:40

+0

我有噸的磁盤空間,以備用。我現在正在導出到一個平面文件。過去30秒內有100k條記錄。 45分鐘左右運氣好。 – 2011-04-26 18:53:59

+0

它是怎麼回事?你還在出口嗎?你創造了這張桌子嗎?你正在進口嗎? – apacay 2011-04-26 21:13:16

1

什麼

  • 選擇TABEL的第一行(前1),存儲LeadID的變種。
  • 加載XML列的值轉換爲XML文檔(.NET)
  • 目標,你需要使用XPath
  • 插入這個值到一個新的記錄
  • 從「主」表中刪除記錄的節點使用leadid(或標記爲「完成」)
  • 提交
  • 步驟1再次
+0

前1不會necesarilly給他在數據庫中的第一行的每一個領域的效率要低得多_As,這將是第一個記錄數據集。不要認爲這會每次都有效。 – clamchoda 2011-04-26 18:29:52

+0

但是,如果我得到第一個TOP 1(不管它是什麼)然後刪除它,那麼獲得下一個TOP 1應該得到另一行,因爲我得到的第一個被刪除了,對吧? – 2011-04-26 19:49:53

+0

我甚至不能從此表中刪除1條記錄。我的字面意思是「從leadid中刪除leadid ='100a7927-5311-4f12-8fe3-95c079d32dd4';」由於「緩衝池中沒有足夠的可用內存」錯誤而失敗。除了將數據導出到文件之外,我完全沒有想法,即使如此,我也不知道如何一次讀取一行,然後刪除該行,因爲該文件可能爲50GB +,並且我不確定.Net會處理這個問題。另外,文件中的XML可能會跨越多行。 – 2011-04-26 21:11:23

0

什麼格式,你得到的最初的提取物?如果它是一個csv或其他,並且你不關心該XML片段中的其他信息,我會使用SSIS並完全跳過這個中間表。原生的XML類型有一些相關的開銷,如果你只是想把一些xml分解一次然後丟棄它,你不需要付出代價。

否則,您應該能夠直接在sql查詢中使用XML路徑語句,以將數據從一個表中獲取到另一個表中。如果你想從設計師那裏添加一個新的PK,它可能會在一張大桌子上失敗。您需要編寫腳本並手動運行它們,並可能調整它們以提高效率。根據現代標準,最終9米行並不是那麼巨大,但你必須通過9k以上的思考。

+0

對不起,只是編輯了這個問題。沒有CSV或任何東西,他們是mdf和ldf文件。 – 2011-04-26 19:49:00

1

調查一下row_number()和rank。

Take a look at this thread。它有讓你開始的基本概念。

+0

這就要求sql可以實際執行OVER(ORDER BY )。我不確定SQL是否可以使用這個表(在我的機器上,我的意思是)。由於運行原始數據導出,我現在無法對其進行測試。但這是一個偉大的想法,如果我不能首先與其他建議一起工作,我會嘗試。 – 2011-04-26 19:48:25

+0

沒有工作。我嘗試這樣做: 與東西AS (SELECT leadid,ROW_NUMBER)OVER(ORDER BY leadid()AS 'ROWNUMBER' FROM信息 ) SELECT * FROM一些地方ROWNUMBER和20 10之間,並將它與味精802炸燬了, 「緩衝池中的內存不足。」 – 2011-04-26 21:00:35

3

添加一個列不是一個選項,因爲添加一個自動編號也沒有工作。 您希望將更改/清理的數據存儲在新表中。 此表格可能具有自動編號和單獨的列,用於從Xml中提取數據。

將數據插入此表後,可以從源表中刪除原始行。 或者創建一個select語句,該語句排除已在新表中的具有GUID的行。

由於源表的行沒有依賴性或特定順序,因此選擇/處理行的順序並不重要。基於註釋

,對於SQL語句的建議:

WHILE EXISTS(SELECT * FROM [source] [s] 
       WHERE NOT EXISTS(SELECT * FROM [destination] [d] WHERE [d].[leadId] = [s].[leadId])) 
BEGIN 
    INSERT INTO [destination] ([leadId], [RawLeadXML], [LeadStatusId]) 
     SELECT TOP 100 [s].[leadId], [s].[RawLeadXML], [s].[LeadStatusId] 
     FROM [source] [s] 
     WHERE NOT EXISTS(SELECT * FROM [destination] [d] WHERE [d].[leadId] = [s].[leadId]) 
END 

我設置的記錄數爲100。這應該放過你的內存使用插入。

+0

我確實嘗試過,但即使「插入到NewT​​able(leadId,RawLeadXML,LeadStatusId)select leadId,RawLeadXML,LeadStatusId」中也會產生內存不足錯誤。 – 2011-04-26 19:00:14

+0

我擴展了我的答案。你似乎試圖一次插入所有記錄? – Jacco 2011-04-26 21:22:07

+0

謝謝你的時間,Jacco - 我複製了上面的陳述,並相應地替換了這些值。我正在觀看我的內存使用情況,並且它堅持2 GB(不僅僅是SQL,而是所有內容)。這可能只是工作。我假設這將需要一段漫長的時間,所以我一定會明天回來,當然,希望它結束​​。它已經運行了25分鐘,但目標表中沒有行。我假設這是事務性的? – 2011-04-26 22:01:22

9

錯誤802不會在傳統意義上是說出來的記憶內存不足以執行分配(這會觸發error 701)。 Error 802實際上表明緩衝池不能生長,這可能是由於兩個原因:

  • max server memory設定明確防止緩衝池的增長,檢查服務器設置。
  • x86虛擬地址空間限制被擊中並且AWE is not enabled。檢查是否有x86(32位)實例,如果是,請檢查是否滿足全部啓用AWE的條件。

如果你還沒有發現問題,請閱讀How to use the DBCC MEMORYSTATUS command to monitor memory usage on SQL Server 2005(文章也同樣適用於SQL Server 2008和2008 R2),並按照指引那裏瞭解誰/什麼在消耗你的記憶。

+0

在我的情況下,在160mil記錄的表上創建一個聚簇索引失敗了這個內存錯誤信息。將最大服務器內存設置爲4GB修復問題 – xhafan 2013-07-02 07:26:06

0

如何將數據直接從Access數據庫提取到文本文件中 - 然後您可以使用批量插入將其導入到您選擇的RDBM中。

通過MSSQL中的鏈接表訪問數據庫並不理想。在這裏,我們使用一個只讀,只進的記錄集遊標來逐行遍歷行。

這是VBScript,所以它不會是最快的,但它應該工作。您必須爲您的模式定製XML抽取例程。


' Code run against a access DB with column RawLeadXML 

Dim connection 

Set connection = CreateObject("ADODB.Connection") 
connection.Open "Driver={Microsoft Access Driver (*.mdb)}; DBQ=d:\path\to\file.mdb;" 

Dim recs 

' By default this is a read only, forward only cursor 
Set recs = connection.Execute("SELECT * FROM Leads") 

Dim fso 
Set fso = CreateObject("Scripting.FileSystemObject") 

Dim out 
Set out = fso.OpenTextFile("d:\path\to\output.txt", 2, True) 

Dim id 

id = 0 

While Not recs.EOF 
    id = id + 1 
    out.Write CStr(id) ' write an ID counter 
    out.Write "," 
    ExtractFieldsFromXML recs.Fields("RawLeadXML").Value, out 
    out.Write Chr(10) ' Linefeed 
    recs.MoveNext 
Wend 

out.Close 
recs.Close 
connection.Close 

' Extract data from the XML and write it to the stream 
' separated by commas 
Sub ExtractFieldsFromXML(xml, out) 
    Dim doc 

    Set doc = CreateObject("MSXML2.DOMDocument") 

    MsgBox xml 

    doc.loadXML xml 

    out.Write doc.selectSingleNode("/xml/firstname").text 
    out.Write "," 
    out.Write doc.selectSingleNode("/xml/lastname").text 

End Sub 
+0

感謝Adrian,但是我無法導出到一個文本文件我嘗試了SQL Server內置的數據導出工具,我嘗試了一個C#程序,沒有任何工作,我懷疑VBScript會更好,它太大了 – 2011-05-04 19:20:02

+0

您是否嘗試導出數據SQL數據庫中的鏈接,還是直接來自JetDB?大小應該無關緊要,一次一行;我懷疑通過MSSQL鏈接表不是處理一行數據儘管 - 我認爲這是什麼導致你的緩衝池問題。 – Adrian 2011-05-04 21:35:15

+0

我不確定我們在這裏的相同頁面上。沒有涉及Access數據庫。它在SQL Server中(我被賦予了一個mdf和ldf文件,只是將它附加到SQL的權利)。還是你說通過Access連接表,然後使用上面的VBScript可能比我嘗試過的其他東西更好? – 2011-05-05 02:15:16