2011-09-30 53 views
4

我正在用C#編寫Visual Studio 2008上的應用程序。應用程序從訪問文件讀取數據,然後生成一個txt文件。我正在做一些具有1.000.000記錄和幾乎1GB大小的mdb文件的測試。 代碼是這樣的,整個過程需要8-10分鐘才能完成。從C#中的Access 2007(accdb)文件中讀取性能真的很差C#

var connStr = string.Format("Provider =Microsoft.Jet.OLEDB.4.0; Data Source={0};Persist Security Info=False", this.dbPath); 

using (var conn = new OleDbConnection(connStr)) 
{ 
      using (var command = conn.CreateCommand()) 
      { 

       command.CommandText = "SELECT * from Registros r, FOIDS f where r.TICKET = f.TICKET"; 
       command.CommandType = System.Data.CommandType.Text; 
       conn.Open(); 

       int i = 0; 
       string ticket = string.Empty; 

       using (var reader = command.ExecuteReader()) 
       { 
        while (reader.Read()) 
        { 
         i++; 

          if (!reader.IsDBNull(reader.GetOrdinal("r.TICKET"))) 
          { 
           ticket=reader.GetString(reader.GetOrdinal("r.TICKET")); 
           // Some process 
          } 
         } 
        } 
       } 
      } 
    } 

今天收到一個ACCDB文件(Access 2007年),所以我改變了我的連接字符串,這一個:

connStr = string.Format(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Persist Security Info=False", this.dbPath); 

但是,這改變後,讀取新的文件正在約4 -5秒每記錄!所以,我的整個過程需要很多天才能完成! 我已經嘗試將accdb文件轉換爲舊的mdb文件,然後再次讀取以前的連接字符串,但問題仍然存在。我認爲這是數據庫本身的一個問題,但我不知道該怎麼做,在互聯網上我沒有找到任何有關這類問題的信息。

任何想法?建議?

+0

它可能不是讀取MDB所花費的時間,而是「//某個進程」部分?是否可以製作異步? – Matt

+0

我做了一些調試,延遲在reader.Read()指令上。此外,我還添加了一些具有相同結果的日誌,並且我也對該過程進行了評論,結果相同。謝謝你快速的回覆 ! – user972331

+0

你嘗試過壓縮數據庫嗎? –

回答

4

根據我的經驗,5年前。

其中一個訪問數據庫超過20000條記錄,大小約爲150 MB。它開始減速並且性能下降。因此轉移到SQL。

您可以考慮使用SQL精簡版,或SQL精簡版

感謝

+0

Check出:http://stackoverflow.com/questions/481719/import-access-data-into-sql-server-ce-mdb-to-sdf – bryanmac

+3

150MBs是Access/Jet/ACE可笑的小。如果這導致性能問題,那麼您的數據架構或應用程序中的設計就會變得很糟糕。在目前的情況下,對於1GB文件,我會推薦升級到服務器數據庫,因爲它只是接近Access/Jet/ACE文件的2GB硬限制的方法。 –

+0

如果這麼少的記錄導致了糟糕的性能,我會首先懷疑笛卡兒加入,其次是缺少索引,或者兩者兼而有之。其他數據庫系統可以優化笛卡爾聯接,但是IIRC Jet不會(或者沒有)。 – phoog

2

除了切換到建議的數據庫之一,您應該從string改變ticket的對象類型StringBuilder

記住...

The String object is immutable. Every time you use one of the methods in the System.String class, you create a new string object in memory, which requires a new allocation of space for that new object. In situations where you need to perform repeated modifications to a string, the overhead associated with creating a new String object can be costly. The System.Text.StringBuilder class can be used when you want to modify a string without creating a new object. For example, using the StringBuilder class can boost performance when concatenating many strings together in a loop.

考慮到這一點,認爲你每次設置你的ticket可變的時間創造了while循環的開銷。 - 你提到你有一百萬條記錄,這意味着你的代碼正在創建一百萬個字符串對象。

使用代替stringStringBuilder類型,你的代碼可能會是這樣......

.... 
StringBuilder ticket = new StringBuilder(); 

using (var reader = command.ExecuteReader()) 
{ 
    while (reader.Read()) 
    { 
     i++; 

      if (!reader.IsDBNull(reader.GetOrdinal("r.TICKET"))) 
      { 
       ticket.Append(reader.GetString(reader.GetOrdinal("r.TICKET"))); 
       // Some process 
      } 
     } 
    } 

    // Write the ticket content to a file 
    using(StreamWriter sw = new StreamWriter("ticket.txt")) 
    { 
     sw.WriteLine(ticket.ToString()); 
    } 
} 
+0

這假定票證變量正在累積每次循環迭代的數據。這個問題似乎另有說明。 – phoog

1

我的經驗轉換數據結構與MDB TO ACCDB文件格式是:

  1. 使用完全相同的對象和數據創建新的accdb文件並壓縮後,accdb將比舊的mdb文件增加近40%的文件大小。

  2. 它比較慢。使用查詢和/或VB代碼的數據處理至少需要3倍的時間才能結束。

  3. 它達到2Gb(數據庫大小限制)比以前的格式更快達到1GB。

而且我意識到,當您壓縮一個accdb文件時,它首先會生成一個mdb文件,並將其重命名爲accdb擴展名。這真的很糟糕!