2012-07-25 82 views
0

我正在使用System.Data.SQLite數據庫,我的選擇語句非常慢。大約需要3-5分鐘查詢大約5000行數據。這裏是我使用的代碼:c# - 優化SQLite選擇語句

 string connectionString; 
     connectionString = string.Format(@"Data Source={0}", documentsFolder + ";Version=3;New=False;Compress=True;"); 
     //Open a new SQLite Connection 
     SQLiteConnection conn = new SQLiteConnection(connectionString); 
     conn.Open(); 

     SQLiteCommand cmd = new SQLiteCommand(); 
     cmd.Connection = conn; 
     cmd.CommandText = "Select * From urls"; 
     //Assign the data from urls to dr 
     SQLiteDataReader dr = cmd.ExecuteReader(); 

     SQLiteCommand com = new SQLiteCommand(); 
     com.CommandText = "Select * From visits"; 
     SQLiteDataReader visit = com.ExecuteReader(); 

     List<int> dbID2 = new List<int>(); 
     while (visit.Read()) 
     { 
      dbID2.Add(int.Parse(visit[1].ToString())); 
     } 
     //Read from dr 
     while (dr.Read()) 
     { 
      string url = dr[1].ToString(); 
      string title = dr[2].ToString(); 
      long visitlong = Int64.Parse(dr[5].ToString()); 
      string browser = "Chrome"; 
      int dbID = int.Parse(dr[0].ToString()); 
      bool exists = dbID2.Any(item => item == dbID); 
      int frequency = int.Parse(dr["visit_count"].ToString()); 

      bool containsBoth = url.Contains("file:///"); 

      if (exists) 
      { 
       if (containsBoth == false) 
       { 
        var form = Form.ActiveForm as TestURLGUI2.Form1; 

        URLs.Add(new URL(url, title, browser, visited, frequency)); 
        Console.WriteLine(String.Format("{0} {1}", title, browser)); 
       } 
      } 

     } 
     //Close the connection 
     conn.Close(); 

這裏是需要很長的一個例子:

IEnumerable<URL> ExtractUserHistory(string folder, bool display) 
{ 
    // Get User history info 
    DataTable historyDT = ExtractFromTable("moz_places", folder); 

    // Get visit Time/Data info 
    DataTable visitsDT = ExtractFromTable("moz_historyvisits", 
              folder); 



    // Loop each history entry 
    foreach (DataRow row in historyDT.Rows) 
    { 
     // Select entry Date from visits 
     var entryDate = (from dates in visitsDT.AsEnumerable() 
         where dates["place_id"].ToString() == row["id"].ToString() 
         select dates).LastOrDefault(); 
     // If history entry has date 
     if (entryDate != null) 
     { 
      // Obtain URL and Title strings 
      string url = row["Url"].ToString(); 
      string title = row["title"].ToString(); 
      int frequency = int.Parse(row["visit_count"].ToString()); 
      string visit_type; 

      //Add a URL to list URLs 
      URLs.Add(new URL(url, title, browser, visited, frequency)); 

      // Add entry to list 
      // URLs.Add(u); 
      if (title != "") 
      { 
       Console.WriteLine(String.Format("{0} {1}", title, browser)); 
      } 
     } 
    } 

    return URLs; 
} 



DataTable ExtractFromTable(string table, string folder) 
{ 
    SQLiteConnection sql_con; 
    SQLiteCommand sql_cmd; 
    SQLiteDataAdapter DB; 
    DataTable DT = new DataTable(); 

    // FireFox database file 
    string dbPath = folder + "\\places.sqlite"; 

    // If file exists 
    if (File.Exists(dbPath)) 
    { 
     // Data connection 
     sql_con = new SQLiteConnection("Data Source=" + dbPath + 
          ";Version=3;New=False;Compress=True;"); 

     // Open the Connection 
     sql_con.Open(); 
     sql_cmd = sql_con.CreateCommand(); 

     // Select Query 
     string CommandText = "select * from " + table; 

     // Populate Data Table 
     DB = new SQLiteDataAdapter(CommandText, sql_con); 
     DB.Fill(DT); 

     // Clean up 
     sql_con.Close(); 
    } 
    return DT; 
} 

現在,我怎麼能優化這些使他們更快?

+0

您是否考慮過讓數據庫爲您進行連接? – 2012-07-25 23:33:48

回答

1

除了將更多的數據聚合作爲連接移動到SQL之外,您還可以考慮讓SQLiteDataReader提供數據類型,而不是始終解析值。

例如,你有行:

long visitlong = Int64.Parse(dr[5].ToString()); 

dr[5]是一個SQLite值您正在第一轉換爲字符串,然後將其解析爲長。這些解析操作需要時間。爲什麼不這樣做,而不是:

long visitlong = dr.GetInt64(5); 

或者:

long visitlong = dr.GetInt64(dr.GetOrdinal("columnName")); 

退房the various methods that SqliteDataReader offers並利用他們時,解析值的可能替代。

編輯:

注意,這要求數據被存儲爲正確的類型。如果數據庫中的所有內容都以字符串形式存儲,則某些解析是不可避免的。

+0

謝謝,但我發現我的問題是,當我使用調試運行它時,它非常慢,但是當我在沒有調試的情況下運行它時,它會在幾秒鐘內完成。 – 2012-07-29 00:00:29

0

確保您最近運行了SQL命令「ANALYZE {db | table | index};」。

我最近在我的ER軟件(Navicat)中遇到了查詢運行速度很快(< 1秒)的情況,即:未調試,但在Visual Studio中調試非常緩慢(> 1分鐘)。事實證明,因爲我在Navicat(SQLite v3.7)中進行了數據庫設計,所以統計數據與Visual Studio(v3.8)中的System.Data.SQLite使用的統計數據不同。運行「ANALYZE」;從Visual Studio整個數據庫文件更新了v3.8使用的[sqlite_statX]表。之後這兩個地方的速度都是一樣的。