www.Litecode.ru – Сборник рецептов для создания сайтов

Функция random в perl

ГлавнаяPerl → Random в perl

Признайтесь, как часто Вам приходилось оптимизировать какие-либо SQL запросы использующие встроенную функцию RAND в MySQL? Обычно таковая полезна для выборки баннеров. Например:

SELECT ... FROM ... WHERE ... ORDER BY RAND() LIMIT 1

Если проект посещает 100 человек в сутки - можно не волноваться. Но на высоко нагруженном проекте, даже если у вас выделенный сервер это не позволительная роскошь. Лишь у новичка может возникнуть вопрос - а почему?. Опытные программисты знают в чем подвох. Дело в том, что любой ORDER, GROUP или JOIN используют жесткий диск для манипуляций с данными. А хард - самое узкое место сервера. Таким образом в периоды активности, iowait начинает зашкаливать. Падает не база, а винчестер. А вроде бы элементарный запрос... Было дело сам наступал на такие грабли.

Избежать неприятность эту очень легко. Все сортировки, группировки и т.д. лучше делать в perl с помощью функции random. Конечно если данных будет очень много - даже этот метод не поможет, но мы сейчас такие случаи рассматривать не станем. Итак, выполняем наш запрос без ORDER BY RAND() LIMIT 1. Даже если взять все, работать будет намного быстрее - проверено. Делается это примерно так:

my @array = (12,14,77,45,89,10); # исходный массив

my @random_array = @{random(\@array)}; # алтернатива ORDER BY RAND()

my $bannerID = shift @random_array; # LIMIT 1


sub random {
	my $array = shift || [];
	my ($i,@a);
	for ($i = @$array; --$i; ) {
		push @a,$i;
		my $j = int rand ($i+1);
		next if $i == $j;
		@$array[$i,$j] = @$array[$j,$i];
	}
	return $array
}