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

Bagaimana cara menerapkan sistem penandaan yang mirip dengan SO di php/mysql?

Sebelum kita masuk ke pengoptimalan prematur mode, mungkin berguna untuk melihat ke template kueri berikut. Jika tidak ada hal lain, ini dapat digunakan sebagai dasar untuk mengukur keefektifan kemungkinan pengoptimalan.

SELECT T.Tagid, TagInfo.TagName,  COUNT(*)
FROM Items I
JOIN Tags TagInfo ON TagInfo.TagId = T.TagId
JOIN ItemTagMap T  ON I.ItemId = T.ItemId 
--JOIN ItemTagMap T1 ON I.ItemId = T1.ItemId
WHERE I.ItemId IN
  (
      SELECT ItemId 
      FROM Items
      WHERE   -- Some typical initial search criteria
         Title LIKE 'Bug Report%'   -- Or some fulltext filter instead...
         AND  ItemDate > '02/22/2008'
         AND  Status = 'C'
  )
--AND T1.TagId = 'MySql'
GROUP BY T.TagId, TagInfo.TagName
ORDER BY COUNT(*) DESC

Subquery adalah "driving query", yaitu yang sesuai dengan kriteria awal pengguna akhir. (lihat di bawah untuk detail tentang bagaimana kueri ini, yang diperlukan beberapa kali agar sesuai dengan alur yang dioptimalkan secara keseluruhan) Yang dikomentari adalah JOIN pada T1 (dan mungkin T2, T3, ketika beberapa tag dipilih), dan, dengan klausa WHERE, yang terkait kriteria. Ini diperlukan ketika pengguna memilih tag tertentu, baik sebagai bagian dari pencarian awal atau dengan perbaikan. (Mungkin lebih efisien untuk menempatkan gabungan ini dan klausa di mana dalam sub-kueri; selengkapnya di bawah ini)

Diskusi... "Kueri mengemudi", atau variasinya diperlukan untuk dua tujuan berbeda:

  • 1 untuk memberikan lengkap daftar ItemId yang diperlukan untuk menghitung semua tag terkait.

  • 2 untuk memberikan nilai N ItemId pertama (N menjadi ukuran halaman tampilan), untuk tujuan mencari info detail Item di tabel Item.

Perhatikan bahwa daftar lengkap tidak perlu diurutkan (atau mungkin mendapat manfaat dari pengurutan dalam urutan yang berbeda), di mana daftar kedua perlu diurutkan berdasarkan pilihan pengguna (katakanlah menurut Tanggal, turun atau Judul, naik abjad ). Perhatikan juga bahwa jika ada urutan pengurutan yang diperlukan, biaya kueri akan menyiratkan berurusan dengan daftar lengkap (malu optimasi aneh oleh SQL itu sendiri, dan/atau beberapa denormalisasi, SQL perlu "melihat" catatan terakhir pada daftar itu , jika mereka termasuk yang teratas, berdasarkan urutan).

Fakta terakhir ini, mendukung memiliki kueri yang sama untuk kedua tujuan, daftar yang sesuai dapat disimpan dalam tabel sementara. Alur umumnya adalah dengan cepat mencari catatan N Item teratas dengan detailnya dan mengembalikannya ke aplikasi sekaligus. Aplikasi kemudian dapat memperoleh ajax-fashion daftar Tag untuk perbaikan. Daftar ini akan dibuat dengan kueri yang mirip dengan yang di atas, di mana subkueri diganti dengan "pilih * dari tabel sementara." Kemungkinannya bagus bahwa pengoptimal SQL akan memutuskan untuk mengurutkan daftar ini (dalam beberapa kasus), mari kita lakukan itu, daripada menebak-nebak dan mengurutkannya secara eksplisit.

Satu hal lain yang perlu dipertimbangkan adalah mungkin membawa gabungan pada tabel ItemTagMap di dalam "permintaan mengemudi" daripada seperti yang ditunjukkan di atas. Mungkin yang terbaik adalah melakukannya, baik untuk kinerja, dan karena itu akan menghasilkan daftar yang tepat untuk tujuan #2 (menampilkan halaman item).

Kueri/alur yang dijelaskan di atas kemungkinan akan diskalakan dengan baik, bahkan pada perangkat keras yang relatif sederhana; sementara ke dalam 1/2 Juta+ Item, dengan pencarian pengguna berkelanjutan mungkin hingga 10 per detik. Salah satu faktor kuncinya adalah selektivitas kriteria pencarian awal.

Ide pengoptimalan

  • [Tergantung pada kasus pencarian umum dan statistik data] mungkin masuk akal untuk melakukan denormalisasi dengan membawa (memang menduplikasi) beberapa bidang Item ke tabel ItemTagMap. Bidang pendek khususnya mungkin 'diterima' di sana.
  • Seiring dengan bertambahnya data dalam jutaan+ Item, kita dapat memanfaatkan korelasi kuat yang khas dari beberapa tag (mis:di SO, PHP sering kali disertai dengan MySql, btw seringkali tanpa alasan yang jelas...), dengan berbagai trik. Misalnya pengenalan TagId "multi-Tag" dapat membuat logika input sedikit lebih rumit, tetapi juga dapat mengurangi ukuran Peta secara signifikan.


-- 'tidak ada kata! --
Arsitektur dan pengoptimalan yang tepat harus dipilih berdasarkan persyaratan aktual dan profil statistik data yang efektif...



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. mySQL:Subquery ke array?

  2. Bagaimana cara mendapatkan bidang dengan nama dalam kueri Python?

  3. MySQL ODBC 5.1 Set Nama tidak diizinkan oleh driver

  4. Tentukan Peringkat berdasarkan Beberapa Kolom di MySQL

  5. Kesalahan saat memasang mysql2:Gagal membuat ekstensi asli permata