asp.net下數(shù)據(jù)庫操作優(yōu)化一例
更新時間:2010年11月19日 16:24:08 作者:
數(shù)據(jù)庫升級,需要對幾個表進行一些數(shù)據(jù)轉(zhuǎn)換,具體是這樣:針對每一個 Item,從 orders 表里查出 Shop_Id,并把此 Id 賦值給 items 和 skus 中的 Shop_Id。
下面是最初實現(xiàn)的代碼,其中 LargerResultProcessor 是一個基類,負(fù)責(zé)遍歷泛型參數(shù) T 所指向的數(shù)據(jù)庫表,并以每頁 100 項的方式分頁,并對每一項調(diào)用 ProcessItem 函數(shù),而子類只需實現(xiàn) ProcessItem 函數(shù)即可:
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());
}
}
}
上面這段代碼,邏輯比較簡單,針對每一項,使用 Select 語句取出 Shop_Id,并且執(zhí)行 Update,只是有個問題,就是執(zhí)行速度比較慢,對于我們 6 萬左右 Item,4 萬左右 Sku,99 萬左右 Order 的表,需要執(zhí)行約 40 分鐘,才能轉(zhuǎn)換完畢。
這些代碼,雖然是一次性操作,但是對于運行系統(tǒng),停機時間越短越好,于是進行一些優(yōu)化工作,數(shù)據(jù)庫對于大量重復(fù)的語句,如果使用參數(shù)的方式,因為可以避免對于語句的重復(fù)解析工作,所以速度會快一些,按照這個思路,簡單的修改如下:
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());
}
}
}
測試這個程序,大概 25 分鐘可以完成轉(zhuǎn)換。有一些提高,不過,我們真正要修改的數(shù)據(jù)量并不大,一共只有 6 萬 加 4 萬 大約 10 萬條數(shù)據(jù),所以 25 分鐘還是有些長了。簡單分析后,Orders 是最大的表,如果整體速度慢,則導(dǎo)致速度慢最大的可能因素,應(yīng)該是查詢 Orders,所以稍換一個思路,提前把 Item_Id 和 Shop_Id 的對應(yīng)關(guān)系查找出來,放到內(nèi)存里,從而避免每次 ProcessItem 都要進行 Orders 表的查詢。至于內(nèi)存里的數(shù)據(jù),本來準(zhǔn)備用 Dictionary 的,后來一想,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());
}
}
}
再測試這一段程序,運行 70 秒就完成了數(shù)據(jù)轉(zhuǎn)換,另外,查詢對應(yīng)關(guān)系那一句 SQL,因為針對的是剛恢復(fù)的數(shù)據(jù)庫,所以用了大概 3、40 秒,實際使用查詢管理器,在運行中的數(shù)據(jù)庫執(zhí)行那一句 SQL,只需要 1 秒左右就可以完成,所以,估計在實際轉(zhuǎn)換的時候,3、40 秒就可以完成轉(zhuǎn)換了。
復(fù)制代碼 代碼如下:
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());
}
}
}
上面這段代碼,邏輯比較簡單,針對每一項,使用 Select 語句取出 Shop_Id,并且執(zhí)行 Update,只是有個問題,就是執(zhí)行速度比較慢,對于我們 6 萬左右 Item,4 萬左右 Sku,99 萬左右 Order 的表,需要執(zhí)行約 40 分鐘,才能轉(zhuǎn)換完畢。
這些代碼,雖然是一次性操作,但是對于運行系統(tǒng),停機時間越短越好,于是進行一些優(yōu)化工作,數(shù)據(jù)庫對于大量重復(fù)的語句,如果使用參數(shù)的方式,因為可以避免對于語句的重復(fù)解析工作,所以速度會快一些,按照這個思路,簡單的修改如下:
復(fù)制代碼 代碼如下:
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());
}
}
}
測試這個程序,大概 25 分鐘可以完成轉(zhuǎn)換。有一些提高,不過,我們真正要修改的數(shù)據(jù)量并不大,一共只有 6 萬 加 4 萬 大約 10 萬條數(shù)據(jù),所以 25 分鐘還是有些長了。簡單分析后,Orders 是最大的表,如果整體速度慢,則導(dǎo)致速度慢最大的可能因素,應(yīng)該是查詢 Orders,所以稍換一個思路,提前把 Item_Id 和 Shop_Id 的對應(yīng)關(guān)系查找出來,放到內(nèi)存里,從而避免每次 ProcessItem 都要進行 Orders 表的查詢。至于內(nèi)存里的數(shù)據(jù),本來準(zhǔn)備用 Dictionary 的,后來一想,Id 都是 long 型的數(shù)據(jù),而且不能算“稀疏”矩陣,基本可以稱為“稠密”矩陣,所以,直接用數(shù)組應(yīng)該是速度更快,所以先查詢出 Items 的最大 Id,用于設(shè)置數(shù)組大小,再按索引賦值即可:
復(fù)制代碼 代碼如下:
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());
}
}
}
再測試這一段程序,運行 70 秒就完成了數(shù)據(jù)轉(zhuǎn)換,另外,查詢對應(yīng)關(guān)系那一句 SQL,因為針對的是剛恢復(fù)的數(shù)據(jù)庫,所以用了大概 3、40 秒,實際使用查詢管理器,在運行中的數(shù)據(jù)庫執(zhí)行那一句 SQL,只需要 1 秒左右就可以完成,所以,估計在實際轉(zhuǎn)換的時候,3、40 秒就可以完成轉(zhuǎn)換了。
您可能感興趣的文章:
- 對于ASP編碼問題的深入研究與最終解決方案
- Asp.Net 網(wǎng)站優(yōu)化系列之?dāng)?shù)據(jù)庫優(yōu)化分字訣上 分庫
- Asp.Net 網(wǎng)站優(yōu)化系列之?dāng)?shù)據(jù)庫優(yōu)化 分字訣 分表(縱向拆分,橫向分區(qū))
- Asp.Net 網(wǎng)站優(yōu)化系列之?dāng)?shù)據(jù)庫優(yōu)化措施 使用主從庫(全)
- asp.net小談網(wǎng)站性能優(yōu)化
- Asp.net 網(wǎng)站性能優(yōu)化二則分享
- ASP.NET性能優(yōu)化之讓瀏覽器緩存動態(tài)網(wǎng)頁的方法
- ASP.NET性能優(yōu)化之減少請求
- asp.net程序優(yōu)化 盡量減少數(shù)據(jù)庫連接操作
- Asp.Net性能優(yōu)化技巧匯總
- Asp編碼優(yōu)化技巧
相關(guān)文章
關(guān)于HttpHandler與HttpModule的理解和應(yīng)用方法
本篇文章小編將為大家介紹,關(guān)于HttpHandler與HttpModule的理解和應(yīng)用方法,有需要的朋友可以參考一下2013-04-04asp.net(c#)下各種進制間的輕松轉(zhuǎn)換(2進制、8進制、10進制、16進制)
在.NET Framework中,System.Convert類中提供了較為全面的各種類型、數(shù)值之間的轉(zhuǎn)換功能。2010-10-10Visual Studio 2010 前端開發(fā)工具/擴展/插件推薦
這篇文章主要介紹了一組我喜愛的擴展和工具能讓Visual Studio在web開發(fā)方面更簡單,我只是集中在我安裝和使用過的一些工具,如果你還有其它好用的的話,請在這里留言。2016-06-06