2015-02-05 44 views
2

我正在使用嵌套查詢從多個表中檢索信息。我需要關於優化這個php代碼的建議。如何優化嵌套查詢的數據庫連接?

該函數創建一個對象。

public function conn($query){ 

$mysqli = new mysqli('test','test','test','test'); 
$result = $mysqli->query("SET NAMES utf8"); 
$result = $mysqli->query("set character_set_client='utf8'"); 
$result = $mysqli->query("set collation_connection='utf8_general_ci'"); 
$result = $mysqli->query($query); 
$mysqli->close(); 
return $result; 
} 

此代碼使用該函數。

$connect = $this->conn("SELECT * FROM Table LIMIT 100000"); 
while($i = $connect->fetch_assoc()){ 
    $name = $i["name"]; 
    $connect2 = $this->conn("SELECT * FROM Names WHERE Name = '$name'"); 
    if($connect2 ->num_rows > 0){ 
    echo $name.'<br>'; 
    } 
} 

需要建議連接到數據庫。

while循環中,如您所見,我正在檢查其他表中是否存在$name。但是我每次都通過循環打開和關閉連接。這將是100001連接打開和關閉。

是否有可能打開到數據庫的連接只有一次?

P.S:該SQL是一個例子 - 請不要有暗示的變化,因爲我試圖找出如何處理重複的查詢,不能優化SQL。

+0

您需要JOIN和GROUP BY。 – 2015-02-05 12:51:35

+0

@SergioTulentsev不,不是。正如我寫在'p.s .: sql編寫例如 - 請不要編輯這個SQL查詢因爲需要建議只連接到數據庫.'即需要建議只用於連接(不查詢)。 – Brown 2015-02-05 12:53:09

+0

祝你好運,然後:) – 2015-02-05 12:54:25

回答

3

連接對象可重複使用。建立連接,然後使用它進行儘可能多的查詢。完成後關閉每個查詢(即每個結果集),然後在運行結束時關閉連接。

關閉連接是一個網絡的操作,因此需要一段時間。關閉查詢主要是內存中操作,所以速度更快。

在你的榜樣,你使用嵌套查詢(更詳細的介紹了一下)。您的代碼應該結束了尋找這樣的僞代碼:(請注意,我還沒有調試的代碼)

public function getconn(){ 
$mysqli = new mysqli('test','test','test','test'); 
$mysqli->query("SET NAMES utf8"); 
$mysqli->query("set character_set_client='utf8'"); 
$mysqli->query("set collation_connection='utf8_general_ci'"); 
return $mysqli; /* return the connection handle */ 
} 

$conn1 = getconn(); 
$conn2 = getconn(); 
$resultset1 = $conn1->query("SELECT * FROM Table LIMIT 100000"); 
while($i = $resultset1->fetch_assoc()){ 
    $name = $i["name"]; 
    $resultset2 = $conn2->query("SELECT * FROM Names WHERE Name = '$name'"); 
    if($resultset2->num_rows > 0){ 
    echo $name.'<br>'; 
    } 
    $resultset2->close(); 
} 
$resultset1->close(); 
$conn1->close(); 
$conn2->close(); 

藉此優化一步,你應該考慮使用事先準備好的聲明查詢while循環內的查詢。這是關於http://php.net/manual/en/mysqli-stmt.fetch.php的文檔。

$conn1 = getconn(); 
$conn2 = getconn(); 

/* create a prepared statement with placeholder parameter ? */ 
$stmt = $mysqli->prepare("SELECT * FROM Name WHERE Name = ?")); 
$name = ''; 
$name_out = ''; 
$stmt->bind_param("s", $name); 
$stmt->bind_result($name_out); 

$resultset1 = $conn1->query("SELECT * FROM Table LIMIT 100000"); 
while($i = $resultset1->fetch_assoc()){ 
    $name = $i["name"]; 
    $resultset2 = $stmt->execute(); /* run query with bound parameter */ 
    if ($stmt_fetch() ({ 
    echo $name.'<br>'; 
    } 
    $resultset2->close(); 
} 
$resultset1->close(); 
$conn1->close(); 
$conn2->close(); 

(請注意,我沒有任何調試此代碼。) 現在,它可能是您對查詢的只是展示了一組嵌套查詢的例子。如果是這樣,那很好。但是,您正在以執行此任務(檢索100K名稱),幾乎無法想象低效的方式。你說過你不想讓任何人重寫這個查詢,但是我很抱歉,我不能讓這個問題通過。

此代碼可以做更簡化的工作。

$conn = getconn(); 
$q = "SELECT t.name FROM Table t JOIN Name n ON t.name = n.name LIMIT 100000"; 
$resultset = $conn->query($q); 
while($i = $resultset->fetch_assoc()){ 
    $name = $i["name"]; 
    echo $name.'<br>'; 
} 
$resultset->close(); 
$conn->close(); 

由於兩個原因,它更有效率。首先,它不使用SELECT *,它最終會通過網絡從MySQL服務器發送各種數據到您的php程序,只是將它扔掉。

其次,它不使用嵌套查詢。相反,JOIN查詢將從Table中抽取name列中的所有列,其列中的匹配列爲name