sexta-feira, 13 de maio de 2011

Ordene Registros Fisicamente com o Comando CLUSTER!

O comando CLUSTER permite a ordenação física dos dados de uma tabela com base em um índice. Esta pode ser uma boa opção quando um grande número de leituras sequenciais for realizado com base em um ou mais campos. É um comando já antigo, mas pouco conhecido e utilizado.

A operação de ordenação é feita uma vez no momento da execução do comando, e caso se deseje que os dados continuem ordenados fisicamente, deve-se reexecutar o comando após alterações nos registros, o que pode tomar muito tempo de processamento.

Um problema com este comando é a utilização de arquivos temporários que pode exigir espaço em disco extra, além de acessos a disco que tornem a operação mais demorada..

A sintaxe é relativamente simples:

CLUSTER [VERBOSE] table_name [ USING index_name ]
CLUSTER [VERBOSE]

A cláusula VERBOSE faz com que sejam mostradas informações do andamento da clusterização.

A sintaxe com nome da tabela e nome do índice é a mais segura, pois se sabe exatamente que tabela e que índice são utilizados.

A redação com o nome da tabela e sem o nome do índice assume que será utilizado para a ordenação o último índice utilizado.

A utilização de CLUSTER sem indicação de tabela ou índice reordena todas as tabelas que já tenham sido clusterizadas, o que pode ser arriscado, pois estas classificações de dados podem tomar um tempo substancial.

Por ser uma operação muito custosa, durante a clusterização a tabela fica indisponível para leituras e escritas, o que faz com que esse comando seja um candidato para momentos do dia de menor quantidade de acessos.

Abaixo temos um exemplo de clusterização, com criação de tabela, índices e dados e execução dos comandos de clusterização:

/*
Criação da tabela e inserção nos dados
*/

begin transaction;

drop table TAB_CLUSTER;
/*
drop index TAB_CLUSTER_COD;
drop index TAB_CLUSTER_VALOR;
*/

CREATE TABLE TAB_CLUSTER (
COD INTEGER, DESCRICAO VARCHAR(50), DATAHORA TIMESTAMP, VALOR INTEGER);

create index TAB_CLUSTER_COD on TAB_CLUSTER(COD);
create index TAB_CLUSTER_VALOR on TAB_CLUSTER(VALOR);

insert into TAB_CLUSTER values (round(CAST (random()*500 AS NUMERIC),0), 'Teste do comando Cluster', current_timestamp, round(CAST (random()*500 AS NUMERIC),0));
insert into TAB_CLUSTER values (round(CAST (random()*500 AS NUMERIC),0), 'Teste do comando Cluster', current_timestamp, round(CAST (random()*500 AS NUMERIC),0));
insert into TAB_CLUSTER values (round(CAST (random()*500 AS NUMERIC),0), 'Teste do comando Cluster', current_timestamp, round(CAST (random()*500 AS NUMERIC),0));
insert into TAB_CLUSTER values (round(CAST (random()*500 AS NUMERIC),0), 'Teste do comando Cluster', current_timestamp, round(CAST (random()*500 AS NUMERIC),0));
insert into TAB_CLUSTER values (round(CAST (random()*500 AS NUMERIC),0), 'Teste do comando Cluster', current_timestamp, round(CAST (random()*500 AS NUMERIC),0));

commit transaction;

cluster tab_cluster using tab_cluster_cod;

cluster tab_cluster using tab_cluster_valor;


Alternativas ao comando CLUSTER envolvem o uso de CREATE TABLE AS (sintaxe recomendada por compatível com Pl/ PgSQL) ou SELECT INTO. Ambos os comandos leem um conjunto der registros, ordenam e gravam em um local determinado:

- CREATE TABLE tab_cluster_teste1 AS SELECT * FROM tab_cluster ORDER BY cod;
- SELECT * INTO tab_cluster3 FROM tab_cluster ORDER BY cod;

Nenhum comentário: