оптимизация на rand()

nullsoft

Active member
Колеги преди няколко седмици бях намерил един много урок за оптизация, но забравих каде беше.

та някой може ли да помогне да оптимизирам този проблем.

Ако се питате защо ето заради това:

първото е със rand(), и обърнете внимание колко време взима. Това е със почти 60,000 rows. А когато говорим за база със 200,000 можете да си представите как товари, и колко е бавно.

slowi.jpg


Врото е нормално показване обърнете внимание за изразходваното време.

fasth.jpg



ЕДИТ:

Трябва да избера примерно 20 песни от базата по случайност,
не е само едно ако е едно може да го викам със $id
 
Последно редактирано:
Re: оптимизация на rand()

Изведи ранда извън заявката и после викни ид-тата.
Преди известно време един приятел си направи подобен експеримент и резултата беше по-лош, отколкото ранда в заявката, но базата беше малка, ако не се лъжа под 5000 записа. Може би за по-голяма да има ефект.
 
Re: оптимизация на rand()

gogobg, сигурно е ставало въпрос за по-малко от 150-200 реда. При повече записи от това е много по-добре да извадиш randomization-а извън заявката.

Примерно може да се извадят 500 записа от позиция rand(0,5000):

Код:
$sql = 'SELECT
    * 
FROM
    ....
LIMIT '.rand(0,50000).', 500;

И след това:
$song_ids = array_rand($songs, 20); // ако иска 20 записа.
 
Re: оптимизация на rand()

Най-простата оптимизация е да селектираш само id-тата подредени по rand() и после да вземеш
всички данни само за селектираните id-та. Това е от таблица с 80 000 записа:

SELECT * FROM product ORDER BY RAND( ) LIMIT 10
Showing rows 0 - 9 (10 total, Query took 1.0123 sec) .............

---------

и оптимизирана:

SELECT
*
FROM
product
JOIN
( SELECT id FROM product ORDER BY RAND() LIMIT 10 ) AS _random
USING (id);
Showing rows 0 - 9 (10 total, Query took 0.0893 sec) ....

за да има ефект трябва id да е PK или поне да има индекс.
 
Re: оптимизация на rand()

Всеки път ли искаш да вадиш различни редове? Ако да, тогава използвай това
$date = mktime();
$q = "select * from tablica order by rand($date) limit 0,10";

целта е да използваш датата като id за rand, така отново всеки път ще вадиш различни редове, но доста по-бързо.
 
Re: оптимизация на rand()

Трябва да избера примерно 20 песни от базата по случайност,
не е само едно ако е едно може да го викам със $id

Т.е. Имаш примерно 5000 песни и искаш да изкараш рандом 20 от тях...

През php-то със един фор си генерираш 20-те рандом айдита и ги лепваш в един стринг за обработка с "IN":

http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_in

Можеш и още да го оптимизираш, като видиш коя е най-малката и голямата рандом стойност и сложиш лимит на заявката.

Давам само идеята, вече колегите са дали доста добри решения с които може да бъде комбинирана.
 
Re: оптимизация на rand()

Всичките предложения имат сериозни проблеми🙂

gogobg, резултата наистина е бил лош точно заради малкия брой.

bisko, така няма да е много случаен, а и хардкодването на броя не е добра идея - той все пак може да се променя.

vaskoa, разликата между 'оптимизираната' и неоптимизираната ти заявка е точно никаква. Експериментирай и ще се убедиш. Hint: спри си куери кеша за да имаш коректни данни от експеримента😉

Viktor Shapilov, ами ако има изтрити полета? Ами ако има много изтрити полета?

Това е най-добрия вариант:
PHP:
// първо взимаш всички редове
$SQL="SELECT count(*) FROM ...";

// Второ вадиш случаен ред ()
$SQL="SELECT * FROM ..  LIMIT ".rand(0,$num_rows).",1";
// където $num_rows  e резултата от първата заявка

Повтарящ заявката колкото реда са ти необходими.

Имай предвид, че нарочно не съм сложил ORDER в заявката! Той може сериозно да я забави.
 
Re: оптимизация на rand()

Viktor Shapilov, ами ако има изтрити полета? Ами ако има много изтрити полета?
Слага се проверка преди IN-а ествествено!
Всичко според нуждите... 😉

Това е най-добрия вариант:
PHP:
// първо взимаш всички редове
$SQL="SELECT count(*) FROM ...";

// Второ вадиш случаен ред ()
$SQL="SELECT * FROM ..  LIMIT ".rand(0,$num_rows).",1";
// където $num_rows  e резултата от първата заявка
Тук се ползват 2 заявки, сами по себе си може да са бързи но.... 😉
Далеч по-оптимизирано е със субкуери или друга подобна алтернатива.
А и в конретният случай вадиш само един резултат, ако дигнеш броя на лимита пък са последователни. ;D

Имай предвид, че нарочно не съм сложил ORDER в заявката! Той може сериозно да я забави.
То той си забавя всичко, все пак разджурква всички резултати и за големите таблици а и не само става весело.... ;D
 
Последно редактирано:
Re: оптимизация на rand()

Слага се проверка преди IN-а ествествено!
Всичко според нуждите... 😉
Тази проверка не е ли допълнителна заявка? ;D Няма ли да се получат доста заявки ако се окаже, че липсват много ID-та?

Тук се ползват 2 заявки, сами по себе си може да са бързи но.... 😉
Но? Кое е по-бързо? 10 заявки по 5мс или една заявка от една секунда?

Далеч по-оптимизирано е със субкуери или друга подобна алтернатива.
Няма смисъл да спорим - пробвай и сам ще разбереш 😉
Малко зависи какво разбираш под "оптимизирано". За мен оптимизирано е "по-бързо". Имам предвид по-бързо изпълнение на функционалност, а не на бързото й и лесно писане 😀

А и в конретният случай вадиш само един резултат, ако дигнеш броя на лимита пък са последователни. ;D
Не, не се вдига, а "Повтарящ заявката колкото реда са ти необходими."

То той си забавя всичко, все пак разджурква всички резултати и за големите таблици а и не само става весело.... ;D
Точно така.
 
Re: оптимизация на rand()

Тази проверка не е ли допълнителна заявка? ;D Няма ли да се получат доста заявки ако се окаже, че липсват много ID-та?
Проверката е във самото куери, а куеритата се изпълняват от ляво надясно, даже ще ускори заявката изключвайки ненужните айдита.

Но? Кое е по-бързо? 10 заявки по 5мс или една заявка от една секунда
Става и с една предостатъчно бърза заявка!

Няма смисъл да спорим - пробвай и сам ще разбереш 😉
Малко зависи какво разбираш под "оптимизирано". За мен оптимизирано е "по-бързо". Имам предвид по-бързо изпълнение на функционалност, а не на бързото й и лесно писане 😀
Имам кофти навика да си пробвам подобни неща всеки ден... 😉

HTML:
SELECT
	<субкуери вземащо броя айдита> 
FROM 
	<таблицата> 
WHERE 
	id IN(<рандом числа разделени със запетайка>)
Като вече се слага някакъв лимит и проверки за затрити записи и т.н. според нуждите които единствено спомагат бързодействието...
Една заявка! 😉


Не, не се вдига, а "Повтарящ заявката колкото реда са ти необходими."
Аха... "Оптимизирано" а.... 😀
 
Последно редактирано:
Re: оптимизация на rand()

Всичките предложения имат сериозни проблеми🙂

vaskoa, разликата между 'оптимизираната' и неоптимизираната ти заявка е точно никаква. Експериментирай и ще се убедиш. Hint: спри си куери кеша за да имаш коректни данни от експеримента😉

Преди да се изкажеш така убедено да беше пуснал един EXPLAIN SELECT да видиш огромната разлика между двете заявки 🙂. Едната заявка използва индекс, другата не използва. А разликата във времето за изпълнение е очевадна - 1 сек. и 0.1 сек.

Освен това има и още една голяма разлика в двете заявки - temp таблицата, която се създава. При ордер по ранд mysql създава временна таблица с всички редове, като на всеки ред постава random индекс. После сортира по този индекс и връща резултат. Тоест при "select *" копира всички полета, при select id копира само едно int поле. Получава се например таблица 50 MB за първия случай (100% МyIsam таблица на диска) и 1 MB (почти винаги MEMORY таблица в паметта) за втория. Според теб кое е по-добре от двете?
 
Re: оптимизация на rand()

Viktor Shapilov, явно има още какво да тестваш. Във всеки един момент мога да ти докажа, че начина който съм написал е най-оптималния за големи бази данни (за малки - все тая, там всичко минава бързо)., дори ти го написах. Това, че си дървен философ е друго.

vaskoa, пич и двете заявки минават през индекс - разликата е само допълнителните данни, който ПАК ги извличаш. Сканирането и в двата случая ти е по индекс. Разликата е, че в единия случай правиш две заявки (заявка и под заявка), а в другя само с една заявка със същото действие. Вземи почети преди да ръсиш подобни безумия.
 
Re: оптимизация на rand()

От голи приказки няма нужда:

EXPLAIN SELECT *
FROM product
ORDER BY RAND( )
LIMIT 10

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE product ALL NULL NULL NULL NULL 84185 Using temporary; Using filesort

Някъде да виждаш USING INDEX ? Какво е explain може да видиш тук: http://dev.mysql.com/doc/refman/5.0/en/using-explain.html.

В единия случай извличаш много по-голямо количество данни, ако за теб това е "само" ....

Ще можеш ли да ме убедиш в противното без да използваш епитети от рода на "безумия"? Така правят големите хора обикновено. Или просто да приема, че си прав, защото имаш 600 поста и си много важен?
 
Re: оптимизация на rand()

vaskoa, май си объркал нещо🙂

В случая става дума за алтернативни варианти на SQL заявка с "order by rand()".
Никой не спори, че order by rand() е добър вариант, точно обратното всички предложихме алтернативни варианти. Някой добри, други недомислени, но алтернативни 🙂
 
Re: оптимизация на rand()

Във всеки един момент мога да ти докажа, че начина който съм написал е най-оптималния за големи бази данни (за малки - все тая, там всичко минава бързо)., дори ти го написах.
Въобще не е оптимално да наблъскаш сървъра с 20 куерита, когато можеш да свършиш всичката работа само с едно.
И двете заявки ровят по индекс, в твоя вариант обаче се правят 20 излишно натоварващи сървъра куерита!

Прочети колко е по-бързо мултикуерито от стандартното куери и защо
и изобщо вземи седни потествай и тогава ще си говорим за оптимизация! 🙂

Това, че си дървен философ е друго.
О не, аз не съм дървен философ, просто не понасям многознаещи дръвници. ;D
Нищо лично... 😉
 
Re: оптимизация на rand()

Въобще не е оптимално да наблъскаш сървъра с 20 куерита, когато можеш да свършиш всичката работа само с едно.
И двете заявки ровят по индекс, в твоя вариант обаче се правят 20 излишно натоварващи сървъра куерита!

Прочети колко е по-бързо мултикуерито от стандартното куери и защо
и изобщо вземи седни потествай и тогава ще си говорим за оптимизация! 🙂


О не, аз не съм дървен философ, просто не понасям многознаещи дръвници. ;D
Нищо лично... 😉

Разбрах къде ти е проблема - пробите ти са били с бази в малки размери. Няма друго обяснение за незнанието ти.

Прави си екпериментите с изключен куери кеш и използвай поне 300-400мб таблица. При малки таблици, както казах, описания от мен начин е по-бавен. При големи бази най-бързия начин е описания от мен.

Това с броя на заявките ... по пътя на твоята логика, ако използвам join на големи бази ще е по-бързо от колкото да си правя отделни заявки за конкретните нужди?;D

С удоволствие някой път ще ти изнеса лекция на по бира и нагледно ще ти покажа в каква илюзия живееш 😉
 
Re: оптимизация на rand()

Разбрах къде ти е проблема - пробите ти са били с бази в малки размери. Няма друго обяснение за незнанието ти.

Прави си екпериментите с изключен куери кеш и използвай поне 300-400мб таблица. При малки таблици, както казах, описания от мен начин е по-бавен. При големи бази най-бързия начин е описания от мен.
Последният сайт на който работих по подобна оптимизация,
имаше база данни с таблица с размер над 600МБ( марки телефони с данни, etc) и определено съм наясно как да си върша работата. 😉

Това с броя на заявките ... по пътя на твоята логика, ако използвам join на големи бази ще е по-бързо от колкото да си правя отделни заявки за конкретните нужди?;D
Зависи от конкретните нужди, в случая 20-те отделни заявки са напълно излишни.

С удоволствие някой път ще ти изнеса лекция на по бира и нагледно ще ти покажа в каква илюзия живееш 😉
Изнеси я тук де, тъкмо сме се събрали макар и не на по бира, хем ще е полезна за останалите колеги "живеещи в матрицата".... 😀
 

Back
Горе