SQL'de nasıl verimli bir basit rastgele örnek alabilirim? Söz konusu veritabanı MySQL kullanıyor; masam en az 200.000 satır ve yaklaşık 10.000'lik basit rastgele bir örnek istiyorum.
"Açık" cevap şudur:
SELECT * FROM table ORDER BY RAND() LIMIT 10000
Büyük tablolar için, bu çok yavaştır: RAND()
her satırı çağırır (zaten onu O (n) 'ye koyar) ve onları sıralar, en iyi ihtimalle O (n lg n) yapar. Bunu O (n) 'den daha hızlı yapmanın bir yolu var mı?
Not : Andrew Mao'nun yorumlarda belirttiği gibi, SQL Server'da bu yaklaşımı kullanıyorsanız, T-SQL işlevini kullanmalısınız NEWID()
çünkü RAND () tüm satırlar için aynı değeri döndürebilir .
DÜZENLEME: 5 YIL SONRA
Bu problemle tekrar daha büyük bir tabloyla karşılaştım ve iki ince ayar ile @ ignorant'ın çözümünün bir sürümünü kullandım:
- İstediğim örnek boyutunun 2-5 katına kadar satırları ucuza örnekleyin
ORDER BY RAND()
- Sonucunu
RAND()
her ekleme / güncellemede dizine alınmış bir sütuna kaydedin . (Veri kümeniz çok güncel değilse, bu sütunu yeni tutmak için başka bir yol bulmanız gerekebilir.)
Bir tablonun 1000 maddelik bir örneğini almak için, satırları sayıyorum ve sonucu frozen_rand sütunuyla ortalama 10.000 satıra indiriyorum:
SELECT COUNT(*) FROM table; -- Use this to determine rand_low and rand_high
SELECT *
FROM table
WHERE frozen_rand BETWEEN %(rand_low)s AND %(rand_high)s
ORDER BY RAND() LIMIT 1000
(Benim gerçek uygulamam, az örneklemediğimden emin olmak ve rand_high'ı manuel olarak kaydırmak için daha fazla çalışma gerektiriyor, ancak temel fikir "N'nizi rastgele birkaç bine düşürmek".)
Bu bazı fedakarlıklar yaratsa da, veritabanını bir dizin taraması kullanarak ORDER BY RAND()
tekrar yeterince küçük olana kadar örneklememe izin veriyor .
RAND()
sonraki her çağrıda aynı değeri döndürür.