2012-07-25 79 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]表。之后这两个地方的速度都是一样的。