私の Web サイトでの検索用に mysql select ステートメントを使用していますが、サイトが非常にビジー状態になるとパフォーマンスの問題が発生します。以下のクエリは、指定された緯度と経度から 25 マイル以内の 10 万レコードを超えるテーブルから広告を検索し、距離で並べ替えます。マイル数は、ユーザーが選択するため、異なる場合があります。
問題は、緯度と経度の 25 マイル以内にあるレコードではなく、テーブル内のすべてのレコードの計算を行うため、遅いと思うことです。where 句が 25 マイル以内の広告のみを選択するように、このクエリを修正することは可能ですか? 境界ボックスと空間インデックスについて読みましたが、それらをこのクエリに適用する方法がわかりません。緯度と経度の半径 25 マイルのレコードを選択する where 句を追加する必要がありますか?
SELECT
adverts.*,
round(sqrt((((adverts.latitude - '53.410778') * (adverts.latitude - '53.410778')) * 69.1 * 69.1) + ((adverts.longitude - '-2.97784') * (adverts.longitude - '-2.97784') * 53 * 53)), 1) as distance
FROM
adverts
WHERE
(adverts.type_id = '3')
HAVING
DISTANCE < 25
ORDER BY
distance ASC
LIMIT 120,10
編集:テーブルスキーマを含めるように更新されました。テーブルはより複雑であり、クエリも複雑であることに注意してください。ただし、この問題に必要のないものは削除しました。
CREATE TABLE `adverts` (
`advert_id` int(10) NOT NULL AUTO_INCREMENT,
`type_id` tinyint(1) NOT NULL,
`headline` varchar(50) NOT NULL,
`description` text NOT NULL,
`price` int(4) NOT NULL,
`postcode` varchar(7) NOT NULL,
`latitude` float NOT NULL,
`longitude` float NOT NULL,
PRIMARY KEY (`advert_id`),
KEY `latlon` (`latitude`,`longitude`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
mysqlステートメントでexplainを実行すると、行数が67900に設定されます。これは、半径25マイルよりもはるかに多く、追加は「場所を使用して;ファイルソートを使用して」に設定されています。
クエリには 0.3 秒かかりますが、これは非常に遅く、特に Web サイトが 1 秒あたりに多くのリクエストを受け取る場合に顕著です。