masalibの日記

システム開発、運用と猫の写真ブログです

今更なんだけどmysqlのデータの取得で「*」を使ってはいけないと思った

SQLでテーブルのすべてを取得するのに「*」を使う事がある。 mysql本にはパフォーマンスが下がるのでカラム指定をしましょうと書いてあった。

プログラムで取得するときはできるかぎり指定するようにしていた。

昨日、自分はインフラとして一部参画していたプロジェクトでトラブルが発生した。 なんでも100万件も満たないデータでかつインデックスも貼っているのに3秒もかかる

今どき、インデックスを貼っていれば100万件程度なら余裕のはずが3秒もかかる。 しかもEXPLAINで調べるとタイプのがALL(インデックスがはられていないという状態)になっている。

EXPLAIN select * from master_data where Code=21321313454;

正直、困惑した。

インデックスが貼っているのにALLになるなんて・・・

壊れているのではないかという指摘があったので再構築のコマンドを実行した。

optimize table master_data;
-- master_dataは対象テーブルのです

参考URL https://hacknote.jp/archives/8852/

このコマンドはテーブルのロックがもろにくらうのでためらったがやってもいいという お達しがあったので実行した。

EXPLAINで対象のSQLを調べても結果は同じだった

EXPLAIN select * from master_data where Code=21321313454;

最終的にはインデックスを削除しなおして作り直すというありえない事をやった

ALTER TABLE master_data DROP INDEX idx_code;
ALTER TABLE master_data ADD INDEX idx_code2(Code);

qiita.com

結果はかわらず・・・困惑した。 どうしたものかと思った瞬間になんで

EXPLAIN select * from master_data where Code=21321313454;

なんで*なんだ? と思ってカラム名を指定してSQLを実行すると

EXPLAIN select id from master_data where Code=21321313454;

1秒もかからずに返ってきた。

カラムを指定するのとしないのでこんなに差がでるとは・・・・

しかもよく見ると Codeはvarcharだったので文字列指定にしたら

EXPLAIN select id from master_data where Code='21321313454';

0.01秒で返ってきた。

まじで本に書いてあるとおり 「*」を使ってはいけないな~と思った

ちなみにトラブルの原因はこのSQLではなく違うSQLだった。 スロークエリログも見ないで推測で相談してきたみたい・・・・。 自分も相談をうけた時に真っ先にスロークエリログを見るべきだった。 この部分を次回のトラブルに役立てたい。