IT技術関連SQL

SQL#14 高度なクエリ最適化とパフォーマンステスト

SQL

はじめに

こんにちは、シルです。
データ量が増えると、「クエリの実行が遅い」「サーバー負荷が高い」 という問題が発生しやすくなります。
このような問題を解決するために、 クエリの最適化インデックスの活用トランザクション管理データのパーティショニング などの技術を駆使します。

例えば:

  • EXPLAIN を使ってボトルネックを特定
  • 適切な インデックス戦略 を設計
  • バッチ処理 を活用し、効率的にデータを処理
  • パーティショニング によって大規模データのクエリを最適化

この Part では、これらの手法を活用し、データベースの最適化 を学んでいきます。

参考までに…
SQLコマンド集:基本から応用

前回までの内容です
SQL#1 環境準備と基本操作
SQL#2 テーブルとデータベースの管理
SQL#3 ユーザー管理と権限の設定
SQL#4 サーバーステータスとインデックス管理
SQL#5 データベースのサイズ管理と構造確認
SQL#6 基本的なデータ操作
SQL#7 データ検索と削除の拡張
SQL#8 ウィンドウ関数を使ったデータ分析
SQL#9 集計と結合
SQL#10 インデックス管理と最適化
SQL#11 バックアップとリカバリ
SQL#12 データモデルの設計と正規化の実践
SQL#13 トリガーとストアドプロシージャの実践

学習の概要

📌 含まれる内容

  1. インデックス戦略の設計
  2. EXPLAINでのクエリの最適化
  3. バッチ処理とトランザクションの最適化
  4. パーティショニングによるパフォーマンス向上

実践

インデックス戦略の設計

インデックスを適切に設計することで、クエリの処理速度を 100倍以上 向上させることも可能です。

例: 適切なインデックスの追加

以下の Employees テーブルに対し、LastName で検索するクエリを最適化します。

1. インデックスなしの検索

SELECT * FROM Employees WHERE LastName = 'Tanaka';

データが増えると、検索速度が遅くなる(フルスキャンが発生)

2. インデックスを追加

CREATE INDEX idx_lastname ON Employees(LastName);

3. インデックスを適用した検索

SELECT * FROM Employees WHERE LastName = 'Tanaka';

インデックスを使うことで、検索が大幅に高速化!

EXPLAINでのクエリの最適化

EXPLAIN を使うと、クエリの実行計画(どのインデックスを使っているか、フルスキャンしているか) を確認できます。

例: クエリのボトルネックを特定

EXPLAIN SELECT * FROM Employees WHERE LastName = 'Tanaka';

出力結果(インデックス未使用時)

+----+-------------+-----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+-----------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | Employees | ALL  | NULL          | NULL | NULL    | NULL | 1000000 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+---------+-------------+

type = ALL(フルスキャン発生) → インデックスを追加すべき!

バッチ処理とトランザクションの最適化

大量のデータを扱う場合、一括処理ではなく、バッチ処理 にすることでパフォーマンスが向上します。

例: バッチ処理で100万件のデータをINSERT

1. 非効率な一括処理

INSERT INTO Sales (SaleDate, Amount)
SELECT NOW(), FLOOR(RAND() * 10000)
FROM generate_series(1, 1000000);

100万件を一気に処理すると、サーバーに大きな負荷がかかる!

2. バッチ処理(1万件ずつコミット)

DELIMITER //

CREATE PROCEDURE InsertLargeData()
BEGIN
    DECLARE i INT DEFAULT 0;
    
    START TRANSACTION;
    WHILE i < 1000000 DO
        INSERT INTO Sales (SaleDate, Amount)
        VALUES (NOW(), FLOOR(RAND() * 10000));

        SET i = i + 1;

        IF i % 10000 = 0 THEN
            COMMIT; -- 1万件ごとにコミット
            START TRANSACTION;
        END IF;
    END WHILE;

    COMMIT;
END;

//
DELIMITER ;

トランザクションを活用し、サーバー負荷を分散!

パーティショニングによるパフォーマンス向上

パーティショニングとは、大量のデータを小さなブロック(パーティション)に分割して管理 する手法です。

例: 日付ごとのパーティショニング

CREATE TABLE Sales (
    SaleID INT PRIMARY KEY,
    SaleDate DATE NOT NULL,
    Amount DECIMAL(10,2) NOT NULL
)
PARTITION BY RANGE (YEAR(SaleDate)) (
    PARTITION p2022 VALUES LESS THAN (2023),
    PARTITION p2023 VALUES LESS THAN (2024),
    PARTITION p2024 VALUES LESS THAN (2025)
);

2022年、2023年、2024年のデータを分けて保存し、検索を高速化!

課題

実践課題

  1. EXPLAIN を使って遅いクエリを特定し、最適化
    • EXPLAIN でインデックスが適用されていないクエリを見つけ、適切なインデックスを追加する。
  2. 100万件のレコードをバッチ処理し、性能を検証
    • バッチ処理を使って Sales テーブルに大量のデータを追加し、処理速度を比較する。

まとめ

インデックスを適切に設計し、クエリを高速化!
EXPLAIN でクエリの実行計画を分析し、ボトルネックを特定!
バッチ処理を使い、大量データの処理負荷を分散!
パーティショニングを活用し、大規模データの管理を最適化!

これらの技術を駆使すれば、数百万件以上のデータでもスムーズに処理できるデータベース を構築できます! 🚀

コメント

タイトルとURLをコピーしました