Türkiye'nin En Eski Webmaster Forumu İyinet'e Hoşgeldiniz!

Kayıt Ol

Rand ile alınan verilere alternatif var mı ?

OsmanAtabey

0
Onaylı Üye
Üye
Katılım
26 Mart 2005
Mesajlar
922
Açılan Konu
52
Tepki puanı
4
PHP:
$sorgu = mysql_query("SELECT * FROM `tablo` ORDER BY RAND() limit 0,10");

mysql sorgusunda kullanılan rand() db büyüdükçe ve anlık girişler çoğaldıkça mysql hatalarına sebep oluyor.

Php 'de verileri for ile çekmeyi denedim fakat db büyüdükçe buda rand() 'dan farksız olacak gibime geliyor. Cache sistemine entegre etmeyi denedim fakat sorgu devamlı olarak çalışmaya devam ediyor.

Şu anda veritabanında 15 bin veri var. Bunu 100 bin yapmak istiyorum. mysql .cnf php.ini ve apache ayarlarında değişiklik yaparak düzgün hızlar sağladım fakat rand() bölümü için bir çözüm arıyorum.

Bu fonksiyon yerine başka bir alternatif varmıdır ?
 

yagmayok

1
Onaylı Üye
Üye
Katılım
25 Ocak 2005
Mesajlar
7,131
Açılan Konu
304
Tepki puanı
86
En mantıklısı sadece random olarak alınan bölgeyi cachelemektir eğer bu sistemi uyguladıysanız ve belirttiğiniz gibi sorgu sürekli olarak gene çalışıyorsa bir yerde hata yapmışsınızdır. Bence bunun üzerinde durun.

Ama onun dışında yapılacak işlemler içinde birkaç düzenleme yapmak daha iyi bir yaklaşım olabilir.

Mesela:

PHP:
$sorgu = mysql_query("SELECT id,baslik FROM `tablo` ORDER BY RAND() limit 0,10");

yukarıdaki gibi tabloda sadece ihtiyaç duyulan bölgeleri almak.

Veya şu şekilde bir yol da izlenebilir. 10000 veriyi günde bir kaç kere (3-4 defa olabilir) bir kısmını başka bir tabloya istediğiniz kadar içerik olacak şekilde random olarak almasını sağlayabilirsiniz. Oradan da random olarak çektirirsiniz. Böylece daha az veri içinde random olarak çektirmiş olursunuz.

Aklıma başka bir yöntem gelmiyor.
 

Angelo

0
Onaylı Üye
Üye
Katılım
13 Aralık 2004
Mesajlar
9,603
Açılan Konu
164
Tepki puanı
106
Konum
AZ
ID'lerde atlama yoksa, php de 10 tane random üret, WHERE id IN ('1','257','867')
gibi bir sorgu yapabilirsin.
 

peep

0
Onaylı Üye
Üye
Katılım
20 Mayıs 2007
Mesajlar
6,383
Açılan Konu
417
Tepki puanı
85
-angelo:
bu işlem sunucuyu rand() a göre daha azmı yorar ?
 

Angelo

0
Onaylı Üye
Üye
Katılım
13 Aralık 2004
Mesajlar
9,603
Açılan Konu
164
Tepki puanı
106
Konum
AZ
Fazlza Kullanmadığım için MySQL'de RAND() tam bilemiyorum. Iki tip query'i analiz edip cevap zamanlarına göre karar verilebilir aslında. Varsa öyle 1 milyon verili bir tablo deneyen sonucu paylaşırsa iyi olur.
 

OsmanAtabey

0
Onaylı Üye
Üye
Katılım
26 Mart 2005
Mesajlar
922
Açılan Konu
52
Tepki puanı
4
Şu şekilde yazdım fakat tam deneyemedim.

PHP:
$s1 = mysql_query("select `sutun1` from `tablo`");
$toplam = mysql_num_rows($s1);
$random = rand(1,$toplam);
$s2 = mysql_query("SELECT `sutun1` FROM `tablo` ORDER BY RAND() limit $random,10");

//$s2 'den alınan veriler ekrana basılıyor.

// Mysql işlemlerinden kontrol ettiğimde çıktısı da aşağıdaki gibi

Sending data	SELECT `sutun1` 
FROM `tablo` 
ORDER BY RAND( ) 
LIMIT 8792 , 10
 

Ozcan

0
Onaylı Üye
Üye
Katılım
12 Mayıs 2007
Mesajlar
3,749
Açılan Konu
428
Tepki puanı
61
Konum
Antalya
angelo nun yazdığı ilk kod hızlı çalışır fakat 1 ile 100 arasında 5 sayı seç dedik diyelim.
1-10-15-34-56 i seçti WHERE id IN (1,10,15,34,56) kodunu yazdık. Sistemimizde 10-15 nolu kayıt silinmiş olabilir bu yüzden hata verebilir. Düzeltmek içinde bir iki tane for eklemek yerine direk sql in içinde rand() ı çalıştırmak daha mantıklı.
 

OsmanAtabey

0
Onaylı Üye
Üye
Katılım
26 Mart 2005
Mesajlar
922
Açılan Konu
52
Tepki puanı
4
Evet kayıtlarda birkaç atlama var oralara denk gelirse sorun yaşayabilirim. Bu arada yazdığım kod sql içindeki rand() 'dan daha hızlı çalışıyor veya ben yanlış görüyorum. Benim yazdığım kodu da deneyebilecek olursa sevinirim. Bu arada benim deneme şeklim dışarıdan ayrı sayfalara gelen anlık 30 bağlantı civarında. Server adsl üzerinde bu arada.
 

Angelo

0
Onaylı Üye
Üye
Katılım
13 Aralık 2004
Mesajlar
9,603
Açılan Konu
164
Tepki puanı
106
Konum
AZ
Maximumu bulmak icin select sutun demek yerine select max(id) kullanımı daha iyi. 5 değil güvenli olsun diye 10 tane random sayı yaratıp, php sorgunun içinde dönerken 5 tane basıldığında break; ile çıkılabilir. Atlayan sayılar kaç tane ki.
 

metadige

0
Onaylı Üye
Üye
Katılım
23 Aralık 2005
Mesajlar
354
Açılan Konu
21
Tepki puanı
4
Arkadaşım tabii ki ilkine göre biraz daha az yorar çünkü ilkinde misal 15000 kayıttan rand yapıyorsa 2. den 8700 den sonraki kayıtlardan rand hesaplamakta. Ancak unutma ki rand le dönen sayı her zaman yüksek olmaz misal 10 da olabilir.

Bu arada id in ile seçilen veri varsa sonuç döner, yoksa hata vermez, o bakımdan sorun olmaz yani, sadece dönen veri az olabilir.

Peki şöyle bir şey yapsan, diyelim rand ile bir sayı belirleyip idi o sayıdan küçük 10 kayıt veya büyük 10 kayıt diye seçsen, işini görmez mi ?

Peşpeşe olan kayıtları çeker ancak, diğerlerine göre çok daha az yoracağı kesin.
 

OsmanAtabey

0
Onaylı Üye
Üye
Katılım
26 Mart 2005
Mesajlar
922
Açılan Konu
52
Tepki puanı
4
Angelo arada sildiğim toplam 20 tane id no var sadece. Şu anki bayağı hızlı çalışıyor gözlemlediğim kadarıyla. Bunun üzerinde çalışayım ve dediklerini uygulayarak yapayım birde.
 

OsmanAtabey

0
Onaylı Üye
Üye
Katılım
26 Mart 2005
Mesajlar
922
Açılan Konu
52
Tepki puanı
4
metadige sadece yüksek sayılarda çekilmiyor veriler gördüğüm kadarıyla. Anlık 30 veya 40 giriş olduğunda saçmalıyordu sql içindeki rand() normal olarak. Phpmyadmin işlemler bölümünde kontrol ettiğimde 100 tane sorguyu görebiliyordum arka arkaya.

Fakat şu ankinde en fazla 7 veya 8 tane yakalayabiliyorum. Tabiki 15 bin kayıt birşey değil daha fazla kayıt üzerinde denemek lazım bunu.

Bu arada veritabanı devamlı güncellendiği için güncel random veri almam şart. Sınırlamak istemiyorum aldığım veriyi.
 

metadige

0
Onaylı Üye
Üye
Katılım
23 Aralık 2005
Mesajlar
354
Açılan Konu
21
Tepki puanı
4
O zaman php ile random 15 sayı seçip sqlden 10 tanesini almak daha mantıklı olabilir gibi. Örneğin:

PHP:
<?php

$al = mysql_query('select count(sutun_id) as say from tablon');
$kac = mysql_fetch_assoc($al);
$kac = $kac['say'];
for($i=0;$i<15;$i++){
$random[] = rand(1,$kac); 
}
sort($random,SORT_NUMERIC );
$random = implode(',',$random);
$query = 'select * from tablon where sutun_id in ('.$random.') limit 10';

?>
 

OsmanAtabey

0
Onaylı Üye
Üye
Katılım
26 Mart 2005
Mesajlar
922
Açılan Konu
52
Tepki puanı
4
metadige Bu kadar karşılaştırma yapan bir fonksiyon büyük veritabanlarında sorun yaratmaz mı ?

Yaptığım sistem şu şekilde
- Sayfaya kategoriye ait içerik basılıyor örnek: 30 tane
- Bir bölüm için 10 tane random veri alınıyor.
- Başka bir bölüm için 5 tane random veri alınıyor.

Bu veritabanı ilerde en az 100 bin kayıttan oluşacak.

Bu arada count(*) ile max(id) arasında hız farkı varmıdır ?
 

metadige

0
Onaylı Üye
Üye
Katılım
23 Aralık 2005
Mesajlar
354
Açılan Konu
21
Tepki puanı
4
Zannetmem sorun yapacağını, daha doğrusu sql'den rand() komutu ile almaktansa çok daha hızlı olur çok fazla kayıtlı tablolarda, çünkü alınacak idleri söylüyoruz sqle, 2-3K ve üzeri kayıtlı tablolarda order by rand() kullanımı zaten sakat seninde farkında olduğun gibi:)

Bunun dışında count(*) ile max(id) arasında hız farkı olur. Count(*) olarak kullanmak akıllıca değil, yukarıda kullandığım gibi count(primary_key) şeklinde kullanmalısın. Bu şekilde kullanımı gayet hızlıdır, çünkü index sütunu bilgileri tutulmaktadır.

Büyük bir taboda optimizasyon için indexleri doğru şekilde ayarlamalı ve sorgularda gereksiz bölümleri almaktan kaçınmalısın, birde online sayın çok fazla ise, basit bir şekilde cache kullanman daha iyi gibi. Yani cronjobla falan, en azından 10 dakikada dahi değişsen 100 lerce gereksiz sorgudan kurtulursun, ki giriş sayısına göre 1000 lerce de olabilir.
 

OsmanAtabey

0
Onaylı Üye
Üye
Katılım
26 Mart 2005
Mesajlar
922
Açılan Konu
52
Tepki puanı
4
metadige

Evet az önce count(*) şeklinde kullandım ve mysql 'a erişemedim kısa bir süre. Bu günlük veritabanı güncellemesi bittiği için count(sutun) şeklini yarın denicem :)

5 dakkalık cache kullanıyorum şu anda işimi görüyor. Fakat site yeni açıldı şu anda. Bakalım ilerde ne olucak

Herkese teşekkürler
 

Invictus

0
Onaylı Üye
Üye
Katılım
4 Şubat 2010
Mesajlar
328
Açılan Konu
5
Tepki puanı
8
Konum
istanbul
hit çok fazla olmadığı sürece order by rand() o kadar da sorun yaratmaz. metadige ve angelo nun önerisinde, id tablon sıralı değilse yani eksik varsa eksik veri gelebilir.

şu şekilde de yapabilirsin;
PHP:
$limit = 10;
$al = mysql_query('select count(id) as say from tablon');
$kac = mysql_fetch_assoc($al);
$kac = $kac['say']-$limit;
$random = rand(0,$kac)

$query = 'select * from tablon where sutun_id order by id limit '.$random.','.$limit;

bu şekilde rastgele yerden başlar ama veriyi sıralı olarak çeker.
 

OsmanAtabey

0
Onaylı Üye
Üye
Katılım
26 Mart 2005
Mesajlar
922
Açılan Konu
52
Tepki puanı
4
Teşekkürler Invictus bu şekilde de denerim daha sonra. Şu anda fazla kayıt olmadığı için sorgulardaki problemleri göremiyorum. Şu an için deneyip gördüğüm tek şey anlık gelen 30-40 ziyaretçinin verdirdiği hatalar. Bunlarada şimdilik çözüm buldum gibi görünüyor.
 

Invictus

0
Onaylı Üye
Üye
Katılım
4 Şubat 2010
Mesajlar
328
Açılan Konu
5
Tepki puanı
8
Konum
istanbul
random çektiğin verileri başka dosyadan çekip, mysql cache yerine file cache kullanıp nerede olması gerekiyorsa oraya dosyayı include edip de kullanabilirsin
 

OsmanAtabey

0
Onaylı Üye
Üye
Katılım
26 Mart 2005
Mesajlar
922
Açılan Konu
52
Tepki puanı
4
Sanıyorum o tür pek de zor olmaz. Devamlı sorgu yapıp alınan veriyi dosya içine kaydettikten sonra ilgili bölümde göstermek. Şimdilik 3000 'e yakın sayfa var ve her birinin ayrı random üretmesi şart. Bunu nasıl sağlayabilirim file cache sistemi ile ?
 
Üst