2010-04-14 2 views
0

Мне нужно взять некоторые данные из одной таблицы (и развернуть некоторые XML на этом пути) и поместить ее в другую таблицу. Поскольку в исходной таблице могут быть тысячи или записи, которые вызвали тайм-аут, я решил сделать это в партиях по 100 записей. Код запускается по расписанию, поэтому его выполнение в пакетах работает нормально для клиента. Если я скажу 200 записей в исходной базе данных, sproc работает очень быстро, но если есть тысячи, это занимает несколько минут. Я предполагаю, что «ТОП-100» занимает только 100 лучших после того, как он прошел через все записи. Мне нужно изменить весь код и sproc в какой-то момент, поскольку он не масштабируется, но на данный момент есть быстрое исправление, чтобы сделать этот запуск быстрее?медленная команда SQL

INSERT INTO [deviceManager].[TransactionLogStores] 
SELECT TOP 100 [EventId], 
    [message].value('(/interface/mac)[1]', 'nvarchar(100)') AS mac, 
    [message].value('(/interface/device) [1]', 'nvarchar(100)') AS device_type, 
    [message].value('(/interface/id) [1]', 'nvarchar(100)') AS device_id, 
    [message].value('substring(string((/interface/id)[1]), 1, 6)', 'nvarchar(100)') AS store_id, 
    [message].value('(/interface/terminal/unit)[1]', 'nvarchar(100)') AS unit, 
    [message].value('(/interface/terminal/trans/event)[1]', 'nvarchar(100)') AS event_id, 
    [message].value('(/interface/terminal/trans/data)[1]', 'nvarchar(100)') AS event_data, 
    [message].value('substring(string((/interface/terminal/trans/data)[1]), 9, 11)', 'nvarchar(100)') AS badge, 
    [message].value('(/interface/terminal/trans/time)[1]', 'nvarchar(100)') AS terminal_time, 
    MessageRecievedAt_UTC AS db_time 
FROM [deviceManager].[TransactionLog] 
WHERE EventId > @EventId 
--WHERE MessageRecievedAt_UTC > @StartTime AND MessageRecievedAt_UTC < @EndTime 
ORDER BY terminal_time DESC 
+0

Включен ли индекс EventId в таблицу транзакций? – zsong

ответ

1

Вам нужен ЗАКАЗ? В TOP не нужно будет возвращать весь результат, чтобы отрубить верхнюю часть 100, если данные не отсортированы. Если вам нужен заказ, убедитесь, что у вас есть индекс в term_time; если это так долго, вы, вероятно, этого не сделали.

Кроме того, убедитесь, что у вас есть индекс в EventID.

+0

+1 для ORDER BY. Не уверен, что вы можете сделать индекс в выражении XPath, хотя (может быть?). – Tomalak

+0

@ Томалак Хорошая точка! Я не заметил, что это выражение XPath, а не стандартный столбец. Retrocoder - это будет потому, что на удивление долгое время нужно выбирать, когда таблица становится больше. Поскольку ORDER BY является выражением XPath, сервер должен будет оценить весь набор результатов, включая выполнение XPath для каждой строки, прежде чем он сможет сортировать данные (и, следовательно, выберете _which_ TOP 100, который вы хотите.) Если вы не может удалить ORDER BY, можете ли вы использовать реальный столбец в таблице для сортировки? –

+0

Очевидно, что вы можете иметь индекс XML в SQL Server (http://msdn.microsoft.com/en-us/library/ms191497.aspx). – Tomalak

0

У вас есть показатели по EventIdMessageRecievedAt_UTC)?

У @EventId и @StartTime/@EndTime те же данные, что и в соответствующих столбцах?

0

Похоже, что (если я ошибаюсь, и это какая-то другая конструкция) message.value() - это UDF, который всегда принимает одинаковые входные данные. Вы вызываете эту функцию примерно в 10 раз за все N строк - это, безусловно, будет проблемой производительности. Если это детерминированная функция (я надеюсь, что это так), вы можете просто кэшировать результаты этих различных вызовов функций в временную таблицу, и производительность должна значительно улучшиться.

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

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