2009-09-21 21 views
3

下載September 2009 StackOverflow data-dump和運行布倫特import query,我收到以下消息後:StackOverflow導入錯誤:超過2,147,483,647字節的LOB?

Msg 7119, Level 16, State 1, Procedure sp_xml_preparedocument, Line 1 
Attempting to grow LOB beyond maximum allowed size of 2,147,483,647 bytes. 
Msg 8179, Level 16, State 5, Procedure usp_ETL_Load_Posts, Line 59 
Could not find prepared statement with handle 0. 
The statement has been terminated. 
Msg 7102, Level 20, State 99, Procedure usp_ETL_Load_Posts, Line 121 
Internal Error: Text manager cannot continue with current statement. 
    Run DBCC CHECKTABLE. 

布倫特的查詢是基於七月份的數據,我懷疑這是九月的數據庫,更大的結果。

除了獲取較舊的數據,任何人都知道如何解決這個問題或以其他方式導入數據?

更新:我正在運行「版本:Microsoft SQL Server 2005-9.00.1399.06(Intel X86)2005年10月14日00:33:37 Copyright(c)1988-2005 Microsoft Corporation Developer Edition on Windows NT 5.1 (內部版本2600:Service Pack 3)「

回答

2

我通過在.Net中編寫一個小型控制檯應用程序來解決這個問題(代碼如下)。它一次導入記錄1(甚至沒有花時間搗毀sqlbulkcopy對象),並在午休時間運行。我忘了給控制檯寫時間戳,所以我不知道它花了多長時間。我最好的估計只有20多分鐘。要警告下一個問題是tempdb:保留默認設置,tempdb在導入過程中會變得非常大。完成後,您需要重新啓動sql服務器服務。

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Diagnostics; 
using System.Data; 
using System.Data.SqlClient; 
using System.IO; 
using System.Xml; 
namespace ImportPostsTable 
{ 
    class Program 
    { 
     //TODO: pull connection string, data path from app.config or command line 
     static string cnString = "Data Source=localhost;Database=SO;Trusted_Connection=True;"; 
     static string dataPath = @"C:\temp"; 
     static string insertString = "INSERT INTO Posts VALUES (@Id, @PostTypeID, @AcceptedAnswerId, @CreationDate, @Score, @ViewCount, @Body, @OwnerUserId, @OwnerDisplayName, @LastEditorUserId, @LastEditDate, @LastActivityDate, @Title, @Tags, @AnswerCount, @CommentCount, @FavoriteCount, @ClosedDate, @ParentId)"; 
     static void Main(string[] args) 
     { 
      Trace.Listeners.Add(new ConsoleTraceListener()); 

      try 
      { 
       ImportPosts(dataPath, cnString); 
      } 
      catch (Exception e) 
      { 
       Trace.WriteLine(e.Message); 
       Trace.WriteLine(e.StackTrace); 
      } 
      Console.ReadKey(true); 
     } 

     public static void ImportPosts(string XmlPath, string ConnectionString) 
     { 
      using (StreamReader sr = new StreamReader(Path.Combine(XmlPath, "posts.xml"))) 
      using (XmlTextReader rdr = new XmlTextReader(sr)) 
      using (SqlConnection cn = new SqlConnection(ConnectionString)) 
      using (SqlCommand cmd = new SqlCommand(insertString, cn)) 
      { 
       cmd.Parameters.Add("@Id", SqlDbType.Int); 
       cmd.Parameters.Add("@PostTypeId", SqlDbType.Int); 
       cmd.Parameters.Add("@AcceptedAnswerId", SqlDbType.Int); 
       cmd.Parameters.Add("@CreationDate", SqlDbType.DateTime); 
       cmd.Parameters.Add("@Score", SqlDbType.Int); 
       cmd.Parameters.Add("@ViewCount", SqlDbType.Int); 
       cmd.Parameters.Add("@Body", SqlDbType.NVarChar); 
       cmd.Parameters.Add("@OwnerUserId", SqlDbType.Int); 
       cmd.Parameters.Add("@OwnerDisplayName", SqlDbType.NVarChar, 40); 
       cmd.Parameters.Add("@LastEditorUserId", SqlDbType.Int); 
       cmd.Parameters.Add("@LastEditDate", SqlDbType.DateTime); 
       cmd.Parameters.Add("@LastActivityDate", SqlDbType.DateTime); 
       cmd.Parameters.Add("@Title", SqlDbType.NVarChar, 250); 
       cmd.Parameters.Add("@Tags", SqlDbType.NVarChar, 150); 
       cmd.Parameters.Add("@AnswerCount", SqlDbType.Int); 
       cmd.Parameters.Add("@CommentCount", SqlDbType.Int); 
       cmd.Parameters.Add("@FavoriteCount", SqlDbType.Int); 
       cmd.Parameters.Add("@ClosedDate", SqlDbType.DateTime); 
       cmd.Parameters.Add("@ParentId", SqlDbType.Int); 

       Trace.Write(DateTime.Now.ToString() + Environment.NewLine + "Reading"); 
       int count = 0; 
       cn.Open(); 
       while (rdr.Read()) 
       { 
        if (rdr.AttributeCount <= 5) continue; //everything but the xml declaration and the root element will have at least 5 attributes 

        cmd.Parameters[0].Value = rdr["Id"]; 
        cmd.Parameters[1].Value = rdr["PostTypeId"]; 
        cmd.Parameters[2].Value = rdr["AcceptedAnswerId"]; 
        cmd.Parameters[3].Value = ParseDate(rdr["CreationDate"]); 
        cmd.Parameters[4].Value = rdr["Score"]; 
        cmd.Parameters[5].Value = rdr["ViewCount"]; 
        cmd.Parameters[6].Value = rdr["Body"]; 
        cmd.Parameters[7].Value = rdr["OwnerUserId"]; 
        cmd.Parameters[8].Value = rdr["OwnerDisplayName"]; 
        cmd.Parameters[9].Value = rdr["LastEditorUserId"]; 
        cmd.Parameters[10].Value = ParseDate(rdr["LastEditDate"]); 
        cmd.Parameters[11].Value = ParseDate(rdr["LastActivityDate"]); 
        cmd.Parameters[12].Value = rdr["Title"]; 
        cmd.Parameters[13].Value = rdr["Tags"]; 
        cmd.Parameters[14].Value = rdr["AnswerCount"]; 
        cmd.Parameters[15].Value = rdr["CommentCount"]; 
        cmd.Parameters[16].Value = rdr["FavoriteCount"]; 
        cmd.Parameters[17].Value = ParseDate(rdr["ClosedDate"]); 
        cmd.Parameters[18].Value = rdr["ParentId"]; 

        for (int i = 0; i < cmd.Parameters.Count; i++) 
         if (cmd.Parameters[i].Value == null) 
          cmd.Parameters[i].Value = DBNull.Value; 

        cmd.ExecuteNonQuery(); 

        if (count++ % 5000 == 0) Trace.Write("."); 
       } 
       Trace.WriteLine(string.Format("\n\n{0:d}\nFinished {1} records.", DateTime.Now, count)); 
      } 
     } 

     public static object ParseDate(string dateValue) 
     { 
      if (string.IsNullOrEmpty(dateValue)) return DBNull.Value; 
      return DateTime.ParseExact(dateValue, "yyyy-MM-ddTHH:mm:ss.fff", null); 
     } 
    } 
} 
+0

Woderful,謝謝。 – 2009-09-22 03:03:46

1

SQL Server沒有任何數據類型能夠在一行的列中存儲超過2 GB的數據。

如果您有足夠的磁盤空間,數據庫(Express Edition除外)可以存儲多於2 GB的數據,但是對一行的列中的數據量的限制適用。

+0

我發現相同的答案谷歌搜索,但我沒有使用快遞。 – 2009-09-21 21:40:30

+1

LiraNuna並不是說它是Express的限制,他/她說這是幾乎所有數據庫的限制。整體數據庫的大小不是限制因素,而是列的大小。提到「快遞版」是無關緊要的,並且顯然會使解釋變得浮躁。 – rmeador 2009-09-21 21:50:49

1

您需要做的就是將帖子文件拆分爲2-3個文件,您仍然可以使用您使用的導入查詢。

你可以通過用EditPad打開文件來做到這一點(不要使用Notepad ++,因爲它會失敗,因爲文件太大,而使用EditPad它會立即打開),只需剪切和粘貼幾個文件(儘可能使它們成爲正確的XML,複製標題和結束標記)。