検索に近いジオコーダーを高速化するためのインデックスを追加

マテウシュ・ウルバンスキー

Railsアプリには、現在ログインしているユーザーに最も近いユーザーを見つけることができる機能があります。これにはGeocodergemを使用しています。ユーザーモデルでは、次のようなスコープがあります。

   scope :close_to, -> (user:, distance:) {
    where.not(id: user.id)
    .near([user.latitude, user.longitude], distance)
  }

これは非常にうまく機能しますが、ユーザーの大規模なコレクションでは遅くなります。このスコープを呼び出すと、次のSQLクエリが生成されます。

SELECT users.*, 6371.0 * 2 * ASIN(SQRT(POWER(SIN((48.471645 - users.latitude) * PI() / 180 / 2), 2) + COS(48.471645 * PI() / 180) * COS(users.latitude * PI() / 180) * POWER(SIN((-83.102801 - users.longitude) * PI() / 180 / 2), 2))) AS distance, MOD(CAST((ATAN2( ((users.longitude - -83.102801) / 57.2957795), ((users.latitude - 48.471645) / 57.2957795)) * 57.2957795) + 360 AS decimal), 360) AS bearing FROM "users" WHERE ("users"."id" != 43362) AND (users.latitude BETWEEN 39.4784289408127 AND 57.46486105918731 AND users.longitude BETWEEN -96.6674214298497 AND -69.5381805701503 AND (6371.0 * 2 * ASIN(SQRT(POWER(SIN((48.471645 - users.latitude) * PI() / 180 / 2), 2) + COS(48.471645 * PI() / 180) * COS(users.latitude * PI() / 180) * POWER(SIN((-83.102801 - users.longitude) * PI() / 180 / 2), 2)))) BETWEEN 0.0 AND 1000) ORDER BY distance ASC;

そのためのインデックスを作成しようとしていますが、機能しません。私は次の組み合わせを試していました:

1.
    add_index :users, [:id, :latitude]
    add_index :users, [:id, :longitude]

2.  add_index :users, [:id, :latitude, :longitude]

3.  add_index :users, [:latitude]
    add_index :users, [:longitude]

4. add_index :users, [:id, :latitude]

このクエリを高速化するには、どのようにインデックスを追加する必要がありますか?

編集:緯度と経度の列が小数であることを追加するのを忘れました。

このクエリのANALYZEは、次のようなものを返します。

 Sort  (cost=7141.66..7142.14 rows=191 width=327) (actual time=575.995..585.543 rows=36598 loops=1)
   Sort Key: ((12742::double precision * asin(sqrt((power(sin((((((48.471645 - latitude))::double precision * 3.14159265358979::double precision) / 180::double precision) / 2::double precision)), 2::double precision) + ((0.662990616338754::double precision * cos((((latitude)::double precision * 3.14159265358979::double precision) / 180::double precision))) * power(sin(((((((-83.102801) - longitude))::double precision * 3.14159265358979::double precision) / 180::double precision) / 2::double precision)), 2::double precision)))))))
   Sort Method: external merge  Disk: 4672kB
   ->  Seq Scan on users  (cost=0.00..7134.43 rows=191 width=327) (actual time=0.381..517.615 rows=36598 loops=1)
         Filter: ((id <> 43362) AND (latitude >= 39.4784289408127) AND (latitude <= 57.46486105918731) AND (longitude >= (-96.6674214298497)) AND (longitude <= (-69.5381805701503)) AND ((12742::double precision * asin(sqrt((power(sin((((((48.471645 - latitude))::double precision * 3.14159265358979::double precision) / 180::double precision) / 2::double precision)), 2::double precision) + ((0.662990616338754::double precision * cos((((latitude)::double precision * 3.14159265358979::double precision) / 180::double precision))) * power(sin(((((((-83.102801) - longitude))::double precision * 3.14159265358979::double precision) / 180::double precision) / 2::double precision)), 2::double precision)))))) >= 0::double precision) AND ((12742::double precision * asin(sqrt((power(sin((((((48.471645 - latitude))::double precision * 3.14159265358979::double precision) / 180::double precision) / 2::double precision)), 2::double precision) + ((0.662990616338754::double precision * cos((((latitude)::double precision * 3.14159265358979::double precision) / 180::double precision))) * power(sin(((((((-83.102801) - longitude))::double precision * 3.14159265358979::double precision) / 180::double precision) / 2::double precision)), 2::double precision)))))) <= 1000::double precision))
         Rows Removed by Filter: 6756
 Planning time: 1.041 ms
 Execution time: 587.695 ms
(8 rows)

編集2:

postgresqlが私の

add_index :users, [:latitude, :longitude]

短い距離を入力した場合のみ。10キロ近くのユーザー。

何もニロフ

速度低下は、テーブルデータのフェッチではなく、数学演算が原因である可能性があります。基準の一部は、レコードフィールドに対してではなく、他のレコードに対する数学演算の結果に対してであるため、O(N 2)になります。

Postgresがインデックスを使用せず、代わりにSeqスキャンを選択する理由は、クエリ中にほとんどのテーブルレコードをフェッチする必要があると判断したためです。テーブル内のほとんどのレコードをフェッチする場合、インデックスがあったとしてもあまりメリットがない場合があります。

物事をスピードアップするには、PostGisの空間インデックスと近傍ベースの検索、または代わりに、Geo DistanceQueryを使用したElasticsearchの使用を検討する必要があります

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

コードを高速化するためのオブジェクトのインスタンス化

分類Dev

データ取得を高速化するためのインデックスの作成方法

分類Dev

複数のリストのインデックスに対するIF / ELIF検索を高速化しますか?

分類Dev

パンダのデータフレーム検索を高速化する方法を探しています

分類Dev

データベースまたはビジュアルスタジオで、更新を高速化するためのドロップダウンメニュー項目を配置するのに最適な場所は?

分類Dev

インデックス検索PYTHONを使用してネストされたforループを高速化する方法

分類Dev

パンダの時間インデックス付きデータフレームの将来の値をローリングするためにループします。これを高速化できますか?

分類Dev

ハッシュコードを使用して、コレクション内のオブジェクト検索を高速化しますか?

分類Dev

クエリを高速化するためのインデックスを作成する

分類Dev

numpy配列でのインデックス検索を高速化

分類Dev

SQLServerでクエリを高速化するためのインデックスを作成します

分類Dev

postgresqlのタイムスタンプ列にインデックスを付けることで検索を高速化しますか?

分類Dev

ハードドライブのバックアップコードを高速化するための提案

分類Dev

結合クエリを高速化するためのSQL列のインデックス作成

分類Dev

読み取りアクセスを高速化するために、データを計算シェーダーの共有ストレージに「プリロード」することは理にかなっていますか?

分類Dev

ネットワークパスでのファイル検索を高速化

分類Dev

numpy配列を使用したインデックスによるエッジ行列の取得を高速化

分類Dev

NASアクセスを高速化するためのブリッジとルーター

分類Dev

マルチインデックスでパンダのインデックス作成を高速化するにはどうすればよいですか?

分類Dev

Dockerイメージのビルドを高速化するための「apt-getupdate」の高速化

分類Dev

大きなパンダのデータフレームで最も近い上限値と下限値の検索を高速化

分類Dev

検索パフォーマンスを最適化するためのPostgreSQLjsonbインデックス作成

分類Dev

Chromeでのマルチタブブラウジングを高速化するためにデュアルコアからクアッドコアに移行

分類Dev

近くに別のルーターを追加した場合、クライアントサーバー通信が高速化されますか?

分類Dev

パンダのデータフレームでの検索を高速化

分類Dev

「移動する」球内の複数の配列間でデータを検索するコードのランタイムを高速化する方法

分類Dev

node.js&非同期データベース検索後にファイルを高速化、リダイレクト、または送信

分類Dev

結合を高速化するために、同じ列に2つのインデックスを作成する必要がありますか?

分類Dev

レジストリのHKUセクションを検索するスクリプトを高速化するにはどうすればよいですか?

Related 関連記事

  1. 1

    コードを高速化するためのオブジェクトのインスタンス化

  2. 2

    データ取得を高速化するためのインデックスの作成方法

  3. 3

    複数のリストのインデックスに対するIF / ELIF検索を高速化しますか?

  4. 4

    パンダのデータフレーム検索を高速化する方法を探しています

  5. 5

    データベースまたはビジュアルスタジオで、更新を高速化するためのドロップダウンメニュー項目を配置するのに最適な場所は?

  6. 6

    インデックス検索PYTHONを使用してネストされたforループを高速化する方法

  7. 7

    パンダの時間インデックス付きデータフレームの将来の値をローリングするためにループします。これを高速化できますか?

  8. 8

    ハッシュコードを使用して、コレクション内のオブジェクト検索を高速化しますか?

  9. 9

    クエリを高速化するためのインデックスを作成する

  10. 10

    numpy配列でのインデックス検索を高速化

  11. 11

    SQLServerでクエリを高速化するためのインデックスを作成します

  12. 12

    postgresqlのタイムスタンプ列にインデックスを付けることで検索を高速化しますか?

  13. 13

    ハードドライブのバックアップコードを高速化するための提案

  14. 14

    結合クエリを高速化するためのSQL列のインデックス作成

  15. 15

    読み取りアクセスを高速化するために、データを計算シェーダーの共有ストレージに「プリロード」することは理にかなっていますか?

  16. 16

    ネットワークパスでのファイル検索を高速化

  17. 17

    numpy配列を使用したインデックスによるエッジ行列の取得を高速化

  18. 18

    NASアクセスを高速化するためのブリッジとルーター

  19. 19

    マルチインデックスでパンダのインデックス作成を高速化するにはどうすればよいですか?

  20. 20

    Dockerイメージのビルドを高速化するための「apt-getupdate」の高速化

  21. 21

    大きなパンダのデータフレームで最も近い上限値と下限値の検索を高速化

  22. 22

    検索パフォーマンスを最適化するためのPostgreSQLjsonbインデックス作成

  23. 23

    Chromeでのマルチタブブラウジングを高速化するためにデュアルコアからクアッドコアに移行

  24. 24

    近くに別のルーターを追加した場合、クライアントサーバー通信が高速化されますか?

  25. 25

    パンダのデータフレームでの検索を高速化

  26. 26

    「移動する」球内の複数の配列間でデータを検索するコードのランタイムを高速化する方法

  27. 27

    node.js&非同期データベース検索後にファイルを高速化、リダイレクト、または送信

  28. 28

    結合を高速化するために、同じ列に2つのインデックスを作成する必要がありますか?

  29. 29

    レジストリのHKUセクションを検索するスクリプトを高速化するにはどうすればよいですか?

ホットタグ

アーカイブ