2014-09-30 58 views
0
子功能的C++

代碼如何使用MySQL加速C++ for循環代碼轉換成查詢

插入數據到MySQL

bool mysqlinsert2(int sourceindex,int targetindex,string source,string target) 
    { 
     MYSQL *conn_ptr; 
     conn_ptr = mysql_init(NULL); 

     if(!conn_ptr) 
     { 
      fprintf(stderr,"mysql_init failed\n"); 
      //return EXIT_FAILURE; 
     } 

     conn_ptr = mysql_real_connect(conn_ptr,"localhost","root","nlpgroup","testdb",0,NULL,0); 

     if(conn_ptr) 
     { 
      int abc; 
      char sql_buffer[500] = {0}; 
      sprintf(sql_buffer,"insert into EM2 (sourceindex,targetindex,source,target) values(\"%d\",\"%d\",\"%s\",\"%s\")",sourceindex,targetindex,source.c_str(),target.c_str()); 
      if((abc = mysql_query(conn_ptr,sql_buffer))) 
      { 
       printf("error code:%s\n",mysql_error(conn_ptr)); 
      } 
      mysql_close(conn_ptr); 
      return true; 
      //connection succees 
     } 
     else 
     { 
      printf("Error code: %d %s %s\n",mysql_errno(conn_ptr),mysql_sqlstate(conn_ptr),mysql_error(conn_ptr)); 
      mysql_close(conn_ptr); 
      return false; 
      //return EXIT_SUCCESS; 
     } 
    } 

用於運行循環和輸入for循環索引和值轉換成代碼MySQL的通過調用函數mysqlinsert2

void write_token_to_data() 
    { 
     typedef double* DynamicMatrix[l+m]; 
     // DynamicMatrix Count; 
     typedef double* DynamicMatrix2[l+m]; 
     //DynamicMatrix2 Prob; 
     for(int i=0; i<(l+m); i++) 
     { 
      for(int j=0; j<(l+m); j++) 
      { 
       if(mysqlinsert2(i,j,combine[i],combine[j])) 
       { 
        cout<<"insert OK!!"<<endl; 
       } 
       else 
       { 
        cout<<"insert failed"<<endl; 
       } 


      } 
     } 

    }//end of function 

當MySQL插入確定程序將返回「插入好!!」 所以,這是我的問題

這些查詢可能是直到30000 * 30000次 ,我想知道如何加快這個,也許我可以優化MySQL的設置或改變在C++編寫代碼,我希望它有相同的結果

回答

2

一對夫婦的言論:

  • 招開你的mysqlinsert方法以外關閉MySQL連接。打開一個連接是一個緩慢的操作,所以這樣做是有意義的,只有一次,只有在完成之前連接丟失才重新打開它;
  • 使用準備好的SQL語句也應該加快速度;
  • 考慮使用批量插入,以便一次插入N行(例如,嘗試N = 100)。
+0

批量插入非常重要的是如何能保持該值,直到循環繼續? – 2014-09-30 06:41:15

+0

你的意思是遞增價值?例如,您可以生成要插入的行數組(以您認爲合適的方式更改數值),然後返回對應於最後一個插入行的值。 – Ashalynd 2014-09-30 08:40:13

2

您正在爲每個插入打開一個新的mysql連接,這會嚴重影響您的性能。打開連接並保持打開狀態,直到完成所有插入。打開一個新的連接有很大的開銷。

還有與事務相關的開銷,所以您也很可能想要爲每個事務執行多次插入。有關詳細信息,請參閱本:using transactions

+0

我曾嘗試將mysql連接移出此功能,並且可能在10,20次後插入錯誤 – 2014-09-30 06:31:28

+1

錯誤是什麼? – krobertson 2014-09-30 06:34:17

+0

我會嘗試交易和批量插入第一,是任何樣品,如循環插入? – 2014-09-30 06:43:25

2

一些改進可以使:

  1. 廣場這兩個函數在一個類中,保持MYSQL *conn_ptr作爲該類的成員字段。那麼你的mysqlinsert2函數不需要每次創建和銷燬連接。

    class MyInserter { 
    public: 
        MyInserter() { 
        conn_ptr = mysql_init(NULL); 
        if (!conn_ptr) throw ...; 
        conn_ptr = mysql_real_connect(conn_ptr, ...); 
        if (!conn_ptr) throw ...; 
        } 
        ~MyInserter() { 
        mysql_close(conn_ptr); 
        } 
        bool mysqlinsert2(...) { ... } 
        void write_token_to_data() { ... } 
    
    private: 
        MYSQL *conn_ptr; 
    } 
    
  2. 使用prepared statementsbound parameters。這不僅可以加快查詢速度,還可以防止SQL注入攻擊(即某人將引號字符放入要插入的字符串中)。

  3. 而不是使用char sql_buffer[500]sprintf,請考慮使用std::ostringstream。這樣可以避免緩衝區溢出,並可以提高代碼的可讀性。注意下面的代碼會改變,如果你在上面幹什麼(2),以及:

    std::ostringstream out; 
    out << "insert into EM2 (sourceindex,targetindex,source,target) values(\"" << sourceindex << "\",\"" << targetindex << "\",\"" << source << "\",\"" << target << "\")""; 
    std::string sql_string = out.str(); 
    ... mysql_query(conn_ptr, sql_string.c_str()) ...