2012-09-11 13 views
8

Tablodan rastgele bir satır seçmeye çalışarak, delik açmadan otomatikleştirilmiş birincil anahtara göre.MySQL: Neden birincil anahtarı anahtar kullanarak rasgele oluşturulmuş bir sayı ile karşılaştırıyorsunuz?

tablo şema:

CREATE TABLE IF NOT EXISTS `testTable` (
    `id` int(9) NOT NULL AUTO_INCREMENT, 
    `data` varchar(100) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=0 ; 

INSERT INTO `testTable` (`id`, `data`) VALUES 
(1, 'hello'), 
(2, 'world'), 
(3, 'new'), 
(4, 'data'), 
(5, 'more and more'), 
(6, 'data '), 
(7, 'more rows here'), 
(8, 'most rows here'), 
(9, 'testing'), 
(10,'last'); 

Sorgular:

1/explain select * from testTable where id = ceil(Rand()*10) limit 1 ;

http://sqlfiddle.com/#!2/6e2b1/1

Sonuç:

| ID | SELECT_TYPE |  TABLE | TYPE | POSSIBLE_KEYS | KEY | KEY_LEN | REF | ROWS |  EXTRA | 
-------------------------------------------------------------------------------------------------------- 
| 1 |  SIMPLE | testTable | ALL |  (null) | (null) | (null) | (null) | 10 | Using where | 

2/explain select * from testTable where id = 7 limit 1 ;

http://sqlfiddle.com/#!2/6e2b1/2

Sonuç: Neden sorgu 1. dizini kullanarak değil

| ID | SELECT_TYPE |  TABLE | TYPE | POSSIBLE_KEYS |  KEY | KEY_LEN | REF | ROWS | EXTRA | 
--------------------------------------------------------------------------------------------------- 
| 1 |  SIMPLE | testTable | const |  PRIMARY | PRIMARY |  4 | const | 1 |  | 

, ceil(rand()*10) ideal ardından birincil anahtar ile karşılaştırılabilir hangi bir sabite değerlendirmek gerekir? Optimizatör bu şekilde çalışmamalı mı? Yoksa burada bariz bir şeyi özlüyorum.

+3

, sistemin bu sonuçları her bir sonuçla karşılaştırabilmek için önce tüm satırları getirmesini sağlar. Rasgele tam sayı değerini almak için "dış" bir seçim kullanmanız daha iyi olacaktır ve ardından birincil anahtarınızı almak için bunu kullanın. – Najzero

cevap

6

Anahtar, bu sorgu ile kullanılamaz çünkü her satır için RAND() çağrılır ve her seferinde farklı bir değer döndürür.

yerine bu kodu deneyebilirsiniz:

SET @rand_value := CEIL(RAND()*10); 
EXPLAIN SELECT * FROM testTable WHERE id = @rand_value; 

İlk rasgele bir değer hesaplar ve bir değişkene atar, sonra da sorguda kullanır.
Aneroid tarafından belirtildiği gibi, LIMIT 1 kullanışsızdır: koşul birincil anahtar için geçerli olduğundan, sorgu hiçbir zaman birden fazla satır döndürmez. Bu sorgu ile

, çıkışı: MySQL documentation for RAND() itibaren

| ID | SELECT_TYPE |  TABLE | TYPE | POSSIBLE_KEYS |  KEY | KEY_LEN | REF | ROWS | EXTRA | 
--------------------------------------------------------------------------------------------------- 
| 1 |  SIMPLE | testTable | const |  PRIMARY | PRIMARY |  4 | const | 1 |  | 
+2

+1 Önerilen kullanım için iyi bir örnek. Ve bu durumda 'id' birincil anahtar olduğundan, 'LIMIT 1' gerekli değildir :-) – aneroid

3

: Bir WHERE fıkrada

RAND()WHERE her yürütüldüğünde yeniden değerlendirilir . Bir sabit ile birincil anahtar karşılaştırarak değil Yani

, bu (her satır için, bu durumda) değişen bir değer her zaman. Sorgunuzda LIMIT 1'u kaldırırsanız, eşleştirilen farklı PK'larla daha fazla satır göreceksiniz. Bu, "her seferinde yeniden değerlendirildi" davranışını gösterir.

Düzenleme: Önce rastgele sayıyı üretmenin bir yolu olarak Jocelyn'in örneğine bakın ve ardından eşleşen PK id (LIMIT 1 gerekli değil, btw) ile bir satır alın. Benzer şekilde Najzero'nun yorumunda da belirtildi.WHERE koşullarındaki (ceil/rand gibi) işlevlerin kullanıldığı

İlgili konular