SQL Server on a virtual machine behaves almost exactly like SQL Server on metal, and that is the problem. It cannot tell that it is sharing. Every counter it shows you describes a machine that does not really exist, and when the real machine underneath is busy, your guest has no way to say so.

Are You Even On One?
Start here, because plenty of people are not sure. SQL Server will tell you:
SELECT virtual_machine_type_desc, cpu_count
FROM sys.dm_os_sys_info;My own development machine answers like this:
virtual_machine_type_desc cpu_count
HYPERVISOR 16HYPERVISOR means the engine knows it is a guest. NONE means it believes it is on real hardware. That is all the engine knows. It can tell you it is a guest, and nothing at all about the host it is sitting on.
Sixteen Processors That Are Not Yours
The count above says sixteen. Those are sixteen virtual processors, which is a promise of scheduling, not a reservation of silicon.
When your guest wants to run on all sixteen, the host has to find sixteen physical threads free at the same moment. On a busy host with other guests, that wait can be real and repeated. The time is known on the host side as CPU ready time, and it is the single most useful number in this whole subject.
Inside the guest that waiting is invisible. Windows shows low processor use. SQL Server shows a query taking longer with no obvious wait. The work is not slow, it is queued, and nothing inside the machine can see the queue.
The practical lesson is uncomfortable for a DBA. Some of your evidence lives on a console you may not have access to, and you have to go and ask for it.
Bigger Is Not Faster
This is the mistake I see most often. A virtual machine is slow, so somebody gives it more virtual processors, and it gets slower.
The reason is scheduling. A guest with eight virtual processors needs eight free physical threads to run. A guest with four needs four, and four are easier to find than eight. Past a certain point, asking for more means waiting longer for a slot.
So sizing a database guest is not like ordering hardware. Start smaller than feels right, measure, and grow only with evidence.

Memory You Were Promised and Memory You Have
Hypervisors can hand out more memory than the host physically holds, on the reasonable assumption that not every guest needs all of it at once. SQL Server is the guest that breaks that assumption, because it takes memory and keeps it.
If the host has to claw memory back, it can do so in ways the guest experiences as its own pages going to disk. Performance falls off a cliff and every counter inside the guest looks like a storage problem.
For any database guest that matters, reserve the memory on the host so it cannot be taken back. Then set max server memory inside SQL Server, leaving room for the operating system. Those two settings together are worth more than most tuning work.
Storage Has Further to Travel
Your data file is a file, on a datastore, on an array, reached over a network, shared with other guests. Each of those layers is reasonable and each one adds a little latency.
This is the query I run first, and it is the same one I would run on physical hardware:
SELECT DB_NAME(vfs.database_id) AS database_name,
vfs.io_stall_read_ms / NULLIF(vfs.num_of_reads, 0) AS avg_read_ms,
vfs.io_stall_write_ms / NULLIF(vfs.num_of_writes, 0) AS avg_write_ms,
mf.physical_name
FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS vfs
JOIN sys.master_files AS mf
ON mf.database_id = vfs.database_id AND mf.file_id = vfs.file_id
ORDER BY avg_read_ms DESC;Read the numbers as a starting point for a conversation, not a verdict. These are averages since the service started, so one bad hour months ago is still in there. What they are good for is pointing at the one file that is far worse than the others.
Snapshots Are Not Backups
A hypervisor snapshot of a running database guest is not a database backup, and nobody should be relying on one.
A snapshot left in place also grows a change file that keeps getting larger and slower for as long as it exists. I have seen a forgotten snapshot from a Tuesday quietly degrade a server for a month.
Take proper database backups. If the virtual machine platform is also protecting the guest, make sure somebody knows which of the two is the real recovery plan.
What I Check First
Four things, in order. Is CPU ready time low on the host. Is the memory reserved. Is max server memory set inside SQL Server. Are there any snapshots.
Three of those four answers live outside the database, which is the honest summary of this whole topic. Virtualisation did not change SQL Server. It moved half the evidence somewhere you have to ask for it.
A virtual machine is not a smaller server, it is a server that cannot see who else is in the room.
This post was rewritten from scratch in September 2026. The original, published on 2013-04-19, was a short announcement about something that no longer exists. The address is the same, the subject is now a basic idea worth keeping.
Published by Pinal Dave on SQLAuthority. More of my work at pinaldave.com.




