MySql批处理存储过程调用.Net / Connector?

时间:2011-01-12 01:25:42

标签: c# .net mysql sql

有没有办法在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)。现在,在此表中存储了销售信息,我想保留给定域的销售历史记录,因此我有一个表和一个 sale 表。 sale 表与表具有多对一关系。

这是存储过程:

    -- --------------------------------------------------------------------------------
-- 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

正如您所看到的,我基本上是在寻找一个不是“已过期”的现有记录,但拥有相同的域名和经纪人,在这种情况下我认为拍卖还没有结束,而且数据是更新现有拍卖。否则,我认为拍卖已经结束,这是一个历史记录,我得到的数据是新的拍卖,所以我创建了一个新的记录。

希望清除我想要实现的目标:)

1 个答案:

答案 0 :(得分:0)

我不完全确定你要做什么,但听起来有点像家务或维护,所以我不会因为发布以下建议而感到羞耻。

为什么不将所有逻辑移入数据库并在服务器端处理它? 以下示例使用游标(shock / horror),但在这种情况下使用它们是完全可以接受的。

如果你可以完全避免使用游标 - 那很好,但我的建议主要是将逻辑从应用程序层移回数据层以节省往返次数。您将调用以下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 ; 

只是因为你觉得我在建议你可能想要阅读的游标时已经完全疯了 Optimal MySQL settings for queries that deliver large amounts of data?

希望这会有所帮助:)