2014-02-20 6 views
0

Моя база данных насчитывает 300 рядов на данный момент, и в ближайшие годы она будет иметь около 5000 строк. Я хочу знать, как я могу выбрать 20 строк в случайном порядке.MySQL выбирает 20 случайных строк из 300 строк быстро

Я нашел здесь MySQL select 10 random rows from 600K rows fast (где он снова refered к http://jan.kneschke.de/projects/mysql/order-by-rand/), что следующий код производит случайный выбор очень быстро:

SELECT name 
    FROM random AS r1 JOIN 
     (SELECT (RAND() * 
        (SELECT MAX(id) 
         FROM random)) AS id) 
     AS r2 
WHERE r1.id >= r2.id 
ORDER BY r1.id ASC 
LIMIT 1 

так в PHP Я попытался следующие, чтобы получить 20 строк:

$anfrage = "SELECT name 
    FROM random AS r1 JOIN 
     (SELECT (RAND() * 
        (SELECT MAX(id) 
         FROM random)) AS id) 
     AS r2 
WHERE r1.id >= r2.id 
ORDER BY r1.id ASC 
LIMIT 20"; 

$ergebnis=$db->query($anfrage) 
     or die($db->error); 
while($zeile=mysqli_fetch_assoc($ergebnis))print_r($zeile); 

Но когда я запускаю сценарий, я не получаю 20 строк большую часть времени. На самом деле вероятность выбора 20 разных строк из 300 составляет около 48,8%.

Могу ли я изменить приведенный выше код, чтобы получить действительно строк очень быстро?

+0

ваша проблема в том, что r2.id может быть 299, и поэтому вы бы только две строки, в которых "r1.id> = r2.id" is true – nidomiro

+0

@niccomatik Я думаю, мне нужно установить Limit в '1' и выполнить весь запрос в цикле. Затем после каждого запроса я должен проверить, является ли полученная строка новой - это то, как это работает? – Adam

+2

даже при 50 000 рядов простой случайный выбор будет быстрым. 5000 строк ничего. MySQL, вероятно, даже не использует индексы по запросам таблиц, размер которых намного проще для сканирования таблицы, поэтому я не уверен, почему вас беспокоит скорость. – Namphibian

ответ

0

Если вы читали article вы упоминаете в своем вопросе, вы обнаружите, что есть 3 решения:

  • ыполните несколько раз Запроса
  • написать хранимую процедуру, которая выполняющийся запрос и магазины результат в виде временного стола
  • сделать союзной

Все они описаны в статье.

0

«медленный» способ получения 20 случайных имен это:

SELECT name 
FROM random 
ORDER BY rand() 
LIMIT 20; 

На 300 строк, это может иметь аналогичные показатели для метода, который вы используете. Ты это пробовал? Я не уверен около 5000 строк, но стоит попробовать и там.

Ваш метод, по существу, это (запрос является немного упрощенным):

SELECT name 
FROM random r1 CROSS JOIN 
    (SELECT RAND() * MAX(id) as id FROM random) r2 
WHERE r1.id >= r2.id 
ORDER BY r1.id ASC 
LIMIT 20; 

Вы полагаете, что r2 вычисляется для каждой итерации с другим значением. Это предположение может быть неверным.

Другой подход, чтобы сделать это:

SELECT name 
FROM random r1 CROSS JOIN 
    (SELECT count(*) as cnt FROM random) const 
WHERE rand() <= 20.0/cnt; 

К сожалению, это дает приблизительное количество строк. Около 20 каждый раз. Может быть, тебе действительно нужно 20.В этом случае, сделать что-то вроде удвоения ожидаемого числа строк, а затем с помощью order by/limit:

SELECT name 
FROM random r1 CROSS JOIN 
    (SELECT count(*) as cnt FROM random) const 
WHERE rand() <= 2*20.0/cnt 
ORDER BY rand() 
LIMIT 20; 
0

Вы можете создать перетасовать таблицу, обновлять время от времени:

INSERT INTO random_ids 
SELECT id 
FROM table_name 
ORDER BY RAND(); 

запись число случайных значения, которые были вставлены в ваше приложение; затем используйте следующее:

SELECT * FROM table_name 
INNER JOIN (SELECT id 
    FROM random_ids 
    LIMIT ?,20 
) r1 ON r1.id = table_name.id; 

Причем предел определяется вашим приложением, чтобы быть в пределах [0, <count>)

Смежные вопросы