PHP - 从 MySQL 数据库循环结果时页面加载缓慢
PHP - slow page load when looping results from MySQL database
我有 php 代码从 MySQL 数据库中获取结果 - users
和 [=85] 的玩具名称(在 toys
table 中) =]玩具和唯一用户数并显示在网页上。
玩具的名称可以是一个单词,也可以是单词的组合。我们想从 toys
中获取这些结果,其中 toys_text
字段包含 words
table 中所有单词组合的单词(示例 - If words
table 具有名为 blue car
的条目 - blue
和 car
都应出现在匹配的 toys
table toys_text
字段中)。随着新玩具的用户被添加和过时的玩具的用户被删除,数据库随着时间的推移而变化。
生成的页面加载速度非常慢,在 GT-metrix 测试中大约需要 10 秒。 Google Analytics 说我的代码有问题。我的代码有如下子查询 -
<?php
$WordQ = $db->query("SELECT * FROM words ORDER BY `words`.`words` ASC");
$i = 1;
while($row = $WordQ->fetch(PDO::FETCH_ASSOC)){
$Word = $row['words'];
$WordsArr = explode(" ", $row['words']);
$query = "";
if(count($WordsArr) > 1){
$query = "SELECT t_id,name,toys_text FROM toys WHERE toys_text
LIKE '%".implode("%' AND toys_text LIKE '%", $WordsArr)."%'";
}else{
$query = "SELECT t_id,name,toys_text FROM toys WHERE toys_text
LIKE '%$WordsArr[0]%'";
}
$countIds = array();
$countNames = array();
$Data = $db->query($query);
while($data = $Data->fetch(PDO::FETCH_ASSOC)){
$countIds[] = $data['t_id'];
$countNames[] = $data['name'];
}
?>
<tr>
<td><?php echo $i;?></td>
<td><?php echo $row['words'];?></td>
<td><a href="showtoys.php?word=<?php echo urlencode($Word); ?
>" target="_blank"><?php echo count(array_unique($countIds)); ?>
</a></td>
<td><a href="showtoys.php?word=<?php echo urlencode($Word); ?
>" target="_blank"><?php echo count(array_unique($countNames));
?></a></td>
</tr>
<?php $i++;} ?>
我试图删除子查询,但页面加载速度仍然很慢。请指导如何使页面加载更快。以下是没有子查询的代码 -
<?php
$query = "SELECT * FROM words ORDER BY `words`.`words`
ASC";
$result = mysqli_query($con, $query);
$i = 1;
while($row = mysqli_fetch_array($result)){
$Word = $row['words'];
$WordsArr = explode(" ", $row['words']);
$query = "";
if(count($WordsArr) > 1){
$query1 = "select COUNT(*) as 'count', COUNT(DISTINCT
t.name) AS 'cnt' from toys t WHERE toys_text LIKE '%".implode("%' AND
toy_text LIKE '%", $WordsArr)."%'";
}else{
$query1 = "select COUNT(*) as 'count', COUNT(DISTINCT t.name) AS
'cnt' from toys t WHERE
toys_text LIKE '%$WordsArr[0]%'";
}
$Data1 = mysqli_query($con, $query1);
$total1 = mysqli_fetch_assoc($Data1);
?>
<tr>
<td><?php echo $i;?></td>
<td><?php echo $row['words'];?></td>
<td><a href="showtoys.php?word=<?php echo
urlencode($Word); ?>" target="_blank"><?php echo
$total1['count']; ?></a></td>
<td><a href="showtoys.php?keyword=<?php echo urlencode($Word);
?>" target="_blank"><?php echo $total1['cnt']; ?></a></td>
</tr>
<?php $i++;} ?>
这是我的MySQLtable的结构-
字数:
S.No 名称类型
id 主 int(11)
单词 varchar(60)
示例 - 白色汽车、气球、蓝色巴士
类型枚举('words', 'phrase')
玩具:
S.No。名称类型
t_id 主 bigint(20)
toys_text FULLTEXT 索引 varchar(255)
user_id BTREE 索引 bigint(20)
名称 BTREE 索引 char(20)
Mysql 是带有 InnoDB 存储的 10.1.30-MariaDB。
编辑-
假设我在 words
table 中有一个名为 little blue car
的玩具。那么真正的比赛将是 -
我有一个 little
car
,它是 blue
。
blue
我的little
car
上色很快
错误匹配将是 -
我有一辆小车。
我的小车很不错
意味着所有单词都应出现在 toys_text
字段中才能真正匹配。
我将查询更改为
if(count($WordsArr) > 1){
$query1 = "select COUNT() as 'count',
COUNT(DISTINCT t.name) AS 'cnt' from toys t WHERE MATCH (toys_text) AGAINST
('".implode("'+'", ($WordsArr))."' IN BOOLEAN MODE)";
}else{
$query1 = "select COUNT() as 'count', COUNT(DISTINCT t.name) AS 'cnt' from
toys t WHERE MATCH (toys_text) AGAINST ('%$WordsArr[0]%')";
现在,对于具有高计数的单词和单词组合,它的计数为 0。这些词不在 Mysql 的非索引字表中。这是对 FULLTEXT 搜索的一些限制吗?
我认为问题来自执行 sql 请求的 PHP 循环。所以为了减少时间,你不应该做很多请求,而是严格的最低限度。在你的情况下,找到干净的方法有点困难,但它应该有一个!
也许有一种方法可以使用 sql 子字符串函数创建 "toys" table 的所有单词(一个接一个)的视图。那么子查询函数就不是一个"like"而是一个简单的“=”,这样就快多了。
https://mariadb.com/kb/en/library/create-view/
我建议使用存储过程来使您的查询更快,因为您使用
一个 while 循环,然后您在其中有另一个查询。如果你只调用一个过程比在 php.
中构建查询更快
尝试检查此 link 以获取参考:https://dev.mysql.com/doc/refman/5.7/en/stored-routines.html
我向你保证它会顺利查询。
如果您只需要计算包含单词的那些玩具的数量
我建议在 while 循环之前的第一部分中使用 Join 查询所有内容,然后对它们进行计数,然后按单词对它们进行分组。
$stringWord= str_replace(' ', '%', $WordsArr);
$query1 = "call toysQuery(".$stringWord.")";
然后在您的过程参数中使用 varchar。
您正在循环中根据 SQL 语句的输出生成并运行 SQL。只需在查询之间进行连接,一次往返数据库,一次循环显示结果。
按照@Sammitch 的建议,在带有 foreach 循环的布尔模式下使用 MATCH() 更改了查询。现在,页面加载时间为三分之一,大约 3 秒。
这是我的代码 -
<?php
$query = "SELECT * FROM words ORDER BY `words`.`words`
ASC";
$result = mysqli_query($con, $query);
$i = 1;
while($row = mysqli_fetch_array($result)){
$Word = $row['words'];
$WordsArr = explode(" ", $row['words']);
$query = "";
if(count($WordsArr) > 1){
foreach ($WordsArr as $value) {
$value1='';
$value1 .= " +"."(".$value."*".")";
}
$query1 = "select COUNT(*) as 'count', COUNT(DISTINCT
t.name) AS 'cnt' from toys t WHERE MATCH (toys_text) AGAINST
('$value1' IN BOOLEAN MODE)";
}else{
$query1 = "select COUNT(*) as 'count', COUNT(DISTINCT t.name) AS
'cnt' from toys t WHERE
MATCH (toys_text) AGAINST ('$WordsArr[0]* IN BOOLEAN MODE')";
}
$Data1 = mysqli_query($con, $query1);
$total1 = mysqli_fetch_assoc($Data1);
?>
<tr>
<td><?php echo $i;?></td>
<td><?php echo $row['words'];?></td>
<td><a href="showtoys.php?word=<?php echo
urlencode($Word); ?>" target="_blank"><?php echo
$total1['count']; ?></a></td>
<td><a href="showtoys.php?keyword=<?php echo urlencode($Word);
?>" target="_blank"><?php echo $total1['cnt']; ?></a></td>
</tr>
<?php $i++;} ?>
我有 php 代码从 MySQL 数据库中获取结果 - users
和 [=85] 的玩具名称(在 toys
table 中) =]玩具和唯一用户数并显示在网页上。
玩具的名称可以是一个单词,也可以是单词的组合。我们想从 toys
中获取这些结果,其中 toys_text
字段包含 words
table 中所有单词组合的单词(示例 - If words
table 具有名为 blue car
的条目 - blue
和 car
都应出现在匹配的 toys
table toys_text
字段中)。随着新玩具的用户被添加和过时的玩具的用户被删除,数据库随着时间的推移而变化。
生成的页面加载速度非常慢,在 GT-metrix 测试中大约需要 10 秒。 Google Analytics 说我的代码有问题。我的代码有如下子查询 -
<?php
$WordQ = $db->query("SELECT * FROM words ORDER BY `words`.`words` ASC");
$i = 1;
while($row = $WordQ->fetch(PDO::FETCH_ASSOC)){
$Word = $row['words'];
$WordsArr = explode(" ", $row['words']);
$query = "";
if(count($WordsArr) > 1){
$query = "SELECT t_id,name,toys_text FROM toys WHERE toys_text
LIKE '%".implode("%' AND toys_text LIKE '%", $WordsArr)."%'";
}else{
$query = "SELECT t_id,name,toys_text FROM toys WHERE toys_text
LIKE '%$WordsArr[0]%'";
}
$countIds = array();
$countNames = array();
$Data = $db->query($query);
while($data = $Data->fetch(PDO::FETCH_ASSOC)){
$countIds[] = $data['t_id'];
$countNames[] = $data['name'];
}
?>
<tr>
<td><?php echo $i;?></td>
<td><?php echo $row['words'];?></td>
<td><a href="showtoys.php?word=<?php echo urlencode($Word); ?
>" target="_blank"><?php echo count(array_unique($countIds)); ?>
</a></td>
<td><a href="showtoys.php?word=<?php echo urlencode($Word); ?
>" target="_blank"><?php echo count(array_unique($countNames));
?></a></td>
</tr>
<?php $i++;} ?>
我试图删除子查询,但页面加载速度仍然很慢。请指导如何使页面加载更快。以下是没有子查询的代码 -
<?php
$query = "SELECT * FROM words ORDER BY `words`.`words`
ASC";
$result = mysqli_query($con, $query);
$i = 1;
while($row = mysqli_fetch_array($result)){
$Word = $row['words'];
$WordsArr = explode(" ", $row['words']);
$query = "";
if(count($WordsArr) > 1){
$query1 = "select COUNT(*) as 'count', COUNT(DISTINCT
t.name) AS 'cnt' from toys t WHERE toys_text LIKE '%".implode("%' AND
toy_text LIKE '%", $WordsArr)."%'";
}else{
$query1 = "select COUNT(*) as 'count', COUNT(DISTINCT t.name) AS
'cnt' from toys t WHERE
toys_text LIKE '%$WordsArr[0]%'";
}
$Data1 = mysqli_query($con, $query1);
$total1 = mysqli_fetch_assoc($Data1);
?>
<tr>
<td><?php echo $i;?></td>
<td><?php echo $row['words'];?></td>
<td><a href="showtoys.php?word=<?php echo
urlencode($Word); ?>" target="_blank"><?php echo
$total1['count']; ?></a></td>
<td><a href="showtoys.php?keyword=<?php echo urlencode($Word);
?>" target="_blank"><?php echo $total1['cnt']; ?></a></td>
</tr>
<?php $i++;} ?>
这是我的MySQLtable的结构-
字数:
S.No 名称类型
id 主 int(11)
单词 varchar(60)
示例 - 白色汽车、气球、蓝色巴士
类型枚举('words', 'phrase')
玩具:
S.No。名称类型
t_id 主 bigint(20)
toys_text FULLTEXT 索引 varchar(255)
user_id BTREE 索引 bigint(20)
名称 BTREE 索引 char(20)
Mysql 是带有 InnoDB 存储的 10.1.30-MariaDB。
编辑-
假设我在 words
table 中有一个名为 little blue car
的玩具。那么真正的比赛将是 -
我有一个 little
car
,它是 blue
。
blue
我的little
car
上色很快
错误匹配将是 -
我有一辆小车。 我的小车很不错
意味着所有单词都应出现在 toys_text
字段中才能真正匹配。
我将查询更改为
if(count($WordsArr) > 1){
$query1 = "select COUNT() as 'count',
COUNT(DISTINCT t.name) AS 'cnt' from toys t WHERE MATCH (toys_text) AGAINST
('".implode("'+'", ($WordsArr))."' IN BOOLEAN MODE)";
}else{
$query1 = "select COUNT() as 'count', COUNT(DISTINCT t.name) AS 'cnt' from
toys t WHERE MATCH (toys_text) AGAINST ('%$WordsArr[0]%')";
现在,对于具有高计数的单词和单词组合,它的计数为 0。这些词不在 Mysql 的非索引字表中。这是对 FULLTEXT 搜索的一些限制吗?
我认为问题来自执行 sql 请求的 PHP 循环。所以为了减少时间,你不应该做很多请求,而是严格的最低限度。在你的情况下,找到干净的方法有点困难,但它应该有一个!
也许有一种方法可以使用 sql 子字符串函数创建 "toys" table 的所有单词(一个接一个)的视图。那么子查询函数就不是一个"like"而是一个简单的“=”,这样就快多了。 https://mariadb.com/kb/en/library/create-view/
我建议使用存储过程来使您的查询更快,因为您使用 一个 while 循环,然后您在其中有另一个查询。如果你只调用一个过程比在 php.
中构建查询更快尝试检查此 link 以获取参考:https://dev.mysql.com/doc/refman/5.7/en/stored-routines.html
我向你保证它会顺利查询。
如果您只需要计算包含单词的那些玩具的数量 我建议在 while 循环之前的第一部分中使用 Join 查询所有内容,然后对它们进行计数,然后按单词对它们进行分组。
$stringWord= str_replace(' ', '%', $WordsArr);
$query1 = "call toysQuery(".$stringWord.")";
然后在您的过程参数中使用 varchar。
您正在循环中根据 SQL 语句的输出生成并运行 SQL。只需在查询之间进行连接,一次往返数据库,一次循环显示结果。
按照@Sammitch 的建议,在带有 foreach 循环的布尔模式下使用 MATCH() 更改了查询。现在,页面加载时间为三分之一,大约 3 秒。
这是我的代码 -
<?php
$query = "SELECT * FROM words ORDER BY `words`.`words`
ASC";
$result = mysqli_query($con, $query);
$i = 1;
while($row = mysqli_fetch_array($result)){
$Word = $row['words'];
$WordsArr = explode(" ", $row['words']);
$query = "";
if(count($WordsArr) > 1){
foreach ($WordsArr as $value) {
$value1='';
$value1 .= " +"."(".$value."*".")";
}
$query1 = "select COUNT(*) as 'count', COUNT(DISTINCT
t.name) AS 'cnt' from toys t WHERE MATCH (toys_text) AGAINST
('$value1' IN BOOLEAN MODE)";
}else{
$query1 = "select COUNT(*) as 'count', COUNT(DISTINCT t.name) AS
'cnt' from toys t WHERE
MATCH (toys_text) AGAINST ('$WordsArr[0]* IN BOOLEAN MODE')";
}
$Data1 = mysqli_query($con, $query1);
$total1 = mysqli_fetch_assoc($Data1);
?>
<tr>
<td><?php echo $i;?></td>
<td><?php echo $row['words'];?></td>
<td><a href="showtoys.php?word=<?php echo
urlencode($Word); ?>" target="_blank"><?php echo
$total1['count']; ?></a></td>
<td><a href="showtoys.php?keyword=<?php echo urlencode($Word);
?>" target="_blank"><?php echo $total1['cnt']; ?></a></td>
</tr>
<?php $i++;} ?>