it-swarm.com.de

So verbessern Sie die Leistung für die Datetime-Filterung in SQL Server

Ich habe ein Problem mit dem Filtern nach datetime Spalten. 

Ich habe diese zwei Methoden ausprobiert:

datefield < '2013-03-15 17:17:55.179'
datefield < CAST('2013-03-15 17:17:55.179' AS datetime)

Ich habe eine große Datenbank mit über 3.000.000 Hauptobjekten.

Daher muss ich die Leistung für meine datetime-Filterung verbessern. Ich habe über UNIX-Zeitstempel gelesen (alle datetime in UNIX-Zeitstempel konvertieren und dann nach diesem UNIX-Feld filtern).

Ich denke, es ist ein besserer Weg als nach datetime zu filtern. Aber wenn jemand einen anderen Weg kennt, würde ich es schätzen.

Meine Frage ist:

SELECT TOP (100)  ev.Title as Event_name, po.Name as POI_name, 
po.Address, po.City, po.Region, po.Country, po.Latitude, po.Longitude, ev.Start_time, 
(Select ID_Category FROM SubCategory s where ev.ID_SubCategory = s.ID_SubCategory) as ID_Category, 
ev.ID_SubCategory, ev.ID_Event, ev.ID_Channel, IDChanelEvent, 
ev.FavoriteCount, po.gmtOffset, v.IsFavorite, v1.IsFavorite  
FROM Events ev 
JOIN POI po ON ev.ID_POI = po.ID_POI 
JOIN (SELECT et.id_event as joinIdEv FROM EventTagLink et, tags t 
 WHERE t.id_tag = et.id_tag 
 AND ( t.Title = N'music' ) 
 ) as joinEvents 
 ON joinEvents.joinIdEv = ev.ID_Event 
LEFT JOIN Viewed v ON v.ID_Event = ev.ID_Event AND v.ID_User = 1 AND v.IsFavorite = 1 LEFT join Viewed v1 ON v1.ID_Event = ev.ID_Event AND v1.ID_User = 1 AND v1.IsFavorite = 0
WHERE 
--ev.GmtStop_time > '2013-03-15 14:17:55.188' AND 
po.Latitude > 41.31423 AND po.Latitude < 61.60511 
AND  po.Longitude > -6.676602 AND po.Longitude < 17.04498  
AND ev.ID_SubCategory in (3, 12, 21, 4, 30, 13, 22, 6, 14, 40, 23, 7, 32, 15, 41, 8, 50, 33, 16, 42, 25, 9, 34, 17, 35, 18, 44, 27, 36, 19, 45, 28, 37, 46, 29, 38, 47, 39, 48, 49, 10, 1, 11, 2, 20) 
--AND ev.GmtStart_time< '2013-03-15 17:17:55.179'
AND v1.IsFavorite is null

filtern nach der Zeit, die ich kommentiert habe.

Wenn ich diese Filter ausschalte, beträgt die Anforderungsdauer einige Sekunden. Wenn ich sie einschalte, dauert die Anforderungsdauer mehr als 25 Sekunden.

Es gibt also viele Diskussionen über Ausführungspläne, Indizes usw. Aber was ist mit UNIX-Zeitstempel? Dies ist der Hauptgrund, warum ich die Frage dort gestellt habe. Würde es die Leistung für datetime-Filterung verbessern? 

Danke im Voraus.

28
Sasha Fentsyk

Nur ein Hinweis, wenn es um Indizes zu datetime in msql geht, ist der Index-Footprint beeinflusst die Suchzeiten (Ja, das scheint offensichtlich ... lesen Sie bitte weiter). 

Die Bedeutung, die dies bei der Indizierung auf die datetime hat, lautet zum Beispiel '2015-06-05 22: 47: 20.102', die der Index für jeden Ort innerhalb der datetime berücksichtigen muss. Dies wird räumlich sehr groß und voluminös. Ein erfolgreicher Ansatz, den ich genutzt habe, ist das Erstellen einer neuen datetime-Spalte und das Auffüllen der Daten, indem die Zeit auf die Stunde gerundet wird und dann der Index auf dieser neuen Spalte erstellt wird. Beispiel '2015-06-05 22: 47: 20.102' wird in '2015-06-05 22: 00: 00.000' übersetzt. Auf diese Weise lassen wir die detaillierten Daten in Ruhe und können sie anzeigen oder durch Suchen in dieser neuen Spalte verwenden, was uns eine (mindestens) 10-fache Rendite auf die schnelle Rückgabe von Ergebnissen liefert. Dies liegt daran, dass der Index die Felder Minuten, Sekunden und Millisekunden nicht berücksichtigen muss.

27
Sean Ford

Sie müssen zuerst Ihren Ausführungsplan ansehen, um zu sehen, was SQL Server gerade tut. Mehr als wahrscheinlich, Sie müssen lediglich einen Index hinzufügen. Kleine Konvertierungen wie diese sind fast nie der Grund, warum Ihre Abfrage langsam ist. Indizes sind eine gute erste Anlaufstelle für das Beheben von Fragen.

Sie müssen diesen Clusterindex nicht erstellen. Wenn Sie den Clustered-Index erstellen, müssen Sie keine Suche durchführen. Bei nur 100 Zeilen ist die Suche jedoch sehr schnell. Ich würde datetime und subcategory in dieser Reihenfolge in einen nicht gruppierten Index einordnen.

Wenn Sie bestellen, sollten Sie auch sicherstellen, dass sich dieser in einem Index befindet. Da es nur sinnvoll ist, einen Index pro Tabelle zu verwenden, müssen Sie sicherstellen, dass sich alle relevanten Spalten in der richtigen Reihenfolge im selben Index befinden.

Holen Sie sich zunächst Ihren tatsächlichen Ausführungsplan!

3
John Tseng

Zur Verbesserung der Leistung empfehle ich Ihnen, neue Indizes zu erstellen:

CREATE INDEX x1 ON LiveCity.dbo.Tags(Title) INCLUDE(ID_Tag)
CREATE INDEX x2 ON LiveCity.dbo.Tags(ID_Event, GmtStart_time, GmtStop_time) 
  INCLUDE(
          FavoriteCount, 
          ID_Channel, 
          ID_POI, 
          ID_SubCategory, 
          IDChanelEvent, 
          Start_time, 
          Title
          )
CREATE INDEX x ON LiveCity.dbo.POI(ID_POI, Latitude, Longitude) 
  INCLUDE(
          Address, 
          City, 
          Country, 
          gmtOffset, 
          Name, 
          Region
          )

Auf diese Weise können Sie RID-Suchvorgänge vermeiden und die Gesamtleistung der Abfrage verbessern.

2

Probier diese -

;WITH cte AS (
     SELECT IsFavorite, ID_Event  
     FROM Viewed
     WHERE ID_User = 1 
)
SELECT TOP (100)
      Event_name = ev.Title 
    , POI_name = po.Name 
    , po.[address]
    , po.City
    , po.Region
    , po.Country
    , po.Latitude
    , po.Longitude
    , ev.start_time
    , s.ID_Category
    , ev.ID_SubCategory
    , ev.ID_Event
    , ev.ID_Channel
    , IDChanelEvent
    , ev.FavoriteCount
    , po.gmtOffset
    , v.IsFavorite
    , IsFavorite = NULL
FROM [events] ev
JOIN POI po ON ev.ID_POI = po.ID_POI
LEFT JOIN SubCategory s ON ev.ID_SubCategory = s.ID_SubCategory
LEFT JOIN cte v ON v.ID_Event = ev.ID_Event AND v.IsFavorite = 1
WHERE po.Latitude BETWEEN 41.31423 AND 61.60511
     AND po.Longitude BETWEEN -6.676602 AND 17.04498
     AND ev.ID_SubCategory IN (3, 12, 21, 4, 30, 13, 22, 6, 14, 40, 23, 7, 32, 15, 41, 8, 50, 33, 16, 42, 25, 9, 34, 17, 35, 18, 44, 27, 36, 19, 45, 28, 37, 46, 29, 38, 47, 39, 48, 49, 10, 1, 11, 2, 20)
     AND v1.IsFavorite IS NULL
     AND EXISTS(
          SELECT 1 
          FROM EventTagLink et
          WHERE t.Title = 'music'
               AND et.joinIdEv = ev.ID_Event
     )
     AND NOT EXISTS (
          SELECT * 
          FROM cte v1 
          WHERE v1.ID_Event = ev.ID_Event AND v1.IsFavorite = 0
     )
0
Devart