Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Indeks Spasial tidak digunakan

Sayangnya ST_Distance() < threshold bukan seorang sargable kriteria pencarian. Untuk memenuhi permintaan ini, MySQL harus menghitung nilai fungsi untuk setiap baris dalam tabel, dan kemudian membandingkannya dengan ambang batas. Jadi ia harus melakukan pemindaian tabel penuh (atau mungkin pemindaian indeks penuh).

Untuk mengeksploitasi indeks untuk mempercepat kueri ini, Anda akan memerlukan kriteria kotak pembatas. Permintaannya jauh lebih rumit tetapi juga jauh lebih cepat. Dengan asumsi titik x/y dalam geometri Anda mewakili garis lintang/garis bujur dalam derajat, kueri tersebut mungkin terlihat seperti ini:

   set @latpoint = 38.0234332;
   set @lngpoint = -94.0724223;
   set @r = 10.0;    /* ten mile radius */
   set @units=69.0;    /* 69 statute miles per degree */
   SELECT AsText(geo) 
     FROM markers
      WHERE MbrContains(GeomFromText( 
       CONCAT('LINESTRING(', @latpoint-(@r/@units),' ',
                             @lngpoint-(@r /(@units* COS(RADIANS(@latpoint)))), 
                          ',', 
                             @latpoint+(@r/@units) ,' ', 
                             @lngpoint+(@r /(@units * COS(RADIANS(@latpoint)))),
                           ')')),
                    geo) 

Bagaimana cara kerjanya? Untuk satu hal, MbrContains( terikat, barang) fungsi adalah sargable . Untuk hal lain, item concat jelek besar menghasilkan garis diagonal dari barat daya ke sudut timur laut dari persegi panjang pembatas. Menggunakan titik data Anda dan radius sepuluh mil akan terlihat seperti ini.

LINESTRING(37.8785 -94.2564,38.1684 -93.8884)

Saat Anda menggunakan GeomFromText() rendering garis diagonal dalam argumen pertama ke MbrContains() itu berfungsi sebagai persegi panjang pembatas. MbrContains() kemudian dapat mengeksploitasi indeks geometri quadtree yang bagus.

Ketiga, ST_Distance() , di MySQL, tidak menangani perhitungan garis lintang dan garis bujur yang bagus. (PostgreSQL memiliki ekstensi GIS yang lebih komprehensif .) MySQL sama bodohnya dengan flapjack di flatland. Ini mengasumsikan poin Anda dalam objek geometris Anda diwakili dalam geometri planar. Jadi ST_Distance() < 10.0 dengan lng/lat poin melakukan sesuatu yang aneh.

Ada satu kekurangan dalam hasil yang dihasilkan kueri ini; itu mengembalikan semua titik di kotak pembatas, tidak hanya dalam radius yang ditentukan. Itu bisa dipecahkan dengan perhitungan jarak terpisah. Saya telah menulis semua ini dalam beberapa detail di sini .

Catatan :Untuk garis lintang dan garis bujur resolusi GPS, FLOAT 32 32-bit data memiliki presisi yang cukup. DOUBLE adalah apa yang digunakan ekstensi geografis MySQL. Saat Anda bekerja dalam derajat, lebih dari lima tempat setelah titik desimal berada di luar ketepatan GPS. DECIMAL() bukan tipe data ideal untuk koordinat lat/lng.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. bagaimana cara mengatur tag nilai yang dipilih <select> html dari database di php?

  2. MySQL dan PHP:UTF-8 dengan karakter Cyrillic

  3. json_encode() array di loop sementara untuk mySQL untuk kalender

  4. Terjadi kesalahan fatal selama eksekusi perintah. di C# ketika saya menggunakan Insert Into

  5. Mengapa MySQL menggunakan indeks yang salah?