Unfortunately this is a big ol' "it depends". Complicated further by your having so many applications, probably with wildly different IO profiles, sharing the same instance/server and arrays.
Usually you would want to isolate data and log files as the IO profiles are polar opposite. Typically weighted toward random read for data files and sequential write for logs. The log element is somewhat different in your case as you have multiple log files.
I'd start by getting an understanding of the IO the databases are consuming relative to each other.
SELECT
DB_NAME(fs.database_id) AS [Database Name]
, mf.physical_name
, io_stall_read_ms
, num_of_reads
, CAST(io_stall_read_ms / (1.0 + num_of_reads) AS NUMERIC(10, 1)) AS [avg_read_stall_ms]
, io_stall_write_ms
, num_of_writes
, CAST(io_stall_write_ms / (1.0 + num_of_writes) AS NUMERIC(10, 1)) AS [avg_write_stall_ms]
, io_stall_read_ms + io_stall_write_ms AS [io_stalls]
, num_of_reads + num_of_writes AS [total_io]
, CAST((io_stall_read_ms + io_stall_write_ms)
/ (1.0 + num_of_reads + num_of_writes) AS NUMERIC(10,1)) AS [avg_io_stall_ms]
FROM
sys.dm_io_virtual_file_stats(NULL, NULL) AS fs
INNER JOIN sys.master_files AS mf
ON fs.database_id = mf.database_id
AND fs.[file_id] = mf.[file_id]
ORDER BY
DatabaseName ASC, mf.physical_name
-- num_of_reads DESC
-- num_of_writes DESC
OPTION (RECOMPILE) ;
If you can format the output of this into a readable form and add to your question, someone can make a more educated guess at the best use of your 18 disks.
If I was doing this blind, I'd probably start off allocating:
- 6 RAID10 for the busiest database's data files
- 6 RAID10 for the other database's data files
- 4 RAID10 shared Logs
- 2 RAID1 Tempdb (your single disk configuration is a risky single point of failure)
Assuming that:
- the SAN hosts other arrays and therefore hot spares are available from a pool
- snapshot isolation isn't in use or isn't placing heavy demands on tempdb
Edit: Following update to question regarding queue lengths:
Queue length counters are oft misunderstood when evaluating SQL Server performance. One of the best analogies I've come across is from a Simon Sabin blog post, Disk Queue Length - a bit like buying Guiness.
In your case, they are so low that you might get by with half the spindles. Would still be interesting to see the other stats from the above query though.
Without the execution plans, it's impossible to say, but I've seen a similar scenario pop up. Had a client once whose database was teetering on the edge of being able to fit in memory. Someone added an index on a large table, queries started using it (which kept big chunks of it in memory.) Things all used to fit in memory perfectly, but they hit a tipping point where they started to hammer the disk much more frequently. We caught it via the sudden spike in disk access and a sudden drop in Page Life Expectancy.
Ideally, you should capture these Perfmon counters continuously on database servers, and alert when they drop dangerously. That'd help correlate things so you'd know if the PLE drop also happened, and that'd indicate you might be running out of memory to cache things.
Best Answer
You should understand how SQL Server data storage works. It isn't like you are used to with client applications.
For performance and other reasons, SQL Server reserves blocks of space on the HD (in the MDF file) for the each database's use (including tempDB). That space as seen by the file size is still reserved even if it is not actively being used.
Whenever the database exceeds the allocated space (depending on the file growth settings), it may grow the amount of reserved space (never to give it back). So 30GB is either the initially reserved space or you did some huge operation at some point that caused it to grow really big.
Tips:
You can use sp_spaceUsed to see how much of that file is actually in use.
You can shrink the database back to size (if it isn't all used) with DBCC_SHRINKDATABASE
As tempting as it may be, don't turn on the DB's AutoShrink property.
As for the last modified date, here is what I found: