quarta-feira, 22 de maio de 2013

Converter segundos (decimal) para timestamp


Pessoal,

Vou descrever como converter um campo em segundos para timestamp.
Imaginem um campo que guarda a data do último boot de um servidor, mas ao invés de estar no formato timestamp, ele está guardado como um DECIMAL(10).

Exemplo;

[db2inst1@myserver ~]$ db2 "select BOOT_TIME from mytable fetch first row only"

BOOT_TIME
------------
 1231982035.

  1 record(s) selected.

Esse valor corresponde a quantidade de segundos que se passaram após a data de 1/1/1970.

Para transforma-lo no timestamp, podemos converter esse campo diretamente, passando como parametro o valor guardado:

[db2inst1@myserver ~]$ db2 "select BOOT_TIME, timestamp('1970-01-01','00:00:00') + BOOT_TIME SECONDS as timestamp from mytable fetch first row only"

BOOT_TIME    TIMESTAMP
------------ --------------------------
 1231982035. 2009-01-15-01.13.55.000000

  1 record(s) selected.


Ou seja, o valor 1231982035 corresponde a data 2009-01-15-01.13.55.000000, no formato YYYY-MM-DD-HH.MM.SS.MMMMMM.

Abs.

quarta-feira, 17 de abril de 2013

Criando "indices virtuais" para avaliação do plano de acesso no db2

Olá pessoal,

Tinha o seguinte cenário aqui no meu banco de dados.
Uma aplicação gerava uma query de relatório que estava demorando cerca de 30 minutos para retornar os resultados. Olhando o db2advis, ele sugeriu a criação de um indice em uma tabela GIGANTE do meu sistema.

db2advis -d nome_do_banco -i arquivo.sql 

E ai pensei: Bom, vou ter um trabalho imenso em criar esse indice, mas será que o plano de acesso vai melhorar?

Dessa forma, encontrei uma opção dentro do comando "explain mode", que irá criar os índices recomendados, na tabela ADVISE_INDEX, fazendo assim com que o explain do db2 entenda que eles já estão disponíveis fisicamente.

[db2inst1@myserver tmp]$ db2 set current explain mode recommend indexes
DB20000I  The SQL command completed successfully.

Depois disso, rodei a query que necessita de um indice novo.

[db2inst1@myserver tmp]$ db2 -tf arquivo.sql
SQL0217W  The statement was not executed as only Explain information requests
are being processed.  SQLSTATE=01604

E finalmente rodei o db2explain.


[db2inst1@myserver tmp]$ db2exfmt -d nome_do_banco
DB2 Universal Database Version 9.5, 5622-044 (c) Copyright IBM Corp. 1991, 2007
Licensed Material - Program Property of IBM
IBM DATABASE 2 Explain Table Format Tool

Connect to Database Successful.
....

Custo da query, antes e depois:

Access Plan:
-----------
        Total Cost:             21815.9
        Query Degree:           1



Access Plan:
-----------
        Total Cost:             1202.9
        Query Degree:           1



Com isso, eu consegui me certificar que o custo realmente cairia bastante, com a criação dos indices recomendados.

Para sair do modo explain, execute:


[db2inst1@myserver tmp]$ db2 set current explain mode no
DB20000I  The SQL command completed successfully.










sexta-feira, 25 de março de 2011

Isolation level de um statement pelo db2pd

Essa semana, testando uma nova versão de uma aplicação da empresa, surgiu a dúvida se um merge (antes executado com um Isolation level CS por default), poderia ser executado como UR ( Uncommited Read ). 


Descobrimos que sim, e, para nos dar a resposta definitiva em tempo de execução, usamos o db2pd.


Para quem não sabe, o db2pd é uma ferramenta usada para throubleshooting no db2, pois ela retorna rapidamente informações (falando de uma forma informal) do que está acontecendo no SGBD, desde uso do bufferpool, tablespaces a coisas relativas a rotinas administrativas, como runstats, reorgs e etc. Existe um amplo material sobre ele no Infocenter.


Bom, vamos parar de conversa e vamos começar a brincadeira.

$ db2 connect to sample
  Database Connection Information
  Database server        = DB2/LINUX 9.5.5
  SQL authorization ID   = DB2INST1
  Local database alias   = SAMPLE

Vamos executar o comando db2pd com os parâmetros necessários:

db2pd -db sample -dynamic


Joguei o output em um arquivo e procurei o MERGE do convdeskps( o merge foi alterado e coloquei nome de colunas e tabelas fakes ) :

Dynamic SQL Statements:

Address                       AnchID     StmtUID    NumEnv     NumVar     NumRef     NumExe     Text
0x00002AAD8D6768C0        78     4490601    1                1               2619         2619           MERGE INTO
    T AS I USING (SELECT C1, C2, C3, C4, C5 FROM Z ) INDATA ( C1, C2, C3, C4, C5, C6 ) ON (I.C1 = INDATA.C1 AND I.C2 = C2 AND I.C3 = INDATA.C4) WHEN MATCHED THEN UPDATE SET C3 = INDATA.C3, C4 = INDATA.C4, C5 = INDATA.C5 WHEN NOT MATCHED THEN INSERT (C1, C2, C3, C4, C5) VALUES ( INDATA.C1, INDATA.C2, INDATA.C3, INDATA.C4, INDATA.C5, INDATA.C6) WITH UR


Depois disso, a partir do StmtUUID [ 4490601 ] , procurei na seção Dynamic SQL Environments

Dynamic SQL Environments:
Address                        AnchID   StmtUID    EnvID    Iso    QOpt  Blk
0x00002AAD8D676D40 78           4490601    1            UR     5       B


Em negrito está o nível de isolamento do statement: UR

Sendo assim, realmente o DB2 está executando isso em Uncommited Read.

sexta-feira, 17 de setembro de 2010

Monitorar estado de um tablespace

Uma maneira fácil de monitorar o estado dos tablespaces do seu banco de dados, é fazer uma consulta a view administrativa SNAPTBSP_PART.

Como usuarío administrador do DB:


$ db2 connect to sample
  Database Connection Information
  Database server        = DB2/LINUX 9.5.5
  SQL authorization ID   = DB2INST1
  Local database alias   = SAMPLE



Execute o comando:

$ db2 "select substr(TBSP_NAME,1,30) as TBSP_NAME, substr(TBSP_STATE,1,30) as TBSP_STATE from sysibmadm.SNAPTBSP_PART"
TBSP_NAME                      TBSP_STATE
------------------------------ ------------------------------
SYSCATSPACE                    NORMAL
TEMPSPACE1                     NORMAL
USERSPACE1                     NORMAL

  3 record(s) selected.

Simples, não?

Até a próxima.

quarta-feira, 15 de setembro de 2010

Populando colunas novas com dados oriundos de uma sequence com DB2

Cenário:
Alterar a primary key de uma tabela qualquer, fazendo com que a nova PK seja um inteiro alimentado por uma sequence. Essa tabela já possui muitos registros inseridos, o que nos impede de descartar os dados antigos.

Solução sugerida: Preencher automaticamente o novo campo, usando uma chamada direta à sequence e utilizando os comandos import/export para manter os dados já inseridos anteriormente.

Bom, mãos a obra ...O exemplo da tabela é bem simples, o objetivo aqui é mostrar como fazer.

Como usuário administrador do DB, vamos conectar o DB (Minha plataforma é Linux)

$ db2 connect to sample

 Database Connection Information

 Database server        = DB2/LINUX 9.5.5
 SQL authorization ID   = DB2INST1
 Local database alias   = SAMPLE


DDL da tabela a ser alterada:

create table inf.t_company (
   name varchar (32) not null,
   cnpj varchar (20) not null,
   phone varchar (20) not null,
   constraint pk primary key (cnpj) 
   ); 

insert into inf.t_company values
('Google Brasil','11.111.111/0001-11','11 3344-5555'),
('Bruno Almeida','22.222.222/0001-22','21 2333-5566'),
('Cartorio ABC ','33.333.333/0001-33','65 6677-8899');

Coloque isso dentro de um arquivo .sql e execute direto no prompt para a criação:

$ db2 -tvf antiga.sql
drop table inf.t_company
DB20000I  The SQL command completed successfully.


create table inf.t_company ( name varchar (32) not null, cnpj varchar (20) not null, phone varchar (20) not null, constraint pk primary key (cnpj) )
DB20000I  The SQL command completed successfully.


insert into inf.t_company values ('Google Brasil','11.111.111/0001-11','11 3344-5555'), ('Bruno Almeida','22.222.222/0001-22','21 2333-5566'), ('Cartorio ABC','33.333.333/0001-33','65 6677-8899')
DB20000I  The SQL command completed successfully.

Para exibir a estrutura da tabela, execute o comando:
db2 "describe table <nome da tabela>

$ db2 describe table inf.t_company
                             Data type                     Column
Column name                  schema    Data type name      Length     Scale Nulls
--------------------------- --------- ------------------- ---------- ----- ------
NAME                         SYSIBM    VARCHAR                   32     0   No
CNPJ                         SYSIBM    VARCHAR                   20     0   No
PHONE                       SYSIBM    VARCHAR                   20     0   No


Vamos criar agora a sequence que vai popular o novo campo:

db2 "CREATE SEQUENCE INF.COMPANY_ID AS INTEGER MINVALUE 1 MAXVALUE 2147483647 START WITH 1 INCREMENT BY 1 CACHE 5 NO CYCLE NO ORDER"
DB20000I  The SQL command completed successfully.

Com isso, vou exportar os dados atuais da tabela, aproveitando para criar um novo campo dentro do .ixf que terá os dados oriundos da sequence. Esses valores serão usados no campo novo da tabela INF.T_COMPANY (que chamaremos de ID).

db2 "export to company.ixf of ixf select nextval for INF.COMPANY_ID as ID, NAME, CNPJ, PHONE from INF.T_COMPANY"
Number of rows exported: 3

Com o export em mãos, vou recriar a tabela nova, com a nova PK. Abaixo está a DDL:

drop table inf.t_company;
create table inf.t_company (
        id integer not null,
        name varchar (32) not null,
        cnpj varchar (20) not null,
        phone varchar (20) not null,
        constraint pk primary key (id) );

Agora vamos importar os dados, com os valores da coluna ID.
$ db2 "import from company.ixf of ixf insert into inf.t_company"
SQL3110N  The utility has completed processing.  "3" rows were read from the
input file.

Number of rows read         = 3
Number of rows skipped      = 0
Number of rows inserted     = 3
Number of rows updated      = 0
Number of rows rejected     = 0
Number of rows committed    = 3


Pronto, agora os dados já estão importados com a nova coluna.

$ db2 "select * from inf.t_company"

ID          NAME                          CNPJ                        PHONE
----------- -------------------------- ------------------------- --------------------
          1 Google Brasil              11.111.111/0001-11   11 3344-5555
          2 Bruno Almeida            22.222.222/0001-22   21 2333-5566
          3 Cartorio ABC              33.333.333/0001-33   65 6677-8899

  3 record(s) selected.



A partir desse momento, a aplicação já pode usar a sequence para popular o campo ID da tabela.

É isso, até a próxima.

segunda-feira, 13 de setembro de 2010

Por que escolhi o DB2?

Às vezes me faço essa pergunta, mas a resposta é sempre a mesma:
Eu não escolhi, simplesmente aconteceu.

Vindo da área Customer Care da empresa e almenjando uma mudança de setor, fui convidado na época pelo gerente de desenvolvimento a entrar em sua equipe, mais especificamente na área de AD (administrador de dados).

Meu conhecimento à epoca era de executador de queries com capacidade de realizar joins simples, de forma que minhas necessidades fossem atendidas. Não que eu não fosse capaz de me especializar, pelo contrário, mas era o que me bastava desde a época de estagiário até a quando me tornei gerente.

Desde então, nos ultimos 3 anos a cada dia fui aprendendo um pouco mais. E é para falar um pouco disso que criei esse blog. Espero ajudar e ser ajudado nesse espaço.

[]s