49

我在按datetime列过滤时遇到问题。

我尝试了这两种方法:

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

我有一个包含超过 3.000.000 个主要对象的大型数据库。

所以我需要提高我的datetime过滤性能。我正在阅读有关 UNIX 时间戳的信息(全部转换datetime为 UNIX 时间戳,然后按此 UNIX 字段过滤)。

我认为这是比过滤更好的方法datetime。但如果有人知道其他方式,我将不胜感激。

我的查询是:

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

按我评论的时间过滤。

如果我关闭这些过滤器,请求持续时间是几秒钟。如果我打开它们,那么请求持续时间超过 25 秒。

所以有很多关于执行计划、索引等的讨论。但是UNIX timestamp呢,这是我提出这个问题的主要原因。它会提高datetime过滤性能吗?

提前致谢。

4

5 回答 5

47

关于 msql 中 datetime 索引的一个建议是索引占用空间会影响搜索时间(是的,这似乎很明显......但请继续阅读)。

对日期时间进行索引时对此的重要性例如“2015-06-05 22:47:20.102”,索引必须考虑日期时间中的每个位置。这在空间上变得非常大并且笨重。我利用的一种成功方法是创建一个新的日期时间列,并通过将时间四舍五入到小时来填充数据,然后在这个新列上构建索引。示例“2015-06-05 22:47:20.102”转换为“2015-06-05 22:00:00.000”。通过采用这种方法,我们可以单独保留详细数据,并可以通过在这个新列上搜索来显示或使用它,这为我们提供了大约 10 倍(至少)返回结果的速度。这是因为索引不必考虑分钟、秒和毫秒字段。

于 2015-06-06T03:55:34.617 回答
5

您需要先查看您的执行计划,以了解 SQL Server 正在做什么。很可能,您只需要添加一个索引。像这样的小转换几乎从来都不是您的查询缓慢的原因。索引是修复查询的良好第一站。

您不需要将其设为聚集索引。使其成为聚集索引意味着您不需要进行查找,但对于仅 100 行,查找速度非常快。我会按顺序将日期时间和子类别放入非聚集索引中。

如果您正在订购,您还应该确保它在索引中。由于每个表只使用一个索引才有意义,因此您需要确保所有相关列都在同一个索引中,并且顺序正确。

但首先,得到你的实际执行计划!

于 2013-06-29T16:43:38.533 回答
2

为了获得更好的性能,我建议您创建新索引:

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
          )

这将帮助您避免 RID 查找操作并提高查询的整体性能。

于 2013-06-30T21:26:35.207 回答
0

试试这个——

;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
     )
于 2013-07-01T05:29:27.747 回答
-8

在日期时间字段上创建集群索引肯定会有所帮助。我们之前遇到了同样的问题。我们通过在 datetime 列上创建索引来解决它。

于 2013-06-29T15:59:14.303 回答