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=myisam
内の/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秒かかります。
EDIT。これは、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タイミングの分析を行いました。これは私の状況に特有のものですが、興味があればとにかく結果を投稿したいと思いました。
私は次の構成を試しました:
/
や/home
などのサブボリュームを持つすべてのもの用の1つのBTRFSパーティション。ディレクトリ/var/lib/mysql
は/
サブボリュームにありました。/var/lib/mysql
用の個別のBTRFSパーティション。ここにサブボリュームはありません。/var/lib/mysql
用の個別のext4パーティション。/var/lib/mysql
用の個別のXFSパーティション。さらに調査を行った後、これはおそらく私が実稼働環境で使用する必要があるものです。 XFSは高いパフォーマンスで知られています。/var/lib/mysql
用の個別のF2FS(フラッシュフレンドリーファイルシステム)パーティション。これは高速ですが、実稼働環境には十分安定していません。これは、データ損失の可能性が許容できる場合にのみ使用してください。fsync_mode=nobarrier
オプションを使用してマウントされます。これにより、キャッシュフラッシュの数が減ります。これは通常のF2FSよりも高速ですが、さらにリスクがあります。すべての場合において、ファイルシステムはdm-cryptで準備されたLUKSパーティションに存在します。
テストケース1
最初に、合計27のテーブルについて、テーブルと外部キー制約を作成する時間を測定しました。ここに実際のコンテンツを投稿することはできませんが、各テーブルには約15のフィールドがあり、大まかなアイデアを提供するために、合計81のFK制約があります。私が実行したスクリプトには、作成後にすべてのテーブルを切り捨てたり、あちこちでいくつかの列を変更したりするなど、他にもいくつかのものが含まれています。タイミングは秒単位です。各数値は2回の実行の平均です。
| | 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を使用し、データベースを/
と同じサブボリュームに維持することは、他の構成よりも桁違いに遅いです。これが、今までアリアを仕事に使った理由です。別のBTRFSパーティションを使用すると、はるかに高速になり、他のファイルシステムの1つへの切り替えがさらに高速になります。 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は他のファイルシステムよりもかなり低速です。
テストケース
これはケース2と同じですが、START TRANSACTION;
ステートメントとCOMMIT;
ステートメントの間にラップした場合はすべてです。
| | 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はトランザクションをサポートしていないため、結果はありません。それ以外の場合、すべてを1つのトランザクションにラップすると、F2FS(バリアなし)を除くすべてのケースで時間を大幅に削減できます。これは、最速のソリューションですが、ケース2に比べてわずかな改善にすぎません。
テストケース4
これは、元の質問と同じtest_table
を使用する短いテストです。測定された時間は、テーブルを作成し、それに203個の値を入力するためのものです。報告される各時間は、5回の実行の平均です。
| | 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
持ってる innodb_file_per_table=OFF
このタスクを実行するとき。これにより、必要なI/Oが削減されます。
また、データディクショナリ関連のものを書き直したMySQL 8.0へのアップグレードも検討してください。
バッチで行うと、行の挿入がはるかに速くなります。