Ich habe ein interessantes für alle SQL-Guru da draußen. Jetzt dauert diese Suche nur ein paar Sekunden, ist aber ziemlich intensiv und es muss einen besseren Weg geben. Vielleicht erwarte ich zu viel?
Einfache Urlaubssuch-App. 2 Millionen Ferien. Paging / Sortieren von ca. 600.000 Zeilen.
Dies ist das Schema der Tabelle
CREATE TABLE [dbo].[Holiday](
[Id] [int] NOT NULL,
[PropertyId] [int] NOT NULL,
[Price] [int] NOT NULL,
[Rating] [int] NOT NULL,
[Country] [char](2) NOT NULL,
[ResortId] [int] NOT NULL,
[DepartureAirport] [char](3) NOT NULL,
[DestinationAirport] [char](3) NOT NULL,
[DepartureDate] [datetime] NOT NULL,
[Basis] [char](2) NOT NULL,
[Duration] [int] NOT NULL,
CONSTRAINT [PK_Holiday] PRIMARY KEY CLUSTERED ([Id] ASC)
)
Wie Sie sehen können, ganz einfach. Wir haben eine Immobilie, einen Preis, eine Dauer, Abflug- / Zielflughäfen usw. Je mehr Felder zur Verfügung gestellt werden, desto schneller ist die Suche. Wenn ich einen Abflughafen, eine Immobilie und ein Datum habe, ist die Suche sehr schnell. Wenn ich jedoch nur ein Land und nichts anderes habe, müssen viele Daten verarbeitet werden.
Mit diesem CSV-Export meiner Tabelle gibt es insgesamt 2 Millionen Zeilen und ungefähr 666.000, nur mit dem Ländercode FR, was mein Beispiel ist.
Dies ist die Suchabfrage. Welches gibt zwei Tabellen zurück. Die erste ist eine Zusammenfassung, also die Gesamtzahl der Feiertage, die Ihren Kriterien entsprechen, und wie viele einzigartige Eigenschaften. Die zweite Tabelle enthält die tatsächlichen Ergebnisse der Suche.
--Build a temp table, and store everything we need in it
CREATE TABLE #Pricing (PropertyId int, Duration int, HolidayId int, Rating int, Price int, StartDate datetime, PropertyRow int);
INSERT INTO #Pricing
SELECT
PropertyId, Duration, [Id], [Rating], [Price], DepartureDate,
ROW_NUMBER() OVER (PARTITION BY PropertyId ORDER BY Price ASC) as PropertyRow
FROM
dbo.Holiday
WHERE
DepartureDate > GETDATE() AND Country = 'FR'
--Get a total number of holidays, and total number of properties
SELECT
COUNT(*) AS TotalHolidaysCount,
COUNT(DISTINCT PropertyId) AS PropertyCount
FROM
#Pricing
--Build the final table, which will contain all the holidays we actually want to return
DECLARE @FinalResults TABLE (HolidayId int, RowNumber int);
INSERT INTO
@FinalResults
SELECT
HolidayId, RowNumber
FROM
(SELECT
PropertyRow, HolidayId,
ROW_NUMBER() OVER (order by (CASE WHEN StartDate <= '01/Apr/2013' THEN 1 ELSE 0 END) ASC, [Price] ASC) as RowNumber
FROM
#Pricing
WHERE
PropertyRow = 1) as SearchResults
WHERE
(RowNumber > (10 * (1 - 1)) and RowNumber <= (1 * 10))
ORDER BY
RowNumber;
SELECT
*
FROM
@FinalResults
INNER JOIN dbo.Holiday ON HolidayId = Holiday.Id
DROP TABLE #Pricing
Jetzt könnte ich mich mit der Indizierung befassen, die offensichtlich die Leistung verbessern würde. Was mich jedoch beunruhigt, ist die unglaubliche Verwendung von temporären Tischen. Sicherlich sollte das nicht so sein, wie es gemacht wird? Das Durchsuchen der letztendlich winzigen Datenmenge dauert 5 Sekunden. Sie werden nur deshalb verwendet, weil später auf die Daten verwiesen werden muss.
Wäre es vielleicht sinnvoll, die Abfrage zweimal auszuführen, anstatt alle Daten im Speicher zu speichern? Es scheint eine Verschwendung zu sein, immer wieder über 25% der Tabelle im Speicher auszuwählen.
Jedes hilfreiche Feedback wäre dankbar. Ich suche nicht nach der 'Antwort', sondern nur nach Hilfe.
Vielen Dank, Dean
(RowNumber > (10 * (1 - 1)) and RowNumber <= (1 * 10))
viel besser geschrieben alsRowNumber Between 1 and 10