2013-07-17 4 views
0

У меня есть таблица, которая имеет столбцыпроизводительности SQL запросов сервер выдает

  • неуникальным ID
  • н-столбцы различных данных

была обновлена ​​дата, когда данные

У меня есть запрос, который, учитывая диапазон дат, получает список записей, которые были обновлены в течение этого диапазона дат и запись последнего обновления до того, который он только что нашел. Обычно диапазон дат находится в пределах дня, поэтому 07-10-2013 00: 00: 000 - 7-11-2013 00: 00: 000.

например. учитывая 07-10-2013 00: 00: 000 - 7-11-2013 00: 00: 000, запрос найдено 2 записей

id new data  updatedate    old data  last updatedate 
3 randomdata 7-10-2013 03:30:343  randomdata 7-05-2013 06:34:764 
4 randomdata 7-10-2013 13:30:343  randomdata 6-09-2013 04:37:376 

Это результат я хотел бы получить. В настоящее время у меня уже есть запрос, который делает это, но запрос медленный, потому что в таблице есть три внутренних соединения, в которых много записей, и мне было интересно, сможет ли кто-нибудь подумать о том, как быстрее сделать запрос. Использование SQL Server 2000.

Таблица Информация

  • неуникальным ID
  • уникальный идентификатор (это просто автоматическое приращение идентификатор)
  • различных данных, которые будут собраны
  • дата обновления

Редактировать:

I ndexes в настоящее время на id и updatedate

Query настоящее время я использую (обобщающих его) :: ВНИМАНИЕ ::Это не очень:: ВНИМАНИЕ ::

select * 
from 
    (select distinct 
     s1.id as id, 
     s1.randData1, s2.randData1, s1.randData2, s2.randData2,..., 
     s1.updatedate as newupdatedate, 
     s2.updatedate as prevupdatedate, 
     datediff(second, s1.updatedate ,s2.updatedate) as maxdate 
    from 
     (select * 
     from updates 
     where updatedate >= '{0}' and updatedate < '{1}' 
      and id in ('{3}')) as s1 
    inner join 
     updates s2 on s1.id = s2.id and s1.updateid != s2.updateid) as t1 
inner join 
    (select 
      s1.id, max(datediff(second, s1.updatedate, s2.updatedate)) as maxdate2 
     from updates s1 
     inner join updates s2 on s1.id in ('{3}') and s1.id = s2.id and s1.updateid != s2.updateid 
     where datediff(second, s1.updatedate, s2.updatedate) < 0 
     and s1.updatedate < '{1}' and s2.updatedate < '{1}' 
     group by 
     s1.id) as t2 on t1.id = t2.id and t1.maxdate = t2.maxdate2 

{0 } {1} и {2} являются переданными параметрами.

Редактировать: запрос выполняется на C#, если это имеет значение. В случае необходимости, 2 запроса тоже будут хороши. То, что я в конечном счете ищу, - это то, что изменилось в данных выбранной даты.

+2

вы могли бы опубликовать запрос и сообщить нам, что индексы находятся на месте? –

ответ

0

Мне очень повезло получить все эти вложенные операторы select в #Temp Tables. В зависимости от того, насколько большой вы говорите, вы можете использовать переменные таблицы.

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

Я думаю, что сложность, наблюдаемая здесь, используя таблицы temp, будет вашим лучшим выбором. Таким образом, все ваши вложенные запросы могут создавать временную таблицу вместо того, чтобы удерживать их в памяти.

Ваш последний запрос был бы намного более компактным и намного более быстрым.

+0

Первый внутренний запрос, который выполняет отдельные randData, это данные, которые я ищу, а второй maxdate2 используется для поиска записи даты, предшествующей выбранной. Я пытался ограничить как можно больше, чем внутреннее соединение, поскольку мои знания о производительности Sql низки. Я решил, что если в первом внешнем столе было минимальное количество записей, тогда внешнее внутреннее соединение было бы быстрее. Надеюсь, это не слишком смущает. – LazyProgrammer

+0

Просто несколько утверждений. Получите свои вложенные операторы выбора, установленные в некоторых реальных таблицах, а затем обрезайте их в конце, когда все будет готово. Таким образом, у вас есть только один оператор select, и он обращается к таблицам на диске, а не в памяти. – TTUGecko

0

Попробуйте использовать временные таблицы -

IF OBJECT_ID (N'tempdb.dbo.#temp') IS NOT NULL 
    DROP TABLE #temp 

SELECT * 
INTO #temp 
FROM dbo.updates 
WHERE ID IN ('{3}') 

SELECT * 
FROM 
    (
    SELECT DISTINCT 
      s1.id AS id, 
      s1.randData1, s2.randData1, s1.randData2, s2.randData2, 
      s1.updatedate AS newupdatedate, 
      s2.updatedate AS prevupdatedate, 
      DATEDIFF(second, s1.updatedate ,s2.updatedate) AS maxdate 
    FROM 
    (
      SELECT * 
      FROM #temp 
      WHERE updatedate BETWEEN '{0}' AND '{1}' 
    ) s1 
    JOIN #temp s2 ON s1.id = s2.id AND s1.updateid != s2.updateid 
) t1 
JOIN (
    SELECT 
      s1.id, 
      MAX(DATEDIFF(second, s1.updatedate, s2.updatedate)) AS maxdate2 
    FROM #temp s1 
    JOIN #temp s2 ON s1.id = s2.id AND s1.updateid != s2.updateid 
    WHERE DATEDIFF(second, s1.updatedate, s2.updatedate) < 0 
      AND s1.updatedate < '{1}' AND s2.updatedate < '{1}' 
    GROUP BY s1.id 
) t2 ON t1.id = t2.id AND t1.maxdate = t2.maxdate2 
+0

Проблема с этим - я выполняю запрос внутри C#, поэтому я не уверен, будет ли это работать или нет, так как есть 2 оператора select. Извините, я, наверное, должен был добавить это к исходному сообщению. – LazyProgrammer

Смежные вопросы