|
Модераторы: skyboy |
|
dm9 |
|
|||
Дмитрий Копытин Профиль Группа: Vingrad developer Сообщений: 3876 Регистрация: 22.7.2002 Где: Москва Репутация: нет Всего: 137 |
Здравствуйте.
У меня стоит задача (быстрой) выборки одной случайной строки из таблицы. MySQL 4.1/5. Я вижу несколько вариантов. 1. Метод чисто СУБД-шный.
Почему это не работает на большой таблице — понятно. 2. Использование скриптового кода. $cnt = (SELECT COUNT(*) FROM ...) $rnd = rand(0, $cnt-1) Затем SELECT ... LIMIT $rnd, 1 Ну или то же самое запихать в хранимую процедуру в MySQL 5. 3. Оптимизированный второй вариант. Периодически (кроном или т. п.) выполнем выборку $cnt = (SELECT COUNT(*) FROM ...) Затем в своём скрипте считываем этот $cnt и используем далее как во втором варианте. Только нужна проверка — если число выбранных таким образом строк равна нулю, значит, строки удалились — тогда делаем ещё раз COUNT(*) и далее опять как во втором варианте. Если строки удаляются редко, этот вариант в большинстве случаев экономит нам один запрос, хотя иногда приводит к трём запросам вместо 1 или 2. Есть ли ещё какие-то варианты для реализации подобных выборок? Это сообщение отредактировал(а) dm9 - 2.11.2006, 12:10 |
|||
|
||||
skyboy |
|
|||
неОпытный Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
dm9, если в этой таблице есть автоинкрементый ключ, то можно сгенерировать rand(max(id)-min(id))+min(id) и выбрать первое значение, большее этого... ORDER BY id должен ведь сработать...
что-то вроде SELECT ... FROM <table> WHERE id> rand()*(max(id) - min(id))+min(id) ORDER BY id limit 1 Впрочем, order делать не надо, то, что вернет тебе в случайном порядке, даже лучше... впрочем, надо бі изучить распределение при помощи опытов... т.е. результат: SELECT ... FROM ... WHERE id> rand()*(max(id)-min(id)) + min(id) |
|||
|
||||
dm9 |
|
|||
Дмитрий Копытин Профиль Группа: Vingrad developer Сообщений: 3876 Регистрация: 22.7.2002 Где: Москва Репутация: нет Всего: 137 |
Интересное решение. Спасибо.
А ещё у кого-нибудь варианты есть под MySQL? |
|||
|
||||
sergejzr |
|
|||
Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 1 Всего: 360 |
Меня тоже вопросик интересует...
|
|||
|
||||
Gold Dragon |
|
|||
Призрачный Профиль Группа: Экс. модератор Сообщений: 6753 Регистрация: 1.3.2004 Где: Россия, Тамбов Репутация: 2 Всего: 71 |
а можно ли в MySQL вытащить из таблицы определённую записть по номеру, ну типа как в ассоциативном массиве вытащить запись по порядку?
Можно было бы сгенерить просто случайное число и вытащить запись с этим номером ... -------------------- Нельзя жить в прошлом, оно уже прошло. Нельзя жить в будущем, оно ещё не наступило. Нужно жить в настоящем, помня прошлое и думая о будущем! |
|||
|
||||
sergejzr |
|
|||
Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 1 Всего: 360 |
||||
|
||||
Gold Dragon |
|
|||
Призрачный Профиль Группа: Экс. модератор Сообщений: 6753 Регистрация: 1.3.2004 Где: Россия, Тамбов Репутация: 2 Всего: 71 |
согласен.
кстати
-------------------- Нельзя жить в прошлом, оно уже прошло. Нельзя жить в будущем, оно ещё не наступило. Нужно жить в настоящем, помня прошлое и думая о будущем! |
|||
|
||||
dm9 |
|
|||
Дмитрий Копытин Профиль Группа: Vingrad developer Сообщений: 3876 Регистрация: 22.7.2002 Где: Москва Репутация: нет Всего: 137 |
Помнится, мы экспериментировали, и работало это очень долго на больших таблицах.
Видимо, MySQL считает этот RAND() для каждой записи таблицы, а потом filesort... Теоретически "ORDER BY RAND()" можно было бы попробовать соптимизировать внутри СУБД, но, видно, этого по каким-то причинам не сделали. Кстати, по-моему, даже в официальном мануале было что-то сказано по поводу того, что для больших таблиц ORDER BY RAND() делать не рекомендуется. Это можно найти в описании ф-ции RAND(), если интересно. |
|||
|
||||
kronos_vano |
|
|||
Новичок Профиль Группа: Участник Сообщений: 41 Регистрация: 13.7.2007 Репутация: нет Всего: нет |
Мой вариант |
|||
|
||||
Бонифаций |
|
||||
Опытный Профиль Группа: Участник Сообщений: 827 Регистрация: 15.9.2005 Где: Brisbane Репутация: 20 Всего: 40 |
пойдем заново по кругу? А если id в таблице с пропусками? скажем id с 1000 до 2000 отсутствует? тогда по Вашей схеме id 2000 будет выбираться чаще других.. -------------------- Бонифаций. |
||||
|
|||||
sergejzr |
|
|||
Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 1 Всего: 360 |
Кстати вроде не было метода:
1) cnt="select count(*) from t where bla bla" Этот запрос закешируется, а если условия нет, то count(primary_key) вообще всегда готовый лежит. т.е высчитывать не надо каждый раз. Ну а дальше высчитываем случайное число r=rand(cnt): И наконец: "select * from <table> where bla bla limit r,1;" |
|||
|
||||
skyboy |
|
|||
неОпытный Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
sergejzr,
первый пост темы, второе предложение dm9 но, пожалуй, самый правильный способ, потому не лишне будет ещё раз про него упомянуть. |
|||
|
||||
sergejzr |
|
|||
Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 1 Всего: 360 |
Да, что-то я бояню
|
|||
|
||||
kronos_vano |
|
|||
Новичок Профиль Группа: Участник Сообщений: 41 Регистрация: 13.7.2007 Репутация: нет Всего: нет |
Бонифаций, есть предложения как сделать лучше для таблицы с миллионами записей?
|
|||
|
||||
Бонифаций |
|
|||
Опытный Профиль Группа: Участник Сообщений: 827 Регистрация: 15.9.2005 Где: Brisbane Репутация: 20 Всего: 40 |
правильный путь озвучен здесь у Яна -------------------- Бонифаций. |
|||
|
||||
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | MySQL | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |