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

Cara meningkatkan kinerja kueri dalam pencarian admin Django pada bidang terkait (MySQL)

Setelah banyak penyelidikan, saya menemukan bahwa masalahnya berasal dari bagaimana kueri pencarian dibuat untuk bidang pencarian admin (di ChangeList kelas). Dalam pencarian multi-istilah (kata-kata dipisahkan oleh spasi) setiap istilah ditambahkan ke QuerySet dengan merantai filter() baru . Ketika ada satu atau beberapa bidang terkait di search_fields , kueri SQL yang dibuat akan memiliki banyak JOIN dirantai satu demi satu dengan banyak JOIN untuk setiap bidang terkait (lihat pertanyaan terkait untuk beberapa contoh dan info lebih lanjut). Rantai JOIN . ini apakah ada sehingga setiap istilah akan dicari hanya di subset filter data dengan istilah preseden DAN, yang paling penting, bahwa bidang terkait hanya perlu memiliki satu istilah (vs harus memiliki SEMUA istilah) untuk membuat kecocokan. Lihat Mencakup hubungan multinilai dalam dokumen Django untuk info lebih lanjut tentang subjek ini. Saya cukup yakin itu adalah perilaku yang paling diinginkan di kolom pencarian admin.

Kelemahan dari kueri ini (dengan bidang terkait yang terlibat) adalah bahwa variasi kinerja (waktu untuk melakukan kueri) bisa sangat besar. Itu tergantung pada banyak faktor:jumlah istilah yang dicari, istilah yang dicari, jenis pencarian lapangan (VARCHAR, dll.), jumlah pencarian lapangan, data dalam tabel, ukuran tabel, dll. Dengan kombinasi yang tepat itu mudah untuk memiliki kueri yang sebagian besar akan memakan waktu lama (kueri yang memakan waktu lebih dari 10 menit bagi saya adalah kueri yang memakan waktu lama dalam konteks bidang penelusuran ini).

Alasan mengapa ini bisa memakan waktu lama adalah karena database perlu membuat tabel sementara untuk setiap istilah dan memindainya sebagian besar untuk mencari istilah berikutnya. Jadi, ini bertambah dengan sangat cepat.

Perubahan yang mungkin dilakukan untuk meningkatkan kinerja adalah dengan DAN semua istilah dalam filter() . yang sama . Dengan cara ini mereka hanya akan menjadi satu JOIN oleh bidang terkait (atau 2 jika banyak ke banyak) alih-alih banyak lagi. Kueri ini akan jauh lebih cepat dan dengan variasi kinerja yang sangat kecil. Kekurangannya adalah bahwa bidang terkait harus memiliki SEMUA istilah yang cocok, jadi, Anda bisa mendapatkan lebih sedikit kecocokan dalam banyak kasus.

PERBARUI

Seperti yang ditanyakan oleh trinchet inilah yang diperlukan untuk melakukan perubahan perilaku pencarian (untuk Django 1.7). Anda perlu mengganti get_search_results() dari kelas admin di mana Anda ingin jenis pencarian ini. Anda perlu menyalin semua kode metode dari kelas dasar (ModelAdmin ) ke kelas Anda sendiri. Maka Anda perlu mengubah baris tersebut:

for bit in search_term.split():
    or_queries = [models.Q(**{orm_lookup: bit})
                  for orm_lookup in orm_lookups]
    queryset = queryset.filter(reduce(operator.or_, or_queries))

Untuk itu:

and_queries = []
for bit in search_term.split():
    or_queries = [models.Q(**{orm_lookup: bit})
                  for orm_lookup in orm_lookups]
    and_queries.append(Q(reduce(operator.or_, or_queries)))
queryset = queryset.filter(reduce(operator.and_, and_queries))

Kode ini tidak diuji. Kode asli saya adalah untuk Django 1.4 dan saya hanya mengadaptasinya untuk 1.7 di sini.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Mengintegrasikan Sphinx ke MySQL

  2. Masalah koneksi SQLPro ke Vagrant

  3. Panggil ke fungsi yang tidak ditentukan session_register()

  4. Cara membuat dan menghapus database dan tabel di MySQL

  5. Di mana MySQL menyimpan file database di Windows dan apa nama filenya?