我在SP呼叫期间遇到丢失的连接错误,从“有效的”和“有效”之间分割出日期。表A中的“有效到”列,并将它们与其他列一起插入到新表B中。
表A有大约300万行,所以我预计表B可能超过1000万行。
SP运行600秒,然后显示2013错误。
我尝试过多次调用此SP,但没有成功。
我该如何解决这个问题? 分区表A会以任何方式帮助吗?
索引怎么样?
表A如下:
CREATE TABLE `test_data`.`offer_master` (
`off_id` INT NOT NULL primary key,
`hot_id` INT NOT NULL,
`curr_id` INT NOT NULL,
`price_dollar` FLOAT NULL DEFAULT NULL,
`price_local` FLOAT NOT NULL,
`curr_code` VARCHAR(35) NOT NULL,
`valid_from` DATETIME NOT NULL,
`valid_to` DATETIME NOT NULL,
`breakfast_included` TINYINT(1) NOT NULL,
`valid_offer` TINYINT(1) NOT NULL)
ENGINE=InnoDB DEFAULT CHARSET=utf8;
表B:
CREATE TABLE `test_data`.`split_by_date` (
`id` int NOT NULL,
`hotel_id` int not NULL,
`original_price` float not NULL,
`currency_id` int not NULL,
`dates` date DEFAULT NULL)
ENGINE=InnoDB DEFAULT CHARSET=utf8;
SP将A&的日期分开插入B:
delimiter //
CREATE PROCEDURE `split_dates`()
BEGIN
DECLARE aid INT;
DECLARE avalid_from_date DATE;
DECLARE avalid_to_date DATE;
DECLARE sp_hotel_id INT;
DECLARE local_price float;
DECLARE sp_currency_id int;
DECLARE tempdt DATE;
DECLARE done INT DEFAULT FALSE;
DECLARE getdates CURSOR FOR
SELECT off_id,valid_from,valid_to,hot_id,price_local,curr_id
from offer_master;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN getdates;
read_loop: LOOP
FETCH getdates
INTO aid,avalid_from_date,avalid_to_date,sp_hotel_id,local_price,sp_currency_id;
IF done THEN
LEAVE read_loop;
END IF;
set tempdt=date(avalid_from_date);
WHILE (tempdt <= date(avalid_to_date)) do
insert into split_by_date(id,hotel_id,original_price,currency_id,dates)
values(aid,sp_hotel_id,local_price,sp_currency_id,tempdt);
set tempdt=tempdt+INTERVAL 1 DAY;
end while;
END LOOP;
CLOSE getdates;
END
//
答案 0 :(得分:0)
快速修复可能是
START TRANSACTION;
CALL ... ;
COMMIT;
更好的解决方法是认识到CURSORs
几乎总是写SQL的错误方法。我们可以通过同时处理所有300万行来摆脱光标。但我不知道如何摆脱WHILE
循环。
SELECT @n := 0; -- Or "1"? (depends on whether you want to start with `valid_from`.
myloop: LOOP
INSERT INTO split_by_date(id, hotel_id, original_price, currency_id, dates)
SELECT off_id, hot_id, price_local, curr_id,
valid_from + INTERVAL n DAY
FROM offer_master
WHERE valid_from + INTERVAL @n DAY < valid_to; -- maybe "<=" ?
IF ROW_COUNT = 0 THEN
LEAVE myloop; -- when a pass over the data has no rows to add
END IF
END LOOP myloop;
否INDEX
或PARTITION
会有所帮助;它只需要反复进行表扫描。
但是,每张桌子上至少应该有一个PRIMARY KEY
。
使用FLOAT
钱是不明智的。请参阅DECIMAL
。