February 23, 2010

Выполнение произвольных запросов с помощью PL/Proxy

Опишу некоторые мысли по поводу организации шардинга. Это ни в коем случае не претендует на общее правило, но в некоторых ситуациях может оказаться полезным. Перед прочтением необходимо ознакомиться с концепцией PL/Proxy:

https://developer.skype.com/SkypeGarage/DbProjects/PlProxy

Допустим необходимо сделать шардинг на основе PL/Proxy. Также есть приложение, типа ORM генерирующее SQL-запросы, которое тяжело переделать на работу с БД через хранимые функции, что является необходимым для PL/Proxy. Это приложение позволяет с определёнными усилиями в обозримые сроки переработать места инициации запросов, указав как дополнительный параметр критерии шардинга, а структура БД допускает существование таких критериев для каждой выборки.

February 13, 2010

Анализ сборки мусора

Запрс выводит статистическую информацию по сборке мусора упорядочивая таблицы по доле мёртвых кортежей в обратном порядке. Наверху оказываются таблицы у которых ситуация со сборкой мусора хуже всего, но тут необходимо помнить про scale factor и другие настройки, т.к. в "топе" скорее всего появятся ещё и таблицы, которые, например, не требуют сборки мусора из-за малого кол-ва записей или не достаточного увеличения таблицы для запуска autovacuum. Также необходимо помнить и учитывать, что отображаемая статистика это данные, накопленные с момента последней очистки статистики.

February 6, 2010

Яркий пример Культуры написания кода

Один мой хороший товарищ из компании где я раньше работал прислал мне кусок кода экс-сотрудника этой компании, в прямом смысле культурное наследие оставшееся после него:

// Ветки и листья, чекбоксы

/* В попытках разобраться в этом коде, я повесть написал сию. Однако, не поэт
я, а сплошное горе, и повесть получилась из кусков... */

makeTree = function(treeData) {
// И тут сказал Шекспир: "мне кажется - сие не есть листок бумаги
// белоснежный А4, а папка езмь в которой он лежит"...
var leaf = false;

// ...но вот мы видим, что бездетной матери подобна папка та, печален ее
// рок - исписанной ей быть, как может быть исписан лишь листок...
if (!treeData.child) leaf = true;

// ...и чисел магия не может ум пленить, как возвышают над землей поэтов
// строфы...
// (кстати, а почему бы не treeData.id.toString?)
if (treeData.id == 0) treeData.id = '0';

// ...ВНЕЗАПНО объявил король поход, взять обязал он воинов благородных
// честь и имя (id, name), бумаги пачку A4 (leaf:leaf), в ножнах
// меч (checked:false)...
var node, obj = {id:treeData.id, text:treeData.name, leaf:leaf, checked:false};

// ...и вот стоит отряд на поле как следует в военном деле: там во главе
// король, за ним придворные, бояре, рядовых толпа, холопов массы...
node = new Ext.tree.TreeNode(obj);

// И тут король окликнул "Кто мне верен, из тех, кто близко ко двору?"
if (treeData.child) {
// и собралась вокруг него толпа, что лобызать готова стопы короля...
for (var i = 0; i < treeData.child.length; i++) {
node.appendChild(
// Подобным образом так поступил из них и каждый.
// Так стал отряд подобен видом дереву тем, кто смотрит с высоты
// полета птиц...
makeTree(treeData.child[i])
);
}
}

return node;
}


Вот так вот, высокими категориями человек мыслит! :)

February 4, 2010

Python for Fun - Транспонируем матрицы

Вспомнил один свой сниплет на Python. Как-то давно проходил собеседование, где получил задачу написать функцию транспонирования матриц. Вот что я им тогда выдал:

gray@gray ~ $ python
Python 2.6.4 (r264:75706, Dec 22 2009, 17:55:44)
[GCC 4.3.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> m = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
>>> map(lambda *l: list(l), *m)
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> m = [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
>>> map(lambda *l: list(l), *m)
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
>>>


Мне сказали, что я сломал всем мозг. Хм... может по этому и на работу не взяли. Но есть ещё одно не менее интересное решение с почти тем же результатом:

>>> m = [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
>>> zip(*m)
[(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)]
>>>

February 3, 2010

Не оптимальная запись

Если необходимо локализовать проблемы связанные с не оптимальной записью, а это очень важные проблемы, т.к. предел возможностей БД в основном упирается в дисковые операции, и начать решать их с более тяжёлой, то этот запрос поможет вам. Он выводит статистику по таблицам в обратном порядке по сумме операций записи. Сверху будут таблицы с наиболее интенсивной записью. В условиях осуществляется фильтрация по схемам, чьи таблицы необходимо исключить из статистики.

Т.о. выявляются счётчики, лишние или временные вставки и т.п. Далее, интенсивность записи счётчиков можно снизить за счёт, например, накопления их в памяти (допустим в memcached) по 10 штук и одного сброса на диск. Где-то можно просто отказаться от некоторых операций, а где-то выявится необходимость рефакторинга приложения.

SELECT
schemaname AS sch, -- схема
relname AS tab, -- таблица
pg_size_pretty(pg_relation_size(relid)) AS tsize, -- размер
n_tup_upd + n_tup_ins + n_tup_del AS wr, -- операций записи
seq_scan + idx_scan AS re, -- всего чтений
n_tup_ins AS i, n_tup_upd AS u, n_tup_del AS d -- I/U/D
FROM
pg_stat_user_tables
WHERE schemaname NOT IN ('pgq')
ORDER BY
n_tup_upd + n_tup_ins + n_tup_del DESC
LIMIT 40;