Nano Hash - криптовалюты, майнинг, программирование

MySQL быстро выбирает 20 случайных строк из 300 строк

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

Я нашел здесь MySQL быстро выбирает 10 случайных строк из 600 тыс. строк (где он снова ссылается на 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%.

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

20.02.2014

  • ваша проблема в том, что r2.id может быть 299, и поэтому у вас будет только две строки, ГДЕ r1.id ›= r2.id верно 20.02.2014
  • @niccomatik Я думаю, мне нужно установить Limit на «1» и выполнить весь запрос в цикле. Затем после каждого запроса я должен проверять, является ли полученная строка новой - так это работает? 20.02.2014
  • даже при 50 000 строк простой случайный выбор будет быстрым. 5000 строк это ничто. MySQL, вероятно, даже не будет использовать индексы для запросов к таблицам, размер которых намного проще, чем просто сканировать таблицу, поэтому я не уверен, почему вы беспокоитесь о скорости. 20.02.2014
  • Забавный вопрос, а вы пробовали применять RAND() * (SELECT MAX(id) - 20 ...? :) 20.02.2014

Ответы:


1

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

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

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

20.02.2014

2

"Медленный" способ получить 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;
20.02.2014

3

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

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>)

20.02.2014
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..