Цикл в хранимой процедуре или в коде клиента - PullRequest
2 голосов
/ 06 мая 2009

С точки зрения эффективности и лучших практик, я ценю все мысли.

У меня есть хранимая процедура, которая делает (n) копий строки и вставляет строку в необходимую таблицу.

Например. Сделайте копию предмета инвентаря и добавьте копии в инвентарь.

Я вижу две опции для этого типа хранимой процедуры.

Вариант 1:

CREATE PROCEDURE CopyInventory
@InventoryID int
AS

BEGIN

INSERT INTO Inventory (fieldOne, fieldTwo, FieldThree)
(SELECT FieldOne, FieldTwo, FieldThree FROM Inventory WHERE InventoryID = @InventoryID)

END

Используя первый вариант, я бы вызывал хранимую процедуру несколько раз из цикла while в коде клиентского приложения.

Вариант 2:

    CREATE PROCEDURE CopyInventory
    @InventoryID int,
    @CopyCount int
    AS

    BEGIN

    DECLARE @counter int

    SET @counter = 0

    WHILE @counter < @CopyCount

    INSERT INTO Inventory (fieldOne, fieldTwo, FieldThree)
    (SELECT FieldOne, FieldTwo, FieldThree FROM Inventory WHERE InventoryID = @InventoryID)

    END
END

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

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

Я ценю ваши мысли о том, почему вы бы предпочли одно другому или ни одно, а также рекомендации о наилучшей практике.

Ответы [ 4 ]

8 голосов
/ 06 мая 2009

Конечно, сделайте это на стороне сервера.

Это избавит вас от многократных поездок между клиентом и сервером.

Будет еще лучше, если вы сделаете свой цикл основанным на наборе:

WITH hier(cnt) AS
        (
        SELECT  1 AS value
        UNION ALL
        SELECT  cnt + 1
        FROM    hier
        WHERE   cnt < @count
        )
INSERT
INTO    Inventory (fieldOne, fieldTwo, FieldThree)
SELECT  FieldOne, FieldTwo, FieldThree
FROM    hier, Inventory
WHERE   InventoryID = @InventoryID
1 голос
/ 06 мая 2009

Если вы ищете только производительность, то вариант 2 - это путь.

Если вам удастся сохранить соединение на клиенте открытым, то есть несколько причин для выбора варианта 1.

  1. Вы можете легко поставить индикатор выполнения в приложении
  2. Вы можете легко прервать процесс в середине цикла ... как, если пользователь нажимает кнопку отмены.
1 голос
/ 06 мая 2009

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

Как правило, я бы сказал, что операции на основе множеств должны выполняться на стороне сервера, поскольку именно в этом SQL Server особенно хорош, а итеративные операции должны выполняться на стороне клиента, поскольку именно в этом хороши компилируемые языки.

0 голосов
/ 06 мая 2009

Это действительно требует профилирования, но я сначала подумал, что серверная сторона будет лучше. Ключевым моментом будет то, больше ли издержки механизма БД, выполняющего цикл, чем издержки повторных вызовов клиент-сервер для повторного выполнения команды, и это будет варьироваться в зависимости от БД (я думал, что это возможно для механизм для обеспечения лучшего параллелизма для хранимой процедуры, если она выполняется с несколькими вызовами, а не с одной хранимой процедурой ... только детали реализации).

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

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