Jede Zeile in einer Tabelle verfügt über eine Systemspalte ctid
des Typs tid
, der den physischen Speicherort der Zeile darstellt:
create table t(id serial); insert into t default values; insert into t default values;
select ctid , id from t;
ctid | Ich würde : ---- | -: (0,1) | 1 (0,2) | 2
dbfiddle hier
Was ist der beste Weg , nur die Seitenzahl wie von der des Erhalten ctid
in dem am besten geeigneten Typ (zB integer
, bigint
oder numeric(1000,0)
)?
Der einzige Weg, den ich mir vorstellen kann, ist sehr hässlich.
postgresql
postgresql-9.4
datatypes
cast
data-pages
Jack Douglas
quelle
quelle
select ct[0], ct[1] from (select ctid::text::point as ct from pg_class where ...) y;
Antworten:
Ihre Geige mit meiner Lösung.
@bma hat bereits in einem Kommentar etwas Ähnliches angedeutet. Hier ist ein ...
Begründung für den Typ
ctid
ist vom Typtid
(Tupelidentifikator), derItemPointer
im C-Code aufgerufen wird . Per Dokumentation:Meine kühne Betonung. Und:
Ein Block hat in Standardinstallationen eine Größe von 8 KB . Die maximale Tabellengröße beträgt 32 TB . Es folgt logischerweise, dass Blocknummern mindestens ein Maximum von (Berechnung gemäß Kommentar von @Daniel festgelegt) aufnehmen müssen:
Welches würde in ein unsigniertes passen
integer
. Bei weiteren Nachforschungen stellte ich im Quellcode fest, dass ...Meine kühne Betonung. Was die erste Berechnung bestätigt:
Postgres verwendet eine Ganzzahl mit Vorzeichen und ist daher ein bisschen kurz. Ich konnte noch nicht festlegen, ob die Textdarstellung verschoben wird, um eine Ganzzahl mit Vorzeichen aufzunehmen. Bis jemand dies aufklären kann, würde ich zurück fallen
bigint
, was auf jeden Fall funktioniert.Besetzung
Es ist keine Besetzung für den
tid
Typ in Postgres 9.3 registriert :Sie können immer noch zu besetzen
text
. Es gibt eine Textdarstellung für alles in Postgres :Die Textdarstellung entspricht der eines Punktes, der aus zwei
float8
Zahlen besteht, die verlustfrei gewirkt werden.Sie können auf die erste Nummer eines Punktes mit Index 0 zugreifen
bigint
. Voilá.Performance
Ich habe einen Kurztest an einer Tabelle mit 30.000 Zeilen (Best-of-5) mit ein paar alternativen Ausdrücken durchgeführt, die mir in den Sinn kamen, einschließlich Ihres Originals:
int
stattbigint
hier, meist irrelevant für den Testzweck. Ich habe es nicht wiederholtbigint
.Die Besetzung
t_tid
baut auf einem benutzerdefinierten zusammengesetzten Typ auf, wie beispielsweise @Jake commented.Das Wesentliche dabei: Das Casting ist in der Regel schneller als die Manipulation von Saiten. Reguläre Ausdrücke sind teuer. Die obige Lösung ist am kürzesten und schnellsten.
quelle
ctid
es 6 Bytes mit 4 für die Seite und 2 für die Zeile. Ich war besorgt über das Casting,float
aber ich denke, ich muss nicht von dem sprechen, was du hier sagst. Es sieht so aus, als wäre ein benutzerdefinierter zusammengesetzter Typ viel langsamer als der verwendetepoint
. Findest du das auch?bigint
. Betrachten Sie das Update.point
Hin- und Hergehenint8
noch schneller ist. Das Umwandeln in vordefinierte Typen ist immer etwas schneller. Ich habe es zu meinem Test hinzugefügt, um es zu vergleichen. Ich würde das machen,(page_number bigint, row_number integer)
um sicher zu sein.2^40
ist nur 1 TB, nicht 32 TB,2^45
was dividiert durch2^13
ergibt2^32
, daher sind die vollen 32 Bits für die Seitenzahl notwendig.bigint
für blkno