SQL Abfrageplan

6. März 2008 23:28

Hallo zusammen

seit geraumer Zeit setzte ich mich (wie wohl auch viele Andere) mit dem Thema Performance - Optimierung von MSSQL (mit Nav. 4SP3) auseinander.

Nach vielen Versuchen, endlosen "Textzeilen" und stöbern in diesem Forum, habe ich einen passenden Weg gefunden, schlechte Abfragen zu erkennen und diese zu optimieren.
Mit unter ist ja der Abfrage-Plan, welcher SQL erstellt sehr aufschlussreich, wie die Abfrage verläuft, und wie viele "Kosten" verursacht werden.
Das alles ist schön und recht, und auf dem Testserver habe ich das Optimum der Keys und deren Konstellation gefunden.
Beim Erstellen der Indexe (habe Testhalber extra nur 2 erstellt, welche die TOP 20 schlechtesten Querys enorm verbesserten (auf Testserver)).
Resultat (nach einem Gemessenen Tag): Schlechtere Performance als zuvor!
Erst verstand ich die Welt nicht mehr. Danach aber machte ich mich daran, den Abfrage-Plan auf dem Live-System zu inspizieren und siehe da:
1. Verwendet der einen ganz anderen Abfrageplan und
2. Indexe, welche er auf dem Testserver gar nicht verwendet hatte, oder umgekehrt (Testserver=SuperIndex, Live=Clusteret Index Scan)

Das Testsystem ist equivalent mit dem Live-Server. Einziger Unteschied 8 anstatt 24 HDD's.

Die Datenbank ist vom selben Tag wie die des Live-Systems.

Wie kommt das? Hat da jemand Erfahrung? :roll:
Ich kann ja schlecht die Indexe aufm Live-Server erpröbeln.

Gruss aus der Schweiz

7. März 2008 16:46

Soweit ich weiss entscheidet der SQL-Server auch anhand der Statistiken welche Abfrage er wie ausführt. Da die Statistiken auf dem Produktiv System komplett anders aussehen (und sich ständig ändern) als in der Test Datenbank, die ja nun auf einem bestimmten Stand Statistiken hält, laufen die Abfragen z.T. anders.

Das kuriose was ich bis heute auch nicht verstehe ist, warum der Query Optimizer unabhängig von der Programmierung in NAV, obwohl man ein und dieselbe Aktion in NAV ausführt z.T. immer was anderes macht.

Das müsste mir auch mal jemand erklären. (z.B. unser SQL Profi Stryk *g*)

7. März 2008 18:30

Tach zusammen :-)

Nun, wenn Indexe optimiert werden, dann gibt es einiges was da eine Rolle spielt.
Was die "Kosten" einer Abfrage angeht, so ist es zunächst mal irrelevant welche "Costs" eine einzelne Operation verbraucht, da dies nur die Gewichtung der einzelen Teiloperationen zueinander darstellt.

Das ausschlaggebende Kriterium ist die Anzahl der "Reads" - je mehr desto schlechter, eben meist dann wenn "Index Scans" (statt "Seeks") durchegführt werden.

Wurde ein passender Index erstellt, so hängt es von den Statistiken ab, ob dieser auch genutzt bzw. "gefunden" wird.

Aber auch optimale Statistiken sind keine Garantie dafür, dass der Index auch benutzt wird.
Unterschiede im Ausführungsplan - also "online" vs. "ad-hoc" - können durch sog. "Parameter Sniffing" hervorgerufen werden.
In solchen "sturen" Fällen ist es gelegentlich notwendig einen "Recompile-" oder "Index-" Hint zu setzten ...

Um konkreter zu werden, müsste man allerding die betroffenen Abfragen und Indexe genauer untersuchen.

Hallo miteinander

7. März 2008 19:32

Danke erst mal beiden für eure Inputs ... bin froh um alles Wissen resp. Erfahrungswerte, wenn es um MSSQL und Nav geht :-)

Wie ist denn das mit den Kosten?

Der Abfrageplan sieht ja z.B. so aus (siehe Anhang).
Wenn man da die Kosten des SELECT's betrachtet "Geschätzte Unterstrukturkosten = 1.62944, dann ist das doch ca. das Gleiche, was der Query Optimizer als Entscheidungsgrundlage verwendet ... oder nicht?

Bei Versuchen mit geringen Abweichungen (mit anderem Index), Beispiel: 1.61219 (anstatt 1.62944), verwendete der Optimizer den anderen Index.

Der "Trick" mit dem Hinting funktioniert einwandfrei, jedoch ist in unserer Firma leider nicht damit zu rechnen, dass sich jeder Programmierer der "Index" resp. Key (Navision) - Verwendung bewusst ist. Daher auch eher kritisch. Wie auch immer :roll:

Gibt es eigentlich eine Fausregel, wie viel mehr "Schreibaufwand" pro Index generiert wird (Beispiel: + "x" milisec. / KB)? Wäre nützlich für eine Kosten/Nutzen analyse.

@tesarolle
Das Phänomen, dass bei der gleichen Query unterschiedliche Pläne erstellt werden, konnten wir grösstenteils beseitigen, in dem wir die "Automatischen Statistikupdates" aktivierten. Sprich, die Statistiken sind aktuell (naja, meistens). Was auch zu beobachten war: Bei exremen Workloads, entschied sich der Optimizer für die gleiche Query jedes mal für einen anderen Plan ... seit der neuen Hardware ist das passé.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

7. März 2008 22:28

Das Kosten/Nutzen eines Indexes Verhältnis kann eigentlich nur subjektiv ermittelt werden. Klar, beim Schreiben muss pro Index zusätzlicher Aufwand betrieben werden, jedoch wird in einem ERP deutlich mehr gelesen als geschrieben; d.h. wenn der Index die Lese-Leistung entsprechend beschleunigt, dann ist der "Verlust" beim Schreiben u.U. durchaus gerechtfertigt ...

Was den gezeigten Ausführungsplan angeht, so würde ich gerne mal die Abfrage dazu sehen - sowas wird von NAV eigentlich nicht verursacht ... insbesondere der "Constant Scan" (sich ausschließende Filterbedingungen) weist auf schlechte Programmierung hin ...

Constant Scan

7. März 2008 23:31

der Code sieht so aus (von Profiler):


declare @C1 varchar(43),@C2 tinyint
select @C1='%59[2²][3³]9%',@C2=0
SELECT TOP 500 *,DATALENGTH("Bild") FROM "Navision"."dbo"."FIRMA$Artikel" WITH (READUNCOMMITTED) WHERE (("Bezeichnung" LIKE @C1)) AND (("Gesperrt"=@C2)) ORDER BY "Gesperrt","Bezeichnung","Nummer"

Das kommt von "@*SuchString*"


Hier kommt es noch schlimmer:

SELECT * FROM "Navision"."dbo"."FIRMA$Artikel" WITH (READUNCOMMITTED) WHERE (("Nummer"<'ARTIKELNUMMER')) AND (("Gesperrt"=0))

Egal was man macht, es wird ein Clustered Index Seek verursacht, und der braucht Zeit. Auch wenn ein Index mit (Gesperrt,Nummer) bereitgestellt wird, interessiert das den Query Analyzer gar nicht.

Gruss
Ramon

8. März 2008 13:24

Also ... werden in Suchausdrücken "Wildcards" benutzt (NAV * = SQL %) - wie auch über Suche nach "Teil des Feldinhaltes" etc. - so besteht die hohe Wahrscheinlichkeit, dass ein "Scan" ausgeführt wird, inbesondere wenn die "Wildcard" am Beginn des Ausdrucks steht: hier kann soz. kein richtiger Einstiegspunkt (Root Node) in einen Index gefunden werden.

Allerdings erklärt das alles nicht den "Constant Scan" ...

Der Operator "<" auf den Primärschlüssel beim zweiten Statement kommt - sofernt nicht ein Benutzer explizit so gefiltert hat - aus einer Übersichtsform (Scrolling), könnte aber auch von einem NEXT im Schleifendurchlauf resutieren ...

Ein Index mit 'nem boolschen Feld am Anfang ("Gesperrt") wir SQL Server nur im absoluten Notfall benutzen, da das Feld extrem "unselektiev" ist.

Was bei allen Abfragen auf die Artikel od. Item Tabelle besonders relevant ist, ist ob tatsächlich Bilder (BLOB!) gespeichert sind - das sollte man tunlichtst unterlassen (gilt auch für Customer, Vendor, etc.)!

8. März 2008 19:12

Hallo stryk

Ich staune nicht schlecht ... du bist ja eine wandelnde SQL - Knowledgebase :shock:

Also ... werden in Suchausdrücken "Wildcards" benutzt (NAV * = SQL %) - wie auch über Suche nach "Teil des Feldinhaltes" etc. - so besteht die hohe Wahrscheinlichkeit, dass ein "Scan" ausgeführt wird, inbesondere wenn die "Wildcard" am Beginn des Ausdrucks steht: hier kann soz. kein richtiger Einstiegspunkt (Root Node) in einen Index gefunden werden.

Kann man das irgend wie unterbinden? Dass die Benutzer diese Möglichkeit nicht mehr haben?

Allerdings erklärt das alles nicht den "Constant Scan" ...

Durch was könnte dann z.B. ein Constant Scan verursacht werden?

Ein Index mit 'nem boolschen Feld am Anfang ("Gesperrt") wir SQL Server nur im absoluten Notfall benutzen, da das Feld extrem "unselektiev" ist.

SELECT * FROM "Navision"."dbo"."FIRMA$Artikel" WITH (READUNCOMMITTED) WHERE (("Nummer"<'ARTIKELNUMMER')) AND (("Gesperrt"=0))

In diesem Falle kann dafür kein passender Index (ausser dem Clustered) verwendent werden? Denn dieser Seek ist sehr langsam.

Was bei allen Abfragen auf die Artikel od. Item Tabelle besonders relevant ist, ist ob tatsächlich Bilder (BLOB!) gespeichert sind - das sollte man tunlichtst unterlassen (gilt auch für Customer, Vendor, etc.)!

Relevant auf die Performance? Aber das ändert nichts daran, dass Navision das Feld selektiert mit DATALENGTH("Bild") oder?

Was ich halt bei Navision generell schlecht finde: SELECT * FROM ...
Machte mal einen Versuch, wo ich per ADO.DATASET die Daten direkt vom SQL holte, und via Navision.Insert einfügte. Das Ergebnis= Massiv schneller ... Nicht der Insert...sondern der SELECT, weil ich da nur die benötigten spalten holte, und nicht alle (*).
Naja, ist wohl nicht zu ändern.

Des weiteren frage ich mich oft bei den gesehenen Abfragen, warum Navision "option(Fast 5)" verwendet, wenn die Forms, von denen der Select stammt, 25 Rows anzeigen. Dann bringen doch die Fast 5 nicht wirklich etwas ... oder irre ich mich da?

Ich glaube ich sollte nicht so viele Fragen stellen ... sorry :roll: ... aber ich interessiere mich gerne für Details um möglichst viel zu verstehen.

9. März 2008 15:53

maod hat geschrieben:Ich staune nicht schlecht ... du bist ja eine wandelnde SQL - Knowledgebase :shock:

Na ja, wenn man sich mit dem Thema "ein paar Tage" auseinandersetzt, dann bleibt so das eine oder andere hängen ...

maod hat geschrieben:
Also ... werden in Suchausdrücken "Wildcards" benutzt (NAV * = SQL %) - wie auch über Suche nach "Teil des Feldinhaltes" etc. - so besteht die hohe Wahrscheinlichkeit, dass ein "Scan" ausgeführt wird, inbesondere wenn die "Wildcard" am Beginn des Ausdrucks steht: hier kann soz. kein richtiger Einstiegspunkt (Root Node) in einen Index gefunden werden.

Kann man das irgend wie unterbinden? Dass die Benutzer diese Möglichkeit nicht mehr haben?

Nicht wirklich. Es ist ja ein viel geprisenes "Feature" in NAV, dass jeder auf alles filtern darf ... und die Funktion "Suchen" bietet nun mal die Option "Teil des Feldinhaltes". Hier kann man die Anwender nur schulen und auf "Verständnis" hoffen ...
maod hat geschrieben:
Allerdings erklärt das alles nicht den "Constant Scan" ...

Durch was könnte dann z.B. ein Constant Scan verursacht werden?

Wie gesagt, sowas kommt durch wiedersprüchliche Filterung; z.B. WHERE KundenNr = '1' AND KundenNr = '2' (vorausgesetzt KundenNr ist eindeutig); ein Kunde kann also entweder die Nummer 1 ODER die Nummer 2 haben, beides gleichzeitig ist nicht möglich = Contant Scan.

maod hat geschrieben:
Ein Index mit 'nem boolschen Feld am Anfang ("Gesperrt") wir SQL Server nur im absoluten Notfall benutzen, da das Feld extrem "unselektiev" ist.
SELECT * FROM "Navision"."dbo"."FIRMA$Artikel" WITH (READUNCOMMITTED) WHERE (("Nummer"<'ARTIKELNUMMER')) AND (("Gesperrt"=0))

In diesem Falle kann dafür kein passender Index (ausser dem Clustered) verwendent werden? Denn dieser Seek ist sehr langsam.

Der Clustered Index sollte bei der Artkeltabelle schon bei "Nummer" bleiben, keinesfalls sollte "Gesperrt" teil des CI sein, da ansonsten bei Änderung der Datensatz physikalisch verschoben werden muss.
Gibt's denn einen Non-Clustered Index nur auf "Gesperrt"? Wie ist die Performance damit?
Wenn auch der CI Seek immer noch zu lange dauert (Reads > 1000) dann kann das auch an der Fragmentierung der Tabelle liegen; ggf. mal mit einem REBUILD optimieren ...

maod hat geschrieben:
Was bei allen Abfragen auf die Artikel od. Item Tabelle besonders relevant ist, ist ob tatsächlich Bilder (BLOB!) gespeichert sind - das sollte man tunlichtst unterlassen (gilt auch für Customer, Vendor, etc.)!

Relevant auf die Performance? Aber das ändert nichts daran, dass Navision das Feld selektiert mit DATALENGTH("Bild") oder?

Mit SELECT * werden in NAV immer alle Felder abgefragt, also auch die BLOB. DATALENGTH gibt zusätzlich darüber Auskunft, ob das BLOB Feld auch gefüllt ist. BLOB Felder werden anders als die sonstigen Felder gespeichert, beim SELECT müssen diese Felder dann von anderen Datenseiten geholt werden, somit sind mehr Lese-Zugriffe notwendig.
Am besten sollte man die Bilder - wenn man sie denn verwenden möchte - in eine spararte Tabelle auslagern. Als Erste Hilfe Maßnahme empfehle ich einen REORGANIZE mit LOB-Compaction.

maod hat geschrieben:Was ich halt bei Navision generell schlecht finde: SELECT * FROM ...
Machte mal einen Versuch, wo ich per ADO.DATASET die Daten direkt vom SQL holte, und via Navision.Insert einfügte. Das Ergebnis= Massiv schneller ... Nicht der Insert...sondern der SELECT, weil ich da nur die benötigten spalten holte, und nicht alle (*).
Naja, ist wohl nicht zu ändern.

Tja, ich fürchte auch, dass sich darin in absehbarer nix ändern wird ...

maod hat geschrieben:Des weiteren frage ich mich oft bei den gesehenen Abfragen, warum Navision "option(Fast 5)" verwendet, wenn die Forms, von denen der Select stammt, 25 Rows anzeigen. Dann bringen doch die Fast 5 nicht wirklich etwas ... oder irre ich mich da?

Dass dieser OPTION(FAST x) Hint blödsinnig ist, hat inzwischen MS auch eingesehen: er wurde in NAV 4.0 SP3 Update 6 entfernt! (NAV 5.0 zieht mit SP1 nach)

maod hat geschrieben:Ich glaube ich sollte nicht so viele Fragen stellen ... sorry :roll: ... aber ich interessiere mich gerne für Details um möglichst viel zu verstehen.

Na ja, dazu sind diese Foren ja da. Nur wer Fragen fragt wird schlauer!
Ich hoffe unsere Antworten helfen Dir!

10. März 2008 15:14

Ja, danke vielmals für die Antworten ... sind mir wirklich eine riesen Hilfe. Das "Puzzle" setzt sich langsam zusammen. :)

Soweit, alles verstanden. :idea:

Du hast sicherlich auch Erfahrungswerte bei deaktivieren ("Maintain SQL Index) von Indexen. Wie verhält sich da Navision, wenn z.B. KEIN Index (SQL) für "Belegnummer,Zeilennummer" besteht, jedoch von Navision her eine Form mit dem Key gebaut wird.
Können die Datensätze dann trotzdem in der folgenden "Order" angezeigt werden? (wahrscheinlich mit aufwändigem Umsortieren von SQL). Oder versagt da die Sortierung?
Mich beschleicht ein dummes Gefühl, dass wir viele Indexes haben, welche gar nicht benötigt werden, resp. nicht SQL-Seitig verwendet werden.

In Nav. Key's inaktiv setzen ist ja nicht ganz ohne, da bei Verwendung im Code (bei keinem passenden Schlüssel), ja hässliche Fehlermeldungen generiert werden und den Betrieb sogar in den Boden zwingen kann.
Daher der Ansatz, nicht an Navision zu schrauben, sondern im SQL.

Was würdest du hier empfehlen?

10. März 2008 18:22

Der "Key"-Kontext (SETCURRENTKEY, TableView, etc.) in NAV bestimmt ausschließlich die Sortierung, also die ORDER BY clause (außer man hat irrsinnigerweise "Index Hinting" global aktiviert).
Den richtigen "Index" wählt sich SQL Server am Besten selbst aus. Soll der "SQL Index" abweichend vom "Key" aufgebaut werden (empfohlen!), so ist dies in der entsprechenden Eigenschaft zu definieren.

Will man einen "Key" nicht als "Index" im SQL Server haben, so muss nur "MaintainSQLIndex" auf FALSE gesetzt werden; würde man "Enabled" auf FALSE setzten, so ist der gesammte "Key" in C/SIDE nicht mehr verfügbar.

Nun, das deaktivieren unnötiger Indexe ist sicherlich empfehlenswert, kann aber nur zuverlässig auf Basis von "Index Usage" Statistiken (SQL 2005) geschehen - Indexe auf Basis von Vermutungen zu "killen" wird eher negative Folgen haben.

10. März 2008 21:33

ok, alles klar. Danke dir für die Tips !

Für die Untersuchung der unbenutzten Indexe verwende ich folgendes Skript, da die Verwaltungs-Berichte nur mässig gut sind.
...oder hast du da ein gutes Tool, welches empfehlenswert ist?

[hr]
declare @dbid int
set @dbid = db_id()

select object_name(i.object_id) object_name,
i.name index_name,
i.index_id index_id,
i.type_desc type_desc,
c.index_columns
from sys.indexes i left outer join sys.dm_db_index_usage_stats d
on d.object_id=i.object_id and i.index_id=d.index_id
and d.database_id = @dbid
left outer join
(select distinct object_id, index_id,
stuff((SELECT ','+col_name(object_id,column_id ) as 'data()' FROM sys.index_columns t2 where t1.object_id =t2.object_id and t1.index_id = t2.index_id FOR XML PATH ('')),1,1,'')
as 'index_columns' FROM sys.index_columns t1 ) c on
c.index_id = i.index_id and c.object_id = i.object_id
where objectproperty(i.object_id, 'IsIndexable') = 1
and d.index_id is null and i.type_desc not in ('heap','clustered')
[hr]

11. März 2008 09:04

Ohne das TSQL ausprobiert zu haben sehe ich in dem Skript nicht die "Usage" Zahlen (User Seeks, User Scans, etc.). Diese sind m.E. aber wichtig, um die effektive Nutzung der Indexe auszuwerten, z.B. um zu filtern: "User Seeks" = 0 AND "User Scans = 0" AND "USer Lookups" = 0 AND "User Updates" > 10000
Somit kann man einen Vorschlag erarbeiten, welche Indexe deaktiviert werden können.
Wichtig beim Umgang mit der Statistik ist es zu wissen, dass diese beim Neustart des SQL Server Dienstes zurückgesetzt werden! Um also zuverlässige "Usage" Daten zu erhalten, sollte über einen längeren Zeitraum beobachtet werden.

Ich verwende in meinen Workshops die "NAV/SQL Performance Toolbox" 8-)
Hier werden die Usage-Statistiken periodisch zur "Langzeit-Analyse" gespeichert, mittels "Index Compare Tool" können dann u.a. Vorschläge zur Index-Löschung erarbeitet werden, was dann auch direkt in NAV umgesetzt werden kann.

19. März 2008 08:05

Vielen dank soweit.
So weit so klar.

Habe mich noch mit der Thematik SIFT und Buckets befasst.
Bei uns ist das Problem konkret so, dass während Stosszeiten alle auf die Verkaufszeile und Lagerposten "schiessen" und somit das System extrem lahm wird. Der Server aber ist nicht wirklich ausgelastet. Nach Analyse scheint es so, als würden die erw. Tabellen resp. die Flowfields erhebliche Locks verursachen, denn die Reads sind <20 aber die Duration >10000 ... das deutet doch auf Sperren der Tables hin. Somit bildet sich eine LockChain. Nun, auf diesen Tabellen sind einige SumIndexFields. Ich habe die Posts diesbezüglich gelesen und frage mich, was bei der Umsetzung der SIFT überlegt wurde? Denn Abfragetechnisch sind diese ja optimal, jedoch bei Schreibaktionen drückt es alles in die Knie? Ist das Einzige Mittel zum Zweck, die deaktivierung der Buckets, bei Tabellen mit Performance-Problmen, resp. Hauptsächlichen Insert/Update's? Wir haben noch Nav. 4 SP3. In V5 soll dies ja per Views verbessert worden sein. Lohnt sich da allenfalls ein Update?

19. März 2008 11:40

Was die SIFT optimierung angeht, so möchte ich auch auf mein BLOG verweisen, wo ich beschrieben habe, welche Optimierungen möglich sind:

http://dynamicsuser.net/blogs/stryk/archive/2007/10/28/included-columns-vs-sift-tables.aspx

Und ja, ein Update auf U6 oder höher ist schon empfehlenswert, da hier einige erhebliche Verbesserungen - auch SIFT - implementiert wurden!
(Achtung: Globales "Index Hinting" deaktivieren!)

http://dynamicsuser.net/blogs/waldo/archive/2008/01/17/platform-updates-overview-3-70-b-5-0-update-1-1.aspx

19. März 2008 17:18

Selbstverständlich habe ich deinen Blog gelesen, bevor dieser Post entstand :-)

Ich verstehe dann nur nicht ganz, warum man die SIFT's nicht gleich vollständig deaktiviert und die entsprechenden Felder auf der "Haupttabelle" indiziert.

Was für eine Berechtigung haben dann überhaupt noch SIFT - Tabellen (SQL) ? Wenn diese nur die Schreibperformance in den Keller drücken. Denn alle SUM's kann man ja via Hilfe von den Indizen optimieren.

Die "Komprimierung" der Daten finde ich im Grundsatz eine gute Idee, um so schnellere Abfragen zu generieren, jedoch verursachen Locks weit grössere Probleme, als mässig performante Select Querys.

Übersehe ich da was?
In der Native-Version sehe ich das nat. ein ... aber mit dem SQL ist das ja nur hinderlich ... oder?

20. März 2008 10:34

maod hat geschrieben:Ich verstehe dann nur nicht ganz, warum man die SIFT's nicht gleich vollständig deaktiviert und die entsprechenden Felder auf der "Haupttabelle" indiziert.

Nun ja, dies würde bedeuten "Decimal" Felder zu indizieren, die Indexe würden dann u.U. zu groß werden und die Lese-Performance erheblich vermindern.
Ein Feature in SQL 2005 sind dafür die "Included Columns", hier müssen die zu summierenden Felder nicht indiziert werden (= kleiner Index), die Dezimal-Felder können aber den "Leaf Nodes" der Indexe hinzugefügt werden, um hier die Summen zu ziehen - ohne "Bookmark Lookup" auf den Clustered Index. Leider ein reines SQL Feature, das man von NAV aus nicht nutzen kann.

maod hat geschrieben:Was für eine Berechtigung haben dann überhaupt noch SIFT - Tabellen (SQL) ? Wenn diese nur die Schreibperformance in den Keller drücken. Denn alle SUM's kann man ja via Hilfe von den Indizen optimieren.

Ab einem bestimmten Schwellenwert mach eine solche Aggregation schon Sinn. Auch wenn die Posten-Tabelle gut indiziert ist, und selbst wenn Indexe mit INCLUDES verwendet werden, so wird irgendwann das Lesen von hunderttausenden von DS zum Problem - das Lesen weniger "Summen-DS" aus den SIFT Tabellen ist dann schneller! (siehe auch diesen Thread: http://www.msdynamics.de/viewtopic.php?t=4933&highlight=)

maod hat geschrieben:Die "Komprimierung" der Daten finde ich im Grundsatz eine gute Idee, um so schnellere Abfragen zu generieren, jedoch verursachen Locks weit grössere Probleme, als mässig performante Select Querys.

Deshalb ist eine Optimierung der SIFT Buckets unbedingt erforderlich! Wie gesagt, beim Tuning geht es immer um die Balance zwischen Lese- und Schreibperformance ... hat ein bisschen was von der Wahl zwischen Pest und Cholera :twisted:

20. März 2008 11:10

Hmm... *grübel* ... ich sehe schon ... Learning by doing :) ... so wie immer ... aber ich sehe den Punkt.

Würdest denn du, nach deaktivieren aller buckets bis auf den 2.Letzten, den Clustered Index durch einen NONCLUSTERED Cov.Index ersetzen?

20. März 2008 14:16

Am "Clustered Index" von SIFT Tabellen sollte man - zunächst - mal lieber nix ändern, da man ansonsten die merkwürdigsten Fehlermeldung in NAV erhalten kann, wenn man in C/SIDE an diesen SIFT Indexen 'was ändert ...

Nach Optimierung ist der CI zwar sub-optimal (erstes Feld ist "bucket" mit einer Dichte von 100% - also schlechtest mögliche Selektivität - weil ja nur noch ein "Bucket" erzeugt wird), ich rate aber dazu, den so zu belassen.

Der "Covering Index" wird benötigt um das "hoch-Summieren" zu beschleunigen; hat man z.B. nur noch einen Bucket der auf "Day" Ebene verdichtet, so müssen meherer "Day"-Buckets summiert werden um auf "Month" zu kommen. Hat man viele "Day" Sätze, dann kann dieses Summieren zu lange dauern, der Cov.Idx beschleunigt das.
Ich empfehle einen zusätzlichen CovIdx (Non-Clustered) auf die großen SIFT Tabellen zu legen, d.h. die, die nach Optimierung (und Bereinigung) mehr als 50.000 DS beinhalten ...

Und: einen solchen CovIdx sollte man NIE zum Clustered Index machen! Da dieser Idx ja die Summenfelder beinhaltet, würde jede Änderung dieser Summen (und dafür sind sie ja da) zu einer physikalischen Verschiebung des DS führen und die Performance damit in den Keller fahren ...

20. März 2008 14:54

Alles klar! Merci. Ich versuche das mal :)

D.H. 1 Bucket, + 1 CI, + 1 Cov.Idx mit INCLUDE der Sum-Fields?
(Bucket,f1,f2,f3, fx .... INCLUEDE(s1,s2,sx)) um das Bookmarking zu verhindern.

21. März 2008 12:11

maod hat geschrieben:D.H. 1 Bucket, + 1 CI, + 1 Cov.Idx mit INCLUDE der Sum-Fields?
(Bucket,f1,f2,f3, fx .... INCLUDE(s1,s2,sx)) um das Bookmarking zu verhindern.


Fast! Bei SIFT Tabellen macht ein Index mit INCLUDES keinen Sinn, da dieser ja dem CI entsprechen würde.
Das mit den INCLUDES kann dazu dienen, eine "SIFT Tabelle" vollständig zu ersetzen: hier wird der Index direkt auf die Postentabelle gesetzt, z.B. T32:

Code:
CREATE INDEX ssi01 on "...$Item Ledger Entry"
("Item No_","Entry Type","Variant Code","Drop Shipment","Location Code","Posting Date")
INCLUDE ("Quantity","Invoiced Quantity")


So etwas könnte hier den ersten SIFT Index in T32 ersetzten. Funktioniert aber nur bis zu einem gewissen Grad, sobald die Tabelle eine entsprechend hohe Anzahl an DS hat, ist SIFT Aggregation notwendig.

(Überlegenswert ist so ein INCLUDE bei "Durchlauferhitzern" wie "Sales Line" etc.. Hier verbraucht das SIFT-Schreiben u.U. viel Zeit; ein Index mit INCLUDES kann schneller aktualisiert werden, und unterstützt auch das Summieren über die Tabelle (FlowFields, CALCSUMS) :idea: )

Für große SIFT Tabellen würde ein "Covering Index" dann so aussehen:

Code:
CREATE INDEX ssi_CovIdx ON "..."$32$0"
([bucket], [f2], [f4], [f5402], [f47], [f8], [f3], [s12], [s14])

23. März 2008 12:13

Ok. Ich sehe den Punkt.

Der einzige Nachteil an der Geschichte bei Bildung der Cov.Idx. in "FlowField"-Tabellen ist die Grösse die durch die Dezimalwerte entstehen. Daher dachte ich, das INCLUDE eine bessere Lösung wäre. Aber hast recht, dann kann genau so gut der CI verwendet werden.

Probleme bei der Bildung von SUM's sollten da nicht entstehen?
Habe bei Feldversuchen festgestellt, dass Navision klug genug ist, zu sehen, ob FlowTables exisiteren, die richtigen Buckets vorhanden sind oder nicht.

Eine Konstelation, in welcher ein CALCSUMS, CALCFIELDS nicht mehr funktionieren würde gibt es nicht oder?
Das ist ein bisschen meine Angst, dass da bei errechneten Feldern etwas in die "Hose" gehen könnte.

24. März 2008 16:54

maod hat geschrieben:Eine Konstelation, in welcher ein CALCSUMS, CALCFIELDS nicht mehr funktionieren würde gibt es nicht oder?
Das ist ein bisschen meine Angst, dass da bei errechneten Feldern etwas in die "Hose" gehen könnte.

Eine solche Konstellation kenne ich nicht, und ich kann mir auch nicht vorstellen, daß es zu einem solchen Problem kommen kann ...

Die SIFT Buckets wurden ja innerhalb C/SIDE definiert, daher sollte C/SIDE auch wissen, wann es Abfragen auf die SIFT Tabellen macht, oder direkt auf die Posten.
Ob und welche zusätzlichen Indexe existieren, braucht C/SIDE nicht zu interssieren, da diese lediglich den SQL Server bei der Bearbeitung der Abfrage unterstützen - die Abfrage selbst wir dabei ja nicht geändert ...

Rein theoretisch könnte man sich derartige Probleme erzeugen, wenn man manuell in den "SQL Triggern" der Postentabellen "herumfummelt" ... was ein absolutes "No Go" sein sollte ...

31. März 2008 11:37

Hallo Jörg

das hat prima funktioniert .. und sind bisher auch weniger Locks zu verzeichnen.

Kannst du mir ev. noch etwas erläutern?

Was hat es mit dem im Profiler ersichtlichen:
FETCH API_CURSOR0000000000002C2C

auf sich?

Bei einem Repeat ... until ? Oder was geht da genau?

31. März 2008 12:52

Hier handelt es sich hier soz. um das "Nachfassen" von Daten aus einem "Cursor" ... eben eine "Cursor Fetch" Operation, siehe auch http://msdn2.microsoft.com/en-us/library/ms180152.aspx oder "Books Online".