2014-06-26 87 views
0

我正在掃描許多網頁上的單詞,然後將它們存儲在MySQL數據庫中。如何優化我的查詢以獲得更快的結果?

我有三個表:

  • :(的wordID
  • 網頁:(的pageid
  • 地圖 :(的wordID的pageid頻率

頻率字段是用於保持一個單詞的出現次數中的頁面。

然後使用PHPExcel,我創建一個表單,頁面和頻率值駐留。

片的基本方案爲以下幾點:

| A | B | C | .... 
|  |page1 |page2 | .... 
|word1 |  10|  7| .... 
|word2 |  2|  1| .... 
... 
... 

所以,我對於獲得該Excel工作表,但需要時間,工作時間太長,瀏覽器停止工作,下面的代碼,說,服務器響應太遲。所以我的工作沒有完成。我也嘗試添加

ini_set('max_execution_time', 0); 
set_time_limit(36000); 

但在添加上面的代碼之前和之後沒有變化。

所以我認爲現在優化查詢可能會更快。

function write2excel($config) 
{ 
    include 'PHPExcel_1.8.0_doc/Classes/PHPExcel.php'; 
    include 'PHPExcel_1.8.0_doc/Classes/PHPExcel/Writer/Excel2007.php'; 

    $objPHPExcel = new PHPExcel(); 

    //retrieve page names from DB in a associative array 
    $pages = getPages($config); 

    //retrieve word names from DB in a associative array 
    $words = getWords($config); 

    $r = 1; 
    $c = 0; 

    //Write each word into the first column in each row. 
    foreach ($words as $w) 
    { 
     $objPHPExcel->setActiveSheetIndex(0) 
       ->setCellValueByColumnAndRow(1, $r, $w['word']); 
     $r++; 
    } 
    //Write page names into the first rows of each column 
    foreach ($pages as $p) 
    { 
     $objPHPExcel->setActiveSheetIndex(0) 
       ->setCellValueByColumnAndRow($c, 2, $p['page']); 
     $c++; 
    } 

    $c = 1; 
    foreach ($words as $w) 
    { 
     $r = 2; 
     foreach ($pages as $p) 
     { 
      $freq = getFrequency($p['page'], $w['word'], $config); 
      $objPHPExcel->setActiveSheetIndex(0) 
        ->setCellValueByColumnAndRow($c, $r, $freq); 

      $r++; 
     } 
     $c++; 
    } 

    $objPHPExcel->getActiveSheet()->setTitle('mySheet'); 

    $objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel); 

    $objWriter->save('mySheet.xlsx'); 
} 

function getWords($config) 
{ 
    require_once $config . '.php'; 

    $conn = new Connection(); 

    $query = $conn->db->query('SELECT word FROM words'); 

    $query->execute(); 

    return $query->FetchAll(PDO::FETCH_ASSOC); 
} 

function getPages($config) 
{ 
    require_once $config . '.php'; 

    $conn = new Connection(); 

    $query = $conn->db->query('SELECT page FROM pages'); 

    $query->execute(); 

    return $query->FetchAll(PDO::FETCH_ASSOC); 
} 

function getFrequency($page, $word, $config) 
{ 
    require_once $config . '.php'; 

    $conn = new Connection(); 

    //find frequency value of the given word for the given page 
    $query = $conn->db->prepare('SELECT freq FROM map WHERE pageid IN ' 
      . '(SELECT pageid FROM pages WHERE page = :page) ' 
      . 'AND wordid IN (SELECT wordid FROM words WHERE word = :word) LIMIT 1'); 

    $query->bindValue(':page', $page, PDO::PARAM_STR); 
    $query->bindValue(':word', $word, PDO::PARAM_STR); 

    $query->execute(); 

    $row = $query->FetchAll(PDO::FETCH_ASSOC); 
    if ($query->rowCount() > 0) 
    { 
     $freq = $row[0]['freq']; 
    } 
    else 
    { 
     $freq = 0; 
    } 
    return $freq; 
} 

我有表超過10000行和超過1000行表

編輯

頁它是如何可以做,如果我想運行這個腳本100行100頁的所有頁面?我的意思是前100個單詞將被提取,然後101-200,201-300,...直到最後。

回答

0

我已經上傳了我的計劃,我認爲它優於我的筆記本電腦的Web服務器。但我沒有解決。所以我決定使用limitoffset來劃分結果集。

我使用地址欄輸入限制和偏移值。我現在正在收到我的牀單。然後我將它們合併成一張表。

感謝您的建議。我已將它們應用於我的代碼。我沒有衡量他們是否加快了我的工作,但似乎是有道理的。

無論如何,我的問題已解決。

我已經改變了功能getWords()如下所示:

function getWords($config, $limit, $offset) 
{ 
    require_once $config . '.php'; 

    $conn = new Connection(); 

    $query = $conn->db->query('SELECT word FROM words LIMIT ' . $limit . ' OFFSET ' . $offset); 

    $query->execute(); 

    $rows = array(); 
    while($row =$query->fetch(PDO::FETCH_ASSOC)){ 
     $rows[]= $row; 
    } 

    return $rows; 
} 

我知道查詢是脆弱的,易發生注射。誰在乎?我已經在我的本地計算機上運行了它。

1

您應該檢查其確切的問題,但你已經可以改善一些事情:

  • 僅使用一個連接,並且每次調用時間傳遞過來,以便你不打開一個新的數據庫連接你的一個職能;
  • 準備好您的語句一次,然後多次執行它,而不是每次在函數中調用該函數時調用該函數。

除此之外,執行在循環查詢(或在這種情況下,嵌套循環),始終將是一個問題,所以試圖減少查詢的數量和使用EXPLAIN優化你的指數可能將給予最大的收益。

1

我親自注意到,一次讀取所有行非常昂貴。

使用fetch()獲取您的記錄逐個會如此之快,嘗試將這些更改:

function getWords($config) 
{ 
    require_once $config . '.php'; 

    $conn = new Connection(); 

    $query = $conn->db->query('SELECT word FROM words'); 

    $query->execute(); 

    $rows = array(); 
    while($row =$query->fetch(PDO::FETCH_ASSOC)){ 
     $rows[]= $row; 
    } 

    return $rows; 
} 

function getPages($config) 
{ 
    require_once $config . '.php'; 

    $conn = new Connection(); 

    $query = $conn->db->query('SELECT page FROM pages'); 

    $rows = array(); 
    while($row =$query->fetch(PDO::FETCH_ASSOC)){ 
     $rows[]= $row; 
    } 

    return $rows; 
} 

function getFrequency($page, $word, $config) 
{ 
    require_once $config . '.php'; 

    $conn = new Connection(); 

    //find frequency value of the given word for the given page 
    $query = $conn->db->prepare('SELECT freq FROM map WHERE pageid IN ' 
      . '(SELECT pageid FROM pages WHERE page = :page) ' 
      . 'AND wordid IN (SELECT wordid FROM words WHERE word = :word) LIMIT 1'); 

    $query->bindValue(':page', $page, PDO::PARAM_STR); 
    $query->bindValue(':word', $word, PDO::PARAM_STR); 

    $query->execute(); 

    $row = $query->fetch(PDO::FETCH_ASSOC); 
    if ($query->rowCount() > 0) 
    { 
     $freq = $row['freq']; 
    } 
    else 
    { 
     $freq = 0; 
    } 
    return $freq; 
} 
相關問題