我正在使用PHP和MYSQL建立一个网站。
我想先按最近的位置点我的搜索结果。我有一个物品表和一个交易表。我需要搜索这些表中的项目/交易位置,然后将位置与我的邮政编码数据库进行比较,并从相应的数据库条目中获取纬度和经度并对结果进行排序。我正在使用PDO准备好的语句。
我的数据库中有3个表。邮政编码,交易和项目。
邮政编码
| postcode | lat | lng |
DEALS
| id | title | location |
项
| id | title | location |
这是我的SQL ......
SELECT SQL_CALC_FOUND_ROWS *
FROM (
SELECT *
FROM items
UNION
SELECT * FROM deals
) AS allitemsdeals
INNER JOIN (
SELECT
postcodes.*,
(3959 * acos(cos(radians(custom.lat)) * cos(radians(postcodes.lat)) * cos(radians(custom.lng) - radians(postcodes.lng)) + sin(radians(custom.lat)) * sin(radians(postcodes.lat)))
) AS distance
FROM postcodes
INNER JOIN postcodes AS custom
WHERE custom.postcode = ?
) postcodes ON allitemsdeals.location = postcodes.postcode
HAVING distance < 5 ORDER BY id LIMIT ? OFFSET ?
我在加入此问题时遇到了问题。查询有效,但大约需要一分钟! :(
任何帮助将不胜感激!谢谢! :)
答案 0 :(得分:0)
子查询正在扼杀您的表现。尝试在EXPLAIN
上预先SELECT
并查看输出 - 我怀疑有很多USING FILESORT
和USING (NULL) INDEX
内容。并检查了很多记录。可能还有一些derived
表......
所有这些JOIN (SELECT ...
语句都会导致查询运行,结果被缓存(或者更糟糕的是仍然为JOIN
左侧的每个记录重新运行)而没有任何索引 - 以及所有内容狠狠地停下来。
最后SQL_CALC_FOUND_ROWS
- 如果你不必这样做,就不要这样做。在应用LIMIT
之前,它会导致MySQL计算所有行并处理所有行以计算它们。即使在LIMIT
之前,您最好还是尽可能地减少的结果,最好不要使用SQL_CALC_FOUND_ROWS
。 (单独的SELECT COUNT(1)
会更好,相信我。去过那里。)
解决方案?不容易。首先更改您的架构。
首先:我将&#34;交易&#34;结合起来和&#34;项目&#34;进入一个大表 - 使用一列来区分类型(除非有很多其他列我没有看到),因为UNION
很可能(或肯定?)杀死任何索引你有
第二次:距离的子查询 - 哦,不!这应该是用于计算最大距离的直接WHERE
子句。如果你愿意,我会尝试优化它 - 但是如果没有SQLfiddle.com或其他东西可以玩,那么在我的空闲时间开始复制你的架构和数据有点多了。 (如果你用它设置了一个SQLfiddle - 我很高兴有一个戳。)
第三:我考虑使用MySQL的空间功能再次使用long / lat数据。有很多可用的文档:
这是一些很酷的东西 - 我希望在很长一段时间内(付费!)小时内找借口玩这种数据。我很想知道你最终会找到什么解决方案。
正如我所说 - 如果你提供一个SQLfiddle(假设其他人没有先提供更好的解决方案),我至少会高兴地看一下接下来的72小时。