Работа с InterBase 7 временни таблици

InterBase 7.5 въведе възможност за работа с временни таблици. За разлика от временните системни таблици (tmp$), табличните данни могат да се създават и използват, докато приложенията работят. Досега разработчиците трябваше да съхраняват временни данни в обикновени таблици, което изискваше постоянно наблюдение на съдържанието на таблиците, както и специфична организация на работа с данни (вижте статията LINK). Най-често, разбира се, временните таблици се изискваха от разработчици, които имаха опит с MS SQL, преди да работят с InterBase/Firebird.

Нека да разгледаме какво точно представляват временните таблици в InterBase 7.5.

метаданни

Самите временни таблици всъщност са постоянни, т.е. когато ги създадете, информацията за тях се съхранява в системната таблица RDB$RELATIONS, точно както обикновените таблици, и тези таблици не само ще се съхраняват постоянно в базата данни, но и ще „оцелеят” при архивиране/възстановяване (за разлика от всички други опити за разширяване или промяна на структурата на системните таблици rdb$).

Синтаксисът за създаване на временни таблици е както следва:

Както можете да видите, това се различава от обикновените таблици по фразатаglobal temporary и добавкатаon commit. IB 7.5 добави колона RDB$RELATION_TYPE в системната таблица RDB$RELATIONS, която съдържа
RDB$RELATION_TYPEОписание
УПОРИТЕЛЕНОбикновени таблици (потребителски или системни), в които записите се изтриват само с delete+commit.
ГЛОБАЛНО ВРЕМЕННОВременни системни таблици, показващи състоянието на сървъра, връзка с бази данни, изпълнявани заявки и др. (TMP$DATABASE и други).
ГЛОБАЛНО ВРЕМЕННО ИЗТРИВАНЕВременни таблици, за които е посочено ON COMMIT DELETE ROWS, т.е. записите ще бъдат безусловно изтрити чрез извършване.
ГЛОБАЛЕН ВРЕМЕНЕН РЕЗЕРВАТВременни таблици, които имат посочени ON COMMIT PRESERVE ROWS, т.е. записите ще бъдат безусловно изтрити само при прекъсване на връзката.
Не се опитвайте сами да променяте тази колона - нищо добро няма да излезе от това, тоест няма да е възможно да превърнете обикновена таблица във временна или обратно.

В момента на сделката

GLOBAL TEMPORARY DELETEтаблиците съхраняват записи само до следващия комит и не само транзакцията, която ги е създала, но ивсяка друга транзакция в същата връзка (това поведение е подобно на грешка, тъй като ангажиментът на конкуриращи се транзакции във връзката не трябва да нулира видимостта на записите. В същото време временните системни таблици работят по абсолютно същия начин, т.е. показват актуализирана информация веднага след всеки комп транзакцията извършва ангажимент). В същото време записите, създадени в таблицата, не се виждат от никого, освен от текущата транзакция. Връщане назад в този случай е еквивалентно на ангажиране, но е ясно, че връщането също ще отмени всички промени, направени в обикновените таблици. И в случай на ангажиране, промените в транзакцията ще бъдат потвърдени и записите във временните таблици ще "изчезнат".

Нека създадем такава таблица и се опитаме да работим с нея.

Изберете броя на записите, които да вмъкнете според вашия вкус - ако просто ще проверявате работата, тогава 100-10K са достатъчни. Ако скоростта е висока, тогава можете да започнете със 100K записа или милион (например на моя компютър тази процедура попълва база данни с размер на страницата 4K 1 милион записа за около 47 секунди).

Бъдете внимателни, след като поставите записите, не се ангажирайте, в противен случай записите ще бъдат загубени. Направиизберете * от tmptran, записите ще бъдат видими. След извършване повторният опит за заявката ще върне празна таблица.

В момента на свързване

Таблиците GLOBAL TEMPORARY PRESERVE съхраняват записи, докато връзката, в която са добавени, не бъде отделена и тяхната видимост е ограничена само до тази връзка.

Направете ангажимент. Сега, в рамките на тази връзка, записът ще бъде видим от различни транзакции. Ако стартирате друг екземпляр на IBExpert или друг инструмент и изпълните същия израз за вмъкване, той ще се изпълни без грешка при нарушение на PK или UNUQIE ключ.

Веднага след като затворите текущата връзка и отворите нова, поставените данни ще бъдат загубени.

Връзки между временни таблици

и създайте FK от ДЕТАЙЛ към МАСТЕР. В резултат на това ще се окаже (всъщност IB няма да позволи създаването на такъв FK), че след създаване на записи в master и detail, първият комит ще унищожи записите в master, което ще доведе до наличието на записи с липсваща връзка в DETAIL (всъщност типът връзка при запазване на ангажиране -> при изтриване на ангажиране не е разрешен. Обратното е разрешено).

За това и като цяло за промяна на типа "временност" на записите, изразът ALTER TABLE има разширение:

АЛТЕР ТАБЛИЦАВЪРХУ РЕДОВЕ ЗА КОМИТ

Този оператор променя типа на таблицата (запазване/изтриване) и може също каскадно да променя типа на свързаните с FK таблици (каскада) към правилния, така че описаните по-горе ситуации с несъответствие между живота на записите в главния и детайлния да не се случват. Подсказката RESTRICT ще докладва грешка, ако таблицата е препратена от други временни таблици.

Временни таблици от всякакъв тип не могат да бъдат препращани от FK към постоянни таблици.

Събиране на боклук

Както бе споменато по-горе, въпреки "временността" на съдържанието на таблиците на записите за изтриване на ангажимент и на записи за запазване на ангажимент, въпреки това,съхранявани в базата данни, като данните от обикновените таблици. Съответно някой ден сървърът трябва да ги изчисти (като боклук). Това се случва в следните моменти
Тип таблицаКогато се събира боклука
ПРИ ИЗТРИВАНЕ НА КОМИТПри първото "изключително" свързване към базата данни
ON COMMIT PRESERVEПри отделяне на връзката, която създава записите
Пример за процедура, която автоматично попълва временна таблица със записи, не е случаен. Извършени са тестове върху обем от 1 милион записа. За тестове бяха използвани 2 работещи екземпляра на IBExpert и един IB_SQL. Без да навлизаме в подробности за теста, веднага ще представим неговите резултати и заключения:
  • заon commit delete таблици, боклукът се събира при първата изключителна връзка към базата данни. Например, има 10 приложения, които попълват временни таблици. За да бъдат изтрити записите във временните таблици, е необходимо всички 10 приложения да прекъснат връзката и поне едно да се свърже - това е моментът, в който ще започне събирането на боклук в таблиците при изтриване на комит. В този момент всички връзки, които се опитват да се свържат със сървъра до края на събирането на боклука, ще "увиснат".
  • Изводи:
  • работата с временни таблици при извършване на изтриване може да доведе до силен растеж на базата данни през деня, т.к по това време рядко има моменти, когато всички потребители прекъсват връзката с базата данни
  • колкото повече боклук се натрупа във временните таблици при изтриване на комит, толкова по-дълга е паузата между първата връзка и работата. За да изтриете 1 милион записа, сървърът харчи

25 секунди за премахване на три милиона -

120 секунди. за таблициon commit Save боклукът се събира в момента на отделяне на тази връзка,който е създал тези записи.

    Изводи:
    Колкото повече записи са създадени от връзката във временни таблици, толкова по-дълго приложението ще "виси" при прекъсване на връзката. Изтриване на 1 милион записа, както в предишния случай −

Временните таблици на InterBase 7.5 са доста полезна функционалност за приложения, които генерират сложни отчети или извършват междинни изчисления на сървъра. Въпреки това, поради странното поведение на изтриване при извършване на ангажимент, временните таблици в контекста на транзакция могат да се използват само в онези приложения, които работят с не повече от една транзакция наведнъж или с няколко транзакции, но с условието, че конкуриращите се транзакции не могат да се ангажират, докато транзакцията, работеща с временната таблица, не направи ангажимент. В допълнение, изтриването при извършване на запис води до натрупване на боклук записи по време на работа с много потребители (увеличаване на размера на базата данни) и до събиране на боклук при първото свързване към базата данни, което може да бъде нежелано забавяне в началото на работата на потребителите.

ON COMMIT PRESERVE изглежда е по-добър вариант, където единствената цена е по-дълго прекъсване на връзката на приложенията (ако са създали записи във временни таблици, разбира се). Вероятно, за да се избегнат оплаквания на потребителите, прекъсването на връзката на приложението ще трябва да се обработи специално, като се покаже съобщение с молба да изчакате известно време.