https://developer.skype.com/SkypeGarage/DbProjects/PlProxy
Допустим необходимо сделать шардинг на основе PL/Proxy. Также есть приложение, типа ORM генерирующее SQL-запросы, которое тяжело переделать на работу с БД через хранимые функции, что является необходимым для PL/Proxy. Это приложение позволяет с определёнными усилиями в обозримые сроки переработать места инициации запросов, указав как дополнительный параметр критерии шардинга, а структура БД допускает существование таких критериев для каждой выборки.
В этом случае можно воспользоваться следующим трюком распределения запросов по нескольким серверам. Смысл его в создании PL/Proxy функции, куда можно передать текст SQL-запроса, а она в свою очередь нициирует выполнение этого запроса на сервере, определённом критериями шардинга и вернёт результат. В данном примере я не указываю критерии, а просто обращаюсь к серверу напрямую.
Функция на стороне прокси-базы:
CREATE OR REPLACE FUNCTION plproxy_run_sql(text /* , place_for_shrding_criteria */)
RETURNS SETOF text AS
$BODY$
CLUSTER 'cluster1';
RUN ON 1;
$BODY$
LANGUAGE 'plproxy' VOLATILE
COST 100;
Функция на стороне партиций:
CREATE OR REPLACE FUNCTION plproxy_run_sql(text)
RETURNS SETOF text AS
$BODY$
DECLARE
t text;
BEGIN
FOR t IN EXECUTE $1 LOOP
RETURN NEXT t;
END LOOP;
RETURN;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 10
ROWS 1000;
Если обращение идёт к одной таблице и возвращаются все её поля, то на стороне прокси-базы достаточно иметь такую же таблицу, не содержащую данных, или тип этой таблицы. Сам запрос будет выглядеть следующим образом:
SELECT (t::table1).*
FROM plproxy_run_sql(
$$ SELECT table1::text
FROM table1
LIMIT 1 $$
) AS t;
Если же запрос возвращает не типизированный набор полей, то его (набр полей) просто надо типизировать:
CREATE TYPE query_type1 AS (
table1_id bigint,
table2_id bigint
);
SELECT (t::query_type1).*
FROM plproxy_run_sql(
$$ SELECT (t1.id, t2.id)::text
FROM table2 t2
JOIN table1 t1 ON
t1.some_field = t2.some_field
LIMIT 1 $$
) AS t;
Как-то так.
No comments:
Post a Comment