php - 为什么我的 PHP/MYSQL 请求加载最多需要 5 分钟?

标签 php mysql database search geocoding

TL;DR - 使用 JOIN 代替低效的 IN

我有一个程序可以返回列为“覆盖”原始位置一定距离内的任何位置的单元。

即用户搜索区域、距离和类别。然后,该查询将返回覆盖原始区域搜索距离内的任何区域的所有办事处。

有两个表格,一个是“出版物/办公室”,另一个是每个出版物涵盖的地区,由它们的索引链接。在区域数据库中,出版物涵盖的每个区域都有一个条目。

问题是,当我运行查询时,最多需要 3 分钟才能返回结果?

我正在使用共享云服务器,但我觉得代码效率低下。任何帮助将不胜感激!

 <?php 
                    }     
                      $sql=mysql_query("select * from publications where ".$subwhereclause." AND publications.entry_id in (( SELECT regions_to_publications.pub_id  from regions_to_publications WHERE ((ACOS(SIN($lat * PI() / 180) * SIN(lat * PI() / 180) + COS($lat * PI() / 180) * COS(lat * PI() / 180) * COS(($lon - lon) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) *(1.6) < ".$_REQUEST["distance"].")) ") or die(mysql_error());

                      ?>
                    <?php while($row3= mysql_fetch_array($sql)) {?>
                    <div class="result-entry-card">

                    <p class="card-title"><?php echo $row3['entry_name'] ;?></p>
                    <p class="card-cat"><?php echo $row3['entry_category'];?></p>

                    <p><?php echo $row3['entry_phone'];?> - <a href="mailto:<?php echo $row3['entry_email'];?>"><?php echo $row3['entry_email'];?></a></p>

                     <p><a href="http://<?php echo $row3['entry_website'];?>">Email</a></p>
                    </div>
                    <?php } ?>

知道为什么要花这么长时间才能完成吗?我还在学习!

更新:我对以下代码运行了 EXPLAIN(替换变量)。

EXPLAIN SELECT * 
FROM publications
WHERE publications.entry_category
IN (
 ".newspapers."
)
AND publications.entry_id
IN (
(

SELECT regions_to_publications.pub_id
FROM regions_to_publications
WHERE (
(
ACOS( SIN( - 33.8683 * PI( ) /180 ) * SIN( lat * PI( ) /180 ) + COS( - 33.8683 * PI( ) /180 ) * COS( lat * PI( ) /180 ) * COS( ( 151.2086 - lon ) * PI( ) /180 ) ) *180 / PI( )
) *60 * 1.1515
) * ( 1.6 ) <  "1000"
)
)

这些是结果。

| id |select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
| 1 | PRIMARY | publications | ALL | NULL | NULL | NULL | NULL | 621 | Using where |
| 2 | DEPENDENT SUBQUERY | regions_to_publications | ALL | NULL | NULL | NULL | NULL | 84173 | Using where

对于任何想知道的人,我查看了这些结果并重新搜索如下,使用 JOIN 而不是 IN

SELECT * 
FROM publications
JOIN regions_to_publications ON entry_id = pub_id
WHERE (
(
ACOS( SIN( - 33.8683 * PI( ) /180 ) * SIN( regions_to_publications.lat * PI( ) /180 ) + COS( - 33.8683 * PI( ) /180 ) * COS( regions_to_publications.lat * PI( ) /180 ) * COS( ( 151.2086 - regions_to_publications.lon ) * PI( ) /180 ) ) *180 / PI( )
) *60 * 1.1515
) * ( 1.6 ) <  "1000"

AND

publications.entry_category
IN (
"radio"
)

GROUP BY publications.entry_id

最佳答案

您的 SQL 在 $_REQUEST["distance"] 和可能的 $subwhereclause 中包含一些主要漏洞,具体取决于它的来源。

另外,考虑使用 PDO或 mysqli 因为这个:

Deprecated: The mysql extension is deprecated and will be removed in the future.

无论如何,要回答您的问题,请尝试使用 explain 并查看 mysql 告诉您的内容。它会告诉您正在使用哪些索引以及正在扫描多少行。这应该会让您走上正确的轨道。

我建议从您的 Shell 或 PHPMyAdmin 执行此操作。

祝你好运!

附言- 要使用 explain,只需将其添加到 SELECT 语句的开头即可。

EXPLAIN SELECT * FROM table WHERE column=value

编辑 - 我看到您已经运行了 EXPLAIN 并发布了结果。

possible_keyskey 非常重要(键与索引相同)。解释是分析每个查询(因为有一个子查询)。

possible_keys 为 NULL 就像 Mysql 说“我查看了每个索引以查看是否可以使用它,但没有一个有效”。通常这意味着您必须进行全表扫描(行数是需要扫描的行数)。

子查询尤其缺乏可用的键。它必须扫描 84173 行。由于您的查询并不十分简单,因此这可能是对每一行的非常密集的扫描。

查看您的索引并弄清楚为什么 mysql 不能使用它们。我建议在 PHPMyAdmin 或 Shell 中执行此操作的原因是现在您可以轻松更改查询并查看索引是否有效。首先尝试简化所有内容,然后再重新构建。

关于php - 为什么我的 PHP/MYSQL 请求加载最多需要 5 分钟?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17984087/

相关文章:

java - 如何阻止 Gradle 复制构建文件夹中的资源

php - PHP 中的 Ruby 风格关系表

php - 通过 PHP 登录保存经过身份验证的 session

mysql - 获取两个日期之间的小时差

mysql - 从单个表中获取前 10 个最近更新或创建的记录

javascript - PHP 中的 If Else 条件与 Ajax responseText

mysql - Phpbb 上的 User_Notify 通知所有成员

php - 哪个更好 : require_once? 或 if (!defined ('FOOBAR' )) require?还是完全不同的东西?

php - 如何在不覆盖现有旧 PHP 版本的情况下安装 PHP 5.4?

php - SQL 错误 1064。语句在 mysqladmin 中有效,但在 PHP 脚本中无效