こんにちは。技術チームの孫です。

技術チームの陳小華さんが「SQL雑談」と題して、3月の技術勉強会を開催しました。 「Index」、「NULL問題」、「存在チェック」、「Paging」と「Explain」などを例に挙げて、sql文の注意点と改善方法を解説しました。

Index

 

先ず、下記の3つのselect文を見てください。

同じ処理に見えますけど、実際には効率が異なります。EXPLAINで一緒に三つのqueryを分析しましょう。

1つ目のselect文の「rows」は62070です。下の2個(「rows」は31035)より取得したレコード数が多いです(効率が悪い)。

結論:Where条件の中で、テーブルのカラムに対して、SQLの関数を使わないように。

次、「Indexの順番」について、例の問題を見ましょう。

テーブルの構造は以下:

CREATE TABLE `index_users` (

 `id` int(11) NOT NULL AUTO_INCREMENT,

 `username` varchar(255) NOT NULL DEFAULT ”,

 `password` varchar(255) NOT NULL,

 PRIMARY KEY (`id`),

 KEY `IDX_PW` (`username`,`password`)

)

下記の4つselect文の中、Indexが効いていないのは、どれでしょうか?

EXPLAINで分析してみましょう!

答えは4番です。4番目の書き方はindexは効かないです。当たりましたか?

結論:一番左のマッチング特性

Key(c1, c2, c3)

✔key(c1, c2, c3)

✔key(c1, c2)

✔key(c1, c3)

✔key(c1)

✖key(c2)

 

■ NULL問題


 

null_testテーブルに4つのレコードが入っています。Null001002003です。

もし下記のqueryを実行すると、何個のデータが返ってきますか?

答えは2個です。nullのデータは引掛けられないです。

結論: スキーマ定義の中、DEFAULT NULL はNG。

 

■ 存在チェック


 

上記のqueryは「sync_order_invoice」が存在するかどうかをチェックしています。0以上の場合、「sync_order_invoice」は存在います。

実際にはこのqueryは改善の余地があります。下記のように変えば検索時間が短縮できます。

SELECT SQL_NO_CACHE 1 FROM test WHERE ACTION = “sync_order_invoice” LIMIT 1;

結論: ベースデータタイプとlimit 1を活用する。

 

■ Paging


 

100万行のデータをロードしてから、次の20行を取得するqueryです。かなり時間がかかりますが、何かチューニング方法がありますか?

上記のようにinner joinしてからselectのは、検索時間が大幅に短縮できました。大量データのpaging処理の役に立ちそうですね。

 

■ Explain


 

Explainのtype、select_type、key、refについても説明しました。

 

Explainのtype

system:システムテーブル、少量データ、Disk I/O なし;

const:PRIMARY KEYまたはUNIQUEインデックスのルックアップによるアクセス。最速;

eq_ref:JOINにおいてPRIARY KEYまたはUNIQUE KEYが利用される時のアクセスタイプ。constと似ているがJOINで用いられるところが違う;

ref:ユニーク(PRIMARY or UNIQUE)でないインデックスを使って等価検索(WHERE key = value)を行った時に使われるアクセスタイプ;

range:インデックスを用いた範囲検索;

index:フルインデックススキャン。インデックス全体をスキャンする必要があるのでとても遅い;

ALL:やめてください;

system > const > eq_ref > ref > range > index > ALL

 

Explainのselect_type

単一のテーブルの場合:

SIMPLE

サブクエリが絡む場合:

PRIMARY:外部クエリ、一番外のクエリ

SUBQUERY:相関関係の無いサブクエリ

DEPENDENT SUBQUERY:相関関係のあるサブクエリ

UNCACHEABLE SUBQUERY:実行する度に結果が変わる可能性のあるサブクエリ

DERIVED: FROM句で用いられているサブクエリ

 

Explainのkey

possible_keys : optimizerがテーブルのアクセスに利用可能だと判断したインデックス;

key :実際にoptimizerによって使用されたキー ;

key_len:選択されたキーの長さ。長さは短いほうが高速。

 

Explainのref

検索条件でkeyと比較されている値やカラムの種類。

定数の場合: const

JOINを使用している場合:結合する相手側のテーブルで検索条件として利用されているカラムが表示される。

 

■  レコードのバージョン管理


 

最後に陳さんがレコードのバージョン管理について説明をしました。

DB設計時に「version」カラムを入れることを勧められました。

データそのものに対してロックは行わずに、更新対象のデータがデータ取得時と同じ状態であることを確認してから更新することで、データの整合性を保証する方式です。楽観ロックを使用する場合は、更新対象のデータがデータ取得時と同じ状態であることを判断するために、Versionを管理するためのカラム(Versionカラム)を用意します。更新時の条件として、データ取得時のVersionとデータ更新時のVersionを同じとすることで、データの整合性を保証することができます。

 

■ 感想


 

DBチューニングはシステムの最適なパフォーマンスを実現するための不可欠な部分です。日々増加するデータに対し、レスポンスの遅延なく処理できるのは大事です。

この記事が気に入ったら
いいね ! しよう

Twitter で