public class ItemRenameCompanyId : LargerResultProcessor<Item>
{
protected override void ProcessItem(Item item)
{
const string template1 = @"select top 1 shop_id from orders where Item_id = '{0}'";
var sql1 = string.Format(template1, item.Id);
const string template2 = @"update Items set shop_id={0} where id = {1};
update skus set shop_id={0} where item_id = {1};";
try
{
var obj = DbEntry.Context.ExecuteScalar(sql1);
var sql2 = string.Format(template2, long.Parse(obj.ToString()), item.Id);
DbEntry.Context.ExecuteNonQuery(sql2);
}
catch (Exception exception)
{
Logger.Default.Warn(exception + item.Id.ToString());
}
}
}
上面這段代碼,邏輯比較簡(jiǎn)單,針對(duì)每一項(xiàng),使用 Select 語(yǔ)句取出 Shop_Id,并且執(zhí)行 Update,只是有個(gè)問(wèn)題,就是執(zhí)行速度比較慢,對(duì)于我們 6 萬(wàn)左右 Item,4 萬(wàn)左右 Sku,99 萬(wàn)左右 Order 的表,需要執(zhí)行約 40 分鐘,才能轉(zhuǎn)換完畢。
這些代碼,雖然是一次性操作,但是對(duì)于運(yùn)行系統(tǒng),停機(jī)時(shí)間越短越好,于是進(jìn)行一些優(yōu)化工作,數(shù)據(jù)庫(kù)對(duì)于大量重復(fù)的語(yǔ)句,如果使用參數(shù)的方式,因?yàn)榭梢员苊鈱?duì)于語(yǔ)句的重復(fù)解析工作,所以速度會(huì)快一些,按照這個(gè)思路,簡(jiǎn)單的修改如下:
代碼如下:
public class ItemRenameCompanyId : LargerResultProcessor<Item>
{
protected override void ProcessItem(Item item)
{
const string template1 = @"select top 1 shop_id from orders where Item_id = @id";
const string template2 =
@"update Items set shop_id=@sid where id = @id;
update skus set shop_id=@sid where item_id = @id;";
try
{
var sql1 = new SqlStatement(template1, new DataParameter("@id", item.Id));
var sid = Convert.ToInt64(DbEntry.Context.ExecuteScalar(sql1));
var sql2 = new SqlStatement(template2, new DataParameter("@sid", sid), new DataParameter("@id", item.Id));
DbEntry.Context.ExecuteNonQuery(sql2);
}
catch (Exception exception)
{
Logger.Default.Warn(exception + item.Id.ToString());
}
}
}
測(cè)試這個(gè)程序,大概 25 分鐘可以完成轉(zhuǎn)換。有一些提高,不過(guò),我們真正要修改的數(shù)據(jù)量并不大,一共只有 6 萬(wàn) 加 4 萬(wàn) 大約 10 萬(wàn)條數(shù)據(jù),所以 25 分鐘還是有些長(zhǎng)了。簡(jiǎn)單分析后,Orders 是最大的表,如果整體速度慢,則導(dǎo)致速度慢最大的可能因素,應(yīng)該是查詢 Orders,所以稍換一個(gè)思路,提前把 Item_Id 和 Shop_Id 的對(duì)應(yīng)關(guān)系查找出來(lái),放到內(nèi)存里,從而避免每次 ProcessItem 都要進(jìn)行 Orders 表的查詢。至于內(nèi)存里的數(shù)據(jù),本來(lái)準(zhǔn)備用 Dictionary 的,后來(lái)一想,Id 都是 long 型的數(shù)據(jù),而且不能算“稀疏”矩陣,基本可以稱為“稠密”矩陣,所以,直接用數(shù)組應(yīng)該是速度更快,所以先查詢出 Items 的最大 Id,用于設(shè)置數(shù)組大小,再按索引賦值即可:
代碼如下:
public class ItemRenameCompanyId : LargerResultProcessor<Item>
{
private readonly long[] _dic;
public ItemRenameCompanyId()
{
var count = Convert.ToInt64(DbEntry.Context.ExecuteScalar("select top 1 Id from items order by id desc")) + 10;
_dic = new long[count];
var sql =
new SqlStatement(
"select items.id as xiid,orders.shop_id as xsid from items inner join orders on orders.item_id = items.id group by items.id,orders.shop_id")
{SqlTimeOut = 300};
dynamic list = DbEntry.Context.ExecuteDynamicList(sql);
foreach(dynamic row in list)
{
_dic[row.xiid] = row.xsid;
}
}
protected override void ProcessItem(Item item)
{
const string template2 =
@"update Items set shop_id=@sid where id = @id;
update skus set shop_id=@sid where item_id = @id;";
try
{
var sid = _dic[item.Id];
var sql2 = new SqlStatement(template2, new DataParameter("@sid", sid), new DataParameter("@id", item.Id));
DbEntry.Context.ExecuteNonQuery(sql2);
}
catch (Exception exception)
{
Logger.Default.Warn(exception + item.Id.ToString());
}
}
}
再測(cè)試這一段程序,運(yùn)行 70 秒就完成了數(shù)據(jù)轉(zhuǎn)換,另外,查詢對(duì)應(yīng)關(guān)系那一句 SQL,因?yàn)獒槍?duì)的是剛恢復(fù)的數(shù)據(jù)庫(kù),所以用了大概 3、40 秒,實(shí)際使用查詢管理器,在運(yùn)行中的數(shù)據(jù)庫(kù)執(zhí)行那一句 SQL,只需要 1 秒左右就可以完成,所以,估計(jì)在實(shí)際轉(zhuǎn)換的時(shí)候,3、40 秒就可以完成轉(zhuǎn)換了。聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com