2008年5月小记(??, #, DataContractJsonSerializer, CTE Ranking top)
1、??运算符
相当于
variable == null ? defaultValue : variable
2、 使用href="javascript:void(0)" 代替href="#",避免url产生没定义的锚点定位。
3、使用System.Runtime.Serialization.Json.DataContractJsonSerializer代替System.Web.Script.Serialization.JavaScriptSerializer
执行JSON的序列化和反序列化
4、解决一例数据库服务器CPU占用资源100%的问题。
最近根据用户技能搜索好友的功能根据新的需求作了调整,要求搜索的结果增加like用户名的结果集。例如:本来是以asp.net这种技能搜索出拥有这种技能的用户列表以供用户寻找好友,现在还要增加一个结果集是以asp.net开头的用户列表如:asp.net01,asp.net02。这两个结果集的排序以论坛专家分的多少为排序的依据。
现在的情况是UserPost表具有15000000的数据量,并且对该表有一个全文检索。根据技能搜索用户列表是通过全文检索进行(contains)得到,而根据用户相拟是通过对表的搜索([UserName] like @key+'%')得到,并且还以order by communityscore desc进行排序。
当这个新功能上线后数据库的CPU总是高居不下,后来通过在数据库端跟踪SQL和存储过程的调用情况就大致找到出问题的语句。分析了原来的语句的写法是把contains和like都写在一个where里了,查看一下执行计划,对于全文检索的搜索的调用耗资非常之大。同时从需求上分析,这个搜索的意图主要还是以技能搜用户为主,以用户名相拟性搜索的用户列表为辅,所以逻辑上可以调整为先从全文检索中获取拥有这此技能的用户列表,再以用户名相拟搜索用户列表,然后进行组合。新的sp如下:
这里用到了几个SQL2005的新功能。
a、CTE
b、Ranking函数集。row_number() over (order by xxx desc)
c、top(select ....)函数
string str = null;
str = str ?? "123";
Console.WriteLine(str ?? "234");
variable ?? defaultValuestr = str ?? "123";
Console.WriteLine(str ?? "234");
相当于
variable == null ? defaultValue : variable
2、 使用href="javascript:void(0)" 代替href="#",避免url产生没定义的锚点定位。
3、使用System.Runtime.Serialization.Json.DataContractJsonSerializer代替System.Web.Script.Serialization.JavaScriptSerializer
执行JSON的序列化和反序列化
public static class JSONExtension
{
public static string ToJSON(this object obj)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
using (MemoryStream ms = new MemoryStream())
{
serializer.WriteObject(ms, obj);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
public static T ParseJSON<T>(this string str)
{
T obj = Activator.CreateInstance<T>();
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(str)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
return (T)serializer.ReadObject(ms);
}
}
}
注意:引用如下组件System.Runtime.Serialization,System.ServiceModel,System.ServiceModel.Web {
public static string ToJSON(this object obj)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
using (MemoryStream ms = new MemoryStream())
{
serializer.WriteObject(ms, obj);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
public static T ParseJSON<T>(this string str)
{
T obj = Activator.CreateInstance<T>();
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(str)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
return (T)serializer.ReadObject(ms);
}
}
}
4、解决一例数据库服务器CPU占用资源100%的问题。
最近根据用户技能搜索好友的功能根据新的需求作了调整,要求搜索的结果增加like用户名的结果集。例如:本来是以asp.net这种技能搜索出拥有这种技能的用户列表以供用户寻找好友,现在还要增加一个结果集是以asp.net开头的用户列表如:asp.net01,asp.net02。这两个结果集的排序以论坛专家分的多少为排序的依据。
现在的情况是UserPost表具有15000000的数据量,并且对该表有一个全文检索。根据技能搜索用户列表是通过全文检索进行(contains)得到,而根据用户相拟是通过对表的搜索([UserName] like @key+'%')得到,并且还以order by communityscore desc进行排序。
当这个新功能上线后数据库的CPU总是高居不下,后来通过在数据库端跟踪SQL和存储过程的调用情况就大致找到出问题的语句。分析了原来的语句的写法是把contains和like都写在一个where里了,查看一下执行计划,对于全文检索的搜索的调用耗资非常之大。同时从需求上分析,这个搜索的意图主要还是以技能搜用户为主,以用户名相拟性搜索的用户列表为辅,所以逻辑上可以调整为先从全文检索中获取拥有这此技能的用户列表,再以用户名相拟搜索用户列表,然后进行组合。新的sp如下:
ALTER PROCEDURE [dbo].[ec_UserInfo_FindUsers2]
@top int,
@key nvarchar(20)
AS
BEGIN
SET NOCOUNT ON;
WITH temp(username, communityscore) AS
(
select top(@top) username,communityscore
from dbo.userinfo with (nolock)
where contains(speciality, @key)
order by communityscore desc
),
temp2(username, communityscore, theCount) AS
(
select username, communityscore, row_number() over(order by communityscore desc) as row from temp
)
,temp3(username, communityscore) AS
(
select username, communityscore from temp2 UNION ALL
select top( select COALESCE((select top 1 @top - theCount from temp2 order by theCount desc),@top)) username, communityscore
from dbo.userinfo with (nolock) where [UserName] like @key+'%' order by communityscore desc
)
select username from temp3 order by communityscore desc
END
经过这样的处理后就能把cpu降到正常水平了。@top int,
@key nvarchar(20)
AS
BEGIN
SET NOCOUNT ON;
WITH temp(username, communityscore) AS
(
select top(@top) username,communityscore
from dbo.userinfo with (nolock)
where contains(speciality, @key)
order by communityscore desc
),
temp2(username, communityscore, theCount) AS
(
select username, communityscore, row_number() over(order by communityscore desc) as row from temp
)
,temp3(username, communityscore) AS
(
select username, communityscore from temp2 UNION ALL
select top( select COALESCE((select top 1 @top - theCount from temp2 order by theCount desc),@top)) username, communityscore
from dbo.userinfo with (nolock) where [UserName] like @key+'%' order by communityscore desc
)
select username from temp3 order by communityscore desc
END
这里用到了几个SQL2005的新功能。
a、CTE
b、Ranking函数集。row_number() over (order by xxx desc)
c、top(select ....)函数