Oracle 与 MySQL 索引重建及表健康性检测 – 刘子毅

Oracle 与 MySQL 索引重建及表健康性检测 – 刘子毅


1. 概念の定義

インデックスの再構築: インデックスの物理ストレージ構造を再構築することを指します。インデックス/テーブル データを読み取り、新しい B ツリー セグメントを並べ替えて生成し、完了後に古いセグメントを新しいセグメントに置き換えます。 「インデックス分析(統計収集)」とは異なります。前者は物理構造を再構築しますが、後者はオプティマイザが使用する統計を更新するだけです。

テーブルのヘルスチェック:表を参照物理的完全性、スペース使用率、統計的精度、行の移行/リンク、断片化の程度他の次元で物理的検査を実行して、テーブルが損傷していないか、膨張していないか、統計的な歪みがないかを確認します。検出するのは「テーブル自体が健全かどうか」であり、単なる統計情報の収集とは異なります。

境界の明確化: インデックスの再構築 ≠ テーブルの再編成 (reorg)、テーブルの健全性テスト ≠ パフォーマンス ストレス テスト。二人はそれぞれ異なる懸念を抱いている。

2. 機能と適用シナリオ

シーン 集中
インデックス状態の異常(例: ALTER TABLE ... MOVE インデックスが使用不能になった後) リビルドリカバリの可用性
インデックスの断片化、高い B ツリー レベル、および削除された行の大部分 アクセス効率を向上させるための再構築/マージ
インデックス ロジックが破損しています (ページ構造が乱れている、非物理的な不良ページ) 再構築修理
この表には、ページ分割とランダムな削除によって大量の空のページが残されています。 テーブルの再編成によりスペースが再利用される
有効期限切れの統計情報による有効期限計画の歪み 分析リフレッシュ
アップグレードおよび移行後のテーブル/インデックスの物理的損傷の疑い 検証(CHECK/VALIDATE)

3. 動作メカニズム(詳細なコマンドと手順を含む)

3.1 Oracle – インデックスの再構築

ステップ 1: どのインデックスを再構築する必要があるかを特定する

-- 普通索引:查看状态是否 UNUSABLE
SELECT owner, index_name, table_name, status
FROM   dba_indexes
WHERE  status="UNUSABLE";

-- 分区索引:DBA_INDEXES.STATUS 对分区索引恒为 'N/A',须查分区级视图
SELECT index_owner, index_name, partition_name, status
FROM   dba_ind_partitions
WHERE  status="UNUSABLE";

キーポイント: パーティションインデックスは次のとおりです。 DBA_INDEXES 真ん中 STATUS として表示される N/A、これは通常の現象(「ステータスがパーティション レベルである」ことを示します)、これは例外ではありません。実際のステータスはによって異なります DBA_IND_PARTITIONS。

ステップ 2: リビルド コマンド (必要に応じて選択)

-- 离线重建(默认,锁表,最快,但阻塞 DML)
ALTER INDEX schema.idx_name REBUILD;

-- 在线重建(重建期间允许 DML,靠 journal 表记录变更)
ALTER INDEX schema.idx_name REBUILD ONLINE;

-- 重建同时收集统计信息
ALTER INDEX schema.idx_name REBUILD ONLINE COMPUTE STATISTICS;

-- 分区索引重建单个分区
ALTER INDEX schema.idx_name REBUILD PARTITION p1 ONLINE;

-- 仅合并 B-tree 同级块碎片(不改变索引逻辑结构,代价小于 REBUILD)
ALTER INDEX schema.idx_name COALESCE;

-- 回收索引尾部未用空间
ALTER INDEX schema.idx_name DEALLOCATE UNUSED;

ステップ3:再構成効果の検証

ANALYZE INDEX schema.idx_name VALIDATE STRUCTURE;
SELECT name, height, blocks, br_blks, lf_blks, lf_rows, del_lf_rows,
       pct_used
FROM   index_stats;

原理:REBUILD 元の索引または表データを読み取り、まず索引が配置されている表スペースに索引を作成します。一時セグメント新しいインデックスを保存します。再構築が完了したら、古いセグメントを破棄し、一時セグメントを正式なインデックス セグメントとして再定義します。したがって再構築します古いインデックスと新しいインデックスの両方を収容するには、インデックス テーブル スペースが必要です。スペース不足が報告されます ORA-01652(エラーレポートは次のことを指していることに注意してください)インデックステーブルスペースユーザーのデフォルトの一時表スペースではありません)。ONLINE さらに、スキーマはログ テーブルを使用して再構築中に DML を記録し、最終的にそれをマージしますが、追加のオーバーヘッドと辞書の不一致リスクが発生する可能性があります。COALESCE 同じレベルのブロックをマージするだけで、ツリー構造は変更されないため、ビットマップのインデックス作成には使用できません。

3.2 MySQL – インデックスの再構築

方法 1: 単一のセカンダリ インデックスを再構築する (最小コスト)

ALTER TABLE db.t DROP INDEX idx_x, ADD INDEX idx_x (col1, col2);

原則: セカンダリ インデックスには行データが格納されず、削除や再構築によってテーブル データが書き換えられることはありません。したがって、コストは最小限であり、影響は制御可能です。これは、インデックスの損傷/断片化を修復するための最初の選択肢です。

方法 2: テーブル全体を再構築する (すべてのインデックスの再構築を含む)

OPTIMIZE TABLE db.t;

-- 等价/更明确的重建写法
ALTER TABLE db.t FORCE;
ALTER TABLE db.t ENGINE=InnoDB;

原則: InnoDB OPTIMIZE TABLE デフォルトはにマッピングされる ALTER TABLE テーブルを再構築する(ソースコードのロジック:ha_innobase::optimize() デフォルトで戻る HA_ADMIN_TRY_ALTER)、のみ innodb_optimize_fulltext_only=ON そうすることで初めて、実際にフルテキスト インデックスの最適化のみが実行されます。インデックスページの再配置、ディレクトリの再構築、再構築後のページヘッダ PAGE_GARBAGE ゼロ化された (つまり、ページ内に再利用可能な削除されたスペースがなくなった) ため、断片化を解消し、論理的な損傷を修復します標準的な意味。

⚠️ OPTIMIZE TABLE この期間中、テーブル レベルのロックが取得され、大量の I/O が生成され、ビジネスの読み取りと書き込みがブロックされます。これは、低ピークのビジネス ウィンドウで実行する必要があります。

オンライン DDL のヒント: MySQL 5.6 以降はセカンダリ インデックスの追加と削除をサポートしています ALGORITHM=INPLACE オンライン モードでは、実行前にアルゴリズムを明示的に指定して、オンラインかどうかを確認することをお勧めします。

ALTER TABLE db.t ADD INDEX idx_x (col1), ALGORITHM=INPLACE, LOCK=NONE;

3.3 Oracle – テーブルの健全性検出

①統計(オプティマイザの健全性)

-- 收集表统计信息(推荐,级联索引)
BEGIN
  DBMS_STATS.GATHER_TABLE_STATS(
    ownname          => 'SCHEMA',
    tabname          => 'TABLE_NAME',
    cascade          => TRUE,          -- 同时收集索引统计
    degree           => 4,             -- 并行度
    method_opt       => 'FOR ALL COLUMNS SIZE AUTO'
  );
END;
/

-- 单独收集索引统计(不排序,资源消耗低于表分析)
BEGIN
  DBMS_STATS.GATHER_INDEX_STATS(ownname => 'SCHEMA', indname => 'IDX_NAME');
END;
/

②行移動・行リンク検出

ANALYZE TABLE schema.t LIST CHAINED ROWS INTO chained_rows;
SELECT COUNT(*) AS chained_cnt FROM chained_rows;

③セグメント/スペースの健全性(セグメントコンサルタント+フリースペース)

-- 段顾问发现行链接等问题:查看建议
SELECT owner, task_name, message
FROM   dba_advisor_findings;

-- 表空间空闲区(判断表空间碎片)
SELECT tablespace_name, COUNT(*) AS free_extents, SUM(bytes)/1024/1024 AS free_mb
FROM   dba_free_space
GROUP  BY tablespace_name;

④構造検証

ANALYZE TABLE schema.t VALIDATE STRUCTURE CASCADE;

原理:テーブル分析(ANALYZE TABLE ... COMPUTE STATISTICS) テーブル全体をソートする必要があるため、大量の CPU/ディスクが消費されます。インデックス分析はソートを行わず、消費量が少ないため、推奨されます。テーブルとインデックスを個別に分析する。行の移行/リンクは成功します LIST CHAINED ROWS 指定されたテーブルに着席し、セグメントコンサルタントと協力して必要かどうかを判断します ALTER TABLE ... MOVE 再編。知らせ:ALTER TABLE ... MOVE 行の物理的な位置 (ROWID) が変更され、その結果、すべてのインデックスがすぐに使用できなくなりますインデックスは MOVE 後に再構築する必要があります。

3.4 MySQL – テーブルの健全性検出

① 完全性チェック

CHECK TABLE db.t;            -- 完整检查,返回 OK / Corrupt
CHECK TABLE db.t QUICK;      -- 快速巡检,只查索引统计,不逐行扫描
CHECK TABLE db.t FOR UPGRADE;-- 升级/迁移后表结构、索引兼容性巡检
CHECKSUM TABLE db.t;         -- 计算校验和(可做主从/前后对比)

②統計情報を更新する

ANALYZE TABLE db.t;                       -- 刷新索引基数统计
ANALYZE TABLE t1, t2, t3;                 -- 一次分析多表
ANALYZE TABLE db.t UPDATE HISTOGRAM ON col1, col2 WITH 100 BUCKETS; -- 8.0 直方图

③ 断片化と空間検査

SHOW TABLE STATUS LIKE 't'\G
-- 关注 Data_free(已分配未使用空间,InnoDB 中通常是碎片)、
--      Data_length、Index_length、Rows

SELECT table_name, table_rows, data_length, index_length, data_free,
       ROUND(data_free/(data_length+index_length+1)*100,2) AS frag_pct
FROM   information_schema.tables
WHERE  table_schema="db"
  AND  data_free > 100*1024*1024;    -- 只看碎片 >100MB 的表

-- 检查统计信息(基数)是否明显失真
SELECT table_name, index_name, seq_in_index, column_name, cardinality
FROM   information_schema.statistics
WHERE  table_schema="db" AND table_name="t";

SHOW INDEX FROM db.t;

④コマンドライン一括検査ツール

mysqlcheck -c  db t          # 检查(--check)
mysqlcheck -a  db t          # 分析(--analyze)
mysqlcheck -o  db t          # 优化(--optimize,即重建表)

原理:CHECK TABLE 内線通話 btr_validate_index B+ ツリー構造インデックスをインデックスで検証し、損傷が見つかった場合は出力します。 ER_NOT_KEYFILE(B ツリーが破損しています)または ER_TABLESPACE_MISSING;協力する SHOW TABLE STATUS/エラー ログでは、特定の不良ページのスペース ID とページ番号を見つけることができます。ANALYZE TABLE リフレッシュする records_per_key カーディナリティと同様に、統計の有効期限が切れると、オプティマイザが誤ってフル テーブル スキャンを選択する可能性があります。 MySQL 8.0 は、歪んだ列の選択性推定を改善するための列ヒストグラムもサポートしています。Data_free 長期間にわたって大きすぎる場合は、断片化が深刻であることを意味し、次のことを行う必要があります。 OPTIMIZE TABLE / ALTER TABLE ... FORCE リサイクルを再構築します。

4. 関連オブジェクトと見学入り口

オラクル

物体 使用
DBA_INDEXES / USER_INDEXES インデックスのステータス (STATUS)、タイプ、およびそれが属するテーブル
DBA_IND_PARTITIONS パーティション化されたインデックスのパーティションレベルのステータス
INDEX_STATS VALIDATE STRUCTURE 次に、B ツリーの高さ、リーフ ブロック、削除された行などを確認します。
DBA_FREE_SPACE 表スペースの空き領域、表スペースの断片化を判断する
DBA_SEGMENTS / DBA_TABLES セグメントサイズとテーブル属性
DBA_ADVISOR_FINDINGS セグメントアドバイザーによる回線連結・再編アドバイス
動的なパフォーマンスビュー 監視可能なオンライン再構築関連の待機 (オンライン インデックス再構築のマージ フェーズなど)

MySQL

物体 使用
information_schema.TABLES テーブルのサイズ、DATA_FREE 断片、列
information_schema.STATISTICS インデックスベース CARDINALITY列の順序
SHOW TABLE STATUS 瓦礫と宇宙を迅速に評価
SHOW INDEX インデックスの構造とカーディナリティ
エラーログ 不正なページ スペース ID / ページの位置がありません

5. よくある誤解と境界線

  1. 「インデックス分析」を「インデックス再構築」として:ANALYZE 統計情報のみが更新され、物理構造は変更されません。インデックスが破損しているか使用できない場合、分析は無効であるため、再構築する必要があります。
  2. Oracle パーティション インデックス STATUS=’N/A’ が例外として誤判定される: これは正常な値です。確認してください。 DBA_IND_PARTITIONS。
  3. ALTER TABLE ... MOVE インデックスを再構築するのを忘れた:MOVE は ROWID を変更します。これによりすべてのインデックスが直ちに使用不能になり、その後に REBUILD を実行する必要があります。
  4. 再構築ではスペースが評価されません: Oracle の再構築には、新しいインデックスと古いインデックスの両方を収容できるインデックス テーブル スペースが必要であり、スペース不足レポートが発行されます。 ORA-01652(エラーレポートのテーブルスペースはインデックステーブルスペース)。
  5. MySQL OPTIMIZE TABLE 軽い操作として: その本質はテーブルを再構築することであり、これによりテーブルがロックされ、大量の I/O が生成されます。低いピーク時に実行する必要があります。
  6. SHOW TABLE STATUS の Rows 真の価値を取得する: 行数は正確ではなく (偏差は最大 2 倍になる可能性があります)、正確なベースとして使用できません。そして information_schema デフォルトの統計キャッシュは約 24 時間です。 ANALYZE 後で確認してください。
  7. 国内ライブラリの比較は機能点に限定: この記事は、Oracle と MySQL の機能とコマンドを比較するだけであり、長所と短所を判断するものではありません。
  8. COALESCE 適用範囲: 同じレイヤーのブロックのみをマージし、ビットマップ インデックスには使用できません。論理構造は変更されず、実際の REBUILD を置き換えることはできません。

6. 知識を広げる

  • Oracle テーブル/インデックスの再編成:ALTER TABLE ... MOVE、DBMS_REDEFINITION オンライン再定義およびセグメント アドバイザーと組み合わせて使用​​されます。
  • Oracle オンライン再構築のリスク:REBUILD ONLINE 辞書の不一致やプロセス終了後の一時オブジェクトの残留オンライン再構築などの既知の境界があり、運用環境で評価する必要があります。
  • MySQL インデックスの損傷の階層的処理: セカンダリ インデックスが破損している → 削除/追加再構築。クラスター化インデックス/データ ディクショナリが破損している → 再構築をエクスポートするか、 innodb_force_recovery 対処する。
  • 断片化されたガバナンス:通常 ALTER TABLE ... FORCE / OPTIMIZE フラグメントをゼロにリセットし、半分空のページを整理し、リサイクルできます。 PAGE_FREE ガベージスペースを削除し、インデックススペースの拡張を削減します。
  • 統計と実行計画: 統計的な有効期限はオプティマイザーの選択に直接影響し、実行計画およびカーディナリティ ビューと組み合わせて判断できます。



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *