2012-07-25 5 views
0

내 데이터베이스에 System.Data.SQLite를 사용하고 있으며 select 문이 매우 느립니다. 약 5000 행의 데이터를 쿼리하는 데 약 3-5 분이 소요됩니다. 여기에 내가 사용하고있는 코드입니다 :C# - SQLite Select 문 최적화

 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

데이터베이스가 연결을 고려한 적이 있습니까? –

답변

1

더 많은 데이터 집계를 조인으로 SQL로 이동하는 것 외에도 항상 값을 파싱하지 않고 데이터 유형을 제공하도록 SQLiteDataReader을 고려할 수 있습니다. 다음 긴에 구문 분석,

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

dr[5]이 먼저 문자열로 변환하는 SQLite는 값입니다

예를 들어, 당신은 라인을 가지고있다. 이러한 구문 분석 작업에는 시간이 필요합니다. the various methods that SqliteDataReader offers

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

체크 아웃하고 가능하면 대신 구문 분석 값으로이를 활용 :

long visitlong = dr.GetInt64(5); 

또는를 왜 대신 할 수 없습니다.

편집 :이 데이터를 필요로

참고 올바른 형식으로 저장 될 수있다. 데이터베이스의 모든 내용이 문자열로 저장되면 일부 구문 분석은 불가피합니다.

+0

고마워,하지만 내 문제는 디버깅 함께 실행할 때 매우 느린 것을 발견했지만 디버깅없이 실행할 때 몇 초 내에 완료됩니다. –

0

SQL 명령 "ANALYZE {db | table | index};"를 최근에 실행했는지 확인하십시오.

내 ER 소프트웨어 (Navicat)에서 쿼리가 빠르게 실행되는 상황 (예 : 디버깅하지 않음)이 Visual Studio에서 매우 느리게 (> 1 분) 디버깅되었습니다. Navicat (SQLite v3.7)에서 데이터베이스 설계를했기 때문에 Visual Studio (v3.8)의 System.Data.SQLite에서 사용한 것과 통계가 동일하지 않은 것으로 나타났습니다. "ANALYZE; 실행 중" Visual Studio의 전체 데이터베이스 파일에서 v3.8에서 사용하는 [sqlite_statX] 테이블을 업데이트했습니다. 그 후 두 곳 모두 같은 속도였습니다.