程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> 關於MYSQL數據庫 >> 提高MySQL 查詢效率的三個有效的嘗試(2)

提高MySQL 查詢效率的三個有效的嘗試(2)

編輯:關於MYSQL數據庫

   隨機的獲取記錄

  在某些數據庫的應用中, 我們並不是要獲取所有的滿足條件的記錄,而只是要隨機挑選出滿足條件的記錄. 這種情況常見於數據業務的統計分析,從大容量數據庫中獲取小量的數據的場合.

  有兩種方法可以做到

  1. 常規方法,首先查詢出所有滿足條件的記錄,然後隨機的挑選出部分記錄.這種方法在滿足條件的記錄數很多時效果不理想.

  2. 使用limit語法,先獲取滿足條件的記錄條數, 然後在sql查詢語句中加入limit來限制只查詢滿足要求的一段記錄. 這種方法雖然要查詢兩次,但是在數據量大時反而比較高效.

  示例代碼如下:

//1.常規的方法
//性能瓶頸,10萬條記錄時,執行查詢140ms, 獲取結果集500ms,其余可忽略
int CDBManager::QueryHostCache(MySQL* connecthandle, char * channelid, int ISPtype, CDBManager::CHostCacheTable * &hostcache)
{    
       char selectSQL[SQL_LENGTH];
       memset(selectSQL, 0, sizeof(selectSQL));
       sprintf(selectSQL,"select * from HostCache where ChannelID = '%s' and ISPtype = %d", channelid, ISPtype);
       if(MySQL_real_query(connecthandle, selectSQL, strlen(selectSQL)) != 0)   //檢索
              return 0;
       //獲取結果集
       m_pResultSet = MySQL_store_result(connecthandle);
       if(!m_pResultSet)   //獲取結果集出錯
              return 0;
       int iAllNumRows = (int)(MySQL_num_rows(m_pResultSet));      ///<所有的搜索結果數
       //計算待返回的結果數
       int iReturnNumRows = (iAllNumRows <= RETURN_QUERY_HOST_NUM)? iAllNumRows:RETURN_QUERY_HOST_NUM;
       if(iReturnNumRows <= RETURN_QUERY_HOST_NUM)
       {
              //獲取逐條記錄
              for(int i = 0; i<iReturnNumRows; i++)
              {
                     //獲取逐個字段
                     m_Row = MySQL_fetch_row(m_pResultSet);
                     if(m_Row[0] != NULL)
                            strcpy(hostcache[i].sessionid, m_Row[0]);
                     if(m_Row[1] != NULL)
                            strcpy(hostcache[i].channelid, m_Row[1]);
                     if(m_Row[2] != NULL)
                            hostcache[i].ISPtype      = atoi(m_Row[2]);
                     if(m_Row[3] != NULL)
                            hostcache[i].externalIP   = atoi(m_Row[3]);
                     if(m_Row[4] != NULL)
                            hostcache[i].externalPort = atoi(m_Row[4]);
                     if(m_Row[5] != NULL)
                            hostcache[i].internalIP   = atoi(m_Row[5]);
                     if(m_Row[6] != NULL)
                            hostcache[i].internalPort = atoi(m_Row[6]);             
              }
       }
       else
       {
              //隨機的挑選指定條記錄返回
              int iRemainder = iAllNumRows%iReturnNumRows;    ///<余數
              int iQuotIEnt = iAllNumRows/iReturnNumRows;      ///<商
              int iStartIndex = rand()%(iRemainder + 1);         ///<開始下標 
              //獲取逐條記錄
        for(int iSelectedIndex = 0; iSelectedIndex < iReturnNumRows; iSelectedIndex++)
        {
                            MySQL_data_seek(m_pResultSet, iStartIndex + iQuotIEnt * iSelectedIndex);
                            m_Row = MySQL_fetch_row(m_pResultSet);
                  if(m_Row[0] != NULL)
                       strcpy(hostcache[iSelectedIndex].sessionid, m_Row[0]);
                   if(m_Row[1] != NULL)
                                   strcpy(hostcache[iSelectedIndex].channelid, m_Row[1]);
                   if(m_Row[2] != NULL)
                       hostcache[iSelectedIndex].ISPtype      = atoi(m_Row[2]);
                   if(m_Row[3] != NULL)
                       hostcache[iSelectedIndex].externalIP   = atoi(m_Row[3]);
                    if(m_Row[4] != NULL)
                       hostcache[iSelectedIndex].externalPort = atoi(m_Row[4]);
                   if(m_Row[5] != NULL)
                       hostcache[iSelectedIndex].internalIP   = atoi(m_Row[5]);
                   if(m_Row[6] != NULL)
                       hostcache[iSelectedIndex].internalPort = atoi(m_Row[6]);
        }
      }
       //釋放結果集內容
       MySQL_free_result(m_pResultSet);
       return iReturnNumRows;
}
 
//2.使用limit版
int CDBManager::QueryHostCache(MySQL * connecthandle, char * channelid, unsigned int myexternalip, int ISPtype, CHostCacheTable * hostcache)
{
       //首先獲取滿足結果的記錄條數,再使用limit隨機選擇指定條記錄返回
       MySQL_ROW row;
       MySQL_RES * pResultSet;
       char selectSQL[SQL_LENGTH];
       memset(selectSQL, 0, sizeof(selectSQL));
 
       sprintf(selectSQL,"select count(*) from HostCache where ChannelID = '%s' and ISPtype = %d", channelid, ISPtype);
       if(MySQL_real_query(connecthandle, selectSQL, strlen(selectSQL)) != 0)   //檢索
              return 0;
       pResultSet = MySQL_store_result(connecthandle);
       if(!pResultSet)      
              return 0;
       row = MySQL_fetch_row(pResultSet);
       int iAllNumRows = atoi(row[0]);
       MySQL_free_result(pResultSet);
       //計算待取記錄的上下范圍
       int iLimitLower = (iAllNumRows <= RETURN_QUERY_HOST_NUM)?
              0:(rand()%(iAllNumRows - RETURN_QUERY_HOST_NUM));
       int iLimitUpper = (iAllNumRows <= RETURN_QUERY_HOST_NUM)?
              iAllNumRows:(iLimitLower + RETURN_QUERY_HOST_NUM);
       //計算待返回的結果數
       int iReturnNumRows = (iAllNumRows <= RETURN_QUERY_HOST_NUM)?
               iAllNumRows:RETURN_QUERY_HOST_NUM;
      
       //使用limit作查詢
       sprintf(selectSQL,"select SessionID, ExternalIP, ExternalPort, InternalIP, InternalPort "
              "from HostCache where ChannelID = '%s' and ISPtype = %d limit %d, %d"
              , channelid, ISPtype, iLimitLower, iLimitUpper);
       if(MySQL_real_query(connecthandle, selectSQL, strlen(selectSQL)) != 0)   //檢索
              return 0;
       pResultSet = MySQL_store_result(connecthandle);
       if(!pResultSet)
              return 0;
       //獲取逐條記錄
       for(int i = 0; i<iReturnNumRows; i++)
       {
              //獲取逐個字段
              row = MySQL_fetch_row(pResultSet);
              if(row[0] != NULL)
                     strcpy(hostcache[i].sessionid, row[0]);
              if(row[1] != NULL)
                     hostcache[i].externalIP   = atoi(row[1]);
              if(row[2] != NULL)
                     hostcache[i].externalPort = atoi(row[2]);
              if(row[3] != NULL)
                     hostcache[i].internalIP   = atoi(row[3]);
              if(row[4] != NULL)
                     hostcache[i].internalPort = atoi(row[4]);            
       }
       //釋放結果集內容
       MySQL_free_result(pResultSet);
       return iReturnNumRows;
}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved