Careful when querying on aspnet_users, aspnet_membership and aspnet_profile tables used by ASP.NET 2.0 Membership and Profile provider

Such queries will happily run on your development
environment:

"F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:b69de480-3c96-4ff9-a6b0-356f747fb570"
style=
"padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;">
Select "color:#808080;">* from
aspnet_users "color:#0000FF;">where "color:#000000;">UserName "color:#808080;">=
blabla "color:#FF0000;">‘

Or you can get some user’s profile without any problem
using:

"F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:229f0421-2414-4c8d-b859-c957aa593571"
style=
"padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;">
Select "color:#808080;">* from
aspnet_profile "color:#0000FF;">where "color:#000000;">userID "color:#808080;">=
…… "color:#FF0000;">‘

Even you can nicely update a user’s email in aspnet_membership
table like this:

"F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:5fa685bc-0e74-43c9-8863-c0b67defb704"
style=
"padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;">
Update "color:#000000;">aspnet_membership "color:#0000FF;">SET "color:#000000;">Email =
"color:#FF0000;">newemailaddress@somewhere.com "color:#FF0000;">‘ Where
Email "color:#808080;">=
"color:#FF0000;">‘

But when you have a giant database on your production server,
running any of these will bring your server down. The reason is,
although these queries look like very obvious ones that you will be
using frequently, none of these are part of any index. So, all of
the above results in “Table Scan” (worst case for any query) on
millions of rows on respective tables.

Here’s what happened to us. We used such fields like UserName,
Email, UserID, IsAnonymous etc on lots of marketing reports at
Pageflakes. These are some
reports which only marketing team use, no one else. Now, the site
runs fine but several times a day marketing team and users used
call us and scream “Site is slow”, “Users are reporting extreme
slow performance”, “Some pages are getting timed out” etc. Usually
when they call us, we tell them “Hold on, checking right now” and
we check the site thoroughly. We use SQL profiler to see what’s
going wrong. But we cannot find any problem anywhere. Profile shows
queries running file. CPU load is within parameters. Site runs nice
and smooth. We tell them on the phone, “We can’t see any problem,
what’s wrong?”

So, why can’t we see any slowness when we try to investigate the
problem but the site becomes really slow several times throughout
the day when we are not investigating?

Marketing team sometimes run those reports several times per
day. Whenever they run any of those queries, as the fields are not
part of any index, it makes server IO go super high and CPU also
goes super high – something like this:

"http://omar.mvps.org/images/203b504bbfce_14EA7/clip_image0016.png">
"http://omar.mvps.org/images/203b504bbfce_14EA7/clip_image001_thumb2.png"
width="655" alt="">

We have SCSI drives which have 15000 RPM, very expensive, very
fast. CPU is Dual core Dual Xeon 64bit. Both are very powerful
hardware of their kind. Still these queries bring us down due to
huge database size.

But this never happens when marketing team calls us and we keep
them on the phone and try to find out what’s wrong. Because when
they are calling us and talking to us, they are not running
any of the reports which brings the servers down
. They are
working somewhere else on the site, mostly trying to do the same
things complaining users are doing.

Let’s look at the indexes:

Table: aspnet_users
Clustered Index = ApplicationID, LoweredUserName
NonClustered Index = ApplicationID, LastActivityDate
Primary Key = UserID

Table: aspnet_membership
Clustered
Index = ApplicationID, LoweredEmail
NonClustered = UserID

Table: aspnet_Profile
Clustered
Index = UserID

Most of the indexes have ApplicationID in it. Unless you put
Application=’…’ in the WHERE clause, it’s not going to use
any of the indexes. As a result, all the queries will suffer from
Table Scan. Just put ApplicationID in the where clause (Find your
applicationID from aspnet_Application table) and all the queries
will become blazingly fast.

DO NOT use Email or UserName fields in WHERE clause.
They are not part of the index instead LoweredUserName and
LoweredEmail fields are in conjunction with ApplicationID field.
All queries must have ApplicationID in the WHERE
clause.

Our Admin site which contains several of such reports and each
contains lots of such queries on aspnet_users, aspnet_membership
and aspnet_Profile tables. As a result, whenever marketing team
tried to generated reports, they took all the power of the CPU and
HDD and the rest of the site became very slow and sometimes
non-responsive.

Make sure you always cross check all your queries WHERE and JOIN
clauses with index configurations. Otherwise you are doomed for
sure when you go live.

8 Comments

  1. re: Careful when querying on aspnet_users, aspnet_membership and aspnet_profile tables used by ASP.NET 2.0 Membership and Profile provider

    What if you alter the table and add the indexes yourself?

  2. re: Careful when querying on aspnet_users, aspnet_membership and aspnet_profile tables used by ASP.NET 2.0 Membership and Profile provider

    New indexes slow down INSERT,UPDATE,DELETE because there are additional index to update. It’s better to have least number of index but have the best possible use of them.

  3. re: Careful when querying on aspnet_users, aspnet_membership and aspnet_profile tables used by ASP.NET 2.0 Membership and Profile provider

    Do use additional Indexes, if the architecture of your app makes it easy for you to utilize other columns for any of the functions stated above.

    The additional cost of additional index for dozen thousand of these functions will be negligible.

  4. Introduction

    IwillshowyouhowIbuiltastartpagesimilartoGoogleIGin7nightsusingASP.Ne…

  5. Introduction

    IwillshowyouhowIbuiltastartpagesimilartoGoogleIGin7nightsusingASP.Ne…

  6. What was the problem again?, the server down because use of to much resource over the aspnet_profile table or the performance of that table?

    So can you sacrifice performance for availability?

    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>