我构建了一个.NET MVC4 / Webapi2应用程序,它使用SimpleMembershipProvider进行身份验证。从yersterday开始,所有app都非常慢,所以我用NewRelic监控它。数据库占用了95%的Web请求,以下SQL请求占据了数据库时间消耗的99%:
SELECT [Id] FROM [User] WHERE (UPPER([UserGuid]) = UPPER(@?))
我想这可以通过以下方式调用:
WebSecurity.CurrentUserId
用户表中有550 000行。
你知道是什么让这个请求变得如此缓慢吗?
答案 0 :(得分:4)
问题是每个查询都扫描550K的记录。当然这将非常缓慢。第一步是定义UserGuid字段的索引(如果您还没有)。
CREATE INDEX
UX_User_UserGuid
ON [User] (
[UserGuid]
);
定义后,检查是否有帮助。它没有99%,因为必须为每条记录计算UPPER呼叫。因此,第二步是确保UserGuid具有不区分大小写的排序规则,因此不需要UPPER调用。
SELECT
collation_name
FROM
sys.columns
WHERE
object_id = OBJECT_ID('User')
AND name = 'UserGuid'
您的结果必须包含" CI ",这意味着" Case-Insensitive"。如果不是,则需要更改排序规则。
第三个问题是SimpleMembershipProvider内部。 UPPER调用是硬编码的,因此您必须将其替换为您自己的实现。 Smth喜欢这个:
public class MyCustomProvider : WebMatrix.WebData.SimpleMembershipProvider
{
public override MembershipUser GetUser(string username, bool userIsOnline)
{
int userId = /*
get from your database without any UPPER calls
just like "SELECT [Id] FROM [User] WHERE [UserGuid] = @?"
*/
return this.GetUser(userId, userIsOnline);
}
}