[MDEV-29035] review InnoDB page fill factor Created: 2022-07-05 Updated: 2022-08-16 |
|
| Status: | Open |
| Project: | MariaDB Server |
| Component/s: | Storage Engine - InnoDB |
| Fix Version/s: | None |
| Type: | Task | Priority: | Minor |
| Reporter: | Axel Schwenke | Assignee: | Axel Schwenke |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Attachments: |
|
||||||||
| Issue Links: |
|
||||||||
| Description |
|
Tests undertaken in PERF-206 show significant performance improvements of 30% for sysbench-tpcc when INSERT uses a column default value instead of NULL. The reason is that the row is UPDATEd later, filling proper values for the columns inserted as NULL. This leads to a growing row image which eventually leads to a page split. The page split in turn leads to mutex contention. The issue has been observed for MySQL as well, as explained here We should review if the hardcoded page fill factor of 15/16 for InnoDB can be chosen better. Other DBMS use a lower fill factor of i.e.70% (PostgreSQL) or make it configurable (Oracle DB, configurable per table). |
| Comments |
| Comment by Axel Schwenke [ 2022-07-05 ] | ||||||||||||||
|
I just found a KB entry about a global variable innodb_fill_factor. But it says it's only used for bulk operations. And indeed grepping for fill_factor in the InnoDB code gives only meaningful hits in btr0bulk.cc. What is more: the variable defaults to 100. WTF? I think it should be also used for INSERT to the tail of a table. If such an INSERT would fill the page beyond the innodb_fill_factor, the row should go to a new page instead. This would cover most real world usecases. | ||||||||||||||
| Comment by Axel Schwenke [ 2022-07-07 ] | ||||||||||||||
|
This shows the impact of setting innodb_fill_factor=90 instead of leaving it at the default of 100. For INSERT NULL the effect is clearly visible even though it impacts only the preloaded data (and not rows inserted during the benchmark). | ||||||||||||||
| Comment by Axel Schwenke [ 2022-07-07 ] | ||||||||||||||
|
The data set size as reported by INFORMATION_SCHEMA for 1000 (10x 100) warehouses is not grown as one would expect:
The variant using DEFAULT is indeed a little bigger, but the difference between a fill factor of 90% vs. 100% is not visible. It should also be in the order of 10%. This could be a side effect of the measuring method. It uses:
although KB says: | ||||||||||||||
| Comment by Marko Mäkelä [ 2022-08-02 ] | ||||||||||||||
|
Since MariaDB Server 10.2 (and MySQL 5.7), there are two code paths for inserting records into index trees. As noted in Postgres CREATE TABLE defaults to fillfactor=100 (complete packing). There is a Postgres benchmark that studies the impact of the fill factor. | ||||||||||||||
| Comment by Axel Schwenke [ 2022-08-02 ] | ||||||||||||||
|
MDEV-29035 is about many issues:
| ||||||||||||||
| Comment by Marko Mäkelä [ 2022-08-02 ] | ||||||||||||||
I would suggest you to test the bulk load mechanism. The scope of this MDEV-29035 could be reduced to ensure that innodb_fill_factor will affect the normal DML code path as well. Maybe we should also introduce a proper index option for the MERGE_THRESHOLD, which was introduced as an index and table comment hack in MySQL 5.7 and MariaDB Server 10.2. | ||||||||||||||
| Comment by Axel Schwenke [ 2022-08-16 ] | ||||||||||||||
|
I patched support for bulk loading ( With fill_factor=95 all subsequent UPDATEs and INSERTs fit onto the page. The dataset has no need to grow and the performance is much better than with the default fill_factor=100. | ||||||||||||||
| Comment by Axel Schwenke [ 2022-08-16 ] | ||||||||||||||
|
Note: OLTP read-write 50:50 = 10 point selects, 4 index updates, 4 non-index update, 1 delete, 1 insert. |