Saya mengoptimalkan banyak kueri yang ada dalam proyek saya. Solusi Quassnoi telah membantu saya mempercepat banyak kueri! Namun, saya merasa sulit untuk memasukkan solusi tersebut di semua kueri, terutama untuk kueri rumit yang melibatkan banyak subkueri di beberapa tabel besar.
Jadi saya menggunakan solusi yang kurang dioptimalkan. Pada dasarnya ini bekerja dengan cara yang sama seperti solusi Quassnoi.
SELECT accomodation.ac_id,
accomodation.ac_status,
accomodation.ac_name,
accomodation.ac_status,
accomodation.ac_images
FROM accomodation, accomodation_category
WHERE accomodation.ac_status != 'draft'
AND accomodation.ac_category = accomodation_category.acat_id
AND accomodation_category.acat_slug != 'vendeglatohely'
AND ac_images != 'b:0;'
AND rand() <= $size * $factor / [accomodation_table_row_count]
LIMIT $size
$size * $factor / [accomodation_table_row_count]
menghitung probabilitas untuk memilih baris acak. Rand () akan menghasilkan nomor acak. Baris akan dipilih jika rand () lebih kecil atau sama dengan probabilitas. Ini secara efektif melakukan pemilihan acak untuk membatasi ukuran tabel. Karena ada kemungkinan itu akan kembali kurang dari jumlah batas yang ditentukan, kita perlu meningkatkan kemungkinan untuk memastikan kita memilih baris yang cukup. Karenanya kami mengalikan $ ukuran dengan $ faktor (saya biasanya menetapkan $ faktor = 2, berfungsi dalam banyak kasus). Akhirnya kami melakukanlimit $size
Masalahnya sekarang adalah mengerjakan accomodation_table_row_count . Jika kita mengetahui ukuran tabel, kita BISA kode keras ukuran tabel. Ini akan berjalan paling cepat, tetapi jelas ini tidak ideal. Jika Anda menggunakan Myisam, mendapatkan hitungan tabel sangat efisien. Karena saya menggunakan innodb, saya hanya melakukan hitungan + pemilihan sederhana. Dalam kasus Anda, akan terlihat seperti ini:
SELECT accomodation.ac_id,
accomodation.ac_status,
accomodation.ac_name,
accomodation.ac_status,
accomodation.ac_images
FROM accomodation, accomodation_category
WHERE accomodation.ac_status != 'draft'
AND accomodation.ac_category = accomodation_category.acat_id
AND accomodation_category.acat_slug != 'vendeglatohely'
AND ac_images != 'b:0;'
AND rand() <= $size * $factor / (select (SELECT count(*) FROM `accomodation`) * (SELECT count(*) FROM `accomodation_category`))
LIMIT $size
Bagian yang sulit adalah mencari kemungkinan yang benar. Seperti yang Anda lihat, kode berikut sebenarnya hanya menghitung ukuran tabel temp kasar (Sebenarnya, terlalu kasar!): (select (SELECT count(*) FROM accomodation) * (SELECT count(*) FROM accomodation_category))
Tetapi Anda dapat memperbaiki logika ini untuk memberikan perkiraan ukuran tabel yang lebih dekat. Perhatikan bahwa lebih baik memilih OVER daripada memilih baris yang kurang. yaitu jika probabilitas disetel terlalu rendah, Anda berisiko tidak memilih cukup baris.
Solusi ini berjalan lebih lambat daripada solusi Quassnoi karena kita perlu menghitung ulang ukuran tabel. Namun, menurut saya pengkodean ini jauh lebih mudah dikelola. Ini adalah trade off antara akurasi + kinerja vs kompleksitas pengkodean . Karena itu, pada tabel besar ini masih jauh lebih cepat daripada Order by Rand ().
Catatan: Jika logika kueri mengizinkan, lakukan pemilihan acak sedini mungkin sebelum operasi gabungan apa pun.