我有以下查询:
SELECT COUNT( Siret ) AS `NbEntr` , `Villes`.`Latitude` AS `Latitude` , `Villes`.`Longitude` AS `Longitude` , ( 6371 * ACOS( COS( RADIANS( 47.29473000 ) ) * COS( RADIANS( `Latitude` ) ) * COS( RADIANS( `Longitude` ) - RADIANS( - 2.35991000 ) ) + SIN( RADIANS( 47.29473000 ) ) * SIN( RADIANS( `Latitude` ) ) ) ) AS `distance`
FROM `Villes`
INNER JOIN `Liste_Etablissements` ON `CodeInsee` = `Code_Insee`
GROUP BY `Code_Insee`
HAVING distance <=30
大公式用于在定义的半径范围内获取所有城市的特定点 (https://developers.google.com/maps/articles/phpsqlsearch_v3#findnearsql)
以下是查询的解释:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 1 | SIMPLE | Liste_Etablissements | ALL | Code_Insee | NULL | NULL | NULL | 5596799 | Using temporary; Using filesort
| 1 | SIMPLE | Villes | eq_ref | PRIMARY | PRIMARY | 15 | outilgeoloc.Liste_Etablissements.Code_Insee | 1 |
问题在于,当我在PhpMyAdmin中执行此查询时,需要6秒才能执行,这很好(我认为?)因为主表大约是5 000 000行,但是当我用我的PHP代码执行它时,它大约需要30/40秒才能执行。
当我在执行查询期间查看进程时,我看到它正在&#34;复制到临时表&#34;在整个30/40期间,但是使用Phpmyadmin,它正在发送数据&#34;。
我已将tmp_table_size和max_heap_table_size设置为256Mo,但查询执行时间仍为30/40秒左右。
那么我该怎么做才能加快查询的执行时间?我可以绕过&#34;复制到临时表&#34;一步?
答案 0 :(得分:0)
我找到了解决方案:
现在,我将查询分为两部分: 首先,我得到一个半径范围内的城市列表,之后,对于每个城市,我得到了我的线路数。
对于那些想要了解我是如何做到的人:
<强>原始强>
SELECT COUNT( Siret ) AS `NbEntr`, `Villes`.`Latitude` AS `Latitude`, `Villes`.`Longitude` AS `Longitude`, ( 6371 * ACOS( COS( RADIANS( 47.29473000 ) ) * COS( RADIANS( `Latitude` ) ) * COS( RADIANS( `Longitude` ) - RADIANS( - 2.35991000 ) ) + SIN( RADIANS( 47.29473000 ) ) * SIN( RADIANS( `Latitude` ) ) ) ) AS `distance`
FROM `Villes`
INNER JOIN `Liste_Etablissements` ON `CodeInsee` = `Code_Insee`
GROUP BY `Code_Insee`
HAVING distance <=30
<强>重构:强>
我首先得到城市的坐标:
SELECT CodeInsee, Latitude, Longitude, ( 6371 * ACOS( COS( RADIANS( 47.29473000 ) ) * COS( RADIANS( `Latitude` ) ) * COS( RADIANS( `Longitude` ) - RADIANS( - 2.35991000 ) ) + SIN( RADIANS( 47.29473000 ) ) * SIN( RADIANS( `Latitude` ) ) ) ) AS `distance`
FROM Villes
HAVING distance <=30
然后,我的Php代码中有一个foreach循环,其中,foreach&#34; CodeInsee&#34; (这是我在&#34; Villes&#34;表中的主键)id执行第二个查询:
SELECT COUNT(Code_Insee) as NbEntr
FROM Liste_Etablissements
WHERE Code_Insee = :codeinsee
我为COUNT(Code_Insee)更改了COUNT(Siret),因为这样,Mysql只使用索引而不是数据,这样更快。
并且将这两个查询分开,mysql不再使用慢速表了。
这篇文章给了我很多帮助(对不起,用法语写的):http://dasini.net/blog/2009/02/18/optimisation-de-requetes-comprendre-loptimiseur-de-mysql/
谢谢你的帮助:D