Choosing innodb_buffer_pool_size
My last post about Innodb Performance Optimization got a lot of comments choosing proper innodb_buffer_pool_size and indeed I oversimplified things a bit too much, so let me write a bit better description.
Innodb Buffer Pool is by far the most important option for Innodb Performance and it must be set correctly. I’ve seen a lot of clients which came through extreme sufferings leaving it at default value (8M). So if you have dedicated MySQL Box and you’re only using Innodb tables you will want to give all memory you do not need for other needs for Innodb Buffer Pool.
This of course assumes your database is large so you need large buffer pool, if not - setting buffer pool a bit larger than your database size will be enough. You also should account for growth of course. You need buffer pool a bit (say 10%) larger than your data (total size of Innodb TableSpaces) because it does not only contain data pages - it also contain adaptive hash indexes, insert buffer, locks which also take some time. Though it is not as critical - for most workloads if you will have your Innodb Buffer Pool 10% less than your database size you would not loose much anyway.
You also may choose to set buffer pool as if your database size is already larger than amount of memory you have - so you do not forget to readjust it later. This is also valid approach as if it is Dedicated MySQL Server you may not have a good use for that memory anyway.
Another thing you should keep into account is Innodb allocates more memory in structures related to buffer pool than you specify for it - I just checked on our set of boxes which use 12GB buffer pool (with very small additional pool and log buffer) and total amount of memory allocated by Innodb is typically a bit over 13GB. Vadim has posted some numbers on it a while back.
After you have decided with database size you need to check if there are any restrictions on Innodb Buffer Size you can use. Typically you would see restriction applying only on 32bit systems but we see these can be still spotted in a wild, especially in Windows world. The restriction would normally apply to total amount of memory process can allocate so make sure to leave space for other MySQL needs while factoring this in.
The next step would be to decide How Much Memory do you need for other needs. This needs would be OS needs - your system processes, page tables, socket buffers etc all need memory. I would put this to 256M for small sized boxes to 5% of memory size on the big boxes, though it can be even less than that. Besides Operating System needs you also have MySQL needs - these include MySQL buffers - query cache, key_buffer, mysql threads, temporary tables, per thread sort buffer which can be allocated. There are also things like innodb additional memory pool (which can grow more than memory you allocated for it, especially in case you have large amount of tables).
I could tell you some numbers, for example sum up all your global buffers plus add 1MB for each connection you’re planning to have but in reality the number can vary significantly depending on the load. Idle connections for example will consume significantly less memory than connections doing work with huge temporary tables and otherwise running complex queries. It is usually much better to simply check it. Start MySQL With 10GB Innodb buffer pool for example and see how large RSS and VSZ get in “ps” output on Unix Systems. If it gets to 12GB when you need 2GB for other stuff, and you can increase it a bit to be on the safe size and scale appropriately.
The third important memory consumer would be OS cache. You want to bypass cache for your Innodb tables but there are other things you need OS cache for - MyISAM tables (mysql database, temporary etc) will need it, .frm file, binary logs, or relay logs, Innodb Transactional Logs also like to be cached otherwise OS will need to do reads to serve writes to these log files as IO to the log files is not aligned to the page boundary. Finally you likely have some system script/processes running on the system which also need some cache. The number can be a lot different depending on system workload but generally I’d see values from 200MB to 1GB good estimates for this number.
Eliminate Double Buffering - This is again very important for buffer pool size choice. You do not want OS to cache what Innodb is caching already. Innodb cache is more efficient compared to OS cache because there is no copying, due to adaptive hash indexes, ability to buffer writes and number of other factors so you just want to make your OS to give a way to Innodb. Note it is not enough to block OS from swapping - as I already mentioned the OS cache will be needed for other things and if you will not make Innodb to bypass OS buffering Innodb TableSpace IO will wipe out cache because it typically makes most of the IO on the system. On Windows you do not need to do anything. On Linux, FreeBSD, Solaris you need to set innodb_flush_method=O_DIRECT. On other Operating Systems you may be able to select it on OS level but make sure to do it. There is a small niche case when it hurts - when you do not have RAID with BBU and your workload is very write intensive but there are always exceptions.
Make your OS Happy The other challenge you may have is making your OS happy and avoiding swapping out MySQL Process or other important processes to make room for file cache. OS may find it unfair there is MySQL process which consumes 95% of memory and the cache is just couple of percent. Some people try to solve it with disabling swap file but it can hurt another way - OS may kill MySQL Process running out of memory (or thinking it is running out of memory) which may happen ie in case of unexpected connection spike. Plus not all kernels work quite well with swap disabled and there are other reasons against it. For some people having no swap works, though they usually play on the safe side, having enough “free” memory used as Cache and Buffers. Kevin Burton wrote a good post about his experiments.
Depending on OS you may want to do different VM memory adjustments. You may want to make MySQL to use Large Pages for allocating Innodb Buffer Pool and few other buffers, which may have other performance benefits as well. Tuning your VM to be less eager to swap things by echo 0 > /proc/sys/vm/swappiness is another helpful change though it does not always save you from swapping. Some specific kernel versions may have other settings to play with. Finally you can try locking MySQL in memory by using –memlock - just be careful as in case you have memory usage spike you may have MySQL Server being killed by OS instead of temporary swapping few things out.
Two things to note about OS Swapping. First looking at “swap used” is not really helpful because you do not know what lies in the swap - there are portions of both MySQL Process and other processes which you do not need during normal operation so it is OK to get them in the swap. Make sure however the swapping is not happening ie your VMSTAT “si/so” columns are zero on Linux. Couple of swaps per minute would not hurt bad but if you’re doing 100+ pages per second of swap IO you’re in trouble.
Second, many people think - who cares if some of buffer pool is swapped out, I would have one IO to fetch page if I would have small buffer pool and now I have one IO to fetch page data swapped out. This is very wrong thinking. First OS would have to swap even clean page from Buffer Pool while Innodb can simply discard that pages in case of memory pressure. But what is more important Innodb algorithms are finely tuned with consideration what is in memory and what is on disk, for example when Innodb tries to avoid holding latches while doing IO while there could be locks set while accessing pages in the buffer pool. If page turns out to be in swap rather than memory you will have another threads piling up waiting on the same lock till IO completion, while they may well have all data they need to proceed in the innodb buffer pool.
I guess these clarifications work better than 70-80% recommendation and of course you should not stick just to 50GB if you have 64G of memory - values of 56-60G would likely make more sense, and depending on bunch of other settings 12G or 14G may well be good choice for 16GB Box, though I would take care at values close to 14G as there is not much room left for other things.
P.S I only described Innodb Buffer Pool selection for dedicated Innodb system. If you have fair amount of MyISAM, Archive, PBXT, Falcon or other storage engines then you will get into complex balancing game besides considering all these factors.
19 Comments











del.icio.us
digg
[...] it to 12G on 16GB box. UPDATE: If you’re looking for more details, check out detailed guide on tuning innodb buffer pool innodb_log_file_size - This depends on your recovery speed needs but 256M seems to be a good [...]
Pingback :: November 3, 2007 @ 4:44 pm
Have you any recommendation about buffer settings for people using both InnoDB and MyIsam on the same server?
Is there any rule of thumb to follow in this case? In my case I prefer to keep logging data in MyIsam table because they are more compact (use much less space) and the insert speed is higher (in my case)
Comment :: November 4, 2007 @ 12:29 pm
Tom,
As I mentioned this becomes rather tricky question - it depends on sizes of MyISAM vs Innodb as well as workload.
Generally you ever have to use your intuition or do benchmarks if you want optimal numbers. For 50:50 space usage I would use 2:1 split towards giving more memory to Innodb ans then for MyISAM part use about 1/3-1/2 for Key buffer and just use other part as extra OS cache as MyISAM depends on that heavily.
Comment :: November 4, 2007 @ 1:35 pm
[...] Check it out! While looking through the blogosphere we stumbled on an interesting post today.Here’s a quick excerpthere. Same as during last time I will provide my comments for some of the answers under PZ and will use HT for original Heikkis answer. Q26: You also say on Unix/Linux only one read-ahead can happen at the same time. How many read-aheads can be waiting in Queue when or Innodb will schedule more read-aheads only when given read-ahead is completed? HT: A query thread normally posts about 64 page read requests per a readahead. The InnoDB buffer is 256 page read requests for the aio read thread. [...]
Pingback :: November 17, 2007 @ 1:35 pm
[...] This is the cached version of http://www.mysqlperformanceblog.com/2007/11/03/choosing-innodb_buffer_pool_size/ We are neither affiliated with the authors of this page nor responsible for its content. Choosing innodb_buffer_pool_size [...]
Pingback :: November 27, 2007 @ 1:37 am
[...] innodb_buffer_pool_size (for InnoDB - default at only 8MB) - reference [...]
Pingback :: April 5, 2008 @ 1:11 am
[...] 3rd 2007 11:41pm [-] From: mysqlperformanceblog.com [...]
Pingback :: June 8, 2008 @ 2:50 pm
Kabonfootprint is the one who open our mind in a better place. kabonfootprint
Comment :: September 11, 2008 @ 12:52 pm
So when not using MyISAM, it would probably be helpful to reduce all its relevant buffers. Could you post more details about it?
Comment :: October 22, 2008 @ 11:43 am
Sure. read_buffer_size and key_buffer_size are the most important and only key_buffer_size is statically allocated (even if you do not use much of MyISAM). Default value for key_buffer is OK even if you do not use MyISAM though if you have raised it dramatically I’d recommend cutting it back to 16M or even less (depending on implicit temporary table use)
Comment :: October 24, 2008 @ 2:17 am
This may be little bit off topic.
With 5.1, if your innodb_buffer_pool is FULL (indicated by “Free buffers”) and you still don’t have everything cached (Buffer pool hit rate < 1000), your response time will go 2 or 3 times longer than the response time you get while building up the cache.
Example, say you have 100 processes reading off the database, when you first start the server (cache is empty) and started the processes, you may get an average response time of 50ms. Then it slowly dropped to 20ms while cache is building up (free buffer decrease, cache hit ratio increase). But now, your cache is full and your cache hit ratio is at 95%, all of sudden, the response time would jump to 60ms or even 80ms.
Comment :: January 13, 2009 @ 12:16 pm
This is easy to explain as flushing dirty pages to make some room for pages that aren’t in the buffer pool. Watch the number of *dirty* pages. Compare that to innodb_buffer_pool_max_dirty_pct.
Is this specific to 5.1? Have you see it behave differently on 5.0? I would expect to see the same behavior in 5.0, but tell me if I’m wrong.
Comment :: January 13, 2009 @ 1:22 pm
That’s exactly the reason I brought it up here. 5.0.67 and 5.0.67 with google patch do NOT have this behavior. The response time stabilized after the buffer pool is full.
Seems like 5.1 has problems to manage eviction.
Comment :: January 14, 2009 @ 9:11 am
I haven’t seen this in the real world, but I don’t disbelieve you. If you want help solving this, I am pretty confident we can find out what is going on and either find a workaround or discuss the possibility of a patch. You could also try a bug report via MySQL, but I don’t know how urgent this is for you to solve.
Comment :: January 14, 2009 @ 12:23 pm
My server configuration
2GB /intelquad
PROBLEM : i start my sql 4.0.12 with innodb_buffer_pool_size = 128
After starting the server my.cnf becomes my_cnf.bak.
but randomly the configuration is reseted and all my previous config is set to the default values inlcuding innodb_buffer_pool_size which is set to 5Mb or so
This happes only since this week.
Do you know what to do ?
I am kind of very stressed due to this .
I can;t migrate now to other version of mysql.
Comment :: February 26, 2009 @ 3:15 am
I now realize I know absolutely nothing about MySQL. Thanks for all the info (book and blog).
Comment :: March 30, 2009 @ 4:14 pm
[...] innodb_buffer_pool_size 设为内存的70%-80%都是安全的。我在一个16G的服务器上把它设成12G。 UPDATE: 如果你想了解更多的细节,请查看tuning innodb buffer pool [...]
Pingback :: April 19, 2009 @ 7:47 am
[...] UPDATE 关于它具体的查看http://www.mysqlperformanceblog.com/2007/11/03/choosing-innodb_buffer_pool_size/ innodb_log_file_size [...]
Pingback :: April 19, 2009 @ 7:51 am
Is the INNODB_BUFFER_POOL shared across all databases or allocated per database? I’m getting ready to run a mysql server in a VMWare environment with a not very busy database. Maybe 10 concurrent users max. With about 5000 records being added per year max per database. I was thinking about running the virtual OS with 2GB of RAM.
Comment :: June 13, 2009 @ 9:35 pm