Projemdeki birçok mevcut sorguyu optimize ediyorum. Quassnoi'nin çözümü sorguları çok hızlandırmama yardımcı oldu! Bununla birlikte, özellikle birden çok büyük tablodaki birçok alt sorguyu içeren karmaşık sorgular için söz konusu çözümü tüm sorgulara dahil etmeyi zor buluyorum.
Bu yüzden daha az optimize edilmiş bir çözüm kullanıyorum. Temelde Quassnoi'nin çözümüyle aynı şekilde çalışır.
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]
rastgele bir sıra seçme olasılığını hesaplar. Rand () rastgele bir sayı oluşturacaktır. Rand () daha küçükse veya olasılığa eşitse satır seçilecektir. Bu, tablo boyutunu sınırlamak için etkili bir şekilde rastgele bir seçim gerçekleştirir. Tanımlanan limit sayısından daha az geri dönme şansı olduğundan, yeterli sayıda satır seçtiğimizden emin olmak için olasılığı artırmamız gerekir. Bu nedenle, $ size'ı bir $ faktör ile çarpıyoruz (genellikle $ faktör = 2 olarak belirledim, çoğu durumda işe yarıyor). Sonunda yapıyoruzlimit $size
Şimdi sorun, accomodation_table_row_count üzerinde çalışmaktır . Masa boyutunu bilirsek, masa boyutunu sabit kodlayabiliriz. Bu en hızlı koşacaktı, ancak açıkçası bu ideal değil. Myisam kullanıyorsanız, masa sayısını almak çok etkilidir. Innodb kullandığım için, sadece basit bir sayım + seçim yapıyorum. Sizin durumunuzda şöyle görünecektir:
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
İşin zor kısmı doğru olasılığı bulmaktır. Gördüğünüz gibi, aşağıdaki kod aslında sadece kaba geçici tablo boyutunu hesaplar (Aslında, çok kaba!): (select (SELECT count(*) FROM accomodation) * (SELECT count(*) FROM accomodation_category))
Ancak daha yakın bir tablo boyutu yaklaşımı vermek için bu mantığı iyileştirebilirsiniz. Satırları eksik seçmektense OVER seçiminin daha iyi olduğunu unutmayın. yani, olasılık çok düşük ayarlanmışsa, yeterince satır seçmeme riskiniz vardır.
Tablo boyutunu yeniden hesaplamamız gerektiğinden, bu çözüm Quassnoi'nin çözümünden daha yavaş çalışıyor. Ancak bu kodlamayı çok daha yönetilebilir buluyorum. Bu, doğruluk + performans ile kodlama karmaşıklığı arasında bir değiş tokuş . Büyük tablolarda bu hala Order by Rand () 'dan çok daha hızlıdır.
Not: Sorgu mantığı izin veriyorsa, rastgele seçimi herhangi bir birleştirme işleminden önce olabildiğince erken gerçekleştirin.