MySql Пакетные вызовы хранимых процедур с .Net / Connector? - PullRequest
1 голос
/ 12 января 2011

Существует ли способ пакетного вызова вызовов процедур в MySql с помощью .Net / Connector для повышения производительности?

Вот сценарий ... Я использую хранимую процедуру, которая принимает несколько параметров в качестве входных данных.,Эта процедура в основном проверяет, нужно ли обновить существующую запись или вставить новую (я не использую INSERT INTO .. ​​ON DUPLICATE KEY UPDATE, потому что проверка включает диапазоны дат, поэтому я не могу действительно сделать первичный ключ изкритериев).

Я хочу вызывать эту процедуру много раз (скажем, партиями по 1000 или около того).Конечно, я могу использовать один экземпляр MySqlConnection и один экземпляр MySqlCommand, постоянно меняя значения параметров и вызывая .ExecuteNonQuery ().

Мне интересно, есть ли лучший способ пакетировать эти вызовы?

Единственная мысль, которая приходит на ум, - это вручную создать строку типа 'call sp_myprocedure (@ parama_1, @ paramb_1); вызовите sp_myprocedure (@ parama_2, @ paramb2); ... ', а затем создайте все соответствующие параметры.Я не уверен, что это будет лучше, чем вызов .ExecuteNonQuery () несколько раз.

Любой совет?Спасибо!

РЕДАКТИРОВАТЬ: Подробнее
На самом деле я пытаюсь регулярно хранить данные из внешнего источника данных.В основном я беру rss-каналы аукционов доменов (из разных источников, таких как godaddy, pool и т. Д.) И обновляю таблицу с информацией об аукционах, используя эту хранимую процедуру (назовем ее sp_storeSale).Теперь, в этой таблице, в которой хранится информация о продажах, я хочу сохранить исторические записи о продажах для данного домена, поэтому у меня есть таблица domain и таблица sale .Таблица sale имеет отношение много к одному с таблицей domain .

Вот хранимая процедура:

    -- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$

CREATE PROCEDURE `DomainFace`.`sp_storeSale` 
(
    middle VARCHAR(63),
    extension VARCHAR(10),
    brokerId INT,
    endDate DATETIME,
    url VARCHAR(500),
    category INT,
    saleType INT,
    priceOrBid DECIMAL(10, 2),
    currency VARCHAR(3)    
)
BEGIN
    DECLARE existingId BIGINT DEFAULT NULL;
    DECLARE domainId BIGINT DEFAULT 0;

    SET @domainId = fn_getDomainId(@middle, @extensions);

    SET @existingId = (
        SELECT id FROM sale
        WHERE 
            domainId = @domainId
            AND brokerId = @brokerId
            AND UTC_TIMESTAMP() BETWEEN startDate AND endDate
    );

    IF @existingId IS NOT NULL THEN
        UPDATE sale SET
            endDate = @endDate,
            url = @url,
            category = @category,
            saleType = @saleType,
            priceOrBid = @priceOrBid,
            currency = @currency
        WHERE
            id = @existingId;
    ELSE
        INSERT INTO sale (domainId, brokerId, startDate, endDate, url,
                category, saleType, priceOrBid, currency)
            VALUES (@domainId, @brokerId, UTC_TIMESTAMP(), @endDate, @url,
                @category, @saleType, @priceOrBid, @currency);
    END IF;
END

Как вы можете видеть, я в основном ищу существующую запись, которая не "просрочена", но имеет тот же домен и брокер,в этом случае я предполагаю, что аукцион еще не закончен, и данные являются обновлением существующего аукциона.В противном случае, я предполагаю, что аукцион окончен, это историческая запись, и у меня есть данные для нового аукциона, поэтому я создаю новую запись.

Надеюсь, это прояснит то, что я пытаюсьдостичь :) 1031 *

1 Ответ

0 голосов
/ 12 января 2011

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

Почему вы не перемещаете всю свою логику в базу данных и не обрабатываете все это на стороне сервера? В следующем примере используется курсор (шок / ужас), но его вполне допустимо использовать в таких обстоятельствах.

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

call house_keeping(curdate() - interval 1 month, curdate());

Кроме того, если вы сможете предоставить чуть больше информации о том, что вы пытаетесь сделать, мы могли бы предложить другие подходы.

Пример хранимой процедуры

drop procedure if exists house_keeping;

delimiter #

create procedure house_keeping
(
in p_start_date date,
in p_end_date date
)
begin

declare v_done tinyint default 0;
declare v_id int unsigned;
declare v_expired_date date;

declare v_cur cursor for 
  select id, expired_date from foo where 
    expired_date between p_start_date and p_end_date;

declare continue handler for not found set v_done = 1;

open v_cur;

repeat
    fetch v_cur into v_id, v_expired_date;

    /*
    if <some condition> then
      insert ...
    else
      update ...
    end if;
    */

until v_done end repeat;
close v_cur;

end #

delimiter ; 

Просто если вы думаете, что я совершенно безумен, предлагая курсоры, возможно, вы захотите прочитать это Оптимальные настройки MySQL для запросов, которые доставляют большие объемы данных?

Надеюсь, это поможет:)

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