First you need to figure out what the actual problem is. The sys.dm_os_wait_stats DMV can help with that. Most values in there are accumulative, so you need to capture it a few times over an extended period to see what is actually going on.
One of the things that this DMV can tell you is if you have RAM pressure. The graphic you posted is basically useless as SQL Server uses all memory it can get (if it needs to). So this is only showing that that mechanism is working.
Once you figured out what your biggest problem is, come back here to get more help.
There are a few wait_types that can be considered noise. You can filter many of those out with this query:
SELECT wait_type,
wait_time_ms / 1000.0 AS wait_in_sec,
(wait_time_ms - signal_wait_time_ms) / 1000.0 AS resource_wait_sec,
signal_wait_time_ms / 1000.0 AS signal_sec,
waiting_tasks_count AS wait_count,
100.0 * wait_time_ms / SUM (wait_time_ms) OVER() AS percentage
FROM sys.dm_os_wait_stats
WHERE wait_type NOT IN (
'CLR_SEMAPHORE', 'LAZYWRITER_SLEEP', 'RESOURCE_QUEUE', 'SLEEP_TASK',
'SLEEP_SYSTEMTASK', 'SQLTRACE_BUFFER_FLUSH', 'WAITFOR', 'LOGMGR_QUEUE',
'CHECKPOINT_QUEUE', 'REQUEST_FOR_DEADLOCK_SEARCH', 'XE_TIMER_EVENT', 'BROKER_TO_FLUSH',
'BROKER_TASK_STOP', 'CLR_MANUAL_EVENT', 'CLR_AUTO_EVENT', 'DISPATCHER_QUEUE_SEMAPHORE',
'FT_IFTS_SCHEDULER_IDLE_WAIT', 'XE_DISPATCHER_WAIT', 'XE_DISPATCHER_JOIN', 'BROKER_EVENTHANDLER',
'TRACEWRITE', 'FT_IFTSHC_MUTEX', 'SQLTRACE_INCREMENTAL_FLUSH_SLEEP')
AND waiting_tasks_count >0
AND wait_time_ms >0
ORDER BY wait_time_ms DESC;
(based on http://www.sqlskills.com/blogs/paul/survey-what-is-the-highest-wait-on-your-system/)
Your process is sound. Putting the index on the date column will make it much faster for SQL Server to find the rows that it is looking for. Without the nonclustered index SQL Server will need to scan the production table every time you go to delete the rows. This means that SQL will need to load the entire table from disk each time the DELETE TOP 500 runs. Having (and using) the nonclustered index will be essential for getting this done quickly.
As for the memory setting, you'll want to set that to give SQL Server access to as much RAM as possible. You are correct, SQL Server will release RAM if other applications need it. The fact that you are seeing PAGEIOLATCH_EX and PAGEIOLATCH_SH waits tells me that you don't have enough RAM to keep the nonclustered index which you created in memory when combined with the other data which the system is using. Increasing the memory settings on the SQL Server will help this, provided that you have more memory in the server.
Those two wait types (PAGEIOLATCH_EX and PAGEIOLATCH_SH) tell us that you are waiting for the disk to respond to your request for more data to be loaded. The more data you can keep in memory the less data you'll need to read from the disk.
Best Answer
Firstly you should take into account the
page_count
of the index. If thepage_count
is less than 1000 (or whatever you decide) then you should ignore the index.We have a maintenance script which analyses the
page_count
and fragmentation of the indexes and follows the following guideline:-ALTER INDEX … REORGANIZE
)ALTER INDEX … REBUILD
)(ONLINE= ON
for Enterprise Editions)This is a starter to find out where you are at present:-
It all depends on your requirements. How is performance effected when you only rebuild once a week? Could you send the report once a week straight after a rebuild? I would base line the performance in a test environment (if possible), and if it doesn't degrade too much, only perform the index maintenance once a week.
An agent job could be something like:-