2016-08-24 2 views
0

Ich habe Tabelle mit created (Timestamptz) -Eigenschaft. Jetzt muss ich Seitenumbrüche basierend auf dem Zeitstempel erstellen, denn während der Benutzer die erste Seite betrachtet, können neue Elemente in diese Tabelle eingegeben werden, was die Daten inkonsistent macht, falls ich OFFSET für die Seitennummerierung verwende.Postgres: mit Zeitstempel für die Seitennummerierung

Also, die Frage ist: Soll ich created Typen wie timestamptz oder es ist besser, es in integer zu konvertieren (UNIX, zum Beispiel 1472031802812). Wenn ja, gibt es irgendwelche Nachteile? Auch atm ich habe now() als Standardwert in created - gibt es alternative Funktion zum Erstellen von Unix-Timestamp?

+1

Es hat keinen Vorteil, datetime als Integer-Zeitmarke zu speichern. Das macht eigentlich nur die Dinge komplizierter. Stellen Sie sich zum Beispiel eine Abfrage "Gib mir alles seit Anfang des Monats" auf Ganzzahlen vor. Tu es einfach nicht. 'Timestamp' ist genau das, was Sie brauchen, benutzen Sie es. – freakish

+0

@freakish, Danke! Wenn ich Integer hätte, würde ich einfach sagen: SELECT * FROM Tabellenname WHERE erstellt . Aber wenn ich 'timestamptz' benutze, sieht es so aus, als würde ich jedes Element in der Tabelle konvertieren, um sicherzustellen, dass es mindestens ein paar Millisekunden später ist als der angegebene Zeitstempel. Liege ich falsch? – stkvtflw

+0

Ich bin mir nicht sicher, ob ich das verstehe. 'timestampz' unterstützt' <'operator. Warum würdest du etwas konvertieren? Ich sehe keinen Sinn darin. – freakish

Antwort

1

Lassen Sie mich Dinge von Kommentaren zu meiner Antwort umschreiben. Sie möchten den timestamp Typ anstelle von integer verwenden, einfach weil das genau dafür gedacht ist. Manuelles Konvertieren zwischen Timestamp-Integern und timestamp Objekten ist nur ein Schmerz und du gewinnst nichts. Und Sie werden es schließlich für komplexere Datetime-basierte Abfragen benötigen.

Um eine Frage über Paginierung zu beantworten. Sie tun einfach eine Abfrage

SELECT * 
FROM table_name 
WHERE created < lastTimestamp 
ORDER BY created DESC 
LIMIT 30 

Wenn es erste Abfrage ist dann stellen Sie lastTimestamp = '3000-01-01' sagen. Andernfalls setzen Sie lastTimestamp = last_query.last_row.created.


Optimierung

Beachten Sie, dass, wenn die Tabelle groß dann ORDER BY created DESC ist nicht effizient sein könnte (vor allem, wenn parallel mit unterschiedlichen Bereichen genannt). In diesem Fall können Sie „Zeitfenster“ verwenden, zum Beispiel bewegt:

SELECT * 
FROM table_name 
WHERE 
    created < lastTimestamp 
    AND created >= lastTimestamp - interval '1 day' 

Das 1 day Intervall arbitrarly gerichtet (stimmen Sie es auf Ihre Bedürfnisse). Sie können Ergebnisse auch in der App sortieren.

Wenn die Ergebnisse nicht leer ist, dann aktualisieren Sie (in der App)

lastTimestamp = last_query.last_row.created 

(vorausgesetzt, Sie Sortier getan haben, andernfalls nehmen Sie min(last_query.row.created))

Wenn die Ergebnisse leer ist, dann wiederholen Sie die Abfrage mit lastTimestamp = lastTimestamp - interval '1 day' bis Sie etwas holen. Sie müssen auch stoppen, wenn lastTimestamp zu niedrig wird, d. H. Wenn es niedriger ist als jeder andere Zeitstempel in der Tabelle (der vorab geholt werden muss).

All das ist unter bestimmten Voraussetzungen für Einsätze:

  1. new_row.created >= any_row.created und
  2. new_row.created ~ current_time
  3. Die Verteilung der new_row.created ist mehr oder weniger einheitliche

Annahme 1 sorgt dafür, dass die Paginierung Ergebnisse in konsistenten Daten, während Annahme 2 nur für das Standarddatum 3000-01-01 benötigt wird. Voraussetzung 3 ist, dass Sie keine großen leeren Lücken haben, wenn Sie viele leere Abfragen absetzen müssen.

+0

Vielen Dank! Eine Frage: Wenn ich einen Index erstellen werde, der auf dem 'created' basiert, wird' DESC' immer noch nicht effizient sein? – stkvtflw

+0

@stkvtflw Wenn wir über Hunderte von Millionen Zeilen sprechen, dann ja. Aber bevor Sie einen Strategie-Benchmark wählen. – freakish

+0

Entschuldigung, dass ich dich wieder belästige, aber ich habe noch eine letzte Frage) Wie konvertiere ich den Unix-Timestamp MIT MILLISECONDS in postgres-acceptable-timestamptz? – stkvtflw

0

Sie meinen sowas?

select extract(epoch from now())::integer as unix_time 
+0

sieht kompliziert aus) Ich meine, wenn ich Ganzzahlen hätte, würde ich einfach sagen: SELECT * FROM Tabellenname WHERE erstellt . Aber in diesem Fall sieht es so aus, als würde ich jedes Element in der Tabelle konvertieren, um sicherzustellen, dass es mindestens einige Millisekunden später als der angegebene Zeitstempel ist. Liege ich falsch? – stkvtflw

Verwandte Themen