I am running a ASP.NET mvc5 app which currently has 5 million users. It is hosted in the Azure cloud. For the authentication I use the Asp.Net Identity for EntityFramework.
Yes, this query is probably the problem. This is why I don't like SQL frameworks.
The problem is here:
WHERE
((UPPER([Extent3].[UserName])) = (UPPER(@p__linq__0)))
The right side is constant and the left side "upper(username)" is SQL engine trying to find somewhere. Index on simple "username" is useless, because it contains simple "username" and not upper(username) values. SQL engine has to calculate upper(username) for all 5 millions lines EVERYTIME you add new user and then find the corresponding value. 7 seconds...
You need to create such index:
create index ix_name on Users(upper(UserName))
Such index will be used automatically by sql engine. But I am afraid, that MS SQL will not allow you to do it without adding computed column (and it is useless for your purpose, because you can not force EF to use another column for username value).
The other option is to force Identity framework not to use UPPER function. But I don't know how.
By the way, I am really surprised to find this type of code in such important package - entity framework. This "searching functional value in index" is on of the basic mistakes when writing efficient sql code.
And one more comment: This everything should have been done by the framework, it is responsible for correct handling of "username" column. It is a bug, this advice is only workaround.