Показаны сообщения с ярлыком db. Показать все сообщения
Показаны сообщения с ярлыком db. Показать все сообщения

12 октября 2009

Cache money warm-up

С недавнего времени использую в своём проекте Cache money. Вещь хорошая, но, конечно же, есть и недостатки, впрочем, это предмет для форка и багфиксов. Стоит также отметить, что решение может уже и существует среди форков, коих много.
Если у вас всё в порядке с памятью (RAM, I mean), то может возникнуть желание принудительно заполнить кеш по всем индексам всех моделей. Сниппет извлечён из моего Rakefile'а и адаптирован для использования в рельсах. Предупреждение: не тестировалось именно в рельсах и против составных индексов (хотя и предусматривает их использование).

02 апреля 2008

Запросы. Хранимые процедуры. Производительность.

Пост сквозь спички в глазах, потому сумбурный.
В ходе эксперимента установил, что запросы (на чистом sql) выполняются немного медленнее, чем хранимые процедуры.
Есть запрос, есть хранимая процедура, которая в цикле возвращает результаты того же запроса построчно (RETURN NEXT). Запрос выполняется за 75-85 мс с вероятностью 75% (приблизительно), процедура - 55-75 мс. К чему бы это?
Ладно, если уж пишется спагетти-код, то на эту мелочь можно и закрыть глаза. Интереснее следующее - первое выполнение запроса занимает около 450 мс, что закономерно, ибо составляется план выполнения запроса. При создании процедуры план (как я понимаю) сохраняется вместе с ней. Вопрос в том, насколько часто при использовании чистого запроса будет составляться его план? Если используется много чистых запросов? Много серверов приложений?

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).

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 представляется в виде столбца, связывается с несколькими таблицами условиями, полученная выборка преобразуется в массив для дальнейшей работы.
В общем, хозяйке на заметку.

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!