MSSQL Clustered Index erstellen und Einträge neu sortieren



  • Hi,

    ich hatte bei einer meiner Tabellen bisher einen Primary Clustered Key. Nun möchte ich aber die Sortierung ändern. Dazu habe ich den Primary Key auf Unclustered geändert und einen neuen, Clustered Index erstellt. Dabei werden die Daten aber nicht neu angeordnet.
    Kann/muss man das neue Sortieren irgendwie separat forcen?



  • Klar werden die Daten dabei neu sortiert.
    Bloss dass das nur die "physikalische" Reihenfolge betrifft, nicht aber die "logische".

    Die Reihenfolge in der du deine Ergebnisse bekommen möchtest musst du bei jeder Abfrage immer angeben, mit einer ORDER BY Klausel.

    Ein Clustered Key der die selbe Reihenfolge definiert, fürht bloss dazu, dass Abfragen die diese Ordnung verwenden schneller werden. Du kannst aber auch ganz ohne irgendwelche Indexe jederzeit eine beliebige Reihenfolge über ORDER BY erzwingen.

    Wenn du ORDER BY nicht angibst, ist die Reihenfolge undefiniert.



  • Und das ist eben nicht so. Bei meinen anderen Tabellen ist es so, dass ohne ORDERED BY die Einträge nach dem Clustered Index sortiert werden.
    Ok, ob sie danach sortiert werden oder unsortiert sind, darüber kann man streiten. Ich denke, die "Sortierung" entspricht der Reihenfolge auf der Festplatte...
    Wichtig ist mir das ganze eigentlich nur, weil ich ADOTabellen verwende, die das Resultat ohne zutun nach einem bestimmten Feld sortiert darstellen sollen. Da das auch die einzige Verwendung solcher Tabellen ist, wäre das schon ganz angenehm.



  • heimchen schrieb:

    Und das ist eben nicht so.

    Ui, Kindergarten-Niveau. Wohl, ist doch so!!!einself

    Du siehst doch dass es nicht funktioniert. Die Realität zu verleugnen bringt einen im Allgemeinen nicht weiter.

    Bei meinen anderen Tabellen ist es so, dass ohne ORDERED BY die Einträge nach dem Clustered Index sortiert werden.
    Ok, ob sie danach sortiert werden oder unsortiert sind, darüber kann man streiten. Ich denke, die "Sortierung" entspricht der Reihenfolge auf der Festplatte...

    Die "Sortierung" entspricht der Reihenfolge, wie SQL Server an die Datensätze drankommt.
    Wenn du eine Range-Query machst, dann entspricht die Reihenfolge in der die Datensätze gelesen werden meistens der Ordnung des Clustered Index. Garantiert ist dies aber AFAIK auch nicht.

    Wenn du aber z.B. einen JOIN machst, dann kommt es darauf an welchen JOIN Operator der Query-Optimizer auswählt, und ob er die beiden Operanden umdreht. D.h. es kann dem entsprechen was du erwartest, muss aber nicht. Und es kann sich jederzeit ändern. Irgendwann aktualisiert SQL Server seine Statistiken, dann kommt ein anderer Execution-Plan raus, und die Reihenfolge passt nicht mehr.

    Wichtig ist mir das ganze eigentlich nur, weil ich ADOTabellen verwende, die das Resultat ohne zutun nach einem bestimmten Feld sortiert darstellen sollen.

    Was sind bitte "ADOTabellen"?
    Und "ohne Zutun" geht beim Programmieren eher wenig.

    Wie gesagt: wenn du eine garantierte Sortierung haben willst, dann musst du die mit ORDER BY angeben.



  • hustbaer schrieb:

    heimchen schrieb:

    Und das ist eben nicht so.

    Ui, Kindergarten-Niveau. Wohl, ist doch so!!!einself

    Du siehst doch dass es nicht funktioniert. Die Realität zu verleugnen bringt einen im Allgemeinen nicht weiter.

    Ja, Kindergartenniveau. :p
    Es funktioniert ja, aber eben nur, wenn ich den Clustered Index erstelle, bevor ich die Tabelle mit Daten fülle. Darum heißt mein Thread ja auch "NEU sortieren" und nicht nur "sortieren".

    hustbaer schrieb:

    Wichtig ist mir das ganze eigentlich nur, weil ich ADOTabellen verwende, die das Resultat ohne zutun nach einem bestimmten Feld sortiert darstellen sollen.

    Was sind bitte "ADOTabellen"?
    Und "ohne Zutun" geht beim Programmieren eher wenig.

    ADO Tabellen ist eigentlich TADOTable, eine VCL Klasse. Dort gibt man nur die Serververbindung und den Tabellennamen an und man hat die komplette SQL Tabelle.
    Man kann beispielsweise auch den Namen eines Indexes oder ein Feld angeben, nach dem sortiert werden soll, aber wenn sich dann etwas ändert, muss ich jedesmal den Code ändern (inkl. Release etc.). Den Clustered Index könnt ich einfach auf die Datenbank anwenden, ohne dass sich die Daten ändern oder ich ein Release erzeugen müsste...



  • heimchen schrieb:

    hustbaer schrieb:

    heimchen schrieb:

    Und das ist eben nicht so.

    Ui, Kindergarten-Niveau. Wohl, ist doch so!!!einself

    Du siehst doch dass es nicht funktioniert. Die Realität zu verleugnen bringt einen im Allgemeinen nicht weiter.

    Ja, Kindergartenniveau. :p
    Es funktioniert ja, aber eben nur

    lol
    Glaub was du willst.

    Man kann beispielsweise auch den Namen eines Indexes oder ein Feld angeben, nach dem sortiert werden soll, aber wenn sich dann etwas ändert, muss ich jedesmal den Code ändern (inkl. Release etc.). Den Clustered Index könnt ich einfach auf die Datenbank anwenden, ohne dass sich die Daten ändern oder ich ein Release erzeugen müsste...

    Oh Mann...

    Du sagst du könntest ... dann tu es doch. Bloss dass du es eben nicht könntest. Aber man sagt ja Glaube versetzt Berge. Glaub es einfach ganz fest, vielleicht hilft das.



  • Naja, die Frage war durchaus ernst gemeint. Vielleicht bekomm ich ja noch eine ernste Antwort darauf.
    Wenn nicht, trage ich halt in die ADOTable das Index-Feld ein und nehm die Codeänderung in Kauf.



  • Meine Antwort war auch ernst gemeint. Du kannst dich einfach auf die Reihenfolge nicht verlassen so lange du kein ORDER BY angibst, das ist bei SQL Server nunmal so.

    Warum es in bestimmten Fällen "zu funktionieren scheint" ist leider etwas schwer zu erklären. Hängt damit zusammen wie SQL Server Tables ablegt/aufbaut die einen Clustered Index haben.

    Aber selbst wenn die Ordnung passt muss es nicht so bleiben. Ein Defragmentieren/Kompaktieren der Datenbank kann ausreichen um diese Ordnung zu zerstören.

    Wenn du mir das nicht glauben willst, kann ich auch nix machen.

    ----

    p.S.: Ich verstehe zwar nicht wieso es für dich so wichtig ist dass du am Programm nix ändern musst wenn du die Sortierreihenfolge ändern willst, aber egal. Ich hätte 3 Vorschläge anzubieten wie du das machen könntest:

    1. Mach ein .ini File zu deinem Programm, wo für jeden Table die passende "ORDER BY" Clause drinnensteht. Dann kannst du im .ini File umstellen wie die Tables sortiert werden sollen.

    2. Gleich wie 1), nur dass du die "ORDER BY" Clause nicht in einem .ini File abspeicherst, sondern in einem Table in der Datenbank selbst. Dann kannst du es zentral umstellen und musst nicht 100 .ini Files anpassen.

    3. Füg deinen Tables eine Spalte "DisplayOrder" hinzu, und sortier die Tables im Programm immer nach dieser Spalte. Wenn auch neue Datensätzen eingefügt werden sollen, dann bietet sich eine sog. "computed column" an. Wenn du die Reihenfolge dann mal ändern willst, kannst du einfach die Definition dieser "computed column" in der Datenbank ändern. Eine "computed column" kann auch persistiert werden, und dann kann man auch einen echten Index drauf machen, so dass das ORDER BY schön schnell wird, bzw. Range-Queries auf diese Spalte schnell werden.

    Die DML dafür sieht z.B. so aus:

    CREATE TABLE my_table(
        [a] int NOT NULL,
        [b] nvarchar(max) NOT NULL,
        [c] varchar(100) NULL,
        [display_order] AS (CAST(a as nvarchar(max)) + b + CAST(ISNULL(c, '') AS nvarchar(max)))
    )
    

    Nach dem "AS" schreibst du einfach den Ausdruck hin, nach dem sortiert werden soll. Du kannst dabei dann nicht wie bei ORDER BY mehrere Felder mit Komma getrennt angeben. Aber du kannst, wie hier zu sehen, mehrere zusammenhängen. Wobei das natürlich bei Feldern mit variabler Länge (varchar, nvarchar etc.) nicht wirklich funktioniert (das Zusammenhängen natürlich schon, aber die Reihenfolge passt dann nicht mehr).

    Natürlich lässt sich so eine Spalte auch im SQL Server Management Studio anlegen. Dort schreibst du den Teil nach dem "AS" einfach im Feld "Computed Column Specification"/"(Formula)" rein. "Computed Column Specification"/"IsPersistent" sollte auch klar sein, da kannst du angeben ob die Spalte persisiert werden soll oder nicht.

    Das sind drei Lösungen die kein neu compilieren der Anwendung erfordern wenn du die Sortierreihenfolge anpassen willst, und die alle drei definitiv funktionieren. (Die "computed column" Variante mit der erwähnten Einschränkung, dass Sortieren nach mehreren Feldern ein Problem ist, wenn ein oder mehrere Felder eine variable Länge haben.)

    Falls du meinst dass das alles für dich nicht in Frage kommt, schreib bitte auch dazu warum. Vielleicht findet sich ja noch eine besser passende Möglichkeit.

    Ich würde dir auf jeden Fall davon abraten irgendwie so lange herumzubasteln, bis SQL Server die richtige Reihenfolge ohne ORDER BY ausspuckt. Das mag eine Zeit lang funktionieren, nur irgendwann geht es nimmer, und dann ist die Kacke am Dampfen.



  • ICh denk, die Geschichte mit der Konfigurationstabelle ist ne nette Sache. Hab sowas für andere Werte (Default-Einträge) schon angelegt, dort könnt ich das mit rein nehmen.
    Ich war davon ausgegangen, dass mit dem Clustered Index sich die Default-Ausgabe beeinflussen lässt, da ich damit etwas experimentiert hab und das Ergebnis immer passte (solange man keine JOINs oder ähnliches macht). Allerdings hab ich halt immer an "frischen" Tabellen experimentiert und nicht an bereits gefüllten...


Anmelden zum Antworten