I have a couple of tables (User & UserRecord) in my database that get extremely fragmented (like 99%) and cause the whole database and therefore the website to grind to a halt.
UserRecord is kind of like a snapshot of that user at a point in time. User is like the master record for that user. User has 0 to many UserRecords. User has around a million rows, UserRecord has around 2.5 million. These tables get written to a lot. They're also being searched a lot. They're both going to get a lot bigger. The main indexes getting badly fragmented are the primary keys of the User and UserRecord tables.
The DB is SQL Server 2012 and I'm using Entity Framework and I'm not using any stored procedures.
Tables look something like this:
USER
UserName string PK ClusteredIndex
FirstName string
LastName string
+SeveralMoreRows
USER_RECORD
UserRecordId int PK ClusteredIndex
ListId int FK(List)
UserName string FK(User) NonClusteredIndex
Community string NonClusteredIndex
DateCreated datetime
+LotsMoreRows
LIST
ListId int PK & ClusteredIndex
Name string
DateCreated datetime
(not sure if List this is important or not but thought I'd include it as it's related to User_Record. List has 0 to many UserRecords)
We've set a SQL Maintenance plan to rebuild the indexes daily which does help, but is sometimes not enough.
A friend has suggested we use two databases, one for reading, one for writing, and we sync the read DB from the write DB. Not that I know anything about doing this, but the first problem I see with this solutation is that we need up to date data when viewing the site. For example if we update a User details or a UserRecord, we want to see those changes straight away.
Does anyone have any suggestions on how I can fix this problem before it spirals out of control?
You can fix index fragmentation by rebuilding or defragmenting the index. If the fragmentation level is low, you can defragment the index. If it's high, then you should rebuild the index. You can use SQL Server Management Studio (SSMS) or T-SQL to get started managing index fragmentation.
Fragmentation ExamplesBecause the target page is full enough that the new row does not fit, SQL Server splits the page roughly in half and inserts the new data on the new page, as shown in the following figure. Now, the logical order of the index does not match the physical order, and the index has become fragmented.
Fragmentation happens when the logical order of pages in an index does not match the physical order in the data file. Because fragmentation can affect the performance of some queries, you need to monitor the fragmentation level of your indexes and, if required, perform re-organize or rebuild operations on them.
Page Density (full) – is the percentage of data that fills each index page. If the percentage is below 50%, each Extent read into memory will be equivalent to less than 4 pages of index data instead of the optimal 8 pages.
Clustered indexes control the order of the data on the DISK. This is one of the main reasons why it's usually recommended that you set up a always increasing integer key to act as the clustered index. This way as more data is added to the table, they're added to the end of the currently existing data.
If it's not an autoincreasing number and new rows may contain values that would be ordered somewhere between existing values, then SQL Server will basically push the data onto the disk where it belongs (to retain the order of the clustered index key values), producing fragmentation and potentially severe overhead as IO writes further slowing down the database.
I suspect you have the same problem with your UserRecord values.
So what I would do, is add a separate clustered autoincreasing primary key to each table and rework your FK references & queries where necessary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With