1

データベースからすべてのユーザーを返し、参照郵便番号から最短距離で結果を並べ替えるシステムがあります。

例:ユーザーがサイトにアクセスし、郵便番号を入力すると、自分の郵便番号に最も近い他のすべてのユーザーが返されます(昇順)。

私は今これをどのようにやっていますか、そしてなぜそれが問題なのですか?

システムには、3,000万人を超えるユーザーとその郵便番号が含まれています。特定の州と都市のすべてのユーザーを取得しています(データセットを約10,000に絞り込みます)。

これが実際に問題が発生する場所です。これで、mysql(10,000)行からPHPに送信されたすべての結果が郵便番号計算ライブラリに送信されます。このライブラリは、基本郵便番号とユーザーの郵便番号の間のこの距離を10,000回計算します。次に、最も近い郵便番号で結果を並べ替えます。

ご覧のとおり、これは非常に最適化されていないコードです。また、10,000レコードは2回ループされます。各httpdプロセスがmysqlとの間でデータを転送するだけで必要なRAMの量は言うまでもありません。

これを最適化するためにとにかくそこにあるここの教祖に私が聞きたいことは何ですか?

私は自分のアイデアをいくつか持っていますが、それらがどれほど効率的かはわかりません。

mysql自体ですべての郵便番号の計算と順序付けを実行し、ページ化された行数を返すようにしてください。このために、郵便番号計算ロジック間の距離をストアドプロシージャに移動する必要があります。このようにして、PHPで10,000レコードが処理されないようにしています。ただし、まだ問題があります。すでに計算されている郵便番号の距離を計算する必要はありません(同じ郵便番号を持つ2人のユーザーの場合)。

次に、ストアドプロシージャを使用してmysqlの行を並べ替えるにはどうすればよいですか?

皆さんはどう思いますか ?これは良い方法ですか?これを使用してパフォーマンスの向上を期待できますか?他に何か提案はありますか?

私はこの質問が巨大であることを知っています、そして私はあなたが最後まで読むのにかかった時間を本当に感謝します。これについてのあなたの考えを本当に聞きたいです。

4

3 に答える 3

1

私はPHPやMySQLにあまり精通していないので、いくつかの基本的なヒントしか提供できませんが、それらは役立つはずです。これは、MySQLからzipライブラリと直接やり取りする方法がないことも前提としています。

まず、都市に10kの郵便番号があるかどうかは疑わしいので、既存のクエリを取得して次のようにします。

SELECT DISTINCT ZipCode FROM Users WHERE ...

これにより、おそらく最大で数十の郵便番号が返され、重複はありません。これを郵便番号ライブラリで実行します。そのライブラリ自体は、郵便番号を検索し、実際の距離を取得するために一連の派手なトリガーを実行する必要があるため、おそらく速度低下の原因になります。この結果を取得し、郵便番号と距離だけを指定して一時テーブルに挿入します。

そのリストが完成したら、必要な残りのユーザーデータを取得する別のクエリを作成し、郵便番号の一時テーブルに参加して距離を取得します。

これにより、かなりのスピードアップが得られるはずです。結果が計算された後、2番目のクエリで必要なページングを実行できます。そして、10k行をループする必要はもうありません。

于 2011-03-06T22:07:25.383 に答える
1

フィルタリングと並べ替えの目的で正確な距離を計算する前に、緯度と経度の範囲を狭めることをお勧めします。

つまり、全表スキャンを実行して、データベース内のすべての郵便番号の参照ポイントからの距離を計算すると、非常に遅くなります。

代わりに、郵便番号を近接度でフィルタリングします。つまり、緯度が10、経度が20の場合、最初に必要な近接度の最大角度範囲を計算します。10マイルの近接範囲が必要だとします。これは0.15度に変換される可能性があります。したがって、郵便番号の最初の緯度は10-0.15から10 + 0.15の間、経度は20-0.15から20+0.15の間でフィルタリングする必要があります。

その後、SQLクエリ条件に正確なdistance句を含めます。フルスキャンを実行しなくなり、最終的に経度と緯度のフィールドで範囲インデックスを使用できるようになるため、これははるかに高速になります。

マイルを度に変換するには、狭い範囲を見つけます。地球の周囲長は約25,000マイルで、25000を360度で割ると、1度あたり70マイルになります。10マイルの範囲が必要な場合、度単位の範囲は最大で0.15度になります。

これらの計算は正確ではありませんが(地球は正確に丸みを帯びていません)、それは重要ではないことに注意してください。重要なのは、実際に正確な値よりも高い次数範囲の値を見つけることです。

于 2011-03-06T22:11:56.307 に答える
0

すべての郵便番号の緯度と経度をMySQLに取得できる場合、またはベースの郵便番号の緯度/経度を取得してMySQLクエリにフィードする簡単な方法がある場合は、MySQL内の距離で10,000人のユーザーを注文できます。ここには非常によく似た質問と回答があり、距離関数の正しい計算ができます。また、lat/longを2DPOINTデータとして挿入およびインデックス付けできるMysql空間拡張を調査することもできます。

于 2011-03-06T21:56:30.540 に答える