Friday, March 01, 2024

Rethinking AUTO_REPREPARE

Revisiting AUTO_REPREPARE parameter (original version here)

English version
A recent customer engagement made me analyze the use of this parameter. I have no absolute certain, but what it seems is that the system starts to use a non-optimal query plan (the reason for this is not yet clear, but seems related to the way statistics are updated) for a specific query. The query can be seen running very frequently and taking much longer than it should and the CPU consumption increases. Running statistics doesn't seem to help, but restarting the applications does solve the issue.

A possible explanation is that the query is PREPAREd, and the query plan doesn't change even when we run the statistics. Eventually new sessions will get the correct query plan, and the system returns to normal. This is (up to a point) a normal effect when using prepared statements. Obviously this is highly inconvenient.

That's where the AUTO_REPREPARE parameter can play a fundamental role. This parameter was introduced to avoid the error -710. This used to happen when a table used in a PREPARED statement was changed (new indexes, new columns, dropping columns etc.). The next occurrences of the execution would raise this error and would require an explicit re-preparation of the query, a re-opening of the associated cursor or another activity that would force the calculation of a new plan.

The parameter exists since version 11.10 but it only accepted two values: 0 to turn the feature off and 1 to turn it off. In version 12.10 new values were introduced but apparently they didn't get enough visibility:

  • 0 = Disables the automatic repreparation of prepared objects after the schema of a directly or an indirectly referenced table is modified. Also disables the automatic reoptimization of SPL routines after the schema of an indirectly referenced table is modified.
  • 1 = Enables automatic repreparation.
  • 3 = Enables automatic repreparation in optimistic mode.
  • 5 = Enables automatic repreparation on update statistics.
  • 7 = Enables automatic repreparation in optimistic mode and on update statistics

As we can see, there are options that will trigger automatic statement re-preparation on UPDATE STATISTICS (I'll address the "optimistic mode" later). 5 should be exactly what we want. It will take care of schema changes and also when we UPDATE STATISTICS on the tables used. This way the existing (bad) plans will be updated automatically and we avoid the need to restart the applications. The process will be transparent to the applications.

I've created a simple test to show the effect of this setting. I picked up the "demo1.ec" sample from a Client SDK installation and made some changes to it:

  1. Added a variable "customer_num" and a "count" to obtain the number of full scans executed on the table.
  2. Changed the query WHERE condition to use "WHERE customer_num > ?". Also changed the query to use a table "customer_tst" which will be created for the test purpose.
  3. Repeated the cursor block. I want to execute the query three times. First with value 1 (when plan is calculated it uses a sequential scan), then with value 115 (will choose an INDEX path if the plan is recalculated) and a last time with the original value of 1.
  4. Added a SET EXPLAIN ON that will give us an overview of what's happening
  5. Execute UPDATE STATISTICS LOW after first query execution to see if it triggers the re-optimization of the statement
  6. Find out how many sequential scans were run on the test table and return it as return code of the program

I also created a test SHELL script that will do the following steps for different values of AUTO_REPREPARE (1 and 5):

  1. Create a copy of the customer table in the stores demo database (includes data and the index on the customer_num column
  2. Launch the demo_tst compiled program and obtain the return code (number of sequential scans executed on the table)
  3. Show the explain output for the demo_tst program

The code is at the end of this article, if you want to run the test. To run it follow this steps:

  1. Compile the demo_tst program with: esql -o demo_tst demo_tst.ec
  2. Execute the shell script with: ./test.sh
     

Hopefully what you'll see is:

  •  For execution with AUTO_REPREPARE set to 1:
    • You will get three sequential scans and the explain plan will show only one plan and three similar executions.
  • For execution with AUTO_REPREPARE set to 5:
    • You will get one sequential scan (triggered by the use of "1" in the first query) and two INDEX path (triggered by the use of "115" on the second query, re-optimized because between first and second execution we run UPDATE STATISTICS). Third execution, although it uses the same value as the first execution will follow the plan calculated on the second execution, because there is nothing that triggers the re-optimization between second and third executions.

 

Conclusion

The (not so) new value of 5 allows PREPARED queries to be re-optimized when statistics on the underlying table(s) are refreshed, allowing the queries to benefit from improved query plans without restarting. It will also avoid the -710 error as the usual value of "1" permits.

Note that sometimes customers don't have AUTO_REPREPARE explicitly set to one, but it assumes this value if AUTO_TUNE is set to 1. However to benefit from this extended improvement we need to explicitly set the value to 5.

The value 3 and 7 are similar respectively to values 1 and 5, but the system will not check for schema changes or UPDATE STATISTICS if a query run successfully in the last second. This will of course open the possibility of getting -710 errors if a query is constantly used.

One question pop out: Is there any reason to run Informix with a different value?



Versão Portuguesa
Uma actividade num cliente fez-me revisitar o uso deste parâmetro (AUTO_REPREPARE). De momento não tenho a certeza absoluta, mas parece que ocasionalmente o sistema começa a usar um plano de execução pior para uma query (a razão para isto ainda não é conhecida mas suspeita-se que está relacionado com a forma como se executam as estatísticas). Nestas alturas a query pode facilmente encontrar-se a correr e demora muito mais que o esperado, e o consumo de CPU aumenta. Recalcular as estatísticas não parece resolver, mas um re-inicio das aplicações faz desaparecer o problema.

Uma possível explicação é que a query está "preparada", e assim o plano não se altera quando executamos o UPDATE STATISTICS. Eventualmente novas sessões obtêm o novo e melhorado plano de execução, e depois o sistema volta ao normal. Isto é (até certo ponto) um efeito esperado da utilização de statements preparados. Obviamente é também bastante inconveniente.

É aqui que o parâmetro AUTO_REPREPARE pode ter um papel fundamental. Este parâmetro foi introduzido para evitar o erro -710. Isto acontecia quando uma tabela usada numa instrução preparada sofria alguma modificação (novos índices, novas colunas, remoção de colunas etc.). A execução seguinte da instrução geraria o erro e seria necessário uma nova abertura de cursor associado, a execução do PREPARE novamente ou outra acção que despoletasse a geração de um novo plano de execução.

Este parâmetro existe desde a versão 11.10, mas só aceitava dois valores: 0 para desligar a funcionalidade e 1 para a ligar. Na versão 12.10 foram introduzidos novos valores, mas aparentemente não tiveram visibilidade suficiente:

  • 0 = Desactiva a "repreparação" automática depois de a estrutura de uma tabela directa ou indirectamente usada na query ser mudada. Desliga também a re-optimizção automática para procedimentos SPL.
  • 1 = Activa a re-optimização automática.
  • 3 = Activa a re-optimização automática em modo "optimista".
  • 5 = Activa a re-optimização automática também para UPDATE STATISTICS.
  • 7 = Activa a re-optimização automática também para UPDATE STATISTICS em modo "optimista".

Como se pode verificar há opções para despoletar a re-optimização das instruções quando ocorre um UPDATE STATISTICS (vermos o modo "optimista" depois). O valor 5 será exactamente o que se pretende. Endereça as alterações de estrutura bem como a execução de estatísticas nas tabelas envolvidas. Desta forma os planos existentes (não óptimos) serão actualizados automaticamente e evitamos o re-inicio das aplicações. Este processo é transparente para as aplicações.

Para demonstrar isto criei um teste simples que permite ver o efeito da funcionalidade. Parti do exemplo "demo1.ec" existente numa instalação de Client SDK e fiz-lhe algumas alterações:

  1. Adicionei uma variável "customer_num" para a condição da query e uma "count" para obter o número de sequential scans efectuados.
  2. Mofifiquei a condição WHERE da query para usar "WHERE customer_num > ?". Também alterei a query para usar uma tabela "customer_tst" que será criada para este propósito.
  3. Repeti o bloco de código que abre o cursor. Quero executar a query três vezes. A primeira será com o valor 1 (o motor escolhe um sequential scan para este valor). Depois com o valor 115 (o plano terá um acesso por índice quando recalculado) e novamente com o valor inicial de 1.
  4. Adicionei um SET EXPLAIN ON que nos dará visibilidade sobre o que se passou.
  5. Execução de um UPDATE STATISTICS LOW depois da primeira execução para vermos de dispara a re-optimização na segunda execução
  6. Obter o número de sequential scans executados na tabela de teste. Esse valor é usado como retorno do programa para que o script possa obter a contagem

Criei também um SHELL script que fará os seguintes passos para ambos os valores do  AUTO_REPREPARE (1 e 5):

  1. Cria uma cópia da tabela "customer" na base de dados de demonstração stores (incluí dados e o índice na coluna customer_num.
  2. Lança o programa referido antes (demo_tst) e obtém o seu código de retorno (número de sequential scans executado na tabela).
  3. Mostra o resultado do EXPLAIN contendo as queries feitas pelo programa demo_tst

O código está no fim do artigo, caso pretenda executar o teste. Os passos serão:

  1. Compilar o demo_tst com: esql -o demo_tst demo_tst.ec
  2. Executar o SHELL script com: ./demo.sh

Em princípio o resultado será:

  •  Para a execução com AUTO_REPREPARE = 1:
    • Serão executados três sequential scans e o EXPLAIN terá apenas um plano e três execuções similares.
  • Para a execução com AUTO_REPREPARE = 5:
    • Será executado apenas um sequential scan (da primeira execução pela utilização do valor "1") e dois acessos por índice (este segundo plano obtido pelo uso do valor "115" na segunda execução, re-optimizado porque entre a primeira e segunda execução fizemos um UPDATE STATISTICS). A terceira execução terá sempre o mesmo plano da segunda, pois não há nada entre ambas que cause uma re-optimização.

 

Conclusão

O (relativamente) novo valor 5 permite que queries preparadas possam ser re-optimizadas logo que sejam refrescadas estatísticas nas tabelas envolvidas, permitindo que as queries beneficiem automaticamente de planos melhoradas, sem re-inicio das aplicações. Também evita o erro -710 como o mais habitual valor 1 permite.

Note-se que é frequente que os clientes não tenham o AUTO_REPREPARE explicitamente definido, mas em alguns casos acaba por assumir o valor 1, caso tenham o AUTO_TUNE a 1. Mas para beneficiarmos desta funcionalidade estendida é necessário defini-lo explicitamente a 5.

O valor 3 e 7 são semelhantes respectivamente aos valores 1 e 5, mas no modo "optimista" onde o sistema não vai verificar se é necessário fazer a re-optimização se a query correu com sucesso há menos de um segundo. Isto deixa naturalmente margem para ocorrência do erro -710 se uma query fôr executada constantemente.

Tendo isto em conta há uma questão que salta à vista: Haverá razão para ter outro valor que não o 5 neste parâmetro?


The code

demo_tst.ec:
 
/****************************************************************************

 * Licensed Material - Property Of IBM
 *
 * IBM Informix Client-SDK
 *
 * (c)  Copyright IBM Corporation 1997, 2013. All rights reserved.
 * (c) Copyright HCL Technologies Ltd. 2017.  All Rights Reserved.
 *
 ****************************************************************************
 */


#include <stdio.h>
#include <string.h>
#include <unistd.h>

EXEC SQL define FNAME_LEN       15;
EXEC SQL define LNAME_LEN       15;

int main()
{
EXEC SQL BEGIN DECLARE SECTION;
    char fname[ FNAME_LEN + 1 ];
    char lname[ LNAME_LEN + 1 ];
    integer customer_num = 1, seq_scans;
EXEC SQL END DECLARE SECTION;
    int count;

    printf( "DEMO1 Sample ESQL Program running.\n\n");
    EXEC SQL WHENEVER ERROR STOP;
    EXEC SQL connect to 'stores';

    EXEC SQL SET EXPLAIN ON;

    EXEC SQL PREPARE p1 FROM "select fname, lname from customer_tst where customer_num > ?";
    printf("======== Statment prepared ====================\n");
    EXEC SQL declare democursor cursor for p1;

    printf("== Opening the cursor with value 1 ============\n");
    EXEC SQL open democursor USING :customer_num;
    count=0;
    for (;;)
        {
        EXEC SQL fetch democursor into :fname, :lname;
        if (strncmp(SQLSTATE, "00", 2) != 0)
            break;
        count++;

        if ( count == 1 )
                printf("Frst row: %s %s\n",fname, lname);
        }
    printf("%d rows were returned\n", count);

    if (strncmp(SQLSTATE, "02", 2) != 0)
        printf("SQLSTATE after fetch is %s\n", SQLSTATE);

    EXEC SQL close democursor;

    printf("== Updating statistics for table =====\n");
    EXEC SQL UPDATE STATISTICS LOW FOR TABLE customer_tst;
    printf("======== Reopening the cursor again with 115 ==\n");

    customer_num = 115;
    EXEC SQL open democursor USING :customer_num;
    count=0;
    for (;;)
        {
        EXEC SQL fetch democursor into :fname, :lname;
        if (strncmp(SQLSTATE, "00", 2) != 0)
            break;
        count++;

        if ( count == 1 )
                printf("Frst row: %s %s\n",fname, lname);
        }
    printf("%d rows were returned\n", count);

    if (strncmp(SQLSTATE, "02", 2) != 0)
        printf("SQLSTATE after fetch is %s\n", SQLSTATE);

    EXEC SQL close democursor;

    printf("======== Reopening the cursor again with original 1 ==\n");

    customer_num = 1;
    EXEC SQL open democursor USING :customer_num;
    count=0;
    for (;;)
        {
        EXEC SQL fetch democursor into :fname, :lname;
        if (strncmp(SQLSTATE, "00", 2) != 0)
            break;
        count++;

        if ( count == 1 )
                printf("Frst row: %s %s\n",fname, lname);
        }
    printf("%d rows were returned\n", count);

    if (strncmp(SQLSTATE, "02", 2) != 0)
        printf("SQLSTATE after fetch is %s\n", SQLSTATE);

    EXEC SQL close democursor;
    EXEC SQL free democursor;


    EXEC SQL SET EXPLAIN OFF;
    EXEC SQL SELECT t2.pf_seqscans INTO :seq_scans FROM sysmaster:systabnames t1, sysmaster:sysptntab t2 WHERE t1.partnum = t2.partnum AND t1.dbsname = 'stores' and t1.tabname = 'customer_tst';
    EXEC SQL disconnect current;
    printf("\nDEMO1 Sample Program over.\n\n");


   printf("======== Sequential scans executed on customer_tst table: %d =======\n",seq_scans);
   return(seq_scans);
}

test.sh:
 


#!/bin/bash

run_actions()
{

AUTO_REPREPARE_MODE=$1
onmode -wm AUTO_REPREPARE=$AUTO_REPREPARE_MODE

printf -- "------------------------------------------------------------------------------------------------\nPreparing the table (customer_tst) and launching the program demo1\n------------------------------------------------------------------------------------------------\n"
dbaccess stores <<EOF

DROP TABLE IF EXISTS customer_tst;
CREATE TABLE customer_tst AS SELECT * FROM customer;
CREATE INDEX cust_fis_pk ON customer_tst(customer_num);
EOF

./demo_tst
NUM_SEQSCANS=$?

cat sqexplain.out
case $NUM_SEQSCANS in
        1)
                printf -- "------------------------------------------------------------------------------------------------\nOnly one sequential scan was done. That was the first. The plan changed between executions\n------------------------------------------------------------------------------------------------\n"
                if [ "X${AUTO_REPREPARE_MODE}" = "X5" ]
                then
                        printf -- "------------------------------------------------------------------------------------------------\nThis is expected with AUTO_REPREPARE set to 5\n------------------------------------------------------------------------------------------------\n"
                else
                        printf -- "------------------------------------------------------------------------------------------------\nThis is NOT expected with AUTO_REPREPARE set to 1\n------------------------------------------------------------------------------------------------\n"
                fi
                ;;
        3)
                printf -- "------------------------------------------------------------------------------------------------\nThree sequential scans were done. The plan didn't change between executions\n------------------------------------------------------------------------------------------------\n"
                if [ "X${AUTO_REPREPARE_MODE}" = "X1" ]
                then
                        printf -- "------------------------------------------------------------------------------------------------\nThis is expected with AUTO_REPREPARE set to 1 or unset if AUTO_TUNE is set to 1\n------------------------------------------------------------------------------------------------\n"
                else
                        printf -- "------------------------------------------------------------------------------------------------\nThis is NOT expected with AUTO_REPREPARE set to 5\n------------------------------------------------------------------------------------------------\n"
                fi
                ;;
        *)
                printf -- "------------------------------------------------------------------------------------------------\nUnexpected value for number of sequential scans ($NUM_SEQSCANS) in customer_tst table. No external access to this table should be done during testing\n------------------------------------------------------------------------------------------------\n"
                exit 1
                ;;
esac

printf -- "------------------------------------------------------------------------------------------------\nPlease check query plans. If three sequential scans were executed it should show only one query plan and three executions.\nIf only one sequential scan was executed it should show two plans and an execution for first and two for second\n------------------------------------------------------------------------------------------------\n"

}



printf -- "------------------------------------------------------------------------------------------------\nRunning for AUTO_REPREPARE = 1\n------------------------------------------------------------------------------------------------\n"
rm -f sqexplain.out
run_actions 1


printf "*************************************************************************\nPRESS ENTER TO CONTINUE WITH SECOND PART OF THE TEST\n*************************************************************************\n"
read DUMMY


printf "*************************************************************************\nSTARTING SECOND PART OF TEST\n*************************************************************************\n"

printf -- "------------------------------------------------------------------------------------------------\nRunning for AUTO_REPREPARE = 5\n------------------------------------------------------------------------------------------------\n"
rm -f sqexplain.out

run_actions 5
dbaccess stores <<EOF
DROP TABLE IF EXISTS customer_tst;
EOF

Thursday, February 29, 2024

New and upcoming features

Announcement of a webcast covering recent and upcoming Informix features (original version here)

English version
IIUG website recently published the announcement of a Webcast covering recent features (in version 14.10) as well as some upcoming news related to future major version (15). The webcast will happen on March 28 at 3PM GMT time. You can find the details and register here:
https://www.iiug.org/event/ibm-informix-whats-new-and-whats-upcoming-thu-mar-28-2024-1100-am-edt/




Versão Portuguesa
O site do IIUG publicou recentemente um anúncio de um webcast cobrindo funcionalidades recentes (da versão 14.10) bem como algumas novidades relacionadas com a futura versão (15). A apresentação terá lugar no dia 28 de Março às 15H GMT. Pode encontrar os detalhes e registar-se no seguinte endereço:
https://www.iiug.org/event/ibm-informix-whats-new-and-whats-upcoming-thu-mar-28-2024-1100-am-edt/


Friday, June 16, 2023

Aha! It's worth it / Aha! Vale a pena!

The joys of Aha (original version here)


English version

In my most recent article I mentioned several features that will be implemented in the future major release of Informix and wrote that several of them came from "customer" requests and a couple of them I had inserted myself in the current or old Request For Enhancements page (now called Aha).
It just happens that today I had to open a new request for another IBM product, and the site listed my requests... And some of them are quite interesting:


I just mentioned the features I requested in Aha (there are a few more I suggested in the previous site). Many of them were refused. Some were or will be implemented. And some are still marked for "future consideration" which means they may still be implemented. It may seem that the majority is ignored/refused, so why do I think it's worth it? Because it may take around 5m to open it... it's easy! And it's somehow rewarding when you see that development actually implemented something you requested.

 

 

Versão Portuguesa

No meu artigo mais recente mencionei algumas funcionalidades que serão implementadas na próxima versão do Informix e indiquei que algumas delas derivam de pedidos de "clientes" e um par delas teriam sido inseridas por mim no actual ou antigo site de pedidos de melhorias (agora chamado  Aha).
Por coincidência, hoje estive a abrir mais um pedido para outro produto IBM, e no site reparei na lista dos meus pedidos... alguns são bastante interessantes:

Apenas mencionei os pedidos que fiz no Aha (haveria outras que sugeri no site antigo). Muitos foram recusados. Alguns foram ou serão implementados. E alguns estão marcados como "Future consideration" o que significa que poderão ainda ser implementados. Pode parecer que a maioria é ignorado/recusado, portanto porque acredito que vale a pena? Porque pode demorar cerca de 5m a abrir um pedido. É fácil! E é de alguma forma gratificante quando vemos que o desenvolvimento efectivamente implementou algo que sugerimos.



Wednesday, June 14, 2023

Yes, I'm still here. And soon so vNext will be / Sim, ainda estou por cá. E em breve a vNext também

 A return or just a notice about vNext (original version here)

English version

Long time "no see"...  I can't really remember about my last post, but apparently it was in 2019, and I only posted two articles during that year. A long time has passed, and the reasons for not posting are the usual ones...: I've been working with other products (although I never stopped working with Informix), lack of time, other priorities etc., etc... That doesn't really matter and this article doesn't necessarily mean I'll be posting frequently in the future... Though I remind I started posting when IBM was about to release version 11.10 (Cheetah). New stuff naturally triggers the will to share some views and (hopefully) some knowledge. And we're getting close to a new major version (currently only known, at least by me, as "vNext"). And a new major version should bring new and interesting stuff... even considering the "continuous delivery" that briefly means that when a feature is ready it will be out of the door in the next fixpack, which naturally means "major" versions may seem to contain very few new things.

Recently my colleague Scott Pickett shared some insights about vNext in an IIUG webcast. And the list of announced changes pushed me write this article... The list seems long and nice. And the focus seems to be the expansion or removal of some internal limits, which were last changed in V10 (March 2005).


This is a slide of the presentation and shows some of the limits that should change. One not listed here, but under consideration is the maximum row size. From the above I'd like to highlight and comment on some:

  • Larger partitions
    Many customers are hitting the current limit. Note however that if they're hitting this limit, you should probably partition your data
  • More rows per page
    Extremely important because it means we can use larger page sizes without the issue of wasting space in each page
  • Timestamp moving to 8-byte
    An end to the issue with incremental backups? Yes, probably, but just this change won't solve the slowness of incremental backups (because we need to read all the pages to identify the ones we should send to the backup)

Besides the focus on limits, development is also concentrating efforts on customer requests, entered through the Aha website. Among these I'd like to highlight a few:

  • Obtain the query plan of a running query
    I've requested this in the website before Aha. I wrote several articles about this (including an hack to try to show this should be easy to implement). Need I say more about this? Only that it comes too late... but apparently it will appear in a proper way, because it can be obtained with "onstat" command and through a pseudo table (although with a limit of 32K)
  • Storing large objects in a file system
    This will allow Smart Blobs to be stored in a filesystem, external to the database system. I have some mixed feelings about this. I'd say that because the filesystem is not a transactional system, this may open up possibilities to create some inconsistency between the filesystem and the metadata in the database. I hope that in the future there will be ways to check this. But on the other hand, this functionality will allow much easier maintenance and backup of this type of data. Whenever I see customers using Smart Blobs I remember a specific customer where most of their database is composed of Smart Blobs. And they have serious issues with backups for example (the backup infra-structure is not properly sized for the load this implies). Filesystem backups can be much more efficient because they already support incremental archiving. Obviously the downside is that a full restore will probably mean dual restore sessions (database and filesystem). But we need more info before deciding if this is a good thing or not. I think it clearly opens up possibilities to solve specific issues at very large databases where most of the data is composed of Smart BLOBs
  • CDC log capture from secondary
    CDC means change data capture, and Informix provides a way (API) for external applications to capture changes that are then replicated by them to external systems. Incidentally IBM has a product called InfoSphere Change Data Capture, and I've been doing a lot of work with it lately. The ability to attach these 3rd party (including IBM other products in this classification) to the secondary servers is a feature I can imagine a lot of customers using in order to lower the load on the primary servers.
  • CREATE/ALTER DATABASE - implicit transactions, owner qualified names unique, cursors for update
    This seems to be adding ANSI features like proper object owner nomenclature and automatic start of transactions to non-ANSI mode databases. Seems interesting for increased compatibility with other RDBMs, but I'd say some of them (implicit transactions) would require application changes. But, being new options that's good. We should like options!
    Something I'd like to see in non-ANSI databases that we already have in ANSI databases is the raising of an error if we try to INSERT/UPDATE CHAR like data that doesn't fit in the field length (currently we silently truncate it)
  • Add SID to audit log
    I also requested this many years ago in the old RFE site. In fact I recall some email exchanges with Jonathan Leffler (old timers will recognize the name for sure) about this. It won't solve all the issues, but it will allow an audit log analysis to reconstruct a sequence of actions, which currently we can't understand, because the logs only contain the client PID (process ID) and for Java applications that's always -1, meaning we see a bunch of audit entries but can't really correlate them.
  • Allow indexes to be made invisible to queries
    This allows a DBA to "test" the removal of an index (applications and query optimizer will stop seeing this index) while still keeping and maintaining the index... if the result is bad we can just "reactivate" it, without having to rebuild the index which can be painful
  • Updated Global Language Support (GLS) (Phase 1)
    Not much information about this (current, standard code sets are mentioned). But I'd like to emphasize that it mentions "Phase 1")
  • Informix should not need ROOT permissions
    It's stated that the default installation will be "non-root" method. This looks nice from a security perspective but it raises some issues (for authentication for example). I'll have to wait and see the implications of this feature. But it will be important, assuming the default installation method will change
  • Incremental Archives
    Not new right? Yes. We already have them (at least in theory), but high activity sites may not be able to use them due to the short timestamp we're using. And this limit will apparently change (see slide above). However, to have proper incremental archives we would need something else: A quick method to identify changed pages without having to read all the instances pages (current method). And I see no mention to this issue
  • SET SCHEMA: Informix should support switching 'schemas' in the middle of a transaction
    Currently there's a limitation on the statement "SET SESSION AUTHORIZATION" where it can't be used in the middle of a transaction. Apparently there are plans to remove this limitation. However, I think a bit of context is required here. This statement could be very useful to allow applications using application server to "propagate" the final user identity to the database, while using a pool of connections opened with a single "application user". This is very important when old systems that rely on the user identity for logging/auditing purposes on the database (using triggers for example) start to get used also by application servers which normally authenticate with a single user and open a series of connections that will be shared by different "application sessions".
    Now... this new feature may facilitate this, but what I've seen in several customers preventing this usage is that during a "session" that changed the authorization with SET SESSION AUTHORIZATION we CANNOT do remote SQL. And by "remote" I mean any action in another database on the same instance. And many customers have several databases that are used by a single application using this type of "remote SQL". So that limitation should also be removed, otherwise I think the usefulness of the feature will be very limited
I did not cover all the new mentioned features. For a full list, please check the webcast. I've only focused on the ones I think are more important or the ones I had comments about. Your preferences may vary of course, so the best is to check the source of information.

The last question is of course "When?". As usual the dates may vary... and there is no compromise about an ETA, but let's assume for now it should be this year. And we're about half way through...

Let's hope I'm able to continue covering these new features here! Glad to be "back", even if it was just this time.
 

 

Versão Portuguesa

Há quanto tempo... Na realidade não me lembro quando fiz a última publicação, mas aparentemente foi em 2019, e só publiquei duas vezes nesse ano. Muito tempo passou e as razões para não publicar são as habituais...: Tenho estado a trabalhar com outros produtos (ainda que nunca tenha deixado de trabalhar com Informix), falta de tempo, outras prioridades etc., etc... Isso agora não interessa, e este artigo não quer necessariamente dizer que irei publicar com frequência no futuro... Embora me recorde que comecei a publicar quando a IBM estava para lançar a V11.10 (Cheetah). Novidades naturalmente inspiram a partilha de perspectivas e (espero) algum conhecimento. E estamos a chegar perto de uma nova versão (actualmente apenas conhecida por "vNext", pelo menos por mim). E uma nova versão deverá trazer uma série de coisas interessantes... mesmo no contexto do "continuous delivery" que sumariamente significa que assim que uma funcionalidade está pronta será lançada no próximo fixpack, o que naturalmente "esvazia" um pouco os lançamentos de novas versões.

 Recentemente o meu colega Scott Pickett partilhou algumas novidades sobre a vNext num webcast do IIUG. E a lista de modificaões anunciadas fez-me escrever este artigo... a lista parece longa e interessante. E o foco parece ser no aumento ou remoção de alguns limites internos, que foram revistos pela última vez na V10 (Março de 2005)


Isto é um diapositivo dessa apresentação e mostra alguns dos limites que deverão ser alterados. Um que não está aqui listado mas que está a ser analisado é o tamanho máximo de uma linha. Dos apresentados acima gostaria de salientar e comentar alguns:

  • Partições maiores
    Muitos clientes estão a atingir este limite. Note-se no entanto que se atingimos este limite, provavelmente já deveríamos ter particionado os dados
  • Mais registos por página
    Extremamente importante porque significa que poderemos usar tamanhos de página maiores sem receio de desperdiçar espaço em cada página
  • Alteração do Timestamp para 8 bytes
    Um fim para o problema dos backups incrementais? Sim, provavelmente, mas esta alteração por si só não resolverá o tema da performance deste tipo de backups (porque temos de ler todas as páginas para identificar aquelas que devem ser colocadas no backup)

Para além do foco nos limites, o desenvolvimento está também a concentrar esforços nos pedidos dos clientes, introduzidos no site Aha . Nestes, gostaria de salientar alguns:

  • Obter o plano de execução de uma query em execução
    Pedi isto no site anterior ao Aha. Escrevi vários artigos sobre isto (incluindo um truque para tentar mostrar que a implementação não deveria ser difícil). Preciso de dizer algo mais sobre o tema? Apenas que vem tarde... Mas aparentemente vai aparecer da forma correta, pois poderá ser obtido através de uma opção do comando "onstat" e também por via de uma view (ainda que limitado a 32K)
  • Guardar Smart Large Objects num filesystem
    Isto permitirá que os Smart BLOBs sejam guardados como ficheiros num filesystem externo ao sistema de base de dados. Tenho sentimentos contraditórios em relação a isto. Dado que os sistemas de ficheiros não são sistemas transaccionais, isto poderá abrir a possibilidade de haver inconsistências entre o conteúdo do sistema de ficheiros e a metadata na base de dados. Espero que o futuro traga ferramentas para verificar isto. Mas por outro lado, esta funcionalidade irá permitir uma gestão e backups deste tipo de dados muito mais fácil. Sempre que vejo clientes a usarem Smart BLOBs lembro-me de um determinado cliente em que a esmagadora maioria do espaço são Smart BLOBs. E dos problemas que daí advêm, nomeadamente em termos de backup (a infra-estrutura de backups está claramente sub-dimensionada para a quantidade de dados que têm). Os backups de filesystem podem ser muito mais eficientes porque já permitem de forma muito simples backups incrementais. A desvantagem deste tipo de solução é que um possível restore implicará sessões de restore ao nível da base de dados e do filesystem. Mas precisamos de mais informação para decidir se isto será uma boa funcionalidade ou não. Penso que isto claramente abre possibilidades para resolução de problemas em bases de dados muito grandes onde a maioria dos dados são Smart BLOBs. 
  • Captura de logs para CDC a partir de um secundário
    CDC significa "change data capture" e o Informix fornece uma forma (API) para que aplicações externas capturem alterações que depois serão replicadas para sistemas externos. A IBM tem um produto chamado InfoSphere Change Data Capture, e eu tenho feito bastante trabalho com ele nos últimos tempos. A capacidade de ligar estes produtos de terceiros (estou a incluir produtos externos ao Informix, ainda que da IBM) aos nós secundários é uma funcionalidade que imagino ver muitos clientes a quererem usar para baixar a carga sobre o servidor primário
  • CREATE/ALTER DATABASE - transações implícitas, nomes com qualificação de owner únicos, cursores para update
    Parece ser a adição de funcionalidades ANSI, como nomenclatura de objectos correctamente qualificadas com identificação de owner e início automático de transações, a bases de dados criadas sem modo ANSI. Parece interessante para compatibilidade com outros RDBMS, mas diria que algumas (transações implícitas) implicarão alterações de aplicações. Mas sendo uma opção nova parece bom. Devemos apreciar o facto de termos opções!
    Uma característica de base de dados ANSI que gostaria de ver em bases de dados não-ANSI é a ocorrência de um erro sempre que tentamos inserir ou alterar dados do tipo CHAR que não caibam na definição do campo. Actualmente truncamos os dados sem dar erro.
  • Adicionar o SID ao log de audit
    Também pedi isto há muitos anos no antigo site de RFE (Requests For Enhancement). Inclusivamente lembro-me de uma troca de emails com o Jonathan Leffler (os mais antigos certamente reconhecem o nome) acerca deste tema. Não resolverá todos os problemas, mas permitirá reconstituir uma sequência de acções através da análise dos logs de audit. Actualmente tal não é possível porque o único elo de ligação entre as acções é o PID (ID de processo) do cliente, mas em aplicações Java isto aparece sempre como -1, o que impede a correlação entre as acções que vemos nos logs de audit
  • Permitir que os índices fiquem invisíveis às queries
    Isto permite que um DBA possa testar a remoção de um índice (as aplicações e o optimizador de queries deixarão de os ver) fazendo no entanto com que o índice continue a ser actualizado... Se o resultado for mau, podemos simplesmente reverter sem ter de reconstruir o índice que pode ser uma operação muito pesada
  • Actualização Global Language Support (GLS) (fase 1)
    Não há muita informação sobre isto (menção ao uso de códigos de caracteres standardizados e actualizados). Mas gostaria de salientar que está marcado como "fase 1"
  • O Informix não deverá precisar de permissões de ROOT
    É indicado que a instalação padrão passará a ser "sem root". Isto soa bem do ponto de vista da segurança, mas levanta algumas questões (relativas à autenticação por exemplo). Terei de esperar para ver as implicações desta funcionalidade. Mas considerando que o método padrão mudará será algo importante no futuro
  • Arquivos incrementais
    Nada de novo, certo? Sim. Já existem arquivos incrementais, mas instalações com muita actividade podem estar impedidas de os usar, devido ao pouco tamanho do timestamp com que as páginas são marcadas. E isto será mudado (ver diapositivo acima). No entanto, para termos arquivos incrementais optimizados necessitaríamos de outra coisa: Uma forma rápida de identificar as páginas alteradas (desde o último arquivo) sem ter de ler todas as páginas da instância (método actual). E não vi nenhuma referência a este tema
  • SET SCHEMA: Informix deveria suportar a troca de 'schemas' no decorrer de uma transação
    Actualmente há uma limitação na instrução "SET SESSION AUTHORIZATION" que é a mesma não poder ser usada no meio de uma transação. Aparentemente há planos para remover esta limitação. Mas penso que temos de adicionar aqui algum contexto. Esta instrução pode ser muito útil para permitir que aplicações que usam servidores aplicacionais possam "propagar" a identidade do utilizador final (usada entre o cliente e o servidor aplicacional) até à base de dados, quando a ligação à base de dados é feita com uma pool de ligações aberta com um único utilizador aplicacional. Isto é muito importante em sistemas antigos que dependem da identidade do utilizador para efeitos de logging/auditing na base de dados (usando triggers por exemplo), quando começam a ser usados  também por aplicações através de servidores aplicacionais, que abrem ligações à base de dados com um utilizador aplicacional.
    Ora... esta funcionalidade pode facilitar isso, mas o que vi em vários clientes que impede este uso é que durante uma "sessão" onde tenha sido usada a instrução "SET SESSION AUTHORIZATION" não podemos executar nenhum tipo de "SQL remoto". E por "remoto" quero dizer qualquer acção noutra base de dados ainda que na mesma instância. E muitos clientes têm várias bases de dados que são usadas por uma única aplicação com este tipo de "SQL remoto". Portanto esta limitação deveria ser removida, caso contrário penso que a funcionalidade continuará a estar limitada.

Não cobri todas as funcionalidades mencionadas na sessão referida. Para uma lista completa por favor assista ao webcast. Apenas foquei as que me parecem mais importantes ou sobre as quais tinha comentários a fazer. As preferências de cada um variam naturalmente, pelo que o melhor é consultar a fonte da informação.

A última questão é "Quando?". Como é hábito, as datas podem variar.... e não existe qualquer compromisso quanto a uma possível data de disponibilização, mas podemos assumir que será este ano. E o ano já vai a meio...

Vamos esperar que eu continue a cobrir estas novas funcionalidades. Estou contente por estar "de volta" mesmo que não haja muita continuidade nestes artigos.