Я написал несколько простых приложений на Rails, получающих доступ к базе данных через абстракцию ActiveRecord, поэтому я боюсь, что не очень разбираюсь во внутренней работе движка PostgreSQL.
Однако я пишу приложение на Rails, которое должно поддерживать более 100 000 строк с динамически обновляемым содержимым, и мне интересно, эффективно ли я использую случайные функции:
Database migration schema setting:
t.float: attribute1
t.integer: ticks
add_index :mytable, :attribute1
add_index :mytable, :ticks
В принципе, я хочу получить следующее распределение случайных функций:
a) строка с 10% -ным верхним значением в attribute1 = 30% вероятности выбора
b) средняя строка 60% (в attribute1) = 50% вероятности выбора
в) наименьший 30% (в атрибуте 1) с менее чем 100 тиками = 15% вероятности выбора,
d) и для тех, у кого атрибут 30% наименьший, у которых больше X (используйте X = 100 в этом вопросе), тики = 5% вероятности выбора.
На данный момент у меня есть следующий код:
@rand = rand()
if @rand>0.7
@randRowNum = Integer(rand(0.1) * Mytable.count )
@row = Mytable.find(:first, :offset =>@randRowNum , :order => '"attribute1" DESC')
else
if @rand>0.2
@randRowNum = Integer((rand(0.6)+0.1) * Mytable.count)
@row= Mytable.find(:first, :offset =>@randRowNum , :order => '"attribute1" DESC')
else
@row= Mytable.find(:first, :offset =>Integer(0.7 * Mytable.count), :order => '"attribute1" DESC')
if !(@row.nil?)
if (@rand >0.05)
@row= Mytable.find(:first, :order => 'RANDOM()', :conditions => ['"attribute1" <= '"#{@row.attribute1}", '"ticks" < 100' ] )
else
@row= Mytable.find(:first, :order => 'RANDOM()', :conditions => ['"attribute1" <= '"#{@row.attribute1}", '"ticks" >= 100' ] )
end
end
end
end
1) Я хотел бы избежать использования: order => 'RANDOM ()', поскольку, согласно моим исследованиям, кажется, что каждый раз, когда он вызывается, механизм SQL сначала сканирует все строк, присваивая им случайные значения. Отсюда использование @randRowNum = Integer (rand (0.1) * Mytable.count) и смещение @randRowNum. а) и б). Я действительно улучшаю эффективность? Есть ли лучший способ?
2) Должен ли я делать то же, что и 1) для c) и d), и использовать: условия => ['attribute1 "<='" #‹@row.attribute1} ", '" ticks "> = 100 '], заставляю ли я механизм SQL сканировать все строки? Есть ли что-то кроме индексации, что я могу повысить эффективность этого вызова (с минимально возможным объемом памяти и служебных данных)?
3) Существует вероятность того, что общее количество записей в Mytable могло быть изменено между вызовами Mytable.count и Mytable.find. Я мог бы поместить два вызова в транзакцию, но кажется чрезмерным заблокировать всю эту таблицу только для операции чтения (на данный момент у меня есть дополнительный код для возврата к простому случайному выбору строки, если я получил @ row.nil из приведенного выше кода). Возможно ли переместить этот вызов .count в один атомарный SQL-запрос в Rails? Или это будет так же эффективно, как блокировка транзакций в Rails?
4) Я также читал о хранимых процедурах в PostgreSQL ... но для этого конкретного случая есть ли какой-то выигрыш в эффективности, стоит ли переносить код из абстракции Activerecording в хранимые процедуры?
Большое спасибо!
P.S. среда разработки / развертывания:
Рубе 1.8.7
Рельсы 2.3.14
PostgreSQL 8 (на Heroku)