如何提高SQL Server中日期时间过滤的性能?

Ole*_*syk 32 sql sql-server

我有按datetime列过滤的问题.

我尝试了这两种方法:

datefield < '2013-03-15 17:17:55.179'
datefield < CAST('2013-03-15 17:17:55.179' AS datetime)
Run Code Online (Sandbox Code Playgroud)

我有一个超过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
Run Code Online (Sandbox Code Playgroud)

过滤我评论的时间.

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

因此,有很多关于执行计划,索引等的讨论.但是UNIX时间戳呢,这就是我把问题放在那里的主要原因.它会提高datetime过滤性能吗?

提前致谢.

小智 36

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

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

  • 在任何数据类型上,BTREE索引都具有空间复杂度O(大小*log(大小)),其中size是被索引的数据量.更高精度值导致索引大小膨胀的想法是不正确的. (6认同)
  • @OleksandrFentsyk。。。我谨建议您不接受这个答案。OP 似乎不了解索引是如何工作的,并且正在传播误导性信息。 (5认同)
  • @Sean 有什么证据吗?为什么木指数关心里面的时间价值?它只关心 =、&lt;、&gt;。 (4认同)
  • 您的回答让我调查一下,我可以通过使用[datetimeoffset](0)将datetimeoffset精度降低到秒(删除毫秒)来提高性能.http://stackoverflow.com/a/2247898/507699 (3认同)
  • 我认为在几乎所有情况下索引包括时间在内的日期都是一个坏主意。它本质上是说,在涉及该字段的任何搜索条件中,您永远不会得到完全匹配的结果。我建议有两个字段,一个用于日期,一个用于时间并在它们上建立索引。然后您的日期搜索将始终找到完全匹配,让您更快地找到相关数据。然后您可以过滤该数据集中的时间。 (2认同)
  • 更改索引键的粒度不会更改索引中的行数,这主要决定了索引大小。仅当您额外应用页面压缩时,索引大小本身才会显着减少,即使如此,这种大小的减少也只会在索引扫描时明显,而不是搜索。作为一个思考练习,想象一个只存储年份的索引(因此将所有行“四舍五入”为“2015”,但仍然必须索引所有行),看看为什么这没有真正的帮助。如果一个全新的索引“有帮助”,那很可能只是因为旧的索引是支离破碎的。 (2认同)

Joh*_*eng 5

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

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

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

但首先,获取您的实际执行计划!


Hir*_*duk -9

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

  • 严重地?@SashaFencyk,不要让这里的人直接访问您的数据*或*您的服务器。 (23认同)