2011-07-04 22 views
2

我是一名爲夏季工作的學生。我已經被賦予處理從excel到SQL Server數據庫的數據輸入的任務,以進行多年的調查。任務如下:我是否正在處理這些文件? (帶PHP的CSV)

有三個表,一個主要事件,一個個別事件和一個個人。一個事件有許多個人事件,一個事件有許多個人事件。我的代碼只關注最後兩個表。

我讀了兩個文件,一個文件中的所有單個事件的列表,以及另一個文件中的所有個人的列表。個人的數據告訴我它與哪個單獨的事件相關聯。

我的代碼基本上讀取一個單獨的事件,然後通過第二個文件查找任何關聯的個人。對於個人文件中的每一行,如果它是關聯的,則將其插入到適當的表中,否則將被寫入新文件。遍歷完整個文件後,新文件將被複制到舊文件中,從而刪除已輸入數據庫的數據。

這個複製過程已經敲了好3分鐘的執行時間,只需重新讀取完整的個人文件即可。但有沒有更好的方法呢?我的樣本數據的執行時間爲〜47秒...理想情況下,我希望更低。

任何意見,無論多麼微不足道的讚賞。

編輯: 這是代碼的削減版本,我使用

<?php 
//not shown: 
//connect to database 
//input event data 
//get the id of the event 
//open files 
$s_handle = fopen($_FILES['surveyfile']['tmp_name'],'r');//open survey file 
copy($_FILES['cocklefile']['tmp_name'],'file1.csv');//make copy of the cockle file 
//read files 
$s_csv = fgetcsv($s_handle,'0',','); 

//read lines and print lines 
// then input data via sql 

while (! feof($s_handle)) 
{ 
    $max_index = count($s_csv); 
    $s_csv[$max_index]=''; 
    foreach($s_csv as $val) 
    { 
     if(!isset($val)) 
     $val = ''; 
    } 
    $grid_no = $s_csv[0]; 
    $sub_loc = $s_csv[1]; 
    /* 
    .define more variables 
    .*/ 


    $sql = "INSERT INTO indipendant_event" 
     ."(parent_id,grid_number,sub_location,....)" 
     ."VALUES (" 
     ."'{$event_id}'," 
     ."'{$grid_no}'," 
     //... 
     .");"; 

    if (!odbc_exec($con,$sql)) 
    { 
     echo "WARNING: SQL INSERT INTO fssbur.cockle_quadrat FAILED. PHP."; 
    } 
    //get ID 
    $sql = "SELECT MAX(ind_event_id)" 
    ."FROM independant_event"; 
    $return = odbc_exec($con,$sql); 
    $ind_event_id = odbc_result($return, 1); 

    //insert individuals 
    $c_2 = fopen('file2.csv','w');//create file c_2 to write to 
    $c_1 = fopen('file1.csv','r');//open the data to read 
    $c_csv = fgetcsv($c_1,'0',',');//get the first line of data 
    while(! feof($c_1)) 
    { 

     for($i=0;$i<9;$i++)//make sure theres a value in each column 
     { 
      if(!isset($c_csv[$i])) 
      $c_csv[$i] = ''; 
     } 
     //give values meaningful names 
     $stat_no = $c_csv[0]; 
     $sample_method = $c_csv[1]; 
     //.... 

     //check whether the current line corresponds to the current station 
     if (strcmp(strtolower($stat_no),strtolower($grid_no))==0) 
     { 
      $sql = "INSERT INTO fssbur2.cockle" 
       ."(parent_id,sampling_method,shell_height,shell_width,age,weight,alive,discarded,damage)" 
       ."VALUES(" 
       ."'{$ind_event_id}'," 
       ."'{$sample_method}'," 
       //... 
       ."'{$damage}');"; 
      //write data if it corresponds 
      if (!odbc_exec($con,$sql)) 
      { 
       echo "WARNING: SQL INSERT INTO fssbur.cockle FAILED. PHP."; 
      }  
      $c_csv = fgetcsv($c_1,'0',','); 
     } 
     else//no correspondance 
     { 
      fputcsv($c_2,$c_csv);//write line to the new file 
      $c_csv = fgetcsv($c_1,'0',',');//get new line 
      continue;//rinse and repeat 
     } 
    }//end while, now gone through all individuals, and filled c_2 with the unused data 
    fclose($c_1);//close files 
    fclose($c_2); 
    copy('file2.csv','file1.csv');//copy new file to old, removing used data 
    $s_csv = fgetcsv($s_handle,'0',','); 
}//end while 

//close file 
fclose($s_handle); 
?> 
+1

請顯示一些代碼。你有沒有嘗試過什麼來改進這個過程?你有沒有使用分析器來衡量執行時間? – Gordon

+0

@戈登我避免發佈代碼,因爲它很長。我只是用microtime()來看看它花了多長時間。我會盡快發佈一些代碼 – Aido

+0

上傳的代碼。感謝迄今爲止的答案! – Aido

回答

2

您可以創建從文件中的數據的臨時數據庫,然後使用臨時數據庫/表來實現數據進入新的形式。這可能運行得更快,特別是如果您需要查找並且需要將條目標記爲已處理。

+0

正是我正在考慮加載到臨時表中並使用SQL select/join將個人與事件進行匹配。如果文件中有很多條目(數千),請考慮使用「MERGE」語句。 –

+0

我還沒有實現這一點,但它指出了我在正確的方向。謝謝! – Aido

3

我可能沒有完全理解過程,但爲什麼不把整個CSV插入到數據庫表中。這可能看起來像浪費的工作,但它可能會得到回報。一旦完成了初始導入,找到與事件相關的任何個人應該更快,因爲DBMS將能夠使用索引來加速這些查找(與基於文件的線性遍歷相比)。準確地說:你的「個人」表大概會在你的「individual_event」表中有一個外鍵。只要你在這個外鍵上創建一個索引,查找就會快得多(可能只是聲明這個字段是一個外鍵會導致SQL服務器自動索引它,但我不能肯定地說,真的使用MSSQL)。

另外,我們在談論多少條記錄?如果我們正在處理1000個記錄,那麼期望這種類型的東西在幾秒鐘內運行是絕對合理的。

+0

我沒有想到這種方法。雖然,我使用自動生成的主鍵,因爲某些事件具有相同的名稱。你知道在數據庫中分配正確的密鑰是否相對容易? [我的PHP比我的SQL更強大]測試數據是第一個文件中的大約300行,然後是第二個文件中的3000行。如此有效的300 * 3000比較 – Aido