diff -Nadur a/sql/handler.h b/sql/handler.h --- a/sql/handler.h 2022-07-13 21:42:43.000000000 +0300 +++ b/sql/handler.h 2022-08-24 09:10:54.617042200 +0300 @@ -755,7 +755,7 @@ */ #define HA_CREATE_USED_TABLESPACE (1L << 25) -/** COMPRESSION="zlib|lz4|none" used during table create. */ +/** COMPRESSION="zlib|lz4|zstd|none" used during table create. */ #define HA_CREATE_USED_COMPRESS (1L << 26) /** ENCRYPTION="Y" used during table create. */ diff -Nadur a/storage/innobase/clone/clone0desc.cc b/storage/innobase/clone/clone0desc.cc --- a/storage/innobase/clone/clone0desc.cc 2022-07-13 21:42:43.000000000 +0300 +++ b/storage/innobase/clone/clone0desc.cc 2022-08-24 09:12:28.642042200 +0300 @@ -631,6 +631,8 @@ static const uint CLONE_DESC_FILE_FLAG_DELETED = 5; /** Clone File Flag: File metadata has encryption key. */ static const uint CLONE_DESC_FILE_HAS_KEY = 6; +/** Clone File Flag: Compression type ZSTD*/ +static const uint CLONE_DESC_FILE_FLAG_ZSTD = 7; /** File Metadata: Tablespace ID in 4 bytes */ static const uint CLONE_FILE_SPACE_ID_OFFSET = CLONE_FILE_FLAGS_OFFSET + 2; @@ -697,6 +699,8 @@ DESC_SET_FLAG(file_flags, CLONE_DESC_FILE_FLAG_ZLIB); } else if (m_file_meta.m_compress_type == Compression::LZ4) { DESC_SET_FLAG(file_flags, CLONE_DESC_FILE_FLAG_LZ4); + } else if (m_file_meta.m_compress_type == Compression::ZSTD) { + DESC_SET_FLAG(file_flags, CLONE_DESC_FILE_FLAG_ZSTD); } /* Set file encryption type */ if (m_file_meta.m_encryption_metadata.m_type == Encryption::AES) { @@ -785,6 +789,8 @@ m_file_meta.m_compress_type = Compression::ZLIB; } else if (DESC_CHECK_FLAG(file_flags, CLONE_DESC_FILE_FLAG_LZ4)) { m_file_meta.m_compress_type = Compression::LZ4; + } else if (DESC_CHECK_FLAG(file_flags, CLONE_DESC_FILE_FLAG_ZSTD)) { + m_file_meta.m_compress_type = Compression::ZSTD; } /* Get file encryption information */ diff -Nadur a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt --- a/storage/innobase/CMakeLists.txt 2022-07-13 21:42:43.000000000 +0300 +++ b/storage/innobase/CMakeLists.txt 2022-08-24 09:11:31.637042200 +0300 @@ -317,7 +317,7 @@ ${INNOBASE_SOURCES} ${INNOBASE_ZIP_DECOMPRESS_SOURCES} STORAGE_ENGINE MANDATORY MODULE_OUTPUT_NAME ha_innodb - LINK_LIBRARIES sql_dd sql_gis ext::zlib ext::lz4 ${NUMA_LIBRARY} + LINK_LIBRARIES sql_dd sql_gis ext::zlib ext::lz4 ${ZSTD_LIBRARY} ${NUMA_LIBRARY} extra::rapidjson) # On linux: /usr/include/stdio.h:#define BUFSIZ 8192 diff -Nadur a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc --- a/storage/innobase/fil/fil0fil.cc 2022-07-13 21:42:43.000000000 +0300 +++ b/storage/innobase/fil/fil0fil.cc 2022-08-24 09:12:48.705042200 +0300 @@ -8864,6 +8864,7 @@ switch (srv_debug_compress) { case Compression::LZ4: case Compression::ZLIB: + case Compression::ZSTD: case Compression::NONE: compression.m_type = static_cast(srv_debug_compress); diff -Nadur a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc --- a/storage/innobase/handler/ha_innodb.cc 2022-07-13 21:42:43.000000000 +0300 +++ b/storage/innobase/handler/ha_innodb.cc 2022-08-24 09:53:53.455042200 +0300 @@ -444,7 +444,7 @@ #ifdef UNIV_DEBUG /** Values for --innodb-debug-compress names. */ -static const char *innodb_debug_compress_names[] = {"none", "zlib", "lz4", +static const char *innodb_debug_compress_names[] = {"none", "zlib", "lz4", "zstd", "lz4hc", NullS}; /** Enumeration of --innodb-debug-compress */ @@ -2601,6 +2601,9 @@ } else if (innobase_strcasecmp(algorithm, "lz4") == 0) { compression->m_type = LZ4; + } else if (innobase_strcasecmp(algorithm, "zstd") == 0) { + compression->m_type = ZSTD; + } else { return (DB_UNSUPPORTED); } @@ -2624,6 +2627,7 @@ case NONE: case ZLIB: case LZ4: + case ZSTD: break; default: ret = false; @@ -22159,6 +22163,12 @@ ", 1 is fastest, 9 is best compression and default is 6.", nullptr, nullptr, DEFAULT_COMPRESSION_LEVEL, 0, 9, 0); +static MYSQL_SYSVAR_UINT( + zstd_compression_level, page_zstd_level, PLUGIN_VAR_RQCMDARG, + "Compression level used for ZSTD page compression. " + "1 is fastest, 20 is best compression, 22 is max (ultra) compression and default is 3.", + nullptr, nullptr, DEFAULT_ZSTD_COMPRESSION_LEVEL, 1, 22, 0); + static MYSQL_SYSVAR_BOOL( log_compressed_pages, page_zip_log_pages, PLUGIN_VAR_OPCMDARG, "Enables/disables the logging of entire compressed page images." @@ -23143,6 +23143,7 @@ MYSQL_SYSVAR(commit_concurrency), MYSQL_SYSVAR(concurrency_tickets), MYSQL_SYSVAR(compression_level), + MYSQL_SYSVAR(zstd_compression_level), MYSQL_SYSVAR(ddl_buffer_size), MYSQL_SYSVAR(ddl_threads), MYSQL_SYSVAR(data_file_path), diff -Nadur a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h --- a/storage/innobase/include/page0zip.h 2022-07-13 21:42:43.000000000 +0300 +++ b/storage/innobase/include/page0zip.h 2022-08-24 09:54:09.046042200 +0300 @@ -54,9 +54,11 @@ /* Compression level to be used by zlib. Settable by user. */ extern uint page_zip_level; +extern uint page_zstd_level; /* Default compression level. */ constexpr uint32_t DEFAULT_COMPRESSION_LEVEL = 6; +constexpr uint32_t DEFAULT_ZSTD_COMPRESSION_LEVEL = 3; /** Start offset of the area that will be compressed */ #define PAGE_ZIP_START PAGE_NEW_SUPREMUM_END /** Predefine the sum of DIR_SLOT, TRX_ID & ROLL_PTR */ diff -Nadur a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i --- a/storage/innobase/include/univ.i 2022-07-13 21:42:43.000000000 +0300 +++ b/storage/innobase/include/univ.i 2022-08-24 09:13:56.441042200 +0300 @@ -371,7 +371,7 @@ MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN + 14; /** Maximum length of the compression algorithm string. Currently we support -only (NONE | ZLIB | LZ4). */ +only (NONE | ZLIB | LZ4 | ZSTD). */ constexpr uint32_t MAX_COMPRESSION_LEN = 4; /* diff -Nadur a/storage/innobase/innodb.cmake b/storage/innobase/innodb.cmake --- a/storage/innobase/innodb.cmake 2022-07-13 21:42:43.000000000 +0300 +++ b/storage/innobase/innodb.cmake 2022-08-24 09:14:15.851042200 +0300 @@ -30,6 +30,10 @@ ADD_DEFINITIONS(-DHAVE_LZ4=1) +IF(ZSTD_LIBRARY) + ADD_DEFINITIONS(-DHAVE_ZSTD=1) +ENDIF() + #ADD_DEFINITIONS("-O0") # OS tests diff -Nadur a/storage/innobase/os/file.cc b/storage/innobase/os/file.cc --- a/storage/innobase/os/file.cc 2022-07-13 21:42:43.000000000 +0300 +++ b/storage/innobase/os/file.cc 2022-08-24 09:43:35.548042200 +0300 @@ -50,6 +50,7 @@ #include #include +#include /** Convert to a "string". @param[in] type The compression type @@ -62,6 +63,8 @@ return ("Zlib"); case LZ4: return ("LZ4"); + case ZSTD: + return ("ZStd"); } ut_d(ut_error); @@ -232,6 +235,16 @@ break; + case Compression::ZSTD: { + size_t zret; + zret = ZSTD_decompress(dst, header.m_original_size, ptr, header.m_compressed_size); + if (ZSTD_isError(zret) || (zret != header.m_original_size)) { + if (allocated) ut::free(dst); + return (DB_IO_DECOMPRESS_FAIL); + } + break; + } + default: #ifdef UNIV_NO_ERR_MSGS ib::error() diff -Nadur a/storage/innobase/os/file.h b/storage/innobase/os/file.h --- a/storage/innobase/os/file.h 2022-07-13 21:42:43.000000000 +0300 +++ b/storage/innobase/os/file.h 2022-08-24 09:34:47.204042200 +0300 @@ -61,7 +61,10 @@ ZLIB = 1, /** Use LZ4 faster variant, usually lower compression. */ - LZ4 = 2 + LZ4 = 2, + + /** Use ZStd */ + ZSTD = 3, }; /** Compressed page meta-data */ @@ -93,6 +96,7 @@ case NONE: case ZLIB: case LZ4: + case ZSTD: break; default: ut_error; @@ -115,6 +119,9 @@ case LZ4: os << "LZ4"; break; + case ZSTD: + os << "ZSTD"; + break; default: os << ""; break; diff -Nadur a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc --- a/storage/innobase/os/os0file.cc 2022-07-13 21:42:43.000000000 +0300 +++ b/storage/innobase/os/os0file.cc 2022-08-24 09:50:50.342042200 +0300 @@ -96,6 +96,8 @@ #include #include +#include + #ifdef UNIV_HOTBACKUP #include #endif /* UNIV_HOTBACKUP */ @@ -807,6 +809,7 @@ /** Default Zip compression level */ extern uint page_zip_level; +extern uint page_zstd_level; static_assert(DATA_TRX_ID_LEN <= 6, "COMPRESSION_ALGORITHM will not fit!"); @@ -1329,6 +1332,7 @@ ulint *dst_len) { ulint len = 0; ulint compression_level = page_zip_level; + ulint zstd_compression_level = page_zstd_level; ulint page_type = mach_read_from_2(src + FIL_PAGE_TYPE); /* The page size must be a multiple of the OS punch hole size. */ @@ -1404,6 +1408,17 @@ break; + case Compression::ZSTD: { + size_t zret; + zret = ZSTD_compress(dst + FIL_PAGE_DATA, out_len, src + FIL_PAGE_DATA, content_len, zstd_compression_level); + if (ZSTD_isError(zret) || (zret == 0)) { + *dst_len = src_len; + return (src); + } + len = zret; + break; + } + default: *dst_len = src_len; return (src); diff -Nadur a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc --- a/storage/innobase/page/page0zip.cc 2022-07-13 21:42:43.000000000 +0300 +++ b/storage/innobase/page/page0zip.cc 2022-08-24 09:53:10.678042200 +0300 @@ -84,6 +84,7 @@ /* Compression level to be used by zlib. Settable by user. */ uint page_zip_level = DEFAULT_COMPRESSION_LEVEL; +uint page_zstd_level = DEFAULT_ZSTD_COMPRESSION_LEVEL; /* Whether or not to log compressed page images to avoid possible compression algorithm changes in zlib. */