У меня есть таблица базы данных с примерно 160 миллионами строк.
Таблица имеет два столбца: id
и listing
.
Мне просто нужно использовать PHP для отображения 1000 случайных строк из столбца listing
и поместить их в теги <span>
. Как это:
<span>Row 1</span> <span>Row 2</span> <span>Row 3</span>
Я пытался сделать это с помощью ORDER BY RAND()
но так долго загружается такая большая база данных, и я не смог найти никаких других решений.
Я надеюсь, что есть быстрый / простой способ сделать это. Я не могу представить, что было бы невозможно просто эхо 1000 случайных строк … Спасибо!
ORDER BY RAND () – это функция mysql, работающая отлично с небольшими базами данных, но если вы запускаете что-либо большее, чем 10k строк, вы должны создавать функции внутри своей программы, а не использовать функции mysql premade или организовывать свои данные особыми манерами.
Мое предложение: сохранить данные mysql с индексом auto increment id
или добавить другую инкрементную и уникальную строку.
Затем постройте функцию select:
<?php //get total number of rows $result = mysql_query('SELECT `id` FROM `table_name`', $link); $num_rows = mysql_num_rows($result); $randomlySelected = []; for( $a = 0; $a < 1000; $a ++ ){ $randomlySelected[$a] = rand(1,$num_rows); } //then select data by random ids $where = ""; $control = 0; foreach($randomlySelected as $key => $selectedID){ if($control == 0){ $where .= "`id` = '". $selectedID ."' "; } else { $where .= "OR `id` = '". $selectedID ."'"; } $control ++; } $final_query = "SELECT * FROM `table_name` WHERE ". $where .";"; $final_results = mysql_query($final_query); ?>
Если некоторые из ваших инкрементных идентификаторов из этой 160-миллионной базы данных отсутствуют, вы можете легко добавить функцию для добавления других случайных идентификаторов (возможно, цикл while), если массив случайно выбранных идентификаторов состоит из менее необходимого.
Дайте мне знать, если вам нужна дополнительная помощь.
Здесь представлены два решения. Оба этих предлагаемых решения являются только mysql и могут использоваться любым языком программирования в качестве потребителя. PHP был бы слишком медленным для этого, но он мог быть его потребителем.
Более быстрое решение . Я могу привести 1000 случайных строк из таблицы из 19 миллионов строк примерно в 2 десятых секунды с более продвинутыми методами программирования.
Более медленное решение : требуется около 15 секунд с использованием технологий, не связанных с питанием.
Кстати, как использование генерации данных видно ЗДЕСЬ, что я написал. Так что это моя маленькая схема. Я использую это, продолжаю с ДВА больше самостоятельных вставок, видимых там, пока у меня не будет 19M строк. Поэтому я не собираюсь это снова показывать. Но чтобы получить эти 19-миллиметровые строки, пойдите посмотреть это и еще 2 из этих вставок, и у вас есть 19M строк.
Во-первых, более медленный метод.
select id,thing from ratings order by rand() limit 1000;
Это возвращает 1000 строк за 15 секунд.
Для тех, кто новичок в mysql, даже не читайте следующее.
Это немного сложнее описать. Суть его в том, что вы предварительно вычисляете свои случайные числа и генерируете in clause
конце случайных чисел, разделенных запятыми и обернутую парой круглых скобок.
Он будет выглядеть как (1,2,3,4)
но в нем будет 1000 номеров.
И вы храните их и используете их один раз. Как однократная клавиатура для криптографии. Хорошо, это не очень хорошая аналогия, но вы надеетесь, что я надеюсь.
Подумайте об этом как о конце для предложения in
и сохраните в столбце TEXT (например, blob).
Почему в мире кто-то хочет это сделать? Поскольку RNG (генераторы случайных чисел) являются чрезмерно медленными. Но сгенерировать их с помощью нескольких машин может быстро вывернуть тысячи. Кстати, (и вы увидите это в структуре моих так называемых приложений, я запишу, сколько времени потребуется, чтобы сгенерировать одну строку. Около 1 секунды с mysql. Но C #, PHP, Java, все может свести это вместе. это не то, как вы собрали это вместе, а то, что у вас оно есть, когда вы этого хотите.
Эта стратегия, длинная и короткая, когда она сочетается с извлечением строки, которая не использовалась в качестве случайного списка, отмечая ее как используемую и выдавая вызов, такой как
select id,thing from ratings where id in (a,b,c,d,e, ... )
и в позиции in содержится 1000 номеров, результаты доступны менее чем за полсекунды. Эффективное использование CBO mysql (оптимизатор, основанный на затратах), чем рассматривает его как соединение по индексу PK.
Я оставляю это в сводной форме, потому что на практике это немного сложно, но включает в себя следующие частицы, потенциально
in
статье для ударов (Приложение D) Таблица, содержащая предварительно вычисленные случайные числа
create table randomsToUse ( -- create a table of 1000 random numbers to use -- format will be like a long "(a,b,c,d,e, ...)" string -- pre-computed random numbers, fetched upon needed for use id int auto_increment primary key, used int not null, -- 0 = not used yet, 1= used dtStartCreate datetime not null, -- next two lines to eyeball time spent generating this row dtEndCreate datetime not null, dtUsed datetime null, -- when was it used txtInString text not null -- here is your in clause ending like (a,b,c,d,e, ... ) -- this may only have about 5000 rows and garbage cleaned -- so maybe choose one or two more indexes, such as composites );
В интересах не превращать это в книгу, см. Мой ответ ЗДЕСЬ о механизме запуска повторяющегося события mysql. Он будет поддерживать содержание таблицы, приведенной в Приложении A, используя методы, описанные в Приложении D, и другие мысли, которые вы хотите придумать. Например, повторное использование строк, архивирование, удаление, что угодно.
хранимую процедуру, чтобы просто получить 1000 случайных строк.
DROP PROCEDURE if exists showARandomChunk; DELIMITER $$ CREATE PROCEDURE showARandomChunk ( ) BEGIN DECLARE i int; DECLARE txtInClause text; -- select now() into dtBegin; select id,txtInString into i,txtInClause from randomsToUse where used=0 order by id limit 1; -- select txtInClause as sOut; -- used for debugging -- if I run this following statement, it is 19.9 seconds on my Dell laptop -- with 19M rows -- select * from ratings order by rand() limit 1000; -- 19 seconds -- however, if I run the following "Prepared Statement", if takes 2 tenths of a second -- for 1000 rows set @s1=concat("select * from ratings where id in ",txtInClause); PREPARE stmt1 FROM @s1; EXECUTE stmt1; -- execute the puppy and give me 1000 rows DEALLOCATE PREPARE stmt1; END $$ DELIMITER ;
Может быть переплетается с концепцией приложения B. Однако вы хотите это сделать. Но это оставляет вам что-то, чтобы увидеть, как mysql может сделать все это самостоятельно на стороне RNG. Кстати, для параметров 1 и 2, составляющих 1000 и 19 М соответственно, это занимает 800 мс на моей машине.
Эта процедура может быть написана на любом языке, как указано в начале.
drop procedure if exists createARandomInString; DELIMITER $$ create procedure createARandomInString ( nHowMany int, -- how many numbers to you want nMaxNum int -- max of any one number ) BEGIN DECLARE dtBegin datetime; DECLARE dtEnd datetime; DECLARE i int; DECLARE txtInClause text; select now() into dtBegin; set i=1; set txtInClause="("; WHILE i<nHowMany DO set txtInClause=concat(txtInClause,floor(rand()*nMaxNum)+1,", "); -- extra space good due to viewing in text editor set i=i+1; END WHILE; set txtInClause=concat(txtInClause,floor(rand()*nMaxNum)+1,")"); -- select txtInClause as myOutput; -- used for debugging select now() into dtEnd; -- insert a row, that has not been used yet insert randomsToUse(used,dtStartCreate,dtEndCreate,dtUsed,txtInString) values (0,dtBegin,dtEnd,null,txtInClause); END $$ DELIMITER ;
Как вызвать вышеуказанную сохраненную процедуру:
call createARandomInString(1000,18000000);
Это генерирует и сохраняет 1 строку, из 1000 номеров, завернутых, как описано выше. Большие числа, от 1 до 18 миллионов
В качестве быстрой иллюстрации, если кто-то должен был модифицировать хранимую процедуру, отмените строку внизу, которая говорит «используется для отладки», и в качестве последней строки в сохраненном proc, который запускается, и запустите это:
call createARandomInString(4,18000000);
… для генерации 4 случайных чисел до 18M, результаты могут выглядеть так:
+-------------------------------------+ | myOutput | +-------------------------------------+ | (2857561,5076608,16810360,14821977) | +-------------------------------------+
Проверка в реальных условиях. Это несколько продвинутые методы, и я не могу наставлять кого-либо на них. Но я все равно хотел их разделить. Но я не могу это учить. Конец связи.
Если ваша функция RAND () слишком медленная, и вам нужны только квази-случайные записи (для тестового образца), а не по-настоящему случайные, вы всегда можете создать быструю, эффективно-случайную группу, сортируя по средним символам (используя SUBSTRING) в индексированных полях. Например, сортировка по 7-й цифре номера телефона … в порядке убывания … а затем по 6-й цифре … в порядке возрастания … это уже квази-случайное. Вы можете сделать то же самое с символьными столбцами: 6-й символ в имени человека будет бессмысленным / случайным и т. Д.
Вы хотите использовать функцию rand
в php. Подпись
rand(min, max);
поэтому, получите количество строк в таблице в $ var и установите это как max
. Способ сделать это с помощью SQL
SELECT COUNT(*) FROM table_name;
затем просто запустите цикл для генерации 1000 рандов с указанной выше функцией и используйте их для получения определенных строк.
Если идентификаторы не являются последовательными, но если они близки, вы можете просто протестировать каждый идентификатор rand, чтобы увидеть, есть ли хит. Если они далеки друг от друга, вы можете вытащить все ID-пространство в php, а затем случайным образом отбирать из этого дистрибутива через что-то вроде
$random = rand(0, count($rows)-1);
для массива идентификаторов в $rows
.
Пожалуйста, используйте mysql rand в своем запросе во время select statement. Ваш запрос будет выглядеть
SELECT * FROM `table` ORDER BY RAND() LIMIT 0,1;