erster freier wert einer index-spalte

hallo!

ist es möglich sich mit einem SQL-befehl den ersten “freien” wert anzeigen zu lassen? also wenn eine index-spalte z.b. die folgenden werte hat:

ID
1
2
3
5
6
7

würde dann 4 herauskommen.

ich habs zuerst mit einem einfachen algorithmus gelöst, der jeden wert ab 1 beginnend einzeln auf vorhandensein prüft. allerdings ist das sehr langsam.

dank & gruß, marco

Wozu?

Nenne mir einen triftigen Grund dafür, dann denk ich drüber nach.

Bis dahin: Deine offensichtlich von einer Sequenz erzeugte ID ist eindeutig und erfüllt exakt ihren Zweck.
Sie ist nicht dafür bestimmt, fortlaufend zu sein, nur eindeutig. Das ist sie.


Btw.: Dein ‘algorithmus’ hat vermutlich und ganz sicher einen Knackpunkt: er ist nicht
Multiuser-fähig.

Und ja: falls Du jetzt z.B. mit Finanzamt und fortlaufener Rechnungsnummer kommst:
ja, das mag ein Problem sein, welches aber Dein ‘algorithmus’ auch nicht lösen kann.
Hint: Rechnungsdatum.

Hallo,

ich bin neu in diesem Forum, arbeite aber schon einige Jahre mit Datenbanksystemen ob nun Oracel, DB2 oder MySql, am liebsten immer mit Postgres. Ich habe in diesem Forum schon viel gelesen und einiges gefunden das mir bei meiner arbeit geholfen hat. Also danke an alle die hier so fleisig schreiben.

Macht durchaus Sinn:
Unter Zahlreichen Bedingungen ist es erforderlich diese Lücken zu Nutzen. Erstes Beispiel sind automatische Abrechnungs oder Auftragssystem im Telekomunikationsbereich. In solchen Systeme laufen Sequezes trotz ihrer beachtlichen größe nach einem Jahr über. Zweites Beispeil ist ein profane Artikel-Nr… In einem von mir verwaltetem Productkatalog gibt es Täglich ca. 10.000 Updates. Aus juristischen Gründen dürfen aber bisher für den Verkauf verwendete Productdatensätze nicht einfach gelöscht werden. Deshalb und aus Performensgründen werden die neuen Daten einfach mit neuer Product-ID eingefügt. Ein Überlauf ist hier weniger das Problem aber die Product-Nr wird in Katalogen und Online Shops verwendet und die lesbarkeit für Menschen nimmt mit jeder Stelle mehr deutlich ab. Wenn nach Ablauf einer bestimmten Zeit diese Sätze gelöscht werden ist es zwingend notwendig diese Lücken neu zu vergeben. Sind nur zwei von vielen Beispielen (Kunden oder Lieferanten Nummern, Konto-Nr. bei der Fibu, usw.).

Soviel zur Erklärung warum es durchaus Sinn macht und jetzt einen möglichen Lösungsansatz der auch Multiuserfähig ist (Nur mal so angemerkt es läst sich auch das durchzählen Multiuserfähig realisereren aber wie marcomania schon anmerkte eine langsame Lösung.)

Lösungsmöglichkeit:
Schneller gehts wenn man in einer eigenen Tabelle solche Lücken verwaltet. Wird ein Datensatz gelöscht diesen Index in die Liste eintragen und beim nächsten Insert einen Wert aus der Tabelle lesen und diesen dann Löschen. Mit der Verwendung von Transaktionen und Satzsperren kann die Multiuserfähikeit sicher gestellt werden.

Will man die Anwendung nicht mit dem Speichern belasten läst man einen Prozess mitlaufen der nach der durchzählen Methode nach Lücken sucht und diese dann in einer eigenen Tabelle speichert. Diesem Prozess muß man aber unbedingt die CPU Zeit begrenzen da er sonst eine hohe Systemlast verursacht.

Man kann diese Methode noch an vielen Stellen verfeinern ich wollte nur mal grob eine prinzipielle möglichkeit beschreiben.

Viele Grüße
Alexander

Zeig mir Anwendung und Hardware, die pro Sekunde ca. 292471208677 Daten erzeugt.

Hint: bigseriel geht bis 9223372036854775807.

Selbst wenn dies alles nicht reichen sollte, gibt es im Contrib Verzeichnis von PostgreSQL einen Datentyp, der 128 Bit breit ist. Das dürfte dann genügen, um alle Atome im Universum zu zählen.

Du siehst also, an Grenzen stoßen wir nicht :wink:

Was glaubst Du wieviele Abrechnungsdaten ein Telefonnetze pro sekunde erzeugt?

Viel Spaß wenn Du so eine ‘9223372036854775807’ Bestell-Nr oder Kunden-Nr oder oder oder auf einen Bestellschein schreiben mußt. Ein Unternehmen das sowas einem Kunden zumutet ist Pleite bevor es richtig gegründet wurde.

Größe ist nicht alles es ist immer noch die Frage wer diese Indexe handeln muß. Menschen oder Maschinen. Also gibt es immer noch gute Gründe Lücken im Index wieder zu verwenden.

alexander_ro: die von dir angesprochenen Probleme bewegen sich sicher ein einem ganz anderen Bereich als die des Originalposters. Wenn ich weiss, das ich pro Tag mehrere Millionen Datensätze generiere, dann schaue ich auch, das dieses System damit einige Jahre mehr arbeiten kann. Für den Normalverbraucher von Sequenzen kommt so etwas aber weniger in Betracht.

Abgesehen davon, das große Datensatznummer nicht gleich Rechnungsnummer nicht gleich Kundennummer ist, wie die Daten intern gehandhabt werden, interessiert eher selten. Der Kunde sieht dann so etwas wie “Jahr/Monat/Kundennummer/Rechnungsnummer” und das entschärft viele Probleme.

Das Argument ist IMHO Unfug. Abrechnungsdaten sind für mich hier die reinen Verbindungsdaten,
die vielleicht in einer Tabelle anfallen, in der 10.000 oder von mir aus noch mehr Kunden
stehen. Der Kunde hat dann eine Kundennummer, die auch auf der Abrechnung steht,
nicht aber die Datensatznummer, mit der sein Anruf in Deiner internen Datenbank steht.

Und Indexe handelt in einer DB nie ein Mensch. Der vergißt nur, diese anzulegen…

Und für den Fragesteller:

Angenommen, die hast eine Table table_with_gaps, die Löcher enthält. Dir ist bekannt,
daß die höchste ID 10.000 ist. Du willst nun das erste Loch finden:

select generate_series(1,10000) except select id from table_with_gaps limit 1;

Allerdings performt das nicht wirklich. Wenn Du von Anfang an Dich um die ‘Löcher’
kümmern willst, wirst Du diese mittels Trigger Dir merken müssen.

Also dass es Indexe nur intern gibt kann ich mir kaum vorstellen.

Was bringt es mir für eine Kunden-Nr. einen zweiten internen Index der ebenfalls eindeutig sein muß zu generieren? Die Frage ob der Fragesteller es brauch kann ich nicht beantworten weil ich nichts über die Anwendung weiß. Das vergessen des Indexes durch Anwender verhindert die Datenbank und oder die Anwendung.

Aber ich sehe schon wir werden uns da wohl nicht einig werden also nix für ungut war nur ein Vorschlag und funktionieren tut er. Ob jemand das braucht muß er selber entscheiden ich verwende die Methode und finde sie auch in Ordnung. :smiley:

moin,

also das beispiel mit den kunden hinkt… erwartete weltbevölkerung bis Mai 2007 (quelle wikipedia):

6.600.000.000 (= 6,6 Mrd)

bigserial geht standardmäßig bis:

9.223.372.036.854.775.807

nur so am rande… aber wir werden off-topic…

cu tb.

Es war die Rede von “‘9223372036854775807’ Bestell-Nr oder Kunden-Nr”, und das ist Quatsch. Bitte zeige mir
die Firma, die ihren Kundenstamm fortlaufend nummeriert auch nur in die Nähe von 9223372036854775807 Kunden
kommt. Und mit Nähe meine ich hier z.B. ein Millionstel. Dasselbe gilt für Bestellnummern. Und selbst wenn Du Telefonverbindungsdaten der Gesamtweltbevölkerung speicherst, bezweifle ich erheblich, innerhalb eines Jahres
Probleme mit BIGSERIAL zu bekommen. Auch nicht in 10 oder 100 Jahren.

Wer aber wirklich viel an Raum für Sequencenummern braucht, hat ganz offensichtlich eine Anwendung, die viel schreibt.
Da ist es eher kontraproduktiv, erst zu schauen, ob es Lücken gibt. Weil, das kostet Zeit, Zeit, die man da nicht hat bzw.
deren Verschwendung ‘teuer’ ist.

Es ging mir bei den Rechnungs-Nr. usw. nicht um den Überlauf sondern um die lesbarkeit und da machen ein paar Stellen mehr oder weniger viel aus. Die Zeit spielt aber in diesem Fall keine so große Rolle.

Den Überlauf habe ich bei einem Telekomunikations Projekt selbst mal erlebt ich war in diesem Projekt aber nicht für die Datenbank zuständig. Es könnte sein dass die einfach den falschen Datentyp verwendet haben. Es ging damals zwar um sehr große Zahlen aber die genaue größe kann ich nicht mehr sagen.