|
|
|
Получение случайной записи (записей) из таблицы
|
|||
|---|---|---|---|
|
#18+
А вот не подскажет ли кто-нибудь оптимальный способ решения этой задачи? Вот допустим, есть таблица table, из неё нужно получить случайную запись (кортеж), или несколько записей. Решение в лоб: Код: plaintext 1. Для извлечения одной случайной записи можно сделать то же самое в два быстрых запроса: Код: plaintext 1. Код: plaintext 1. Однако же, если нужно получить не одну случайную запись, а 10, 100, 1000? 1001 запрос или запрос с 999 юнионами мне уже кажется приемлемым. Может быть, есть более приемлемое решение в рамках стабильной ветки MySQL? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.08.2005, 04:40:55 |
|
||
|
Получение случайной записи (записей) из таблицы
|
|||
|---|---|---|---|
|
#18+
О! Интересный вопрос, наконец-то :-) Я думаю так - если надо настоящую случайность, то это подразумевает затраты на перенумерацию всего набора, просто по-определению случайного процесса. Как оптимизировать перенумерацию - зависит от конкретного случая. Сервер копирует во временные таблицы, можно разве что "возглавить" этот процесс, создав такую таблицу самому, примерно так: Код: plaintext 1. 2. 3. 4. 5. Однако истинного выигрыша без поступления принципом случайности не получить никак, это математика. Если, к примеру, брать каждую n-ю запись. N менять. Тогда просто 1 раз скан по таблице. Или, неплохой вариант, сначала узнаем @count_var, потом выполняем что-то навроде Код: plaintext 1. Либо хранить якобы "случайное" поле в БД. Как его заполнять, вопрос второй, решение зависит от задачи. Тут вообще производительность максимальная, так как для сервера данные упорядочены. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.08.2005, 21:01:07 |
|
||
|
Получение случайной записи (записей) из таблицы
|
|||
|---|---|---|---|
|
#18+
Спасибо, интересный вариант. Однако же, утверждение насчёт по определению невозможности получить этот случайный набор без явной перенумерации всех элементов -- я бы поспорил. Ну, по крайней мере, если нас устраивает та степень "случайности", которую нам обеспечивает функция rand() и её аналоги. Ведь мне необязательно "нумеровать" случайными числами реальный ряд данных, он уже как-то пронумерован, при указании сортировки по, скажем, первичному ключу -- однозначно, т.е. в помощью ORDER BY id LIMIT n мы в любой момент времени имеем взаимно однозначное сопоставление произвольной записи какому-то определённому натуральному числу из отрезка [0; m], где m -- количество записей. Т.е. по-сути мы можем просто сгенерировать нужное количество случайных чисел, лежащих в диапазоне от 0 до m и с помощью LIMIT извлечь эти, в достаточной, для большинства случаев, степени, случайные записи. Проблема лишь в том, что если извлечь надо n чисел, это создаёт n+1, пусть и быстрых, запросов. Ну и по-хорошему, на время генерации случайных чисел и извлечения записей таблицу нужно либо блокировать, либо осуществлять всё это внутри транзакции. Ну транзакции-то в MySQL давно есть, это не проблема, а вот n+1 запросов выглядят некрасиво. Теоретически можно было бы поддерживать в таблице некоторый недырявый индекс cid0, начинающийся с нуля, и запрос делать с условием WHERE cid0 IN (a, b, c...), где a, b, c... -- те самые n случайных, по неявному условию задачи, различных целых числа из диапазона [0; m]. Проблема только в том, что поддерживать такой индекс в таблице с частыми удалениями записей будет довольно-таки накладно.) В общем, вопрос в том, как бы скормить LIMIT не один аргумент, а список, грубо говоря) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2005, 12:27:00 |
|
||
|
Получение случайной записи (записей) из таблицы
|
|||
|---|---|---|---|
|
#18+
Ну насчет поспорить - я бы послушал, у меня по этому предмету был твердый трояк. И было это лет 15 назад. Но смутно припоминается, что случайный процесс - это такой процесс, значение которого мы не можем предсказать в произвольный момент времени и зная начальную точку. А это есть перенумерация. Оставим пока в стороне алгоритм RAND, наверняка обычное само-отображение, нас тут может интересовать разве что равномерность распределения результатов. Итого, если уж угодно истинную (с поправкой на неидеальность RAND) случайность - перенумеровывай набор каждый раз, иначе ты "сможешь предсказать значение" процесса.... Просто случайные результаты бывают двух назначений - точный (казино, кидаем карты) и не особо точный (список кандидатов на сайте знакомств). Для первого варианта - перенумерация однозначно, для второго мой вариант со случайным (но довольно хорошо попадающим в нормальное распределение) количеством записей идеально подходит. Прикинь, сидит мужик, жизнь не удалась, все бросили, дай думает познакомлюсь - покажи мне сервер 10 случайных женщин - а ему в ответ 0! И это правильно будет :-) А кому-то выскочит 20 :-) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2005, 15:47:38 |
|
||
|
Получение случайной записи (записей) из таблицы
|
|||
|---|---|---|---|
|
#18+
Я писал про перенумерацию... Попробую покороче) При наличии взаимно однозначного отображения записей в базе, и некоторого отрезка натуральных чисел, нам необязательно "нумеровать" записи, можно и этот самый отрезок. Если это отрезок от 0 до m, и нужно получить n случайных записей -- то "нумерация" заключается в получении n различных случайных чисел из этого диапазона. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2005, 15:52:37 |
|
||
|
|

start [/forum/topic.php?fid=47&fpage=651&tid=1853773]: |
0ms |
get settings: |
8ms |
get forum list: |
20ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
71ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
52ms |
get tp. blocked users: |
1ms |
| others: | 200ms |
| total: | 376ms |

| 0 / 0 |
