Подтвердить что ты не робот

Как повысить производительность фильтрации datetime в SQL Server?

У меня проблема с фильтрацией столбцами datetime.

Я пробовал эти два метода:

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

У меня есть большая база данных с более чем 3000 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?

Спасибо заранее.

4b9b3361

Ответ 1

Простое предложение, когда дело доходит до индексов в datetime в msql, - это индексный след, влияющий на время поиска (да, это кажется очевидным... но, пожалуйста, прочитайте дальше).

Значения для этого при индексировании в datetime говорят, например, "2015-06-05 22: 47: 20.102", индекс должен учитывать каждое место в datetime. Это становится очень большим пространственно и громоздким. Успешный подход, который я использовал, - создать новый столбец datetime и заполнить данные, округляя время до часа, а затем создав индекс в этом новом столбце. Пример "2015-06-05 22: 47: 20.102" переводится в "2015-06-05 22: 00: 00.000". Используя этот подход, мы оставляем только подробные данные и можем отображать его или использовать его путем поиска в этом новом столбце, который дает нам приблизительно 10-кратное (как минимум) возвращение о том, как быстро возвращаются результаты. Это связано с тем, что индекс не должен учитывать минуты, секунды и миллисекунды.

Ответ 2

Сначала вам нужно посмотреть на план выполнения, чтобы посмотреть, что делает SQL Server. Скорее всего, вам просто нужно добавить индекс. Маленькие конверсии, подобные этому, почти никогда не являются причиной того, что ваш запрос медленный. Индексы являются хорошей первой остановкой для исправления запросов.

Вам не нужно делать этот кластеризованный индекс. Создание кластеризованного индекса означает, что вам не нужно выполнять поиск, но всего за 100 строк поиск выполняется очень быстро. Я бы поставил datetime и подкатегорию в некластеризованный индекс в этом порядке.

Если вы заказываете, вы также должны убедиться, что в индексе. Поскольку имеет смысл использовать только один индекс для таблицы, вам нужно убедиться, что все соответствующие столбцы находятся в одном и том же индексе в правильном порядке.

Но сначала получите реальный план выполнения!

Ответ 3

Для повышения производительности я предлагаю вам создавать новые индексы:

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 и повысить общую производительность запроса.

Ответ 4

Попробуйте этот вариант -

;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
     )

Ответ 5

Создайте индекс кластера в поле datetime, это определенно поможет. раньше мы столкнулись с такой же проблемой. мы решили это, создав индекс в столбце datetime.