Chaque ligne d'une table possède une colonne système ctid
de type tid
qui représente l'emplacement physique de la ligne:
create table t(id serial); insert into t default values; insert into t default values;
select ctid , id from t;
ctid | id : ---- | -: (0,1) | 1 (0,2) | 2
dbfiddle ici
Quelle est la meilleure façon d'obtenir uniquement le numéro de page à partir du ctid
type le plus approprié (par exemple integer
, bigint
ou numeric(1000,0)
)?
La seule façon dont je peux penser est très moche.
postgresql
postgresql-9.4
datatypes
cast
data-pages
Jack Douglas
la source
la source
select ct[0], ct[1] from (select ctid::text::point as ct from pg_class where ...) y;
Réponses:
Votre violon avec ma solution.
@bma a déjà fait allusion à quelque chose de similaire dans un commentaire. Voici une ...
Justification du type
ctid
est de typetid
(tuple identifier), appeléItemPointer
dans le code C. Par documentation:Accentuation sur moi. Et:
Un bloc fait 8 Ko dans les installations standard. La taille maximale de la table est de 32 To . Il s'ensuit logiquement que les numéros de bloc doivent contenir au moins un maximum de (calcul fixé selon le commentaire de @Daniel):
Ce qui rentrerait dans un non signé
integer
. Après une enquête plus approfondie, j'ai trouvé dans le code source que ...Accentuation sur moi. Ce qui confirme le premier calcul:
Postgres utilise un entier signé et est donc un peu court. Je ne pouvais pas encore déterminer si la représentation du texte était décalée pour s'adapter à un entier signé. Jusqu'à ce que quelqu'un puisse éclaircir ce point, je reviendrais sur
bigint
ce qui fonctionne dans tous les cas.Jeter
Il n'y a pas de distribution enregistrée pour le
tid
type dans Postgres 9.3:Vous pouvez toujours lancer sur
text
. Il y a une représentation textuelle pour tout dans Postgres :La représentation textuelle correspond à celle d'un point, composé de deux
float8
nombres, que la distribution est sans perte.Vous pouvez accéder au premier numéro d'un point avec l'index 0. Cast to
bigint
. Voilá.Performance
J'ai effectué un test rapide sur une table avec 30k lignes (le meilleur de 5) sur quelques expressions alternatives qui me sont venues à l'esprit, y compris l'original:
int
au lieu d’bigint
ici, ce qui n’est généralement pas pertinent aux fins du test. Je n'ai pas répété pourbigint
.Le cast à
t_tid
s'appuie sur un type composite défini par l'utilisateur, comme @Jake a commenté.L'essentiel: le casting a tendance à être plus rapide que la manipulation de cordes. Les expressions régulières coûtent cher. La solution ci-dessus est la plus courte et la plus rapide.
la source
ctid
6 octets avec 4 pour la page et 2 pour la ligne. J'étais inquiet à propos du casting,float
mais je suppose que je n'ai pas besoin de ce que vous dites ici. Il semble qu'un type composite défini par l'utilisateur soit beaucoup plus lent que son utilisationpoint
, le trouvez-vous également?bigint
. Considérez la mise à jour.point
et versint8
est toujours plus rapide). La conversion vers des types prédéfinis sera toujours un peu plus rapide. Je l'ai ajouté à mon test pour comparer. Je ferais ça(page_number bigint, row_number integer)
pour être sûr.2^40
est seulement 1 To, pas 32 To qui est2^45
, qui est divisé par2^13
donne2^32
, d'où les 32 bits complets étant nécessaires pour le numéro de page.bigint
pour blkno