Suggested SQLite3 DB Optimizations

Ohhhh? That’s interesting.

The same binary hack can be made to the Windows exe. Sed exists for windows, and there are lots of other binary-friendly editors.

Note that a larger page_size will itself increase the amount of memory used for cache. Page size is the single biggest help anyway. Plus it doesn’t need to be performed for each upgrade.

Plex offers server downloads for Windows, macOS, FreeBSD, and Linux. I decided to test them all with fresh installs of 1.27.0.5849-99e933842 (Update: I skipped FreeBSD after finding consistent results on the other operating systems). All values below are for “PRAGMA page_size”.

macOS:
DB = 1024
BLOBS.DB = 1024

Windows:
DB = 1024
BLOBS.DB = 1024

Linux (Ubuntu 22.04):
DB = 1024
BLOBS.DB = 1024

1 Like

FreeBSD is 1024 as well.

And unless Plex is doing something really surprising, every other platform too.

If they don’t exist when Plex starts, the active database files are cloned from the distribution template file Resources/com.plexapp.plugins.library.db, which is 1024.

Sorry for the confusion, it was 4096 because I changed it a few year ago after a reddit post made the same discovery and sugjested changing the value.

I’m confortable enough to edit the database, but not to alter the binaries, Plex have enough crash cases already, if i do change something in the binaries everytime it will have a problem I will be wundering if it was my fault :slight_smile:

That is a reasonable and prudent position. :slight_smile:

I have never actually gone beyond page sizes of 4k or 8k (with the block size of the filesystem at 4k), since at that point it starts slowing down writes enough to not be worth it anymore.

I would think the ideal value of page_size should be the same (or at most 2x of the value) as the block size of the filesystem without unduly effecting writes.

From https://phiresky.github.io/blog/2020/sqlite-performance-tuning/:

useful if you are storing somewhat large blobs in your database and might not be good for other 
projects where rows are small. For writing queries SQLite will always only replace whole pages, so
this increases the overhead of write queries.

Increasing cache_size to 512M or even 1024M, on the other hand, should give a significant improvement.


Thread from Emby when they made these options configurable last year and the corresponding tests with various options & their results: https://emby.media/community/index.php?/topic/96065-performance-improvements-for-large-databases/

Link requires user sign-in.

As a reminder for anyone else that decides to try this, the value for cache_size is in kibibytes.

512MB = 500000 KiB

EDIT: As mentioned, a positive value defines total page count. A negative value defines a target size of cache. The old default was 2000 pages which it appears Plex has simply never updated.

*Backwards compatibility note:* The behavior of cache_size with a negative N was different prior to [version 3.7.10](https://www.sqlite.org/releaselog/3_7_10.html) (2012-01-16). In earlier versions, the number of pages in the cache was set to the absolute value of N.

The default changed in 2012 to -2000 to define cache_size as 2000KiB instead of 2000 pages. However, since Plex is still using a positive integer, the cache size will be pages (2000) * page_size (default of 1024). This has been stated several times by @Volts. If you crank up cache_size to 9999 and increase the page_size to the SQLite recommended default of 4096, you have increased your memory footprint to a whopping 40M. A max setting of 9999 * 65536 will still only consume ~655MB.

Not sure if this is a “if you don’t know, don’t do it” type of thing, but I’ve managed to change my page size, just unsure of where the cache_size portion needs to be executed from? /usr/lib/plexmediaserver/ ?

Thank you in advance, this thread has been a great read!

It won’t be possible to try this right now with binary editing since the number of characters need to be same while replacing so the most you can try is 9999 (positive value means pages) or -999 (negative meaning kibibytes).

The above mentioned command should work when executed from /usr/lib/plexmediaserver/:

If executed from elsewhere, you need to specify the complete path of the executable like /usr/lib/plexmediaserver/Plex Media Server

2 Likes

Great, thank you very much!

As mentioned by @gbooker02, that value is for iTunes and doesn’t really need to be changed.

2 Likes

It is also worth mentioning the obvious:

Any binary changes won’t survive Plex updates unless you script for sed to run after each update.

3 Likes

So far it looks like the changes have been surviving updates. I run a pragma check after every update and the page size has stayed at 65536 each time. I’ve only ever had to run the tweaks once when I first did it.

Overall client performance has been great, items on pages load almost instantly!

2 Likes

Following this with great interest, anything that boosts performance is great in my book… At least my 64 GB will get some usage out of them!

Although, I jumped in rather too quick, and found out I can’t edit the settings from the .db in windows, and this sed tool isn’t exactly self explanatory, is there a way to use this on Windows (Server) and to set those values there?

edit: managed to edit in the new cache_size, although most PRAGMA values can’t be adapted/changes/refuse to save :\

Low effort bash script I threw together for the binary modifications:

#!/bin/bash

# Parameters are for linuxserver/plex containers
# Adjust for other container distributions
# https://forums.plex.tv/t/suggested-sqlite3-db-optimizations/794749/2

CONTAINER="plex"
SHELL="/bin/bash"
PLEX_DATA="/config/Library/Application Support/Plex Media Server"
STOP_PLEX="s6-svc -d /run/service/service-plex"
START_PLEX="s6-svc -u /run/service/service-plex"

####################################

# Check if PMS binary has original cache_size value
CACHESIZE=$(docker exec $CONTAINER $SHELL -c "tr -d '\0' < /usr/lib/plexmediaserver/Plex\ Media\ Server | grep -a 'cache_size=2000'")

if [ ! -z "$CACHESIZE" ]; then
        echo "Modifications needed"
        docker exec $CONTAINER $SHELL -c "sed -i.orig -e 's/cache_size=2000/cache_size=8192/' '/usr/lib/plexmediaserver/Plex Media Server'"
fi

# Stop Plex instance within container
docker exec $CONTAINER $SHELL -c "$STOP_PLEX"

# Wait for Plex service to stop
sleep 6

# Update SQLite DB
docker exec $CONTAINER $SHELL -c "/usr/lib/plexmediaserver/Plex\ SQLite $PLEX_DATA/Plug-in\ Support/Databases/com.plexapp.plugins.library.db 'PRAGMA page_size=65536' 'PRAGMA journal_mode=DELETE' 'VACUUM' 'PRAGMA journal_mode=WAL' 'PRAGMA optimize'"
docker exec $CONTAINER $SHELL -c "/usr/lib/plexmediaserver/Plex\ SQLite $PLEX_DATA/Plug-in\ Support/Databases/com.plexapp.plugins.library.blobs.db" "PRAGMA page_size=65536" "PRAGMA journal_mode=DELETE" "VACUUM" "PRAGMA journal_mode=WAL" "PRAGMA optimize"

# Start Plex instance within container
docker exec $CONTAINER $SHELL -c "$START_PLEX"

You could use https://sqlitebrowser.org/ to modify the database in Windows without using the command line.

You might be able to use Set-Content in PowerShell Set-Content (Microsoft.PowerShell.Management) - PowerShell | Microsoft Learn.

I’ve tried the sqlitebrowser, changing the PRAGMA values mentioned above is impossible, it refuses to save and returns to default values when I re-open the program.

That depends on the table your editing. Example, metadata_items won’t edit correctly so always best to use sqlite from plex itself.

Did you turn off the Plex server first?