Innodb

MariaDB 10.3:InnoDB 比 MyISAM 慢得多

  • January 11, 2020

我在 Arch Linux 上使用 MariaDB 10.3.12 並且沒有修改/etc/mysql. 以下腳本使用預設的 InnoDB 引擎平均需要 0.75 秒才能執行:

drop database if exists test_database;
create database test_database;
USE test_database;
CREATE TABLE test_table (namespace char(31) NOT NULL);

對於這麼簡單的事情來說,這是相當多的。使用 MyISAM ( default_storage_engine=myisamin /etc/mysql/my.cnf.d/server.cnf) 執行時間為 0.016 秒(使用 aria 為 0.07 秒)。在我擁有 MariaDB v 10.1.38 的 Ubuntu 虛擬機中,它的平均執行時間為 0.04 秒。

有什麼方法可以解釋為什麼 InnoDB 這麼慢以及我應該測試哪些變數?我知道微調性能有很多變數,但令人費解的是,與其他引擎相比*,數量級*差異可能來自哪裡。

這是我目前的 InnoDB 變數:

+---------------------------------------------+------------------------+
| Variable_name                               | Value                  |
+---------------------------------------------+------------------------+
| ignore_builtin_innodb                       | OFF                    |
| innodb_adaptive_flushing                    | ON                     |
| innodb_adaptive_flushing_lwm                | 10.000000              |
| innodb_adaptive_hash_index                  | ON                     |
| innodb_adaptive_hash_index_parts            | 8                      |
| innodb_adaptive_max_sleep_delay             | 150000                 |
| innodb_autoextend_increment                 | 64                     |
| innodb_autoinc_lock_mode                    | 1                      |
| innodb_background_scrub_data_check_interval | 3600                   |
| innodb_background_scrub_data_compressed     | OFF                    |
| innodb_background_scrub_data_interval       | 604800                 |
| innodb_background_scrub_data_uncompressed   | OFF                    |
| innodb_buf_dump_status_frequency            | 0                      |
| innodb_buffer_pool_chunk_size               | 134217728              |
| innodb_buffer_pool_dump_at_shutdown         | ON                     |
| innodb_buffer_pool_dump_now                 | OFF                    |
| innodb_buffer_pool_dump_pct                 | 25                     |
| innodb_buffer_pool_filename                 | ib_buffer_pool         |
| innodb_buffer_pool_instances                | 1                      |
| innodb_buffer_pool_load_abort               | OFF                    |
| innodb_buffer_pool_load_at_startup          | ON                     |
| innodb_buffer_pool_load_now                 | OFF                    |
| innodb_buffer_pool_size                     | 134217728              |
| innodb_change_buffer_max_size               | 25                     |
| innodb_change_buffering                     | all                    |
| innodb_checksum_algorithm                   | crc32                  |
| innodb_checksums                            | ON                     |
| innodb_cmp_per_index_enabled                | OFF                    |
| innodb_commit_concurrency                   | 0                      |
| innodb_compression_algorithm                | zlib                   |
| innodb_compression_default                  | OFF                    |
| innodb_compression_failure_threshold_pct    | 5                      |
| innodb_compression_level                    | 6                      |
| innodb_compression_pad_pct_max              | 50                     |
| innodb_concurrency_tickets                  | 5000                   |
| innodb_data_file_path                       | ibdata1:12M:autoextend |
| innodb_data_home_dir                        |                        |
| innodb_deadlock_detect                      | ON                     |
| innodb_default_encryption_key_id            | 1                      |
| innodb_default_row_format                   | dynamic                |
| innodb_defragment                           | OFF                    |
| innodb_defragment_fill_factor               | 0.900000               |
| innodb_defragment_fill_factor_n_recs        | 20                     |
| innodb_defragment_frequency                 | 40                     |
| innodb_defragment_n_pages                   | 7                      |
| innodb_defragment_stats_accuracy            | 0                      |
| innodb_disable_sort_file_cache              | OFF                    |
| innodb_disallow_writes                      | OFF                    |
| innodb_doublewrite                          | ON                     |
| innodb_encrypt_log                          | OFF                    |
| innodb_encrypt_tables                       | OFF                    |
| innodb_encryption_rotate_key_age            | 1                      |
| innodb_encryption_rotation_iops             | 100                    |
| innodb_encryption_threads                   | 0                      |
| innodb_fast_shutdown                        | 1                      |
| innodb_fatal_semaphore_wait_threshold       | 600                    |
| innodb_file_per_table                       | ON                     |
| innodb_fill_factor                          | 100                    |
| innodb_flush_log_at_timeout                 | 1                      |
| innodb_flush_log_at_trx_commit              | 1                      |
| innodb_flush_method                         | fsync                  |
| innodb_flush_neighbors                      | 1                      |
| innodb_flush_sync                           | ON                     |
| innodb_flushing_avg_loops                   | 30                     |
| innodb_force_load_corrupted                 | OFF                    |
| innodb_force_primary_key                    | OFF                    |
| innodb_force_recovery                       | 0                      |
| innodb_ft_aux_table                         |                        |
| innodb_ft_cache_size                        | 8000000                |
| innodb_ft_enable_diag_print                 | OFF                    |
| innodb_ft_enable_stopword                   | ON                     |
| innodb_ft_max_token_size                    | 84                     |
| innodb_ft_min_token_size                    | 3                      |
| innodb_ft_num_word_optimize                 | 2000                   |
| innodb_ft_result_cache_limit                | 2000000000             |
| innodb_ft_server_stopword_table             |                        |
| innodb_ft_sort_pll_degree                   | 2                      |
| innodb_ft_total_cache_size                  | 640000000              |
| innodb_ft_user_stopword_table               |                        |
| innodb_idle_flush_pct                       | 100                    |
| innodb_immediate_scrub_data_uncompressed    | OFF                    |
| innodb_io_capacity                          | 200                    |
| innodb_io_capacity_max                      | 2000                   |
| innodb_lock_schedule_algorithm              | fcfs                   |
| innodb_lock_wait_timeout                    | 50                     |
| innodb_locks_unsafe_for_binlog              | OFF                    |
| innodb_log_buffer_size                      | 16777216               |
| innodb_log_checksums                        | ON                     |
| innodb_log_compressed_pages                 | ON                     |
| innodb_log_file_size                        | 50331648               |
| innodb_log_files_in_group                   | 2                      |
| innodb_log_group_home_dir                   | ./                     |
| innodb_log_optimize_ddl                     | ON                     |
| innodb_log_write_ahead_size                 | 8192                   |
| innodb_lru_scan_depth                       | 1024                   |
| innodb_max_dirty_pages_pct                  | 75.000000              |
| innodb_max_dirty_pages_pct_lwm              | 0.000000               |
| innodb_max_purge_lag                        | 0                      |
| innodb_max_purge_lag_delay                  | 0                      |
| innodb_max_undo_log_size                    | 10485760               |
| innodb_monitor_disable                      |                        |
| innodb_monitor_enable                       |                        |
| innodb_monitor_reset                        |                        |
| innodb_monitor_reset_all                    |                        |
| innodb_old_blocks_pct                       | 37                     |
| innodb_old_blocks_time                      | 1000                   |
| innodb_online_alter_log_max_size            | 134217728              |
| innodb_open_files                           | 2000                   |
| innodb_optimize_fulltext_only               | OFF                    |
| innodb_page_cleaners                        | 1                      |
| innodb_page_size                            | 16384                  |
| innodb_prefix_index_cluster_optimization    | OFF                    |
| innodb_print_all_deadlocks                  | OFF                    |
| innodb_purge_batch_size                     | 300                    |
| innodb_purge_rseg_truncate_frequency        | 128                    |
| innodb_purge_threads                        | 4                      |
| innodb_random_read_ahead                    | OFF                    |
| innodb_read_ahead_threshold                 | 56                     |
| innodb_read_io_threads                      | 4                      |
| innodb_read_only                            | OFF                    |
| innodb_replication_delay                    | 0                      |
| innodb_rollback_on_timeout                  | OFF                    |
| innodb_rollback_segments                    | 128                    |
| innodb_scrub_log                            | OFF                    |
| innodb_scrub_log_speed                      | 256                    |
| innodb_sort_buffer_size                     | 1048576                |
| innodb_spin_wait_delay                      | 4                      |
| innodb_stats_auto_recalc                    | ON                     |
| innodb_stats_include_delete_marked          | OFF                    |
| innodb_stats_method                         | nulls_equal            |
| innodb_stats_modified_counter               | 0                      |
| innodb_stats_on_metadata                    | OFF                    |
| innodb_stats_persistent                     | ON                     |
| innodb_stats_persistent_sample_pages        | 20                     |
| innodb_stats_sample_pages                   | 8                      |
| innodb_stats_traditional                    | ON                     |
| innodb_stats_transient_sample_pages         | 8                      |
| innodb_status_output                        | OFF                    |
| innodb_status_output_locks                  | OFF                    |
| innodb_strict_mode                          | ON                     |
| innodb_sync_array_size                      | 1                      |
| innodb_sync_spin_loops                      | 30                     |
| innodb_table_locks                          | ON                     |
| innodb_temp_data_file_path                  | ibtmp1:12M:autoextend  |
| innodb_thread_concurrency                   | 0                      |
| innodb_thread_sleep_delay                   | 10000                  |
| innodb_tmpdir                               |                        |
| innodb_undo_directory                       | ./                     |
| innodb_undo_log_truncate                    | OFF                    |
| innodb_undo_logs                            | 128                    |
| innodb_undo_tablespaces                     | 0                      |
| innodb_use_atomic_writes                    | ON                     |
| innodb_use_native_aio                       | ON                     |
| innodb_version                              | 10.3.12                |
| innodb_write_io_threads                     | 4                      |
+---------------------------------------------+------------------------+

**編輯。**這是一個將 204 個值添加到數據庫中的測試。

USE test_database;
insert into test_table values
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),
('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a'),('a');

使用 InnoDB 平均需要 0.22 秒,使用 MyISAM 平均需要 0.01 秒。

**編輯。**這是使用 InnoDB 創建表的配置文件:

+------------------------+----------+----------+------------+
| Status                 | Duration | CPU_user | CPU_system |
+------------------------+----------+----------+------------+
| Starting               | 0.000035 | 0.000000 |   0.000079 |
| Checking permissions   | 0.000005 | 0.000000 |   0.000009 |
| Opening tables         | 0.000011 | 0.000000 |   0.000030 |
| After opening tables   | 0.000003 | 0.000000 |   0.000009 |
| System lock            | 0.000002 | 0.000000 |   0.000004 |
| Table lock             | 0.000030 | 0.000000 |   0.000061 |
| Creating table         | 0.455613 | 0.036331 |   0.107722 |
| After create           | 0.000022 | 0.000004 |   0.000015 |
| Query end              | 0.000011 | 0.000069 |   0.000240 |
| Commit                 | 0.000011 | 0.000005 |   0.000017 |
| Closing tables         | 0.000010 | 0.000005 |   0.000015 |
| Unlocking tables       | 0.000009 | 0.000056 |   0.000193 |
| Closing tables         | 0.000009 | 0.000031 |   0.000109 |
| Commit_implicit        | 0.000017 | 0.000051 |   0.000175 |
| Starting cleanup       | 0.000008 | 0.000007 |   0.000026 |
| Freeing items          | 0.000010 | 0.000003 |   0.000010 |
| Updating status        | 0.000035 | 0.000008 |   0.000028 |
| Reset for next command | 0.000054 | 0.000342 |   0.000000 |
+------------------------+----------+----------+------------+

MyISAM 也是如此:

+------------------------+----------+----------+------------+
| Status                 | Duration | CPU_user | CPU_system |
+------------------------+----------+----------+------------+
| Starting               | 0.000062 | 0.000018 |   0.000043 |
| Checking permissions   | 0.000014 | 0.000004 |   0.000009 |
| Opening tables         | 0.000024 | 0.000007 |   0.000017 |
| After opening tables   | 0.000009 | 0.000003 |   0.000007 |
| System lock            | 0.000007 | 0.000002 |   0.000004 |
| Table lock             | 0.000052 | 0.000015 |   0.000037 |
| Creating table         | 0.006708 | 0.000235 |   0.000554 |
| After create           | 0.000018 | 0.000005 |   0.000012 |
| Query end              | 0.000009 | 0.000002 |   0.000006 |
| Commit                 | 0.000008 | 0.000002 |   0.000005 |
| Closing tables         | 0.000008 | 0.000003 |   0.000005 |
| Unlocking tables       | 0.000006 | 0.000001 |   0.000004 |
| Closing tables         | 0.000006 | 0.000002 |   0.000004 |
| Commit_implicit        | 0.000014 | 0.000004 |   0.000010 |
| Starting cleanup       | 0.000007 | 0.000002 |   0.000005 |
| Freeing items          | 0.000008 | 0.000003 |   0.000006 |
| Updating status        | 0.000028 | 0.000008 |   0.000019 |
| Reset for next command | 0.000008 | 0.000002 |   0.000006 |
+------------------------+----------+----------+------------+

這是使用 InnoDB 向表中插入值的配置文件:

+------------------------+----------+----------+------------+
| Status                 | Duration | CPU_user | CPU_system |
+------------------------+----------+----------+------------+
| Starting               | 0.000439 | 0.000093 |   0.000345 |
| Checking permissions   | 0.000013 | 0.000003 |   0.000010 |
| Opening tables         | 0.000029 | 0.000006 |   0.000022 |
| After opening tables   | 0.000010 | 0.000002 |   0.000008 |
| System lock            | 0.000009 | 0.000002 |   0.000007 |
| Table lock             | 0.000009 | 0.000002 |   0.000007 |
| Init for update        | 0.000041 | 0.000009 |   0.000033 |
| Update                 | 0.001986 | 0.000000 |   0.002014 |
| End of update loop     | 0.000020 | 0.000000 |   0.000018 |
| Query end              | 0.000008 | 0.000000 |   0.000008 |
| Commit                 | 0.089969 | 0.011578 |   0.006221 |
| Closing tables         | 0.000030 | 0.000006 |   0.000019 |
| Unlocking tables       | 0.000011 | 0.000002 |   0.000008 |
| Closing tables         | 0.000019 | 0.000004 |   0.000016 |
| Starting cleanup       | 0.000009 | 0.000002 |   0.000006 |
| Freeing items          | 0.000023 | 0.000005 |   0.000018 |
| Updating status        | 0.000042 | 0.000009 |   0.000033 |
| Reset for next command | 0.000012 | 0.000002 |   0.000009 |
+------------------------+----------+----------+------------+

MyISAM 也是如此:

+------------------------+----------+----------+------------+
| Status                 | Duration | CPU_user | CPU_system |
+------------------------+----------+----------+------------+
| Starting               | 0.000569 | 0.000561 |   0.000000 |
| Checking permissions   | 0.000015 | 0.000013 |   0.000000 |
| Opening tables         | 0.000031 | 0.000032 |   0.000000 |
| After opening tables   | 0.000010 | 0.000009 |   0.000000 |
| System lock            | 0.000009 | 0.000009 |   0.000000 |
| Table lock             | 0.000010 | 0.000010 |   0.000000 |
| Init for update        | 0.000062 | 0.000062 |   0.000000 |
| Update                 | 0.000246 | 0.000247 |   0.000000 |
| End of update loop     | 0.000018 | 0.000017 |   0.000000 |
| Query end              | 0.000008 | 0.000008 |   0.000000 |
| Commit                 | 0.000007 | 0.000007 |   0.000000 |
| Closing tables         | 0.000008 | 0.000007 |   0.000000 |
| Unlocking tables       | 0.000036 | 0.000037 |   0.000000 |
| Closing tables         | 0.000016 | 0.000016 |   0.000000 |
| Starting cleanup       | 0.000007 | 0.000007 |   0.000000 |
| Freeing items          | 0.000014 | 0.000013 |   0.000000 |
| Updating status        | 0.000030 | 0.000030 |   0.000000 |
| Reset for next command | 0.000009 | 0.000010 |   0.000000 |
+------------------------+----------+----------+------------+

**TLDR;**問題原來是文件系統。不要將 BTRFS 用於數據庫儲存。


我使用一些我必須使用的數據對不同文件系統的 MariaDB 時序進行了分析。儘管這是針對我的情況的,但我認為無論如何我都會發布結果以防萬一。

我嘗試了以下配置:

  • “BTRFS(子卷)” - 這是我在發布這個問題之前所擁有的。一個 BTRFS 分區,用於所有內容,並帶有子卷,例如//home. 該目錄/var/lib/mysql位於/子卷上。
  • “BTRFS” - 為/var/lib/mysql. 這裡沒有子卷。
  • “ext4” - 為/var/lib/mysql.
  • “XFS” - 為/var/lib/mysql. 在做了更多的研究之後,這可能是我應該在生產環境中使用的。XFS 以高性能著稱。
  • “F2FS” - 為/var/lib/mysql. 這速度很快,但對於生產環境來說不夠穩定。只有在可以接受潛在數據失去的情況下才使用此選項。
  • “F2FS (no_barrier)” - 與 “F2FS” 相同,但安裝了fsync_mode=nobarrier選項,這減少了記憶體刷新的次數。這比正常 F2FS 更快,但風險更大。

在所有情況下,文件系統都駐留在使用 dm-crypt 準備的 LUKS 分區上。

測試案例 1。

首先,我測量了總共 27 個表的創建表和外鍵約束的時間。我不能在這裡發布實際內容,但是每個表大約有 15 個欄位,總共有 81 個 FK 約束,只是為了給你一個粗略的想法。我執行的腳本還包括其他一些內容,例如在創建所有表後截斷它們並在此處和那裡更改某些列。這是時間,以 s 為單位。每個數字是兩次執行的平均值。

|                   | InnoDB | Aria |
|-------------------+--------+------|
| BTRFS (subvolume) |  473.9 | 86.7 |
| BTRFS             |   53.0 | 40.9 |
| ext4              |   35.1 | 29.0 |
| XFS               |   29.2 | 27.2 |
| F2FS              |   18.0 | 26.3 |
| F2FS (nobarrier)  |    5.6 | 16.9 |
|-------------------+--------+------|

如您所見,使用 InnoDB 並將數據庫保持在與其他配置相同的子卷上/比其他配置慢一個數量級。這就是為什麼我直到現在才真正使用 Aria 來工作。使用單獨的 BTRFS 分區要快得多,切換到其他文件系統的速度更快。我對 F2FS 擊敗所有其他文件系統的優勢感到驚訝。

測試案例 2。

在這裡,我將數據插入到案例 1 中創建的表中。同樣,我無法發布實際內容,但執行的 SQL 語句的總大小約為 28 MiB,因此對於產生有意義的計時來說是一個很好的數量。這些是時間:

|                   | InnoDB |  Aria |
|-------------------+--------+-------|
| BTRFS (subvolume) | 1483.6 | 144.3 |
| BTRFS             |  134.3 | 137.7 |
| ext4              |   90.2 | 121.5 |
| XFS               |   82.6 | 116.3 |
| F2FS              |   51.1 | 105.6 |
| F2FS (nobarrier)  |   20.4 |  26.9 |
|-------------------+--------+-------|

結論與案例 1 相同。BTRFS 明顯慢於其他文件系統。

測試案例 3。

這就像案例 2,但所有內容都包含在START TRANSACTION;andCOMMIT;語句之間。

|                   | InnoDB | Aria |
|-------------------+--------+------|
| BTRFS (subvolume) |  351.7 | N/A  |
| BTRFS             |   38.0 | N/A  |
| ext4              |   31.4 | N/A  |
| XFS               |   30.8 | N/A  |
| F2FS              |   26.1 | N/A  |
| F2FS (nobarrier)  |   18.8 | N/A  |
|-------------------+--------+------|

Aria 沒有結果,因為它不支持事務。否則,將所有內容包裝到單個事務中會顯著減少所有情況的時間,除了 F2FS(無屏障),這仍然是最快的解決方案,但與情況 2 相比只有很小的改進。

測試案例 4。

這是一個簡短的測試,我使用與test_table原始問題相同的方法。測量的時間用於創建表格並將 203 值輸入其中。每個報告的時間是五次執行的平均值。

|                   | InnoDB |  Aria |
|-------------------+--------+-------|
| BTRFS (subvolume) |  0.914 | 0.105 |
| BTRFS             |  0.164 | 0.015 |
| ext4              |  0.122 | 0.080 |
| XFS               |  0.099 | 0.070 |
| F2FS              |  0.068 | 0.070 |
| F2FS (nobarrier)  |  0.037 | 0.053 |
|-------------------+--------+-------|

我們在這裡看到的時間尺度要小得多這一事實並沒有改變結論。如果數據庫保存在同一個子卷上,使用 BTRFS/仍然慢得令人無法接受。

結論

我決定使用安裝了該fsync_mode=nobarrier選項的 F2FS,這顯然是最快的解決方案。由於我只使用我的個人電腦進行開發,因此我對可能失去 SQL 數據的情況很好(應該不太可能,但仍然如此)。否則我會選擇 XFS。


使用的硬體:i7-6700HQ@2.60GHz,256 GB PCIe M.2 Samsung SM951

引用自:https://dba.stackexchange.com/questions/230807