我使用嵌套查询从多个表中检索信息。我需要有关优化此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 :(得分: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查询会从name
中提取Table
列name
列中Names
列的所有{{1}}列。