Cada linha em uma tabela possui uma coluna ctid
do sistema do tipo tid
que representa o local físico da linha:
create table t(id serial); insert into t default values; insert into t default values;
select ctid , id from t;
Ctid Eu iria : ---- | -: (0,1) 1 1 (0,2) 2
dbfiddle aqui
Qual é a melhor maneira de obter apenas o número da página ctid
no tipo mais apropriado (por exemplo integer
, bigint
ou numeric(1000,0)
)?
A única maneira de pensar é muito feia.
postgresql
postgresql-9.4
datatypes
cast
data-pages
Jack Douglas
fonte
fonte
select ct[0], ct[1] from (select ctid::text::point as ct from pg_class where ...) y;
Respostas:
Seu violino com a minha solução.
A @bma já sugeriu algo semelhante em um comentário. Aqui está um ...
Justificativa para o tipo
ctid
é do tipotid
(identificador de tupla), chamadoItemPointer
no código C. Por documentação:Negrito ênfase minha. E:
Um bloco tem 8 KB em instalações padrão. O tamanho máximo da tabela é 32 TB . Segue-se logicamente que os números de bloco devem acomodar pelo menos um máximo de (cálculo corrigido de acordo com o comentário de @Daniel):
O que caberia em um não assinado
integer
. Em uma investigação mais aprofundada, encontrei no código fonte que ...Negrito ênfase minha. O que confirma o primeiro cálculo:
O Postgres usa inteiro assinado e, portanto, é um pouco curto. Ainda não pude determinar se a representação do texto foi alterada para acomodar um número inteiro assinado. Até que alguém possa esclarecer isso, eu voltaria a
bigint
, que funciona em qualquer caso.Fundida
Não há elenco registrado para o
tid
tipo no Postgres 9.3:Você ainda pode transmitir para
text
. Existe uma representação de texto para tudo no Postgres :A representação de texto corresponde à de um ponto, que consiste em dois
float8
números, que é convertido sem perdas.Você pode acessar o primeiro número de um ponto com o índice 0. Transmitir para
bigint
. Voilá.atuação
Fiz um teste rápido em uma tabela com 30k linhas (melhor de 5) em algumas expressões alternativas que vieram à mente, incluindo o original:
int
em vez debigint
aqui, principalmente irrelevantes para a finalidade do teste. Eu não repeti parabigint
.A
t_tid
conversão a partir de um tipo composto definido pelo usuário, como o @Jake comentou.A essência disso: o elenco tende a ser mais rápido que a manipulação de cordas. Expressões regulares são caras. A solução acima é mais curta e mais rápida.
fonte
ctid
são 6 bytes com 4 para a página e 2 para a linha. Eu estava preocupado com o elenco,float
mas acho que não preciso do que você diz aqui. Parece que um tipo composto definido pelo usuário é muito mais lento do que o utilizadopoint
. Você acha isso também?bigint
. Considere a atualização.point
e para o retornoint8
ainda seja mais rápida). A conversão para tipos predefinidos sempre será um pouco mais rápida. Eu o adicionei ao meu teste para comparar. Eu faria isso(page_number bigint, row_number integer)
para ter certeza.2^40
é de apenas 1 TB, e não 32 TB,2^45
dividido por2^13
dá2^32
, portanto os 32 bits completos são necessários para o número da página.bigint
para blkno