понедельник, 12 января 2009 г.

Работа с разделами в 11.50.xC3

В версии информикса 11.50.xC3 обнаружил неприятный баг (а когда баги бывают приятными?): при попытке добавить новый раздел (partitions) к фрагментированной по условию таблице, либо при попытке удалить раздел, происходит (не всегда) полное сканирование таблицы, и сам процесс удаления/добавления разделов происходит очень долго либо приводит к длинной транзакции если таблица большая. В предыдущих версиях такая операция даже на больших (размер каждого фрагмента десятки гигабайт) занимала неск.секунд.
Однако такой баг уже вроде бы исправили в версии 11.50.xC3W1 Fix List см. очень похожий APAR IC59271 ADDING A FRAGMENT USING THE BEFORE CLAUSE SCANS ALL FRAGMENTS

среда, 10 декабря 2008 г.

Копирование данных без длинных транзакций

Как быть если требуется перенести большой объем данных из одной таблицы в другую? Можно воспользоваться например выгрузкой данных в промежуточный файл. Если данных не очень много то можно попробовать использовать прямую вставку с помощью insert into ... select ... from ... однако такой способ не будет работать если данных очень много, поскольку высока вероятность длинной транзакции. Напрашивается способ использования таблицы без журналирования (raw table) однако он не подходит если сервер используется в паре HDR.
Следующий способ был бы универсальным однако он не реализован:

insert into t1 select ... from t2 where ... commitrows N;


Таким образом приходится придумывать свои способы. Один из таких способов это использование хранимой процедуры и объявления курсора через foreeach. Этот способ позволяет делать commit через нужное число вставленных строк. Вот примерная реализация этого способа (нечто подобное обсуждали как то на конференции comp.databases.informix):

CREATE PROCEDURE batch_move(commitrows int);
...
DEFINE count_rows INT;
...
LET count_rows = 0;
BEGIN WORK;
...
lock table table2 in exclusive mode;
FOREACH cur_ins WITH HOLD FOR
SELECT список полей INTO список переменных FROM table1
LET count_rows = count_rows + 1;
INSERT INTO table2 values (список переменных);
IF mod(count_rows, commitrows) = 0 THEN
COMMIT WORK;
BEGIN WORK;
lock table table2 in exclusive mode;
END IF;
END FOREACH;
COMMIT WORK;
...
END PROCEDURE;


commitrows в параметре процедуры это число записей, через которые последует очередной commit. Таким способом можно перенести любое число записей не опасаясь длинной транзакции, надо лишь задавать реалистичное значение commitrows, которое выбирается индивидуально исходя из настроек сервера и размера записи в таблице-источнике. Опционально можно эксклюзивно блокировать таблицу источник и таблицу приемник, выставлять нужный уровень изоляции и т.д.

пятница, 7 ноября 2008 г.

Вышло обновление Informix 11.50.xC3

Вышло очередное обновление ветки 11.50 Informix 11.50.xC3. В новой версии появились следующие возможности:

Использование SQL Admin API для установки конфигурационных параметров.
Это значит что можно через SQL команды SET ONCONFIG менять конфигурационные параметры. Раньше конфигурационные параметры можно было менять только командами onmode либо непосредственно с помощью текстового редактора.

Динамическое изменение параметров для длинных транзакций LTXEHWM, LTXHWM, и DYNAMIC_LOGS.
Теперь без перезагрузки сервера можно менять эти параметры, что очень необходимо в некоторых случаях.

Улучшенная трассировка SQL с помощью Admin API.
Теперь можно задавать уровень трассировки для отдельной базы и отдельной сессии, а также приостанавливать и возобновлять трассировку без перераспределения ресурсов.

Изменение первого экстента таблицы
Экстент может быть изменен при перестроении либо добавлении нового фрагмента таблицы.

Откат транзакции и Savepoint
Позволяет откатывать транзакцию к определенной точке, которая была заранее объявлена.

Capturing Transactional Data with the Change Data Capture API
Непонятно пока что это такое, надо читать документацию :)

А также ряд других улучшений.

Подробнее читать здесь IBM Informix Dynamic Server v11.50 Information Center

среда, 10 сентября 2008 г.

Разделяй и властвуй или когда данных ну очень много

Комментарий к статье Data Partitioning with Informix Dynamic Server от 2.09.2008 из IBM Database Magazine

Базы бывают маленькие, большие и ну очень большие. И любые вычислительные системы имеют свои ограничения, если это не ZFS (хотя и ZFS тоже имеет ограничения, но они трудно достижимы). И если в случае с маленькими базами проблем с ограничениями как правило не возникает, то для больших баз это становиться актуально. Одно из таких ограничений это кол-во страниц на фрагмент, т.е. Data pages per fragment 16,775,134. Если таблица состоит из одного фрагмента (не фрагментирована) то у нее может быть не более чем указанное выше число страниц. Как избежать такого ограничения? Фрагментировать таблицу по какому либо условию. Либо переложить таблицу в dbspace с размером страницы побольше (макс.кол-во страниц останется тем же, но максимально возможное кол-во записей конечно увеличится), а можно сделать и то и другое. В 10 версии информикса появилась такая удобная штука как разделы (partitions). По сути это те же фрагменты с одним отличием: разделы могут лежать не только в разных dbspace (как фрагменты) но и в одном. После того как таблица фрагментирована, очередной фрагмент можно добавить используя attach существующей таблицы такой же структуры, либо выполнив оператор alter fragment on table ... add partition partname expression in dbspace что конечно же проще, чем создавать вначале новую таблицу а затем присоединять ее к фрагментированной.

четверг, 31 июля 2008 г.

Connection Manager

Клиент информикса версия 3.5xC1 вышел (еще в мае). В клиенте появился новый компонент: Менеджер соединений (Connection Manager). Он позволяет автоматически перенаправлять соединения клиентов в зависимости от нагрузки на серверах к менеее нагруженному серверу в кластере HDR. Кроме того можно реализовать автоматический failover (перенаправление на работающий сервер) в случае сбоя одного из серверов HDR.
IBM - IBM Informix Client SDK v3.50.xC1: Release notes, documentation notes, and machine notes

вторник, 22 июля 2008 г.

btscanner и производительность: настраиваем range scan

Ранее я уже писал про btscanner. Сегодня расскажу как его настроить на тип сканирования range scan.
Не секрет что по умолчанию в информиксе btscanner настроен на очистку индексных страниц при помощи способа leafscan, который является довольно затратным и сильно влияет на общую производительность экземпляра при очистке больших индексов. В этом можно убедиться понаблюдав за работой btscanner'a при очистке индексов на больших таблицах: работа нити btscanner приводит к ощутимой нагрузке на диски и буферный пул при таком методе. Чтобы избежать существенного снижения производительности при очистке больших индексов, надо настроить btscanner на другой метод очистки, например range scan. Для настройки есть специальный параметр который надо добавить в файл $ONCONFIG. Например настроим btscanner следующим образом: 1 нитка, минимальный размер индекса для очистки методом range scan не менее 10000 страниц:

BTSCANNER num=1,rangesize=10000

Для того чтобы новые параметры вступили в силу надо перезапустить экземпляр информикса.
То же самое можно сделать и без перезапуска с помощью следующей команды:

onmode -C rangesize 10000

Однако чтобы при последующем перезапуске изменения оставались в силе, все же необходимо добавить в файл конфигурации параметр BTSCANNER c необходимыми значениями.

Через некоторое время когда накопится статистика, с помощью команды onstat -C можно посмотреть сколько индексов каким способом обрабатывалось, вот пример:

...
Number of leaves pages scanned 420428
Number of leaves with deleted items 23992
Time spent cleaning (sec) 631
Number of index compresses 3940
Number of deleted items 934612
Number of index range scans 100
Number of index leaf scans 562
Number of index alice scans 0


Как видим часть индексов (которые превысили установленный размер rangesize) обрабатываются методом range scan, остальные индексы чистятся как обычно методом leaf scan.

вторник, 1 июля 2008 г.

Получаем список нитей для процесса

Иногда пользовательский процесс может открывать несколько сессий на сервере информикс, и требуется сгруппировать все сессии для данного процесса, чтобы удобнее просмотреть чем же они занимаются. Для решения этой задачи я написал следующий скрипт (на bash):


#!/bin/bash
# getuthbypid.sh
# Получение всех пользовательских нитей по заданному PID

if [ ${#*} -ne 1 ]
then
echo Get all user threads by PID
echo USE: getuthbypid PID
echo where PID is process ID
exit
fi

# Получение всех SID по заданному PID
sids=`onstat -g ses|egrep "$1"|awk '{print $1}'`
# Преобразование набора SID в строку с разделителями
siddelim=`echo $sids |sed -e 's/ /|/g'`
# Список user threads
onstat -u|egrep "address|$siddelim"



запускаем данный скрипт с параметром в качестве которого указан process ID клиентского процесса и получаем список нитей с их свойствами (флаги, SID, сколько читает/пишет и т.д.)