MySQL"复制到临时表"太慢了

时间:2014-08-20 15:35:50

标签: php mysql sql phpmyadmin

我有以下查询:

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;一步?

1 个答案:

答案 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