С недавнего времени использую в своём проекте Cache money. Вещь хорошая, но, конечно же, есть и недостатки, впрочем, это предмет для форка и багфиксов. Стоит также отметить, что решение может уже и существует среди форков, коих много.
Если у вас всё в порядке с памятью (RAM, I mean), то может возникнуть желание принудительно заполнить кеш по всем индексам всех моделей. Сниппет извлечён из моего Rakefile'а и адаптирован для использования в рельсах. Предупреждение: не тестировалось именно в рельсах и против составных индексов (хотя и предусматривает их использование).
12 октября 2009
Cache money warm-up
на
20:30
0
коммент.
02 апреля 2008
Запросы. Хранимые процедуры. Производительность.
Пост сквозь спички в глазах, потому сумбурный.
В ходе эксперимента установил, что запросы (на чистом sql) выполняются немного медленнее, чем хранимые процедуры.
Есть запрос, есть хранимая процедура, которая в цикле возвращает результаты того же запроса построчно (RETURN NEXT). Запрос выполняется за 75-85 мс с вероятностью 75% (приблизительно), процедура - 55-75 мс. К чему бы это?
Ладно, если уж пишется спагетти-код, то на эту мелочь можно и закрыть глаза. Интереснее следующее - первое выполнение запроса занимает около 450 мс, что закономерно, ибо составляется план выполнения запроса. При создании процедуры план (как я понимаю) сохраняется вместе с ней. Вопрос в том, насколько часто при использовании чистого запроса будет составляться его план? Если используется много чистых запросов? Много серверов приложений?
на
03:05
0
коммент.
01 февраля 2008
Аггрегируй это.
Проблема
Уже в стародавние времена в STL языка C++ была функция для подсчёта элементов, удовлетворяющих условию. В SQL этому, по идее, должны служить аггрегатные функции (аггрегаты), однако там есть лишь элементарные count.
А они и не умеют, поскольку могут принимать только 1 столбец. А нам надо туда же передавать и значение для сравнения. И решение есть, неизящное, но надёжное.
Решение
1 create or replace function inc_if(
2 count int8,
3 arr anyarray
4 )
5 returns int8 as
6 $$
7 declare
8 begin
9 if (arr[1]=arr[2]) then
10 return count+1;
11 else
12 return count;
13 end if;
14 end
15 $$
16 language 'plpgsql';
17
18 CREATE AGGREGATE count_if
19 (
20 BASETYPE=anyarray,
21 SFUNC=inc_if,
22 STYPE=int8,
23 INITCOND=0
24 );
Использование
Удобно использовать при группировке:
select count_if(ARRAY["passed_exams", 0]) from students group by id_group;
Вот вам и количество кандидатов на отчисление в каждой группе (чёрный юмор).
Недостатки
- Накладные расходы на создание массивов. Не лечится. Аггрегаты принимают 1 столбец.
- Необходимость создания агрегата для каждого потенциально нужного условия, негибкость. Возможно решение в виде использования динамических языков (PL/Python && PL/Ruby), передачи условия внутрь аггрегата с последующим его вычислеием (eval).
на
14:31
0
коммент.
15 января 2008
И вдоль и поперёк
Ещё когда только пришёл в проект, в котором предполагалось много и занудно писать на PL/pgSQL, написал две элементарные функции. И все спрашивали - да зачем оно надо... Однако сейчас используют широко и говорят спасибо.
Первая является агрегатом (как min, max, avg, sum и подобные) и собирает столбец в массив. Ну а дальше с помощью PL/pgSQL его можно обрабатывать. Используется в SELECT clause. Объявляется так:
CREATE AGGREGATE col_to_arr(BASETYPE = anyelement, SFUNC = array_append, STYPE = anyarray, INITCOND = '{}' );
Вторая решает обратную задачу - представляет массив как столбец. Используется в FROM clause.
1 create or replace function "arr_to_col"(arr anyarray)
2 returns setof anyelement as
3 $$
4 declare
5 size int;
6 index int;
7 begin
8 select array_upper(arr,1) into size;
9 for index in 1..size loop
10 return next arr[index];
11 end loop;
12 return;
13 end
14 $$
15 language 'plpgsql';
При желании можно в одном запросе повернуть скаляр, доставшийся от какого-то другого куска кода, как вдоль так и поперёк. Что иногда приходится проделывать. Выглядит это примерно так:
113 SELECT col_to_arr(old_id_alias)
114 INTO new_id_array
115 FROM table1,table2,tableN, arr_to_col(old_id_arr) old_id_alias
116 WHERE table1.id=old_id_alias AND ...
Сначала old_id_arr представляется в виде столбца, связывается с несколькими таблицами условиями, полученная выборка преобразуется в массив для дальнейшей работы.
В общем, хозяйке на заметку.
на
11:00
0
коммент.
07 января 2008
then idiots come. ave idiots!
Перед тем, как окончательно засесть за прочтение статьи Rails Is A Ghetto, балую себя различными отзывами о ней, вот например один из них, весьма интересный.
Да, я люблю ruby и изучаю в первую очередь его. Да, в настоящий момент один из проектов, в которых я участвую, подразумевает программирование на уровне СУБД Postgre SQL. И да, всем популярным дистрибутивам я предпочёл Gentoo (если вы можете переварить словосочетание "Linux From Scratch on steroids" - то вы поняли, что это такое). Но сосуществование Rails & Ruby, MySQL & PostgreSQL, Ubuntu & Debian не вызывают во мне столь бурных эмоций ("Fuck you rail0rz, Ruby is not Rails"), коль скоро оно взаимовыгодно. Если развитие сущностей-сателлитов приносит пользу и основе - я за.
Так что ave, idiots!
на
04:40
0
коммент.
