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