InnoDBでの単純なSELECTがMyISAMよりも遅いのはなぜですか?


33

私にはかなり厄介な問題があります。メインデータベースエンジンとして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_pa​​cket = 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_pa​​cket = 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_pa​​ges | オン|
| 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_pa​​ges | 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_pa​​ges | オフ|
| 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秒以内に返されることが私にとって重要です(掲示板のメインテーブルです)。これらのスレッド。


コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました
ポールホワイトはGoFundMonicaを言う

回答:


24

あなたの質問

SELECT post.postid, post.attach FROM newbb_innopost AS post WHERE post.threadid = 51506;

一見すると、そのクエリはテーブルの1.1597%(5390146のうち62510)にのみ接触するはずです。threadid 51506のキー配布を考慮すると、高速でなければなりません。

現実性チェック

どのバージョンのMySQL(Oracle、Percona、MariaDB)を使用しても、それらのどれもが共通の敵であるInnoDBアーキテクチャと戦うことはできません。

InnoDBアーキテクチャ

クラスター化インデックス

各threadidエントリには主キーが添付されていることに注意してください。これは、インデックスから読み取るときに、ClusteredIndex(内部でgen_clust_indexという名前)内で主キー検索を行う必要があることを意味します。ClusteredIndexでは、各InnoDBページにデータとプライマリキーインデックス情報の両方が含まれています。詳細については、私の投稿Best of MyISAMおよびInnoDBを参照してください。

冗長インデックス

一部のインデックスの先頭列が同じであるため、テーブルには多くの混乱があります。MySQLとInnoDBは、必要なBTREEノードに到達するためにインデックスクラッターをナビゲートする必要があります。次のコマンドを実行して、混乱を減らす必要があります。

ALTER TABLE newbb_innopost
    DROP INDEX threadid,
    DROP INDEX threadid_2,
    DROP INDEX threadid_visible_dateline,
    ADD INDEX threadid_visible_dateline_index (`threadid`,`visible`,`dateline`,`userid`)
;

なぜこれらのインデックスを削除するのですか?

  • 最初の3つのインデックスはthreadidで始まります
  • threadid_2threadid_visible_dateline同じ3列から始めます
  • threadid_visible_dateline PRIMARY KEYであり、埋め込まれているため、postidは必要ありません

バッファキャッシュ

InnoDBバッファープールは、データとインデックスページをキャッシュします。MyISAMはインデックスページのみをキャッシュします。

この領域だけで、MyISAMはデータのキャッシュに時間を浪費しません。データをキャッシュするように設計されていないためです。InnoDBは、触れるすべてのデータページとインデックスページ(およびその祖母)をキャッシュします。InnoDBバッファープールが小さすぎる場合、1つのクエリでページをキャッシュし、ページを無効化し、ページをすべて削除する可能性があります。

テーブルのレイアウト

あなたは考慮して行からいくつかのスペースを剃ることができimportthreadidimportpostid。あなたはそれらをBIGINTとして持っています。ClusteredIndexでは、行ごとに16バイトを使用します。

これを実行する必要があります

SELECT importthreadid,importpostid FROM newbb_innopost PROCEDURE ANALYSE();

これにより、特定のデータセットに対してこれらの列がどのデータ型であるかが推奨されます。

結論

MyISAMは、特にキャッシングの分野でInnoDBよりも競合するものがはるかに少ないです。

RAMの量(32GB)とMySQLのバージョン()を明らかにしましたが、Server version: 10.0.12-MariaDB-1~trusty-wsrep-log mariadb.org binary distribution, wsrep_25.10.r4002このパズルにはまだ明らかにしていない他の部分があります

  • InnoDB設定
  • コアの数
  • 他の設定 my.cnf

これらのことを質問に追加できれば、さらに詳しく説明できます。

更新2014-08-28 11:27 EDT

スレッドを増やす必要があります

innodb_read_io_threads = 64
innodb_write_io_threads = 16
innodb_log_buffer_size = 256M

クエリキャッシュを無効にすることを検討します(MySQL 5.6からデフォルトでquery_cache_typeが無効になっているのはなぜですか?

query_cache_size = 0

バッファプールを保存します

innodb_buffer_pool_dump_at_shutdown=1
innodb_buffer_pool_load_at_startup=1

パージスレッドを増やす(複数のテーブルでDMLを実行する場合)

innodb_purge_threads = 4

試してみる !!!


私はInnoDBが純粋な速度テストで遅くなることを意図していることを知っていますが、この程度ですか?私は、MySQLチームがこのギャップを埋めるために一生懸命働いていることを読みました。まだ100倍の増加に対応しています!質問-この種のクエリは、「直接」の非クラスタ化Bツリーインデックスを使用した方が適切だと言っていますか(つまり、PKデータが含まれていない)。もしそうなら、なぜこれが実装されていない/実装されていないのですか?OPが必要とする機能は、間違いなくわずかなユースケースではありません。
ベレース14

その写真のフルサイズバージョンへのリンクを追加できますか?読みにくい部分もあります:
水っぽい14

@RolandMySQLDBA情報に感謝します。InnoDBの100倍のスローダウンが「通常」であることを示唆していないことを願っています。要求に応じて、不足している情報を質問に追加しました:)これまでの説明に感謝します!マシンのコア数は8である
jollyroger

2
@wateryこれはフルサイズの画像です:scribd.com/doc/31337494/XtraDB-InnoDB-internals-in-drawing
RolandoMySQLDBA

1
@RolandoMySQLDBAのご協力に感謝します。残念ながら、これらの最後の調整でも役に立たず、InnoDBの完了には約11〜20秒かかります。私はあなたの答えに基づいて何かを試みました-すべてのインデックスを削除し、カバーするインデックスを作成します。それは大いに役立っています。インデックスの説明がなければ、このソリューションは見つかりませんでした。あなたの答えを確認し、私がやったことを説明する答えを自分で書きに行きます:)
jollyroger 14

7

@RolandMySQLDBAは、質問に答えるための適切なヒントを提供しました。問題はクエリにあるようで、結果を返すには、それらの各フィールドを(何らかの方法でデータベースから)読み取る必要があります。

を除くすべてのインデックスを削除しPRIMARY KEY、この新しいインデックスを挿入しました。

ALTER TABLE newbb_innopost ADD INDEX threadid_visible_dateline_index (threadid,visible,dateline,userid,attach,ipaddress);

このリンクは、ここで何が起こるかを説明しています(indexをカバー):postid,attachキー自体から抽出できるクエリのクエリされたフィールド。これにより、実際のデータを確認し、ハードディスクにI / Oを使用する必要がなくなります。

すべてのクエリが0.00秒で実行されるようになりました。

どうもありがとうございました。

編集:実際の根本的な問題は解決されていません、私はこのテクニックでそれを回避しました。InnoDBは、この領域でいくつかの深刻な修正が必要です。


私は同じ問題に直面しています。myismaクエリには0.01秒かかり、innodbには60秒かかります。提案を試してください。
AMB

@AMB-0.01はクエリキャッシュのような匂いがします。で再び時間を計るSQL_NO_CACHE
リックジェームズ

0

クエリとテーブルの両方に基づいて、時系列テーブルのデータを選択しているようです。このように、同時に挿入しているためにクエリ時間が遅くなっている可能性がありますか?

これら2つのことが当てはまる場合は、ScaleDBを代替案として検討することをお勧めしますか?まだ(おそらく)より適切なエンジンであるMariaDBを引き続き使用します。

http: //www.scaledb.com-ホームページ http://www.scaledb.com/download-form.php-当社の製品


2
メジャーエディションは無料ではないことを追加する必要があります。
ypercubeᵀᴹ

0

両方のエンジンは、クエリより高速に実行します

INDEX(threadid, attach, postid)

これは、「カバーする」インデックスであり、実質的に同じ方法で動作するためです(インデックスBTreeを使用)。

また、「コールド」サーバー上のいずれのエンジンでこれは不可能だと言います。

62510 rows in set (0.13 sec)

SQL_NO_CACHEタイミングを実行するときはいつでも使用してください-クエリキャッシュが結論を汚染することは望ましくありません。

別の高速なアプローチ(I / Oキャッシングに関係なく):

InnoDBを使用し、からに変更PRIMARY KEY (postid)します

PRIMARY KEY(threadid, postid),
INDEX(postid)

その理由は、これにより、関連するすべての行が隣接するため、必要なI / Oなどが少なくなるためです。これINDEX(postid)は、AUTO_INCREMENT満足しておくためです。警告:これはすべての二次キーを台無しにします-いくつかはより速く、いくつかはより遅くなります。


0

@jollyrogerは既に正しい設定になっているため、直接適用できませんが、myisamがInnodbより遅い理由でinnodb_buffer_pool_size説明されているように、RAMの70%に変更することで大きな改善が得られました

最初MyISAMは遅かったが、大丈夫。次にInnoDB、この質問の100倍遅くなり、設定InnoDBを変更した後に10倍速くなったのと同様に、事態を悪化させましたMyISAM

私のデフォルト設定は8MBでしたが、これはほとんどありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.