2010-06-15 9 views
2

Существует хранимая процедура:Параллелизм в SQL Server 2008

CREATE PROCEDURE [dbo].[TestProc] 
AS 
BEGIN 
    SET NOCOUNT ON; 

    create table #thistable (rid char(32)) 
    insert into #thistable(rid) 
    select A0RID from tblCdbA0 with (nolock) 
    END 

Когда процедура выполняется в одиночку он занимает 400-500 мс, но при 10 потоков выполнения той же процедуры, параллельно, то первый поток заканчивается в 1300 мс, последний - через 6000 мс и средний - 4800 мс. Как вы можете видеть, нет блокировки, когда потоки ожидают, когда другой конец будет выполнен. Кроме того, серверный процессор загружается менее чем на 100%, т. Е. Для их выполнения достаточно ресурсов. Как это могло быть?

EDIT: Нашел хорошая статья о параллельных вставок: Resolving PAGELATCH Contention on Highly Concurrent INSERT Workloads

+0

Кажется, что вставлять то же самое 8 раз. Это верно? Если так, возможно, сделать декартовое соединение на 8-строчной производной таблице будет быстрее (или это просто демо-тест для тестирования)? –

+0

спасибо за комментарий, вопрос не в производительности кода, а в параллелизме: почему, когда 10 потоков выполняют эту простую процедуру, она, похоже, заблокирована? (точно это демонстрация) – Tim

+0

@tim - Вы пробовали loking на 'sys.dm_os_wait_stats', чтобы узнать, что ждет? NB: Чтобы очистить это до тестирования, вы можете сделать «DBCC SQLPERF (« sys.dm_os_wait_stats », CLEAR)' –

ответ

3

Для начала ЦП не является единственным ресурсом в базе данных. Вы отправили запрос в таблицу #temp в tempdb, для которой понадобятся такие ресурсы, как:

  • tempdb SGAM/GAM.
  • Tempdb войти
  • пул буферов
  • Tempdb IO

Так что если у вас есть 400-500 мс для одного потока и 10 нитей закончить в 6000 мс, что меня не удивляет. Вы запрашиваете в 10 раз больше работы (т. Е. В 10 раз больше ввода-вывода, чтобы записать эти таблицы #temp на диск), поэтому ожидается 4000-5000 мс. Дополнительные 1000 мс могут быть от конкуренции (потоки, конкурирующие за тот же ресурс).

В конечном счете, вам необходимо измерить, где потрачено время, см. SQL Server 2005 Waits and Queues за хорошую методологию, как проанализировать проблему.

+0

Если я рискну предположить, я бы сказал, что ограничивающим фактором является скорость сбрасывания журнала. Один поток занимает 400-500 мс, потому что это то, сколько нужно, чтобы записать в файл LDF данные, которые вы вставляете, и оператор не может вернуться до тех пор, пока он не завершится (журнал затвердеет на диске). Так что 10 потоков пишут в 10 раз больше, возьмут в 10 раз больше. –

+0

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

+0

Конечно, сервер пишет в журнале параллельно :) Но если ваш жесткий диск делает максимальную передачу на 130 Мб/с (что обычно максимальная/идеальная скорость передачи данных на потребительском диске), тогда один запрос будет использовать все 130 Мбит/с, 10 потоков будут делиться им и получать около 13 Мбит/сек каждый. –

2

почему выбрать из той же таблицы 8 раз, просто дублировать строки, как только вы получите их в первый раз, попробуйте следующее:

CREATE PROCEDURE [dbo].[TestProc] 
AS 
SET NOCOUNT ON; 

create table #thistable (rid char(32)) 

;WITH AllNumbers AS 
(
    SELECT 1 AS Number 
    UNION ALL 
    SELECT Number+1 
     FROM AllNumbers 
     WHERE Number<8 
) 
insert into #thistable 
     (rid) 
    select A0RID 
     from tblCdbA0    t with (nolock) 
     INNER JOIN AllNumbers  a ON 1=1 

RETURN 0 
GO 

, если вы делаете это с UNIONs, у вас есть 8 сканирований таблицы на поток, и это добавит и повлияет на производительность.

+0

спасибо за комментарий, в основном код предназначен только для демонстрации, сама производительность сама по себе не интересна. Вопрос заключается в параллелизме. – Tim

+1

@ В вашем вопросе вы указываете конкретное время выполнения и задаете конкретный (странный) запрос, но вы просите что-то еще? возможно, вам нужно пересмотреть свой вопрос, но я не уверен, что вам нужно. Возможно, вы после чего-то менее конкретного, как ответ @Remus Rusanu. Если да, действительно ли вы ожидаете, что SQL Server будет иметь неограниченную ширину чтения/записи для одновременной обработки всех ваших IO (для каждого потока)? –