Cada fila de una tabla tiene una columna ctid de tipo de sistematid que representa la ubicación física de la fila:
create table t(id serial); insert into t default values; insert into t default values;
select ctid , id from t;ctid | carné de identidad : ---- | -: (0,1) | 1 (0,2) | 2
dbfiddle aquí
¿Cuál es la mejor manera de obtener solo el número de página del ctidtipo más apropiado (por ejemplo integer, biginto numeric(1000,0))?
La única forma en que puedo pensar es muy fea.
postgresql
postgresql-9.4
datatypes
cast
data-pages
Jack Douglas
fuente
fuente

select ct[0], ct[1] from (select ctid::text::point as ct from pg_class where ...) y;Respuestas:
Tu violín con mi solución.
@bma ya insinuó algo similar en un comentario. Aquí hay un ...
Justificación del tipo
ctides de tipotid(identificador de tupla), llamadoItemPointeren el código C. Por documentación:El énfasis en negrita es mío. Y:
Un bloque es de 8 KB en instalaciones estándar. El tamaño máximo de la mesa es de 32 TB . Se deduce lógicamente que los números de bloque deben acomodar al menos un máximo de (cálculo fijado según el comentario de @Daniel):
Lo que encajaría en un sin firmar
integer. En una investigación adicional encontré en el código fuente que ...El énfasis en negrita es mío. Lo que confirma el primer cálculo:
Postgres usa un entero con signo y, por lo tanto, es un poco corto. No pude precisar, aún, si la representación de texto se desplaza para acomodar un entero con signo. Hasta que alguien pueda aclarar esto, recurriría a
bigint, lo que funciona en cualquier caso.Emitir
No hay elenco registrado para el
tidtipo en Postgres 9.3:Todavía puedes lanzar a
text. Hay una representación de texto para todo en Postgres :La representación de texto coincide con la de un punto, que consta de dos
float8números, ese reparto no tiene pérdidas.Puede acceder al primer número de un punto con índice 0. Transmitir a
bigint. VoiláActuación
Realicé una prueba rápida en una tabla con 30k filas (la mejor de 5) en un par de expresiones alternativas que me vinieron a la mente, incluido el original:
inten lugar debigintaquí, mayormente irrelevante para el propósito de la prueba. No repetí parabigint.El elenco para
t_tidconstruir sobre un tipo compuesto definido por el usuario, como @Jake comentó.La esencia de esto: el casting tiende a ser más rápido que la manipulación de cuerdas. Las expresiones regulares son caras. La solución anterior es más corta y más rápida.
fuente
ctidson 6 bytes con 4 para la página y 2 para la fila. Estaba preocupado por el casting,floatpero supongo que no necesito tener lo que dices aquí. Parece que un tipo compuesto definido por el usuario es mucho más lento que el usopoint, ¿también lo encuentra?bigint. Considera la actualización.pointy el regresoint8son aún más rápidos). La conversión a tipos predefinidos siempre será un poco más rápida. Lo agregué a mi prueba para comparar. Lo haría(page_number bigint, row_number integer)para estar seguro.2^40es solo 1TB, no 32TB, que es2^45dividido por2^13da2^32, por lo tanto, los 32 bits completos son necesarios para el número de página.bigintpara blkno