私にはかなり厄介な問題があります。メインデータベースエンジンとしてINNODBを使用し、冗長性のためにgalera-clusterを使用するために前者が必要なため、MyISAMを放棄します。
newbb_post
テーブルをコピー(説明が続きます)という新しいテーブルにコピーnewbb_innopost
し、InnoDBに変更しました。現在、テーブルには5,390,146
それぞれエントリがあります。
新しく起動したデータベースでこれらの選択を実行すると(この時点でキャッシュは関係しません!)、データベースは次の結果を生成します(完全な出力は省略します。結果の並べ替えをデータベースに依頼しないことに注意してください)。
SELECT post.postid、post.attach FROM newbb_post AS post WHERE post.threadid = 51506; 。 。 | 5401593 | 0 | | 5401634 | 0 | + --------- + -------- + セット内の62510行(0.13秒)
SELECT post.postid、post.attach FROM newbb_innopost AS post WHERE post.threadid = 51506; 。 。 | 5397410 | 0 | | 5397883 | 0 | + --------- + -------- + セット内の62510行(1分22.19秒)
0.13秒から86.19秒(!)
なぜこれが起こっているのだろうか。ここでInnoDBを含むStackexchangeに関するいくつかの回答を読みましたが、いくつかはinnodb_buffer_pool
インストールされたRAMの80%にサイズを増やすことを提案しています。これでは、特定のIDへの最初のクエリに少なくとも50倍の時間がかかり、Webサーバー全体が停止し、データベースへの接続とクエリがキューイングされるという問題は解決しません。その後、キャッシュ/バッファーが作動する可能性がありますが、このデータベースには100.000を超えるスレッドが存在するため、キャッシュには、提供される関連クエリがすべて保持されることはほとんどありません。
上記のクエリは単純(結合なし)であり、すべてのキーが使用されます。
EXPLAIN SELECT post.postid、post.attach FROM newbb_innopost AS post WHERE post.threadid = 51506; + ------ + ------------- + ------- + ------ + ------------- ---------------------------------- + ---------- + ---- ----- + ------- + -------- + ------- + | id | select_type | テーブル| タイプ| possible_keys | キー| key_len | ref | 行| エクストラ| + ------ + ------------- + ------- + ------ + ------------- ---------------------------------- + ---------- + ---- ----- + ------- + -------- + ------- + | 1 | シンプル| 投稿| ref | threadid、threadid_2、threadid_visible_dateline | threadid | 4 | const | 120144 | | + ------ + ------------- + ------- + ------ + ------------- ---------------------------------- + ---------- + ---- ----- + ------- + -------- + ------- +
これはMyISAMテーブルです。
CREATE TABLE `newbb_post`( `postid` int(10)unsigned NOT NULL AUTO_INCREMENT、 `threadid` int(10)unsigned NOT NULL DEFAULT '0'、 `parentid` int(10)unsigned NOT NULL DEFAULT '0'、 `username` varchar(100)NOT NULL DEFAULT ''、 `userid` int(10)unsigned NOT NULL DEFAULT '0'、 `title` varchar(250)NOT NULL DEFAULT ''、 `dateline` int(10)unsigned NOT NULL DEFAULT '0'、 `pagetext` mediumtext、 `allowsmilie` smallint(6)NOT NULL DEFAULT '0'、 `showsignature` smallint(6)NOT NULL DEFAULT '0'、 `ipaddress` varchar(15)NOT NULL DEFAULT ''、 `iconid` smallint(5)unsigned NOT NULL DEFAULT '0'、 `visible` smallint(6)NOT NULL DEFAULT '0'、 `attach` smallint(5)unsigned NOT NULL DEFAULT '0'、 `infraction` smallint(5)unsigned NOT NULL DEFAULT '0'、 `reportthreadid` int(10)unsigned NOT NULL DEFAULT '0'、 `importthreadid` bigint(20)NOT NULL DEFAULT '0'、 `importpostid` bigint(20)NOT NULL DEFAULT '0'、 `converted_2_utf8` int(11)NOT NULL、 `htmlstate` enum( 'off'、 'on'、 'on_nl2br')NOT NULL DEFAULT 'on_nl2br'、 主キー( `postid`)、 キー `threadid`(` threadid`、 `userid`)、 キー `importpost_index`(` importpostid`)、 キー `dateline`(` dateline`)、 キー `threadid_2`(` threadid`、 `visible`、` dateline`)、 KEY `converted_2_utf8`(` converted_2_utf8`)、 キー `threadid_visible_dateline`(` threadid`、 `visible`、` dateline`、 `userid`、` postid`)、 キー `ipaddress`(` ipaddress`)、 KEY `userid`(` userid`、 `parentid`)、 KEY `user_date`(` userid`、 `dateline`) )ENGINE = MyISAM AUTO_INCREMENT = 5402802 DEFAULT CHARSET = latin1
これはInnoDBテーブルです(まったく同じです):
CREATE TABLE `newbb_innopost`( `postid` int(10)unsigned NOT NULL AUTO_INCREMENT、 `threadid` int(10)unsigned NOT NULL DEFAULT '0'、 `parentid` int(10)unsigned NOT NULL DEFAULT '0'、 `username` varchar(100)NOT NULL DEFAULT ''、 `userid` int(10)unsigned NOT NULL DEFAULT '0'、 `title` varchar(250)NOT NULL DEFAULT ''、 `dateline` int(10)unsigned NOT NULL DEFAULT '0'、 `pagetext` mediumtext、 `allowsmilie` smallint(6)NOT NULL DEFAULT '0'、 `showsignature` smallint(6)NOT NULL DEFAULT '0'、 `ipaddress` varchar(15)NOT NULL DEFAULT ''、 `iconid` smallint(5)unsigned NOT NULL DEFAULT '0'、 `visible` smallint(6)NOT NULL DEFAULT '0'、 `attach` smallint(5)unsigned NOT NULL DEFAULT '0'、 `infraction` smallint(5)unsigned NOT NULL DEFAULT '0'、 `reportthreadid` int(10)unsigned NOT NULL DEFAULT '0'、 `importthreadid` bigint(20)NOT NULL DEFAULT '0'、 `importpostid` bigint(20)NOT NULL DEFAULT '0'、 `converted_2_utf8` int(11)NOT NULL、 `htmlstate` enum( 'off'、 'on'、 'on_nl2br')NOT NULL DEFAULT 'on_nl2br'、 主キー( `postid`)、 キー `threadid`(` threadid`、 `userid`)、 キー `importpost_index`(` importpostid`)、 キー `dateline`(` dateline`)、 キー `threadid_2`(` threadid`、 `visible`、` dateline`)、 KEY `converted_2_utf8`(` converted_2_utf8`)、 キー `threadid_visible_dateline`(` threadid`、 `visible`、` dateline`、 `userid`、` postid`)、 キー `ipaddress`(` ipaddress`)、 KEY `userid`(` userid`、 `parentid`)、 KEY `user_date`(` userid`、 `dateline`) )ENGINE = InnoDB AUTO_INCREMENT = 5402802 DEFAULT CHARSET = latin1
サーバー、32GB RAM:
サーバーバージョン:10.0.12-MariaDB-1〜trusty-wsrep-log mariadb.orgバイナリ配布、wsrep_25.10.r4002
すべてのinnodb_変数の設定が必要な場合は、この投稿に添付できます。
更新:
プライマリインデックスとは別にすべてのインデックスを削除しました。その後、結果は次のようになりました。
。 。 | 5402697 | 0 | | 5402759 | 0 | + --------- + -------- + セット内の62510行(29.74秒)
EXPLAIN SELECT post.postid、post.attach FROM newbb_innopost AS post WHERE post.threadid = 51506; + ------ + ------------- + ------- + ------ + ------------- -+ ------ + --------- + ------ + --------- + ------------- + | id | select_type | テーブル| タイプ| possible_keys | キー| key_len | ref | 行| エクストラ| + ------ + ------------- + ------- + ------ + ------------- -+ ------ + --------- + ------ + --------- + ------------- + | 1 | シンプル| 投稿| すべて| NULL | NULL | NULL | NULL | 5909836 | whereを使用する| + ------ + ------------- + ------- + ------ + ------------- -+ ------ + --------- + ------ + --------- + ------------- + セット内の1行(0.00秒)
この後、ミックスに1つのインデックスthreadidを追加しました。結果は次のとおりです。
。 。 | 5402697 | 0 | | 5402759 | 0 | + --------- + -------- + セット内の62510行(11.58秒)
EXPLAIN SELECT post.postid、post.attach FROM newbb_innopost AS post WHERE post.threadid = 51506; + ------ + ------------- + ------- + ------ + ------------- -+ ---------- + --------- + ------------------- + ------- + | id | select_type | テーブル| タイプ| possible_keys | キー| key_len | ref | 行| エクストラ| + ------ + ------------- + ------- + ------ + ------------- -+ ---------- + --------- + ------------------- + ------- + | 1 | シンプル| 投稿| ref | threadid | threadid | 4 | const | 124622 | | + ------ + ------------- + ------- + ------ + ------------- -+ ---------- + --------- + ------------------- + ------- + セット内の1行(0.00秒)
奇妙なことに、関連するインデックスがない場合、インデックスを使用した88秒(!)と比較して、フルスキャンは29秒しかかかりませんでした。
完全に調整されたインデックスが1つしかないため、完了までにまだ11秒かかります。実際の使用には遅すぎます。
アップデート2:
MySQL(5.5.38-0ubuntu0.14.04.1(Ubuntu))を、まったく同じハードウェア構成とまったく同じデータベース/テーブルを持つ別のサーバーにセットアップしました。
結果はほぼ同じで、最初はMyISAMテーブルです。
。 。 | 5401593 | 0 | | 5401634 | 0 | + --------- + -------- + セット内の62510行(0.14秒)
そして、これはInnoDBテーブルの結果です
。 。 | 5397410 | 0 | | 5397883 | 0 | + --------- + -------- + セット内の62510行(1分17.63秒)
更新3: my.cnfの内容
#MariaDBデータベースサーバー構成ファイル。 # #このファイルを次のいずれかにコピーできます。 #-「/etc/mysql/my.cnf」でグローバルオプションを設定し、 #-「〜/ .my.cnf」はユーザー固有のオプションを設定します。 # #プログラムがサポートするすべての長いオプションを使用できます。 #--helpを使用してプログラムを実行し、使用可能なオプションのリストを取得します。 #--print-defaultsは、実際に理解して使用するものを確認します。 # #説明については #http://dev.mysql.com/doc/mysql/en/server-system-variables.html #これはすべてのmysqlクライアントに渡されます #パスワードは目盛り/引用符で囲む必要があることが報告されています #特に「#」文字が含まれている場合... #ソケットの場所を変更するときは、必ず/etc/mysql/debian.cnfを編集してください。 [クライアント] ポート= 3306 ソケット= /var/run/mysqld/mysqld.sock #特定のプログラムのエントリはこちら #次の値は、少なくとも32MのRAMがあることを前提としています #これは正式には[safe_mysqld]として知られていました。両方のバージョンは現在解析されています。 [mysqld_safe] ソケット= /var/run/mysqld/mysqld.sock いい= 0 [mysqld] # # * 基本設定 # ユーザー= mysql pid-file = /var/run/mysqld/mysqld.pid ソケット= /var/run/mysqld/mysqld.sock ポート= 3306 basedir = / usr datadir = / var / lib / mysql tmpdir = / tmp lc_messages_dir = / usr / share / mysql lc_messages = en_US スキップ外部ロック # #ネットワークをスキップする代わりに、デフォルトではリッスンするだけです #localhostはより互換性が高く、安全性は劣りません。 バインドアドレス= 127.0.0.1 # # * 微調整 # max_connections = 100 connect_timeout = 5 wait_timeout = 600 max_allowed_packet = 16M thread_cache_size = 128 sort_buffer_size = 4M bulk_insert_buffer_size = 16M tmp_table_size = 32M max_heap_table_size = 32M # #* MyISAM # #これはスタートアップスクリプトを置き換え、必要に応じてMyISAMテーブルをチェックします #初めて触れたとき。エラーが発生したら、コピーを作成して修復を試みます。 myisam_recover = BACKUP key_buffer_size = 128M #open-files-limit = 2000 table_open_cache = 400 myisam_sort_buffer_size = 512M 同時挿入= 2 read_buffer_size = 2M read_rnd_buffer_size = 1M # #*クエリキャッシュの構成 # #小さな結果セットのみをキャッシュするので、クエリキャッシュにさらに収まることができます。 query_cache_limit = 128K query_cache_size = 64M #書き込み集中型のセットアップの場合は、DEMANDまたはOFFに設定 #query_cache_type = DEMAND # #*ロギングとレプリケーション # #両方の場所がcronjobによって回転されます。 #このログタイプはパフォーマンスを低下させることに注意してください。 #5.1以降、実行時にログを有効にできます! #general_log_file = /var/log/mysql/mysql.log #general_log = 1 # #/etc/mysql/conf.d/mysqld_safe_syslog.cnfが原因でエラーログがsyslogに記録されます。 # #ネットワークエラーなどについて知りたい log_warnings = 2 # #スロークエリログを有効にして、特に長時間のクエリを表示する #slow_query_log [= {0 | 1}] slow_query_log_file = /var/log/mysql/mariadb-slow.log long_query_time = 10 #log_slow_rate_limit = 1000 log_slow_verbosity = query_plan #log-queries-not-using-indexes #log_slow_admin_statements # #次は、バックアップログを簡単に再生したり、複製したりするために使用できます。 #注:レプリケーションスレーブをセットアップする場合は、README.Debianを参照してください #変更が必要なその他の設定。 #server-id = 1 #report_host = master1 #auto_increment_increment = 2 #auto_increment_offset = 1 log_bin = / var / log / mysql / mariadb-bin log_bin_index = /var/log/mysql/mariadb-bin.index #パフォーマンスのためのファブではないが、より安全 #sync_binlog = 1 expire_logs_days = 10 max_binlog_size = 100M #奴隷 #relay_log = / var / log / mysql / relay-bin #relay_log_index = /var/log/mysql/relay-bin.index #relay_log_info_file = /var/log/mysql/relay-bin.info #log_slave_updates #read_only # #アプリケーションがサポートしている場合、この厳密なsql_modeは #無効な日付の挿入などの間違い #sql_mode = NO_ENGINE_SUBSTITUTION、TRADITIONAL # #* InnoDB # #InnoDBは、デフォルトで/ var / lib / mysql /の10MBデータファイルで有効になっています。 #InnoDB関連のオプションについては、マニュアルをお読みください。沢山あります! default_storage_engine = InnoDB #ログファイルのサイズを変更することはできません。特別な手順が必要です #innodb_log_file_size = 50M innodb_buffer_pool_size = 20G innodb_log_buffer_size = 8M innodb_file_per_table = 1 innodb_open_files = 400 innodb_io_capacity = 400 innodb_flush_method = O_DIRECT # # * セキュリティ機能 # #chrootが必要な場合は、マニュアルも読んでください! #chroot = / var / lib / mysql / # #SSL証明書を生成するには、OpenSSL GUI "tinyca"をお勧めします。 # #ssl-ca = / etc / mysql / cacert.pem #ssl-cert = / etc / mysql / server-cert.pem #ssl-key = / etc / mysql / server-key.pem [mysqldump] 速い 引用名 max_allowed_packet = 16M [mysql] #no-auto-rehash#mysqlの起動は速くなりましたが、タブ補完はありません [isamchk] key_buffer = 16M # #*重要:このファイルの設定を上書きできる追加設定! #ファイルは「.cnf」で終わる必要があります。そうでない場合は無視されます。 # !includedir /etc/mysql/conf.d/
そして、inno変数の内容:
MariaDB [(none)]> 'inno%'のような変数を表示します。 + ------------------------------------------- + ----- ------------------- + | 変数名| 価値| + ------------------------------------------- + ----- ------------------- + | innodb_adaptive_flushing | オン| | innodb_adaptive_flushing_lwm | 10 | | innodb_adaptive_hash_index | オン| | innodb_adaptive_hash_index_partitions | 1 | | innodb_adaptive_max_sleep_delay | 150000 | | innodb_additional_mem_pool_size | 8388608 | | innodb_api_bk_commit_interval | 5 | | innodb_api_disable_rowlock | オフ| | innodb_api_enable_binlog | オフ| | innodb_api_enable_mdl | オフ| | innodb_api_trx_level | 0 | | innodb_autoextend_increment | 64 | | innodb_autoinc_lock_mode | 1 | | innodb_buffer_pool_dump_at_shutdown | オフ| | innodb_buffer_pool_dump_now | オフ| | innodb_buffer_pool_filename | ib_buffer_pool | | innodb_buffer_pool_instances | 8 | | innodb_buffer_pool_load_abort | オフ| | innodb_buffer_pool_load_at_startup | オフ| | innodb_buffer_pool_load_now | オフ| | innodb_buffer_pool_populate | オフ| | innodb_buffer_pool_size | 21474836480 | | innodb_change_buffer_max_size | 25 | | innodb_change_buffering | すべて| | innodb_checksum_algorithm | innodb | | innodb_checksums | オン| | innodb_cleaner_lsn_age_factor | high_checkpoint | | innodb_cmp_per_index_enabled | オフ| | innodb_commit_concurrency | 0 | | innodb_compression_failure_threshold_pct | 5 | | innodb_compression_level | 6 | | innodb_compression_pad_pct_max | 50 | | innodb_concurrency_tickets | 5000 | | innodb_corrupt_table_action | 主張する| | innodb_data_file_path | ibdata1:12M:autoextend | | innodb_data_home_dir | | | innodb_disable_sort_file_cache | オフ| | innodb_doublewrite | オン| | innodb_empty_free_list_algorithm | バックオフ| | innodb_fake_changes | オフ| | innodb_fast_shutdown | 1 | | innodb_file_format | アンテロープ| | innodb_file_format_check | オン| | innodb_file_format_max | アンテロープ| | innodb_file_per_table | オン| | innodb_flush_log_at_timeout | 1 | | innodb_flush_log_at_trx_commit | 1 | | innodb_flush_method | O_DIRECT | | innodb_flush_neighbors | 1 | | innodb_flushing_avg_loops | 30 | | innodb_force_load_corrupted | オフ| | innodb_force_recovery | 0 | | innodb_foreground_preflush | exponential_backoff | | innodb_ft_aux_table | | | innodb_ft_cache_size | 8000000 | | innodb_ft_enable_diag_print | オフ| | innodb_ft_enable_stopword | オン| | 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_io_capacity | 400 | | innodb_io_capacity_max | 2000 | | innodb_kill_idle_transaction | 0 | | innodb_large_prefix | オフ| | innodb_lock_wait_timeout | 50 | | innodb_locking_fake_changes | オン| | innodb_locks_unsafe_for_binlog | オフ| | innodb_log_arch_dir | ./ | | innodb_log_arch_expire_sec | 0 | | innodb_log_archive | オフ| | innodb_log_block_size | 512 | | innodb_log_buffer_size | 8388608 | | innodb_log_checksum_algorithm | innodb | | innodb_log_compressed_pages | オン| | innodb_log_file_size | 50331648 | | innodb_log_files_in_group | 2 | | innodb_log_group_home_dir | ./ | | innodb_lru_scan_depth | 1024 | | innodb_max_bitmap_file_size | 104857600 | | innodb_max_changed_pages | 1000000 | | innodb_max_dirty_pages_pct | 75 | | innodb_max_dirty_pages_pct_lwm | 0 | | innodb_max_purge_lag | 0 | | innodb_max_purge_lag_delay | 0 | | innodb_mirrored_log_groups | 1 | | 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 | 400 | | innodb_optimize_fulltext_only | オフ| | innodb_page_size | 16384 | | innodb_print_all_deadlocks | オフ| | innodb_purge_batch_size | 300 | | innodb_purge_threads | 1 | | innodb_random_read_ahead | オフ| | innodb_read_ahead_threshold | 56 | | innodb_read_io_threads | 4 | | innodb_read_only | オフ| | innodb_replication_delay | 0 | | innodb_rollback_on_timeout | オフ| | innodb_rollback_segments | 128 | | innodb_sched_priority_cleaner | 19 | | innodb_show_locks_held | 10 | | innodb_show_verbose_locks | 0 | | innodb_sort_buffer_size | 1048576 | | innodb_spin_wait_delay | 6 | | innodb_stats_auto_recalc | オン| | innodb_stats_method | nulls_equal | | innodb_stats_on_metadata | オフ| | innodb_stats_persistent | オン| | innodb_stats_persistent_sample_pages | 20 | | innodb_stats_sample_pages | 8 | | innodb_stats_transient_sample_pages | 8 | | innodb_status_output | オフ| | innodb_status_output_locks | オフ| | innodb_strict_mode | オフ| | innodb_support_xa | オン| | innodb_sync_array_size | 1 | | innodb_sync_spin_loops | 30 | | innodb_table_locks | オン| | innodb_thread_concurrency | 0 | | innodb_thread_sleep_delay | 10000 | | innodb_track_changed_pages | オフ| | innodb_undo_directory | 。| | innodb_undo_logs | 128 | | innodb_undo_tablespaces | 0 | | innodb_use_atomic_writes | オフ| | innodb_use_fallocate | オフ| | innodb_use_global_flush_log_at_trx_commit | オン| | innodb_use_native_aio | オン| | innodb_use_stacktrace | オフ| | innodb_use_sys_malloc | オン| | innodb_version | 5.6.17-65.0 | | innodb_write_io_threads | 4 | + ------------------------------------------- + ----- ------------------- + セット内の143行(0.02秒)
マシンのコアの数は8です。
Intel(R) Xeon(R) CPU E3-1246 v3 @ 3.50GHz
の時点で /proc/cpuinfo
最後に、RolandoMYSQLDBAによって提案されたインデックスを使用してクエリを実行しました。クエリはそれぞれ約11〜20秒かかりました。60.000を超えるスレッドとgoogle-botが絶えずクロールするため、threadidについての最初のクエリが1秒以内に返されることが私にとって重要です(掲示板のメインテーブルです)。これらのスレッド。