Ich bin noch neu in der Datenbankverwaltung und versuche, eine Suchabfrage zu optimieren.
Ich hatte eine Abfrage, die so aussah und in einigen Fällen 5 bis 15 Sekunden für die Ausführung benötigte. Außerdem verursachte sie eine 100% ige CPU-Auslastung:
DECLARE @point geography;
SET @point = geography::STPointFromText('POINT(3.3109015 6.648294)', 4326);
SELECT TOP (1)
[Result].[PointId] AS [PointId],
[Result].[PointName] AS [PointName],
[Result].[LegendTypeId] AS [LegendTypeId],
[Result].[GeoPoint] AS [GeoPoint]
FROM (
SELECT
[Extent1].[GeoPoint].STDistance(@point) AS distance,
[Extent1].[PointId] AS [PointId],
[Extent1].[PointName] AS [PointName],
[Extent1].[LegendTypeId] AS [LegendTypeId],
[Extent1].[GeoPoint] AS [GeoPoint]
FROM [dbo].[GeographyPoint] AS [Extent1]
WHERE 18 = [Extent1].[LegendTypeId]
) AS [Result]
ORDER By [Result].distance ASC
Diese Tabelle enthält einen Clustered-Index für die PK und einen räumlichen Index für die geography
Typspalte.
Als ich die obige Abfrage ausführte, führte sie einen Scanvorgang durch.
Also habe ich einen nicht gruppierten Index für die LegendTypeId
Spalte erstellt:
CREATE NONCLUSTERED INDEX [GeographyPoint_LegendType_NonClustered] ON [dbo].[GeographyPoint]
(
[LegendTypeId] ASC
)
INCLUDE ( [PointId],
[PointName],
[GeoPoint])
WITH (PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
DROP_EXISTING = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
und änderte die Abfrage in:
DECLARE @point geography;
SET @point = geography::STPointFromText('POINT({0} {1})', 4326);
SELECT TOP (1)
[GeoPoint].STDistance(@point) AS distance,
[PointId],
[PointName],
[LegendTypeId],
[GeoPoint]
FROM [GeographyPoint]
WHERE 18 = [LegendTypeId]
ORDER By distance ASC
Und jetzt führt SQL Server eine Suche anstelle des Scans durch:
Dies hat meiner Ansicht nach die Effizienz der Abfrage erhöht, aber wenn ich diese für die Produktion bereitstelle, erhalte ich immer noch die gleichen Ergebnisse (hohe CPU-Auslastung und durchschnittlich 10 Sekunden für die Ausführung der Abfrage).
Hinweis: In diese Tabelle werden keine Daten eingefügt, aktualisiert oder entfernt - nur Suchen / Lesen.
Ist es etwas, was ich falsch mache?
Wie kann ich das beheben?
BEARBEITEN
Index Seak Details
EDIT 2:
Ich habe die Abfrage geändert, um die Methode "Nächster Nachbar" vom Link: https://msdn.microsoft.com/en-us/library/ff929109.aspx zu verwenden . Dies ist nun das Ergebnis. Diese Abfrage benötigt ebenfalls 3 -5 Sekunden für die Suche - ähnlich wie bei der zweiten Abfrage (jedoch nicht in der Produktion getestet)
Raumindexeinstellungen:
CREATE SPATIAL INDEX [SPATIAL_Point] ON [dbo].[GeographyPoint]
(
[GeoPoint]
)USING GEOGRAPHY_GRID
WITH (GRIDS =(LEVEL_1 = MEDIUM,LEVEL_2 = MEDIUM,LEVEL_3 = MEDIUM,LEVEL_4 = MEDIUM),
CELLS_PER_OBJECT = 16, PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE =
OFF, SORT_IN_TEMPDB = OFF,
DROP_EXISTING = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
BEARBEITEN 3
Ich habe die Anweisungen von @MickyT befolgt, den Index gelöscht [LegendTypeId]
und die folgende Abfrage ausgeführt:
DECLARE @point geography;
SET @point = geography::STPointFromText('POINT(3.3109 6.6482)', 4326);
SELECT TOP (1)
[PointId],
[PointName],
[LegendTypeId],
[GeoPoint]
FROM [GeographyPoint] WITH(INDEX(SPATIAL_Point))
WHERE
[GeoPoint].STDistance(@point) IS NOT NULL AND
18 = [LegendTypeId]
ORDER By [GeoPoint].STDistance(@point) ASC
OPTION(MAXDOP 1)
Statistiken für diese Abfrage sind
Und dann habe ich diese Abfrage erneut ausgeführt:
DECLARE @point geography;
SET @point = geography::STPointFromText('POINT(3.3109 6.6482)', 4326);
SELECT TOP (1)
[GeoPoint].STDistance(@point) AS distance,
[PointId],
[PointName],
[LegendTypeId],
[GeoPoint]
FROM [GeographyPoint] --WITH(INDEX(SPATIAL_Point))
WHERE 18 = [LegendTypeId]
ORDER By distance ASC
Statistiken für diese Abfrage sind
quelle
ORDER BY Distance
Klausel sortiert werden muss .Antworten:
Ich habe das folgende Setup verwendet, um einige Tests durchzuführen.
Dies ergibt eine Tabelle mit 1.000.000 zufälligen Punkten mit einer Streuung von 2 x 2 Grad.
Nachdem ich einige verschiedene Optionen ausprobiert hatte, war die beste Leistung, die ich erzielen konnte, die Verwendung des räumlichen Index zu erzwingen. Es gab verschiedene Möglichkeiten, dies zu erreichen. Löschen des Index auf LegendTypeID oder Verwenden eines Hinweises.
Sie müssen entscheiden, welches für Ihre Situation am besten geeignet ist. Persönlich verwende ich keine Indexhinweise und würde den anderen Index löschen, wenn er für andere Abfragen nicht benötigt wird.
Die Abfragen stapelten sich gegeneinander
quelle