Bruno Almeida dos Santos
DB2 LUW, Administração e desenvolvimento.
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.
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.
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.
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
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.
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)
DDL da tabela a ser alterada:
$ 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:
Com o export em mãos, vou recriar a tabela nova, com a nova PK. Abaixo está a DDL:
Agora vamos importar os dados, com os valores da coluna ID.
$ 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.
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 <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
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
Assinar:
Postagens (Atom)