asp.net下数据库操作优化一例_实用技巧

下面是最初实现的代码,其中 LargerResultProcessor 是一个基类,负责遍历泛型参数 T 所指向的数据库表,并以每页 100 项的方式分页,并对每一项调用 ProcessItem 函数,而子类只需实现 ProcessItem 函数即可:

复制代码 代码如下:

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,并且执行 Update,只是有个问题,就是执行速度比较慢,对于我们 6 万左右 Item,4 万左右 Sku,99 万左右 Order 的表,需要执行约 40 分钟,才能转换完毕。
这些代码,虽然是一次性操作,但是对于运行系统,停机时间越短越好,于是进行一些优化工作,数据库对于大量重复的语句,如果使用参数的方式,因为可以避免对于语句的重复解析工作,所以速度会快一些,按照这个思路,简单的修改如下:

复制代码 代码如下:

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 分钟可以完成转换。有一些提高,不过,我们真正要修改的数据量并不大,一共只有 6 万 加 4 万 大约 10 万条数据,所以 25 分钟还是有些长了。简单分析后,Orders 是最大的表,如果整体速度慢,则导致速度慢最大的可能因素,应该是查询 Orders,所以稍换一个思路,提前把 Item_Id 和 Shop_Id 的对应关系查找出来,放到内存里,从而避免每次 ProcessItem 都要进行 Orders 表的查询。至于内存里的数据,本来准备用 Dictionary 的,后来一想,Id 都是 long 型的数据,而且不能算“稀疏”矩阵,基本可以称为“稠密”矩阵,所以,直接用数组应该是速度更快,所以先查询出 Items 的最大 Id,用于设置数组大小,再按索引赋值即可:

复制代码 代码如下:

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 秒就完成了数据转换,另外,查询对应关系那一句 SQL,因为针对的是刚恢复的数据库,所以用了大概 3、40 秒,实际使用查询管理器,在运行中的数据库执行那一句 SQL,只需要 1 秒左右就可以完成,所以,估计在实际转换的时候,3、40 秒就可以完成转换了。

时间: 2024-10-11 07:05:49

asp.net下数据库操作优化一例_实用技巧的相关文章

asp.net下数据库操作优化一例

下面是最初实现的代码,其中 LargerResultProcessor 是一个基类,负责遍历泛型参数 T 所指向的数据库表,并以每页 100 项的方式分页,并对每一项调用 ProcessItem 函数,而子类只需实现 ProcessItem 函数即可: 复制代码 代码如下: public class ItemRenameCompanyId : LargerResultProcessor<Item> { protected override void ProcessItem(Item item)

ASP.NET下使用WScript.Shell执行命令_实用技巧

ASP.NET提供了两种方法让我们使用COM组件:1.Server对象的CreatObject方法:2.将COM组件转化为.NET组件. ·Server对象的CreatObject方法 这个方法比较简单,直接使用就是.当然前提是服务器上已经注册了该组件,而WScript.Shell是系统自带的,我们不用担心.只是在编写代码时注意ASP.NET与ASP语法上的细微差别就可以了.直接给出代码如下: <!-- Titel: WScript.Shell .NET Version 1 Author: la

ASP.NET列出数据库活跃链接的方法_实用技巧

本文实例讲述了ASP.NET列出数据库活跃链接的方法.分享给大家供大家参考.具体分析如下: 这里列出数据库的活跃链接.主要使用geeric列表和一个贮存器,创建一个泛型列表的链接,如果他们是活跃的,那么他们将显示在导航了. //First in C# where you create the controller action method //to create the method that will populate all content details //add the follow

Asp.net下拉树的实现过程_实用技巧

场景描述:某个公司有多个部门并且部门存在子部门,通过一个下拉框选取多个部门,但是如果某个部门的子部门被全部选择,则只取该部门,而忽略子部门.(叶子节点全被选中时,只取父节点) 知识点:ComboTree.一般处理程序.递归.Json 效果如图   数据库表设计:unit_main   节点类设计: public class Unit { public decimal id { get; set; } public string text { get; set; } public string s

利用Dom操作字符串一例_实用技巧

有时对字符串的处理可以利用Dom模式,例如下面字符串: <a1>a1的值</a1><a2>a2的值</a2><a3>a3的值</a3><a4><b4 id='b4'>b4的值</b4></a4> 要将b4元素的值修改为"修改后的b4". 除了用正则的方法外,还可以考虑Dom操作,下面分别用XmlDocument类和HtmlAgilityPack操作. 方法1,用Xml

ASP.NET动态添加控件一例_实用技巧

第一次单击页面中有3个Label,第二次单击有6个,第三次单击有9个,也就是每次单击要在上次的状态下再添加3个. 我的方法是,可以通过Session来保存上次的状态,一种解法如下: Test.aspx关键代码: 复制代码 代码如下: <form id="form1" runat="server"> <asp:DropDownList ID="DropDownList1" runat="server">

ADO.Net对oracle数据库操作的实例代码_实用技巧

首先要写连接字符串 可以在web.config里写上 复制代码 代码如下: <connectionStrings>     <add name="oracleson" connectionString="Data Source=dingsenorcl;Persist Security Info=True;User ID=ds;Password=ds;Unicode=True" providerName="System.Data.Oracl

asp.net下检测SQL注入式攻击代码_实用技巧

两个类: (页面数据校验类)PageValidate.cs 基本通用. 代码如下: 复制代码 代码如下: using System; using System.Text; using System.Web; using System.Web.UI.WebControls; using System.Text.RegularExpressions; namespace Common {     /// <summary>     /// 页面数据校验类     /// </summary&

asp.net下linkbutton的前后台使用方法_实用技巧

前台: 复制代码 代码如下: <asp:LinkButton runat="server" ID="lbtnUp" CommandArgument='<%#Eval("id") %>' OnClick="lbtnUp_Click">修改</asp:LinkButton> 后台:  复制代码 代码如下: protected void lbtnUp_Click(object sender, Ev