- Поисковые системы
- Практика оптимизации
- Трафик для сайтов
- Монетизация сайтов
- Сайтостроение
- Социальный Маркетинг
- Общение профессионалов
- Биржа и продажа
- Финансовые объявления
- Работа на постоянной основе
- Сайты - покупка, продажа
- Соцсети: страницы, группы, приложения
- Сайты без доменов
- Трафик, тизерная и баннерная реклама
- Продажа, оценка, регистрация доменов
- Ссылки - обмен, покупка, продажа
- Программы и скрипты
- Размещение статей
- Инфопродукты
- Прочие цифровые товары
- Работа и услуги для вебмастера
- Оптимизация, продвижение и аудит
- Ведение рекламных кампаний
- Услуги в области SMM
- Программирование
- Администрирование серверов и сайтов
- Прокси, ВПН, анонимайзеры, IP
- Платное обучение, вебинары
- Регистрация в каталогах
- Копирайтинг, переводы
- Дизайн
- Usability: консультации и аудит
- Изготовление сайтов
- Наполнение сайтов
- Прочие услуги
- Не про работу
Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий
30.000 записей? Да это детская таблица совсем. Вы про нее сказали, что она огромная? :)
30.000 записей? Да это детская таблица совсем. Вы про нее сказали, что она огромная? :)
на том сервере было выделено 1М оперативки в my.cnf из 256 рекоммендованого для минимума :)
и под ключи 1М
и на серваке еще работало 10 сайтов :)
как только написать не правильный запрос или сделать ошибку в сложном запросе, то CPU сервера сразу под 100% :)
====
я стараюсь писать все время правильно, чтобы потом 1000 раз не переделывать одно и тоже самое, или я не прав?
прав, но не прав. Все обычно дотачивается под систему, поэтому нужно писать и правильно и гибко, чтобы потом можно было переделать немного.
По теме: не существует нормальных способов ORDER BY RAND().
можно сделать вот так:
далее каждой строке назначаем новое рандомное значение
выборка
будет быстрее работать. Разница в том, что тут сортировка идет по индексированному полю и при большом количестве записей такая выборка с сортировкой будет работать в разы быстрее.
можно вот это
по крону запустить и не делать update в скрипте, если вам не важно получать каждый раз новые данные.
ENGINE тут нужно InnoDB делать, а не MyISAM если будете делать сначала update, потому что он заблокирует в случае MyISAM таблицу на чтение целиком.
я только что попробовал на таблице в 30 000 значений, запрос - выполнялся около 0.1 - 0.09 что есть не красиво...?? (правда потом через раз по разному)
За 0.1 вся ваша система вылазить не должна. а не 1 запрос
update `your_table` set order1 = round(rand()*100)
тоже думал о таком, но идея мне не понравилась.
1. немного не рандомные уже значения будут,
а в случае с * 100 всего 100 вариантов.
Представьте что у вас база из 100 000 записей, а рандомных наборов у вас будет ВСЕГО 100.
может я правда чего то вашей теме не допонял.
Как вариант можно поробовать так:
1. Генерим одно случайное число (r)
2. Во внутреннем подзапросе выбираем 10 записей начиная с позиции r
3. Во внешнем подзапросе ставим рандомную сортировку
Плюсы: Нет доп полей и тяжелая рандомная сортировка работает только с 10 записями, это быстро.
Минусы: Псевдослучайность.
тоже думал о таком, но идея мне не понравилась.
1. немного не рандомные уже значения будут,
а в случае с * 100 всего 100 вариантов.
Представьте что у вас база из 100 000 записей, а рандомных наборов у вас будет ВСЕГО 100.
может я правда чего то вашей теме не допонял.
Ну сделайте умножение на миллион (правда тут MySQL-ю прийдется построить BTREE побольше, но это все равно пустяк). tinyint на что-нибудь побольше поменяйте. Рандомных значений будет столько, сколько нужно и в случае умножения на 100 - проведите эксперимент и посмотрите на результаты. Даже на базе с миллионом записей. Напишите скриптик, который будет загонять вмассив полученные значения, прогоните по циклу, а дальше по всем получившимся массивам сделайте diff. Так или иначе моим способом можно добиться получения выборки рандомных записей относительно "малой кровью".
можно попробовать такой вариант
SELECT FLOOR(RAND() * COUNT(*)) AS rand_row FROM foo;
SELECT * FROM foo LIMIT $rand_row, 1;
DeveloperRu добавил 02.08.2010 в 06:56
или
SELECT * FROM my_table
WHERE pk_column >=
(SELECT FLOOR( MAX(pk_column) * RAND()) FROM my_table)
ORDER BY pk_column
LIMIT 1;
Из вроде не упоминавшихся, но вполне кошерных вариантов на практике вполне годных (вместо извращений с хитрыми выборками, индексами строящимися по 2 часа и т.д.).
Отдельная таблица с ID, состоящая только из них. Будет сравнительно шустро. Основной бонус - не мучать основную таблицу индексами и выборками по ней. Побочный бонус - это будет маленькая таблица. Для полного кайфа в таблице можно создать поле с последовательными ИД и выбирать по ним.
Дальнейшее развитие решения - отдельный скрипт, который иногда создает эту таблицу, а потом на основе этой таблицы генерит нужные наборы случайных чисел и куда-нибудь складывает (откуда их потом уже и берет основной скрипт и удаляет после использования). Это позволит нагрузку вынести ее за пределы основной цмс (цмс будет летать, ну а скорость работы отдельного скрипта генератора кого волнует?), плюс работу скрипта можно зачедулить на время когда посетителей нет.
Следующий возможный этап это не уникальность рандома. Во многих случаях она не нужна. Тогда после генерации случайных наборов, достаточно не удалять их сразу после использования. Если речь идет про сайт с реальными пользователями, то вероятность повторения набора для отдельно взятого юзера достаточно мала и даже если она случится - ничего вроде как страшного. А в свободное время можно перегенерить наборы сгенеренных рандомов.
edogs, что стоит MySQL-ю построить бинарное дерево по одному полю? (это про индексы, которые строятся по 2 часа). Вот индексы, состоящие из нескольких полей в принципе могут строиться достаточно долго особенно если есть не integer поля (varchar, например).
Отдельная таблица с ID не учитывает параметры запроса
Отдельный скрипт, который строит доп таблицу по крону не гарантирует актуальность данных.
SELECT * FROM foo LIMIT $rand_row, 1;
тут мывыбираем одну запись, а нам чаще всего нужно много. LIMIT $row_count, 10 даст 10 последовательных, но не рандомных записей.
WHERE pk_column >=
(SELECT FLOOR( MAX(pk_column) * RAND()) FROM my_table)
ORDER BY pk_column
LIMIT 1;
то же самое только тут даже ORDER лишний, т.к. нечего сортировать, если в выборке одна запись.
Как я и сказал, не существует нормальных быстрых способов ORDER BY RAND()
Тема пережевывется на большом количестве форумов и нормального ответа я нигде не находил. Под специфические задачи пишутся свои наиболее преемлемые решения.