使用SimpleMembershipProvider的.NET MVC中的用户SELECT非常慢

时间:2014-06-12 08:54:23

标签: asp.net-mvc asp.net-web-api azure-sql-database simplemembership

我构建了一个.NET MVC4 / Webapi2应用程序,它使用SimpleMembershipProvider进行身份验证。从yersterday开始,所有app都非常慢,所以我用NewRelic监控它。数据库占用了95%的Web请求,以下SQL请求占据了数据库时间消耗的99%:

SELECT [Id] FROM [User] WHERE (UPPER([UserGuid]) = UPPER(@?))

我想这可以通过以下方式调用:

WebSecurity.CurrentUserId

用户表中有550 000行。

你知道是什么让这个请求变得如此缓慢吗?

1 个答案:

答案 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);
    }
}