web-dev-qa-db-ja.com

非常に大きなテーブルでのmariadbデータベースのパフォーマンスの管理

Mardorab-10.2.19がインストールされたFedora29にjoomla-3.9およびApache-2.4.34システムがあり、検索コンテンツを含むテーブルが非常に大きい。いくつかは1.2GBより大きく、1つは5.5GBより大きいです。記事の削除には非常に時間がかかります。

それが実行されているシステムはIntel(R)Xeon(R)CPU E5-2623 v3 @ 3.00GHzで、64GBのRAMとRAID5 SSDを搭載しています。他にアクティビティはありません。 。

パフォーマンスを向上させるためのオプションはありますか?基本的なmariadbのチューニングをいくつか行いましたが、データベース自体にできることは実際にはあまりありません。

これはガレラの目的ですか?データベースをramdiskに入れると役に立ちますか?

AWSへの移行には何が関係していますか?

Ext4以外の別のファイルシステムに変更すると、かなりの違いが生じますか?

RAID5を使用せずに簡単に再構築できるため、検索テーブルだけを別のSSDに置くことを考えていましたが、他のデータベースからそれらを分離する方法がわかりませんでした。

これは、このシステムのmy.cnf構成です。パフォーマンスを改善するために行う他のチューニング変更はありますか?

[client]
port            = 3306
socket          = /var/lib/mysql/mysql.sock
[mysqld]
port            = 3306
socket          = /var/lib/mysql/mysql.sock
skip-external-locking
key_buffer_size = 256M
max_allowed_packet = 16M
table_open_cache = 256
sort_buffer_size = 1M
read_buffer_size = 1M
read_rnd_buffer_size = 4M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size= 16M
thread_concurrency = 8
relay_log_space_limit = 500M
relay_log_purge = 1
log-slave-updates = 1
max_heap_table_size = 256M
tmp_table_size = 256M
relay-log=bwimail01-relay-bin
log_bin                 = /var/log/mariadb/mysql-bin.log
expire_logs_days        = 5
max_binlog_size         = 100M
plugin_load=server_audit=server_audit.so
server_audit_events=connect,query
server_audit_file_path = /var/log/mariadb/server_audit.log
server_audit_file_rotate_size           = 1G
server_audit_file_rotations             = 1
slow-query-log = 1
slow-query-log-file = /var/log/mariadb/mariadb-slow.log
long_query_time = 1
log_error = /var/log/mariadb/mariadb-error.log
binlog_format=mixed
server-id       = 5
report-Host=bwimail01.example.com
innodb_data_home_dir = /var/lib/mysql
innodb_defragment=1
innodb_file_per_table
innodb_flush_log_at_trx_commit = 2
innodb_data_file_path = ibdata1:10M:autoextend:max:500M
innodb_buffer_pool_size=850M
innodb_log_file_size = 64M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method=O_DIRECT
innodb_lock_wait_timeout = 50
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash
[myisamchk]
key_buffer_size = 128M
sort_buffer_size = 128M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout

編集:これは「show create table Finder_links」です

Finder_links | CREATE TABLE `Finder_links` (
`link_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`url` varchar(255) NOT NULL,
`route` varchar(255) NOT NULL,
`title` varchar(400) DEFAULT NULL,
`description` text DEFAULT NULL,
`indexdate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`md5sum` varchar(32) DEFAULT NULL,
`published` tinyint(1) NOT NULL DEFAULT 1,
`state` int(5) DEFAULT 1,
`access` int(5) DEFAULT 0,
`language` varchar(8) NOT NULL,
`publish_start_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`publish_end_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`start_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`end_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`list_price` double unsigned NOT NULL DEFAULT 0,
`sale_price` double unsigned NOT NULL DEFAULT 0,
`type_id` int(11) NOT NULL,
`object` mediumblob NOT NULL,
PRIMARY KEY (`link_id`),
KEY `idx_type` (`type_id`),
KEY `idx_title` (`title`(100)),
KEY `idx_md5` (`md5sum`),
KEY `idx_url` (`url`(75)),
KEY `idx_published_list` 
(`published`,`state`,`access`,`publish_start_date`,`publish_end_date`,`list_price`),
KEY `idx_published_sale`
(`published`,`state`,`access`,`publish_start_date`,`publish_end_date`,`sal e_price`)
) ENGINE=InnoDB AUTO_INCREMENT=62705 DEFAULT CHARSET=utf8mb4 

問題の一部は、これがjoomlaの一部であるため、テーブルの編成方法、スキーマを改善するために行うことができる変更、またはスキーマへの書き込みを編成する方法を実際には制御できないことです。

次のような遅いクエリがたくさんあるようです:

INSERT  IGNORE INTO  `xu5gc_Finder_terms`
    (`term`, `stem`, `common`, `phrase`, `weight`, `soundex`, `language`) 
  SELECT  ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight,
        SOUNDEX(ta.term), ta.language
    FROM  `xu5gc_Finder_tokens_aggregate` AS ta
    WHERE  ta.term_id = 0
    GROUP BY  ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight,
        SOUNDEX(ta.term), ta.language;

INSERT INTO  `xu5gc_Finder_tokens_aggregate`
               (`term_id`, `map_suffix`,
                `term`, `stem`, `common`, `phrase`, `term_weight`, `context`,
                `context_weight`, `total_weight`, `language`) 
  SELECT  COALESCE(t.term_id, 0), '', t1.term, t1.stem, t1.common,
          t1.phrase, t1.weight, t1.context,
          ROUND( t1.weight * COUNT( t2.term ) * 0.700000, 8 ) AS context_weight,
          0, t1.language
    FROM (
        SELECT  DISTINCT t1.term, t1.stem, t1.common, t1.phrase, t1.weight,
                t1.context, t1.language
            FROM  `xu5gc_Finder_tokens` AS t1
            WHERE  t1.context = 2 
         ) AS t1
    JOIN  `xu5gc_Finder_tokens` AS t2  ON t2.term = t1.term
    LEFT JOIN  `xu5gc_Finder_terms` AS t  ON t.term = t1.term
    WHERE  t2.context = 2
    GROUP BY  t1.term, t.term_id, t1.term, t1.stem, t1.common,
        t1.phrase, t1.weight, t1.context, t1.language
    ORDER BY  t1.term DESC;

そして

UPDATE  `xu5gc_Finder_terms` AS t
    INNER JOIN  `xu5gc_Finder_tokens_aggregate` AS ta
                    ON ta.term_id = t.term_id 
    SET t.`links` = t.links + 1;

SET timestamp=1546570831;
SELECT DISTINCT t.term_id AS id, t.term AS term
    FROM xu5gc_Finder_terms AS t
    WHERE t.soundex = SOUNDEX('2018 2594-1')
      AND t.phrase = 1;

編集:要求された情報をさらに追加します。現在、約24時間稼働していますが、これは開発システムであるため、現在あまり活動がありません。

グローバル変数を表示
https://Pastebin.com/W0BPKtU5

GLOBALKステータスを表示
https://Pastebin.com/gB0AQut6

ファインダーテーブル(SHOW INDEX FROMおよびEXPLAIN)
xu5gc_Finder_termsは5.4GBテーブルです
https://Pastebin.com/rJxts9Sp

MySQLTuner-Perl-master
https://Pastebin.com/AW6F0uMj

Mariadbエラーログ(/var/log/mariadb/mariadb-error.log)
https://Pastebin.com/EE8Q0k1D

いくつかの画像があると役立つと思いました。他の統計情報が役立つかどうか教えてください。

innodb_io_pend-daysorts - dayhandler_write-day

編集:追加されたulimit出力(ルートとして):

# ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 128545
max locked memory       (kbytes, -l) 16384
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 128545
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
1
Alex Regan

変数とグローバルステータスの分析:

観測:

  • バージョン:10.2.18-MariaDB-log
  • 64 GBのRAM
  • 稼働時間= 20:39:00;一部のGLOBAL STATUS値は、まだ意味がない場合があります。
  • Windowsで実行していません。
  • 64ビットバージョンの実行
  • 完全に(またはほとんど)InnoDBを実行しているようです。

より重要な問題:

  • innodb_io_capacityは、おそらく1000以上に増やすことができます。

  • このサーバーでは、Galeraはオフになっています。制作のためにオンにしていますか?通常のレプリケーションを使用している場合は、sync_binlog = ON

  • 6テーブルスキャン/秒。クエリの半分にはテーブルスキャンが含まれます。クエリをもう少し見てみましょう。 (1時間あたり79回のソートマージパスのみ。)

  • MySQL Clusterを使用していますか? (Handler_discoverが表示されます。)

  • (ありがとう:slowlogの適切な設定。)

  • innodb_use_atomic_writes-RAIDコントローラハードウェアですか?どんなブランド?アトミック16KB書き込みをサポートしていますか?

  • engine_condition_pushdown = off - なぜ?

詳細と他の観察:

( innodb_buffer_pool_size / _ram ) = 15360M / 65536M = 23.4%-RAMの%がInnoDB buffer_poolに使用されます(ただし、価値のあるものにするための十分なデータがありません)

( ( Binlog_commits - Binlog_group_commits ) / Binlog_group_commits ) = ( 74938 - 74938 ) / 74938 = 0-並行して実行できるCOMMITの割合-マスターのbinlog_commit_wait_usecまたはbinlog_commit_wait_count、あるいはその両方を増やします。

( innodb_page_cleaners / innodb_buffer_pool_instances ) = 4 / 15 = 0.267-page_cleaners-innodb_page_cleanersをinnodb_buffer_pool_instancesに設定することをお勧めします

( innodb_lru_scan_depth ) = 1,024-「InnoDB:page_cleaner:1000ms意図したループにかかった...」はlru_scan_depthを下げることで修正できる

( Innodb_buffer_pool_pages_free * 16384 / innodb_buffer_pool_size ) = 705,616 * 16384 / 15360M = 71.8%-バッファプールフリー-buffer_pool_sizeはワーキングセットよりも大きい。それを減らすことができます

( Innodb_buffer_pool_pages_free / Innodb_buffer_pool_pages_total ) = 705,616 / 983040 = 71.8%-現在使用されていないbuffer_poolの部分-innodb_buffer_pool_sizeが必要以上に大きいですか?

( Innodb_buffer_pool_bytes_data / innodb_buffer_pool_size ) = 4,475,404,288 / 15360M = 27.8%-データが占めるバッファープールの割合-小さなパーセントmayは、buffer_poolが不必要に大きいことを示します。

( Uptime / 60 * innodb_log_file_size / Innodb_os_log_written ) = 74,340 / 60 * 1024M / 465657856 = 2,856-InnoDBログローテーション間の分5.6.8以降、これは動的に変更できます。 my.cnfも必ず変更してください。 -(ローテーション間の60分の推奨はやや恣意的です。)innodb_log_file_sizeを調整します。 (AWSでは変更できません。)

( innodb_io_capacity ) = 200-ディスク上で実行可能な1秒あたりのI/O操作。遅いドライブの場合は100。ドライブを回転させる場合は200。 SSDの場合は1000〜2000。 RAID係数を掛けます。

( sync_binlog ) = 0-追加のセキュリティのために1を使用します。I/ Oのコストは= 1の場合、多くの「クエリの終了」につながる可能性があります。 = 0は「不可能な位置でのバイナリログ」につながり、クラッシュでトランザクションを失う可能性がありますが、より高速です。

( innodb_print_all_deadlocks ) = innodb_print_all_deadlocks = OFF-すべてのデッドロックをログに記録するかどうか。 -デッドロックに悩まされている場合は、これをオンにします。注意:デッドロックが多い場合、ディスクに大量に書き込まれる可能性があります。

( join_buffer_size / _ram ) = 1M / 65536M = 0.00%-スレッドごとに0-N。 JOINを高速化する可能性があります(クエリ/インデックスを修正する方が良い)(すべてのエンジン)インデックススキャン、範囲インデックススキャン、全テーブルスキャン、各全JOINなどに使用されます。サイズが大きい場合は、join_buffer_sizeを減らしてメモリ負荷を回避します。 RAMの1%未満を推奨します。小さい場合は、RAMの0.01%に増やして、一部のクエリを改善します。

( net_buffer_length / max_allowed_packet ) = 16,384 / 16M = 0.10%

( local_infile ) = local_infile = ON-local_infile = ONは潜在的なセキュリティ問題です

( bulk_insert_buffer_size / _ram ) = 8M / 65536M = 0.01%-複数行のINSERTおよびLOAD DATAのバッファー-小さすぎると、このような操作が妨げられる可能性があります。

( tmp_table_size ) = 256M-[〜#〜]メモリのサイズの制限[〜#〜]SELECTをサポートするために使用される一時テーブル-tmp_table_sizeを減らして回避RAMが不足しています。おそらく64M以下です。

( (Com_insert + Com_update + Com_delete + Com_replace) / Com_commit ) = (20260 + 69883 + 2901 + 0) / 62678 = 1.48-コミットごとのステートメント(すべてのInnoDBを想定)-低:トランザクションでクエリをグループ化するのに役立つ場合があります。

( Select_scan ) = 448,754 / 74340 = 6 /sec-全テーブルスキャン-インデックスを追加する/クエリを最適化する(小さなテーブルでない限り)

( Select_scan / Com_select ) = 448,754 / 871456 = 51.5%-全表スキャンを実行する選択の%。 (ストアドルーチンにだまされる可能性があります。)-インデックスを追加する/クエリを最適化する

( relay_log_space_limit ) = 500M-スレーブのリレーログの最大合計サイズ。 (0 =無制限)-制限を設ける根拠について説明しましょう。

( binlog_format ) = binlog_format = MIXED-STATEMENT/ROW/MIXED。 ROWが推奨されます。デフォルトになる場合があります。

( wsrep_log_conflicts ) = wsrep_log_conflicts = OFF-COMMIT中にデッドロックの競合が発生した場合、このフラグが役立ちます。

( back_log / max_connections ) = 80 / 151 = 53.0%

異常に小さい:

Handler_read_next / Handler_read_key = 0.647
Innodb_secondary_index_triggered_cluster_reads = 7.8MB
Rows_tmp_read = 2.3MB
eq_range_index_dive_limit = 0
innodb_log_block_size = 0
innodb_max_bitmap_file_size = 0
innodb_max_changed_pages = 0
innodb_mirrored_log_groups = 0
innodb_sched_priority_cleaner = 0
innodb_show_locks_held = 0
lock_wait_timeout = 86400
slave_net_timeout = 60

異常に大きい:

Com_show_binlogs = 25 /HR
Com_show_engine_status = 26 /HR
Com_show_plugins = 25 /HR
Com_show_slave_hosts = 0.15 /HR
Com_show_slave_status = 0.04 /sec
Handler_discover = 27 /HR
Innodb_buffer_pool_pages_flushed / max(Questions, Queries) = 1
Innodb_buffer_pool_pages_free = 705,616
Innodb_system_rows_deleted = 0.81 /sec
Innodb_system_rows_inserted = 0.81 /sec
Innodb_system_rows_read = 60,203
Opened_plugin_libraries = 0.097 /HR
Performance_schema_file_classes_lost = 1
Slave_received_heartbeats = 656
Slaves_running = 1
group_concat_max_len = 1MB
innodb_adaptive_hash_index_partitions = 8
max_relay_log_size = 100MB

異常な文字列:

Slave_running = ON
binlog_annotate_row_events = ON
innodb_buffer_pool_dump_at_shutdown = ON
innodb_buffer_pool_load_at_startup = ON
innodb_corrupt_table_action = deprecated
innodb_data_home_dir = /var/lib/mysql
innodb_defragment = ON
innodb_fast_shutdown = 1
innodb_file_format = Barracuda
innodb_file_format_max = Barracuda
innodb_large_prefix = ON
innodb_locking_fake_changes = OFF
innodb_undo_directory = ./
innodb_use_atomic_writes = ON
innodb_use_global_flush_log_at_trx_commit = OFF
innodb_use_trim = ON
log_slow_admin_statements = ON
log_slow_slave_statements = ON
myisam_stats_method = NULLS_UNEQUAL
opt_s__engine_condition_pushdown = off
replicate_annotate_row_events = ON
2
Rick James

遅いクエリに関するヒント。これは、提案の簡単なリスト、_CREATE TABLE_であり、テーブルサイズが役立つ場合があります。

  • _INSERT...SELECT_は繰り返し行われていますか?段階的に行うことはできますか?同様に、今日のデータを今日はコピーしますが、明日はコピーしませんか?

  • _xu5gc_Finder_tokens_aggregate_-SELECTで処理するのではなく、別の列にSOUNDEX(term)を事前計算することを検討してください。

  • _SELECT ... FROM xu5gc_Finder_tokens_aggregate_テーブル全体を読み取り、一時ファイルを作成してから、_GROUP BY_を実行する必要があります。それだけの出力が必要かどうかを考え直してください。待つ!なぜ_GROUP BY_があるのですか?集合体はありませんか?

  • WHERE t.soundex = SOUNDEX('2018 2594-1') AND t.phrase = 1にはINDEX(phrase, soundex)が必要です(どちらの順序でも)。

  • _JOIN t2 ON t2.term = t1.term ... WHERE t2.context = 2_ mayコンテキストが同じであるため、_JOIN t2 ON t2.term = t1.term AND t2.context = t1.context_のように機能します。次に、INDEX(term, context)(どちらの順序でも)がおそらく有益です。

  • termと_term_id_は1:1ですか?グループ化と結合は、いつ使用するかについて一貫していないようです。 may _term_id_を削除してtermを_PRIMARY KEY_に昇格する価値はありますか?

0
Rick James

私のマントラ:「パフォーマンスの問題でハードウェアをスローできるのは1回だけです。ソフトウェアソリューションを探すことをお勧めします。」

電源障害(または他のクラッシュまたはROLLBACKの必要性)が発生した場合に古い行を保存するため、多数の行を削除するとコストがかかります。

  • 行数が少ない場合、適切なインデックスがない可能性がありますか? SHOW CREATE TABLEおよびDELETEステートメントを提供してください。

  • 行数が多い場合は、チャンク単位で行うのが最適です。

  • これが1か月以上経過したレコードを削除するなどの反復的なプロセスである場合、PARTITION BY RANGEは非常に有益です。

最後の2つのケースは両方ともカバーされています here

通常、「パフォーマンスの問題を回避することはできません」。ただし、適切に調整されていないものが1つまたは2つあります。

64GB of RAM with a 5.5GB table and innodb_buffer_pool_size=850M

その設定は、利用可能なRAMの70%まで上げることができます。しかし、10Gでもメリットがあります。

再、あなたの黙想:

  • RAMディスクを使用しないしない

  • AWSが役立つかどうかはわかりません。彼らはbuffer_poolを適切なサイズに設定したはずですが、他の問題があるかもしれません。

  • Galeraの主な用途はHA(高可用性)であり、ほとんど問題なくサーバーのクラッシュに耐えます。

  • 別のファイルシステムは「かなり役立つ」とは言えません。

  • SSDを搭載したRAID5は、間違いなく最良の方法です。それから離れないでください。バッテリーバックアップ式ライトキャッシュを備えたハードウェアRAIDコントローラーが含まれているといいのですが?テーブル(ファイル)の配置を手動で行うよりも、RAIDにアクセスを処理させるほうが良いです。

クエリ

望ましいインデックス:

xu5gc_Finder_tokens_aggregate:  INDEX(term_id)   -- for insert..select #1 & Update

xu5gc_Finder_tokens:  INDEX(context, term)  -- in that order.  
xu5gc_Finder_terms:   INDEX(term)

xu5gc_Finder_terms:   INDEX(term_id)

xu5gc_Finder_terms:  INDEX(phase, soundex,  -- first, in either order
                           term, term_id)   -- in either order (for 'covering')

SHOW CREATE TABLEを参照すると役立つ場合があります。)

0
Rick James

1秒あたりのレート= my.cnf [mysqld]セクションで考慮すべきRPSの提案

innodb_io_capacity=1900  # from 200 to enable SSD additional IOPS
read_rnd_buffer_size=512K  # ~4M to reduce handler_read_rnd_next RPS of 7,601
innodb_lru_scan_depth=100  # from 1024 to reduce CPU busy cycles 90% for this function
innodb_log_buffer_size=16M  # from 8M to support ~ 30 minutes in buffer before WD
table_definition_cache=500  # from 500 to reduce opened_table_definitions count

Ulimit -aの結果の投稿を楽しみにしています。お使いのOSが、MySQLがテーブル管理に使用できるオープンファイルハンドルの数を制限している可能性があります。

その他の提案については、私のプロフィールをご覧ください。ネットワークプロフィールには連絡先情報があります。

0
Wilson Hauck

2019年1月13日02:20アレックス、正解です。1024のオープンファイルは、アクティビティのレベルに対して低すぎます。

Linuxコマンドプロンプトからulimit -aを検討するための提案

ulimit -n 16384#より多くのOSファイルハンドルをアクティブにできるようにする1024から。

上記はLinux OSで動的です。停止/開始サービスはハンドルにアクセスできます。

OSのシャットダウン/再起動後もこれを維持するには、このURLで同様のOSの手順を確認してください

これらの手順ではfile-maxに500000を設定しています。今のところ容量を16384に設定してください。

ulimitは16384に設定してください。これにより、MySQLはリクエストされた1206を使用できるようになります

他のアプリ用のスペアがあります

https://glassonionblog.wordpress.com/2013/01/27/increase-ulimit-and-file-descriptors-limit/

Skypeでの連絡を楽しみにしています。私のSkype IDは[email protected]です。最新のコメントをありがとうございます。

0
Wilson Hauck