Реклама на сайте Advertise with us

Random MySQL реализация

Расширенный поиск по форуму
 
Новая тема Новая тема   
Автор
Поиск в теме:



С нами с 01.04.07
Сообщения: 4378
Рейтинг: 2970

Ссылка на сообщениеДобавлено: 29/03/09 в 19:13       Ответить с цитатойцитата 

Подскажите пожалуйста.

Есть таблица, допустим, на 100.000 записей. Нужно делать простенький рандом с одним-двумя условиями where. Допустим, в пиковые моменты будет делаться до 100 запросов в секунду.
Как лучше организовать?
Либо стандартный " ORDER BY RAND LIMIT 1", либо через "count" - рандом средствами пхп? Может ещё какие варианты.

Спасибо.

0
 

« ... full on ... »

С нами с 17.03.07
Сообщения: 670
Рейтинг: 1686

Ссылка на сообщениеДобавлено: 29/03/09 в 20:17       Ответить с цитатойцитата 

ORDER BY RAND() довольно тормознутый, особенно на больших таблицах. А если ещё 100 запросов в секунду - вполне может подвесить базу.

Как вариант (если есть ID), сделать "кучу" и хранить в ней список битых ID (т.е. тех записей, которые были удалены из последовательности 1-100000). Если нет битых ID, т.е. записи чётко по порядку, то просто хранить максимальное значение ID (last id).
И далее на PHP в цикле формировать случайный список ID с исключениями "битых" (это вопрос уже чисто технический), а потом делать выборку через SELECT ... WHERE ID IN (23,565,9232,23843)... и т.д. Это значительно снизит нагрузку, особенно при таком большом кол-ве запросов в секунду.
А "кучу" и LAST ID (или тот же результат count()) лучше хранить вне базы.

Power of the lime madness...

5
 

ищу работу (php,mysql,js)

С нами с 26.05.07
Сообщения: 576
Рейтинг: 393

Ссылка на сообщениеДобавлено: 29/03/09 в 20:25       Ответить с цитатойцитата 

потёрто

Каталог для Блогов, Фрих и Галёр, ссылки $0.03
рекламные дрочетексты на микросиджах

5
 



С нами с 01.04.07
Сообщения: 4378
Рейтинг: 2970

Ссылка на сообщениеДобавлено: 29/03/09 в 20:28       Ответить с цитатойцитата 

Corex: возможно, неправильно объяснил. Имел в виду - 100 обращений к скрипту, рандом должен выбирать только одно значение.

0
 

www.phpdevs.com

С нами с 24.10.02
Сообщения: 16633
Рейтинг: 16105


Передовик Master-X (01.09.2005) Передовик Master-X (16.09.2005) Передовик Master-X (01.10.2005) Передовик Master-X (16.08.2006) Передовик Master-X (16.10.2006) Ветеран трепа Master-X ()
Ссылка на сообщениеДобавлено: 29/03/09 в 20:31       Ответить с цитатойцитата 

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

Пишу на php/mysql/django за вменяемые деньги.
Обращаться в личку.

5
 



С нами с 01.04.07
Сообщения: 4378
Рейтинг: 2970

Ссылка на сообщениеДобавлено: 29/03/09 в 20:36       Ответить с цитатойцитата 

Надо icon_smile.gif
Задача скрипта - кидать пользователя на случайный адрес. То есть, как out в сиджеях, ТДС и некоторых топлистах.

0
 

ищу работу (php,mysql,js)

С нами с 26.05.07
Сообщения: 576
Рейтинг: 393

Ссылка на сообщениеДобавлено: 29/03/09 в 20:39       Ответить с цитатойцитата 

от задачи и от структуры данных зависит, можно и так и так...

можно создать дополнительную таблицу с заранее отобраными рандомными значениями (в 10 раз меньше основной), брать значения из дополнительной таблицы, раз в час дополнительную таблицу обновлять

многое зависит от условия WHERE (если по ключу - то запрос будет быстрее работать, чем если %LIKE% ...)

имхо - мускуль с оптимизироваными таблицами/запросами

Каталог для Блогов, Фрих и Галёр, ссылки $0.03
рекламные дрочетексты на микросиджах

5
 



С нами с 01.04.07
Сообщения: 4378
Рейтинг: 2970

Ссылка на сообщениеДобавлено: 29/03/09 в 20:44       Ответить с цитатойцитата 

Условие простое, никаких like

0
 

Чингачгук, вождь красноглазых

С нами с 14.05.04
Сообщения: 4744
Рейтинг: 1824

Ссылка на сообщениеДобавлено: 29/03/09 в 21:35       Ответить с цитатойцитата 

Вообще-то, 100.000 записей IP-адресов - это всего лишь 400.000 байтов данных на C или Java, даже не смешно. Самый быстрый вариант - это вообще отказаться от PHP (поскольку оно не может перманентно в памяти что-то держать), написать эту хренобень на Java, держа все данные в памяти аппликейшн-сервера со старта приложения, и хреначить просто по случайному индексу из массива, будет лупить как пулемет при любом количестве запросов в секунду smail54.gif

C php тоже можно решение найти, типа класть это все в DBM и кэшировать в shared memory -не так просто и элегантно, конечно, и вероятность багов поймать больше. Но полюбэ лучше, чем к базе лезть каждый раз - ибо рандомные выборки на таблице в 100.000 записей 100 раз в секунду вообще нехило нагрузят сервак. Немножко не того масштаба задача, имхо, чтобы ее в лоб решать.

5
 



С нами с 01.04.07
Сообщения: 4378
Рейтинг: 2970

Ссылка на сообщениеДобавлено: 29/03/09 в 22:07       Ответить с цитатойцитата 

Цитата:
DBM и кэшировать в shared memory

Я слов-то таких не знаю icon_smile.gif

Поэтому, предпочёл бы решения в пределах пхп+mysql

0
 

www.phpdevs.com

С нами с 24.10.02
Сообщения: 16633
Рейтинг: 16105


Передовик Master-X (01.09.2005) Передовик Master-X (16.09.2005) Передовик Master-X (01.10.2005) Передовик Master-X (16.08.2006) Передовик Master-X (16.10.2006) Ветеран трепа Master-X ()
Ссылка на сообщениеДобавлено: 30/03/09 в 00:52       Ответить с цитатойцитата 

<?php
$rand = rand(0,100000);

$sql = "SELECT * FROM table LIMIT ".$rand.',1';
?>

Ну как то так можно извернуться icon_smile.gif Число для рандома можно тупо кроном определять. В общем уже дальше от задачи зависит.

Пишу на php/mysql/django за вменяемые деньги.
Обращаться в личку.

5
 

Чингачгук, вождь красноглазых

С нами с 14.05.04
Сообщения: 4744
Рейтинг: 1824

Ссылка на сообщениеДобавлено: 30/03/09 в 03:01       Ответить с цитатойцитата 

Stek писал:
<?php
$rand = rand(0,100000);

$sql = "SELECT * FROM table LIMIT ".$rand.',1';
?>


Ух.. а это не приведет ли к тому, что MySQL сделает сначала $rand SELECT'ов, тупо перебирая ряды и вернет только 1 из них? Имхо offset в LIMIT так и работает. Это уж базу убьет наповал точно.

gimcnuk писал:

Поэтому, предпочёл бы решения в пределах пхп+mysql


..Ну и будет работать оно соответственно.

Не удивляет, что игры на php+mysql не пишут? ;)

В любом случае в подобной ситуации "1 запрос = 1 SELECT" будет смертью неминучей и какое-то кэширование предусматривать надо. Держать какие-то результаты в таблице, размещенной в памяти и выбирать из них (есть у MySQL и такое). Типа выбираем в нее 1000 рядов, 10 секунд раздаем из нее, потом переписываем, дальше работаем. Но только не 100.000 рядов по 100 запросов/сек на MyISAM, упаси боже.

5
 



С нами с 01.04.07
Сообщения: 4378
Рейтинг: 2970

Ссылка на сообщениеДобавлено: 30/03/09 в 07:34       Ответить с цитатойцитата 

Всем спасибо.

Stek: ну я про такой вариант и спрашивал в первом сообщении, как лучше-то: random средствами mysql или php
Dr.Syshalt: предложенные условия теоретические, в реальности всё будет меньше. Поэтому и не хочу выходить за пределы php+mysql. Не тот уровень.

0
 



С нами с 15.01.08
Сообщения: 79
Рейтинг: 48

Ссылка на сообщениеДобавлено: 30/03/09 в 09:54       Ответить с цитатойцитата 

рандом из mysql это жопа. по любому жопа...
я в свое время решил так
раз в минуту по крону выгружал из базы данные в текстовый файл, а потом из пхп

$tmp = file('base.txt');
shuffle($tmp);
echo $tmp[0];

5
 

« ... full on ... »

С нами с 17.03.07
Сообщения: 670
Рейтинг: 1686

Ссылка на сообщениеДобавлено: 30/03/09 в 09:58       Ответить с цитатойцитата 

gimcnuk
Выборка по конкретному ID тогда более оптимальный вариант, т.к. будет работать значительно быстрее. + на ID сделать индексы. Это, конечно, если есть ID. Dr.Syshalt правильно написал про промежуточный вариант на 10 секунд - при большой нагрузке это поможет.

DMV_
Грузить в память 100К записей не лучший вариант, это не даст выиграша в скорости. А если это делать в несколько потоков 100 раз в секунду и каждый раз читать с диска файл в несколько Мб. - будут те же тормоза, если вообще всё не сдохнет.

Power of the lime madness...

5
 



С нами с 15.01.08
Сообщения: 79
Рейтинг: 48

Ссылка на сообщениеДобавлено: 30/03/09 в 10:24       Ответить с цитатойцитата 

Corex: недописал слово рандомно icon_smile.gif
раз в минуту по крону выгружал из базы РАНДОМНО данные в текстовый файл, а потом из пхп
то есть выгружаешь например 1000 записей раз в минуту.

5
 



С нами с 01.02.07
Сообщения: 231
Рейтинг: 294

Ссылка на сообщениеДобавлено: 30/03/09 в 12:58       Ответить с цитатойцитата 

Stek писал:
<?php
$rand = rand(0,100000);

$sql = "SELECT * FROM table LIMIT ".$rand.',1';
?>

Ну как то так можно извернуться icon_smile.gif Число для рандома можно тупо кроном определять. В общем уже дальше от задачи зависит.


Абсолютно правильное решение, только вместо 100000 желательно подставлять реальное кол-во записей (если оно меняется):
SELECT count(*) FROM table;

ЗЫ: Запрос полностью идентичен следующему (просто синтаксис сокращенный):
SELECT * FROM table LIMIT 1 OFFSET $rand;
который работает очень быстро.

5
 

www.phpdevs.com

С нами с 24.10.02
Сообщения: 16633
Рейтинг: 16105


Передовик Master-X (01.09.2005) Передовик Master-X (16.09.2005) Передовик Master-X (01.10.2005) Передовик Master-X (16.08.2006) Передовик Master-X (16.10.2006) Ветеран трепа Master-X ()
Ссылка на сообщениеДобавлено: 30/03/09 в 13:12       Ответить с цитатойцитата 

Цитата:
Абсолютно правильное решение, только вместо 100000 желательно подставлять реальное кол-во записей (если оно меняется):
SELECT count(*) FROM table;

Просто $rand вообще может тупо из файла браться, куда оно кроном раз в минуту пишется. Тогда в скрипте остается только один запрос в базу.

В общем и говорю, что проще создать таблицу на 100к записей и прогнать тестом разные варианты. Там дело то на 20 минут icon_smile.gif

Пишу на php/mysql/django за вменяемые деньги.
Обращаться в личку.

5
 

Чингачгук, вождь красноглазых

С нами с 14.05.04
Сообщения: 4744
Рейтинг: 1824

Ссылка на сообщениеДобавлено: 30/03/09 в 13:21       Ответить с цитатойцитата 

zuborg писал:

ЗЫ: Запрос полностью идентичен следующему (просто синтаксис сокращенный):
SELECT * FROM table LIMIT 1 OFFSET $rand;
который работает очень быстро.


Серьезно?

Цитата:

SELECT ... LIMIT offset, limit, where offset is a large number == bad, at least with InnoDB tables, as MySQL actually counts out every record until it gets to the offset.


Отсюда. Но на самом деле, запрос на Гугле "mysql select limit offset performance" выдаст много чего интересного. А можно просто дать себе труд подумать над тем, как может работать реализация "limit/offset" - и все понятно уже.

5
 

Чингачгук, вождь красноглазых

С нами с 14.05.04
Сообщения: 4744
Рейтинг: 1824

Ссылка на сообщениеДобавлено: 30/03/09 в 13:39       Ответить с цитатойцитата 

Вообще из того, как работает random на MySQL, самый быстрый рандомный запрос - это рандом по первичному ключу, где только он извлекается из таблицы. И вот тут человек уже боролся с подобной проблемой. Интересное для ТС решение - последнее:

Код:

SELECT * FROM Table T JOIN (SELECT CEIL(MAX(ID)*RAND()) AS ID FROM Table) AS x ON T.ID >= x.ID LIMIT 1;


Боюсь, средствами MySQL быстрее рандомной выборки не сделать. Как я уже сказал, более глобальное решение - это перманентный кэш в памяти (что, с использованием только PHP, возможно лишь средствами Zend Platform, иначе надо быть программером уровня, который найти на Master-X будет нелегко, такой тут вообще один... шутка), или, что то же самое - некий демон на том же перле, который в памяти сидит постоянно и выдает эти случайные данные - только так.

5
 
Новая тема Новая тема   

Текстовая реклама в форме ответа
Заголовок и до четырех строчек текста
Длина текста до 350 символов
Купить рекламу в этом месте!


Перейти:  



Спонсор раздела Стань спонсором этого раздела!

Реклама на сайте Advertise with us

Опросы

Рецепт новогоднего блюда 2022



Обсудите на форуме обсудить (11)
все опросы »