Как выполнять подзадачи в процедуре SQL параллельно - PullRequest
2 голосов
/ 01 декабря 2010

У меня есть процесс, который анализирует данные аудита из одной системы для создания данных отчетов для другой системы.Существует процедура управления, которая зацикливается на каждый день для анализа и вызывает специфичную для сущности процедуру с текущим днем ​​итерации.Некоторым объектам требуется меньше секунды, а другим - минуты.Работая поочередно, как в t-sql, загрузка ЦП никогда не превышает 8% на 16-ядерном сервере.Каждая из процедур, специфичных для объекта, не зависит от других, просто все объекты для этого дня завершены до начала следующего дня.

Моя идея состоит в том, чтобы иметь процедуру управления CLR и запускать более длинныйзапустив процедуры для дня, выполняющегося в их собственных потоках, затем, как только быстрые из них будут выполнены, Thread.Join () долго выполняющиеся потоки ожидают завершения всех сущностей за этот день, прежде чем перейти к следующему.

Ниже приведена моя самая простая попытка, которая может работать только для одного рабочего потока, и вызов Start для этого потока не приводит к вызову статического метода.Я установил точку останова в методе HelloWorld, и он никогда не срабатывает.

Я пробовал что-то очень похожее на это в консольном приложении, и оно работало так же, как и при вызове этого же потока в закомментированномлиния в начале AsyncHelloWorld.Есть ли что-то в потоке в процедурах SQL CLR, которое отличается?

using System.Threading;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
    [SqlProcedure]
    public static void AsyncHelloWorld()
    {
        // HelloWorld(SqlContext.Pipe);

        var worker = new Thread(HelloWorld);
        worker.Start(SqlContext.Pipe);
        worker.Join();
    }

    public static void HelloWorld(object o)
    {
        var pipe = o as SqlPipe;

        if (pipe != null)
            pipe.Send("Hello World!");
    }
}

1 Ответ

6 голосов
/ 01 декабря 2010

Вы абсолютно не можете этого сделать. SqlPipe очень сильно привязан к контексту потока, в который вы были вызваны. Хотя технически вы можете запускать потоки из SQLCRL, эти потоки должны выполнять все взаимодействия с вызывающей стороной из исходного потока. Но даже в этом случае запуск потоков CLR в среде, размещенной на SQL, является очень плохой идеей (и я не буду вдаваться в детали, почему).

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

Но, скорее всего, ваши процедуры не нуждаются в явном параллелизме. Нагрузки T-SQL, которые могут извлечь выгоду из явного параллелизма, управляемого пользователем, настолько редки, что не стоит упоминать (не говоря уже о том, что использование транзакционной семантики в параллельных задачах выходит за рамки простых смертных). T-SQL может использовать параллелизм внутренних операторов для параллельной обработки данных, поэтому явный параллелизм никогда не нужен.

Так что лучше объясните, что вы действительно 1015 * пытаетесь решить, и, возможно, мы можем помочь.

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