はじめに
こんにちは、シルです。
データ量が増えると、「クエリの実行が遅い」「サーバー負荷が高い」 という問題が発生しやすくなります。
このような問題を解決するために、 クエリの最適化、インデックスの活用、トランザクション管理、データのパーティショニング などの技術を駆使します。
例えば:
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 トリガーとストアドプロシージャの実践
学習の概要
📌 含まれる内容
- インデックス戦略の設計
- EXPLAINでのクエリの最適化
- バッチ処理とトランザクションの最適化
- パーティショニングによるパフォーマンス向上
実践
インデックス戦略の設計
インデックスを適切に設計することで、クエリの処理速度を 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年のデータを分けて保存し、検索を高速化!
課題
実践課題
- EXPLAIN を使って遅いクエリを特定し、最適化
EXPLAINでインデックスが適用されていないクエリを見つけ、適切なインデックスを追加する。
- 100万件のレコードをバッチ処理し、性能を検証
- バッチ処理を使って
Salesテーブルに大量のデータを追加し、処理速度を比較する。
- バッチ処理を使って
まとめ
✅ インデックスを適切に設計し、クエリを高速化!
✅ EXPLAIN でクエリの実行計画を分析し、ボトルネックを特定!
✅ バッチ処理を使い、大量データの処理負荷を分散!
✅ パーティショニングを活用し、大規模データの管理を最適化!
これらの技術を駆使すれば、数百万件以上のデータでもスムーズに処理できるデータベース を構築できます! 🚀


コメント