Squishy Limits in SQL Server Express Edition

It’s an old story you’ve probably heard before.  Provide a free version of your software product with strict limitations on performance or other specific capabilities so that folks can give it a try without risk, while you minimize the chance of cannibalizing sales of your commercial products.  Microsoft has take this strategy with SQL Server Express Edition, not only to increase adoption in the student market but also to counter the threat of open-source (i.e. free) relational databases like MySQL for entry-level applications.

One such limitation of SQL Server Express Edition is that it supports no more than 1GB of RAM for the instance.  Of course, you could have many Express Edition instances on a single Windows server, each with its own 1GB of RAM.

But what does that metric of 1GB of RAM actually mean?  The key thing to remember is that the restriction is for buffer cache.  Since SQL Server has many other caches, even when not counting the plan cache, there are plenty of other caches within SQL Server.  (Run a query against sys.dm_os_memory_clerks if you’d like to see some of the others).  Because only the buffer cache has the strict 1GB limitation, you can actually watch SQL Server Express Edition’s memory working set size grow to around 1.4-1.5GB due to the other memory caches at play.

Pawel Potasinski, a SQL Server MVP from Poland (Twitter | Blog), once posted an interesting repro for this behavior:

— Assess amount of databases resident in buffer cache

SELECT
 CASE
 WHEN database_id = 32767 THEN 'mssqlsystemresource'
 ELSE DB_NAME(database_id)
 END AS [Database],
 CONVERT(numeric(38,2),(8.0 / 1024) * COUNT(*)) AS [MB in buffer cache] 
FROM sys.dm_os_buffer_descriptors 
GROUP BY database_id 
ORDER BY 2 DESC; 
GO
-- Assess amount of tables resident in buffer cache
SELECT
 QUOTENAME(OBJECT_SCHEMA_NAME(p.object_id)) + '.' +
 QUOTENAME(OBJECT_NAME(p.object_id)) AS [Object],
 CONVERT(numeric(38,2),(8.0 / 1024) * COUNT(*)) AS [MB In buffer cache] 
FROM sys.dm_os_buffer_descriptors AS d 
 INNER JOIN sys.allocation_units AS u ON d.allocation_unit_id = u.allocation_unit_id 
 INNER JOIN sys.partitions AS p ON (u.type IN (1,3) AND u.container_id = p.hobt_id) OR (u.type = 2 AND u.container_id = p.partition_id) 
WHERE d.database_id = DB_ID() 
GROUP BY QUOTENAME(OBJECT_SCHEMA_NAME(p.object_id)) + '.' + QUOTENAME(OBJECT_NAME(p.object_id))
ORDER BY [Object] DESC;
GO
-- Fill up Express Edition's buffer allocation
IF OBJECT_ID(N'dbo.test', N'U') IS NOT NULL
 DROP TABLE dbo.test;
GO
CREATE TABLE dbo.test (col_a char(8000));
GO
INSERT INTO dbo.test (col_a)
 SELECT REPLICATE('col_a', 8000)
 FROM sys.all_objects 
 WHERE is_ms_shipped = 1;
CHECKPOINT; 
GO 100

 The bottom line for the hard memory limit of SQL Server Express Edition is “Yes, it’s limited. But it’s a squishy limit. Not a hard limit.”

Although your mileage may vary, I’d bet a dollar that you’ll find more than 1GB in the active working set for your instance of SQL Server Express Edition.  I am curious, however, if you’re seeing much variation between versions and even service packs of SQL Server?  Let me know if you try this out on more than one version and/or service pack level of SQL Server.  Did it change much between versions?  Let me know!

Enjoy,

-Kevin

-Follow me on Twitter!
Google Author

 

Comments

  1. Yup, same. Do ms advertise this limit of sql express? Id never heard about it before today

Speak Your Mind

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.