Параллелизм в SQL Server 2008 - PullRequest
2 голосов
/ 15 июня 2010

Существует хранимая процедура:

 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%, то есть ресурсов достаточно для их одновременного выполнения.Как это может быть?

РЕДАКТИРОВАТЬ: Обнаружил хорошую статью о одновременных вставках: Разрешение конфликтов PAGELATCH на высокопараллельных рабочих нагрузках INSERT

Ответы [ 2 ]

3 голосов
/ 15 июня 2010

Начнем с того, что CPU - не единственный ресурс в базе данных.Отправленный вами запрос вставляется в таблицу #temp в базе данных tempdb, для которой потребуются такие ресурсы, как:

  • tempdb. Распределение SGAM / GAM.
  • журнал tempdb
  • пул буферов
  • tempdb IO

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

В конечном счете, вам нужно измерить, где потрачено время, см. Ожидания и очереди SQL Server 2005 Методология, как проанализировать вопрос.

2 голосов
/ 15 июня 2010

зачем выбирать из одной и той же таблицы 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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...