20210731のMySQLに関する記事は3件です。

SQLの実行計画のインデックス表記を調べたけど、細かいところがわからなかった

SQLのパフォーマンスチューニングをしていたのですが、 explainで実行計画をみていて、なんとなく解消できるんだけど 後輩にうまく説明できないところを調べてみました。(結局まだちゃんと理解していないですが...) ちなみに遅い原因は複合インデックスが設定されていないことでした。 実行計画をみてみる とりあえず実行計画をみる。(select文はサンプル) select * from user from name = "サンプル" and age < 20 explain select * from user from name = "サンプル" and age < 20 Extraのところに、indexの使用状況が書いています。ケースとしては大体以下の3つをよくみます。 Using index Using where Using index condition 今回の遅いケースはUsing index conditionでした。 複合インデックスが効いていないことはなんとなくわかったのですが、そういえばUsing index conditionってなんだっけと。 公式をちょっと調べてもすぐに出てこなかったので、一旦別の記事で調べてみることに。 https://stackoverflow.com/questions/28759576/mysql-using-index-condition-vs-using-where-using-index https://qiita.com/aidy91614/items/f17ab862986e9e5cdea6 Using index conditionはインデックスは一部効いているのですが、検索対象のカラムを網羅していないので、SQLが遅くなってしまうという理解です。 Using index > Using Where Using index > Using Index Condition と感じで良いかと。 Using whereについては結局ちゃんとまだ理解できていないです。 MySQLの公式に以下のような説明があります。 https://dev.mysql.com/doc/refman/8.0/en/explain-output.html#explain_extra Using where (JSON property: attached_condition`) A WHERE clause is used to restrict which rows to match against the next table or send to the client. Unless you specifically intend to fetch or examine all rows from the table, you may have something wrong in your query if the Extra value is not Using where and the table join type is [ALL](https://dev.mysql.com/doc/refman/8.0/en/explain-output.html#jointype_all) or [index](https://dev.mysql.com/doc/refman/8.0/en/explain-output.html#jointype_index). - Using where has no direct counterpart in JSON-formatted output; the attached_condition property contains any WHERE condition used. 読んだけど、よくわかりませんでした... SQLでwhere句使っているよ。くらいの認識で良いのでしょうか。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CASE式の中で集約関数を使って普通は2回SQLを書くところを1回で済ませるテクニック

ポイント 集計結果に関する条件分岐はHAVING句を使うことが一般的かもしれませんが CASE式を使えば、SELECT句の中でも同等の条件が書けます MAX、MIN、SUM、COUNTといった集計関数は WHERE句やGROUP BY句で指定した条件で集約することが一般的かもしれませんが 集計関数のカッコ内でも使える(カッコ内はカラム名だけではなく、式を入れることもできる) なので、CASE式も使える 実例 テーブルのイメージ 店舗と、その店舗で働くスタッフを表現する中間テーブルをイメージして欲しいです。 スタッフが働く店舗が複数ある場合、主に働いている店舗以外は0というフラグが割り当てられます。 (設計の良し悪しに関する言及は不要) テーブルのデータのイメージ(テーブル名 shop_staffs) だいぶ簡略化しています。 店舗id(shop_id) スタッフid(staff_id) 主要店舗フラグ(main) 1 22 1 1 23 0 2 5 1 3 123 1 4 34 0 4 35 1 4 36 0 5 23 1 上記のテーブルに対して、1度のSQLで、以下のような条件のデータを取得したいとき 出力結果 スタッフid 店舗id 1 22 2 5 3 123 4 35 5 23 店舗idの条件 働く店舗が 1つなら、その店舗のidを取得 複数なら、主要店舗idを取得 SELECT staff_id AS 'スタッフid', CASE WHEN COUNT(*) = 1 THEN MAX(shop_id) ELSE MAX(CASE WHEN main = 1 THEN shop_id ELSE NULL END) END AS '店舗id' FROM shop_staffs GROUP BY staff_id CASE式はどこでもかける これまでに何回かCASE式を見てきましたが、CASE式はどこにでも書けます。 SELECT 句 WHERE 句 GROUP BY 句 HAVING 句 ORDER BY 句 関数の引数 式の中(CASE式の中でも) など 参照 18-20p アウトプット100本ノック実施中
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MySQL[基礎的なデータ操作]

WHERE,AND,ORについて olinpiansテーブル id name sport gold_medal 1 大橋 競泳 2 2 橋本 体操 1 3 伊藤 卓球 1 4 高橋 柔道 1 前回の振り返り olinpiansテーブルのデータを全て抽出する場合 SELECT * FROM olinpians; // 全てのデータ抽出 「金メダルを1つ獲得した選手のデータが欲しい!」という要望に応えるために、WHEREを使おう。 SELECT name,gold_medal FROM olinpians WHERE gold_medal = 1; //select では、nameとgold_medalを指定しているのでこの2つが表として生成 //where で、金メダルが1つのデータに検索を掛けて、マッチするものを抽出 name gold_medal 橋本 1 伊藤 1 高橋 1 「卓球で金メダルを1つ獲得した選手のデータが欲しい!」という要望に応えるために、 ANDを使おう。 $ SELECT name,sport,gold_medal FROM olinpians WHERE gold_medal = 1 AND sport = '卓球'; // ANDを用いることで、 〜と〜に合致するデータを抽出してねという意味でクエリを発行できる。 伊藤選手のデータを抽出できました!(idがあるので、そちらを検索してもいいのですが...w) name sport gold_medal 伊藤 卓球 1 「卓球か柔道の選手のデータが欲しい!」という要望に応えるために、ORを使おう。 $ SELECT name,sport FROM olinpians WHERE sport = '卓球' OR sport = '柔道'; // whereで抽出したい情報を連結させる。 name sport 伊藤 卓球 高橋 柔道 SELECT = どの列(カラム)を検索するか FROM = どのテーブルから検索するか WHERE = どのような条件で行(レコード)を検索するか を抑えておけば良さそうですね。 LIKE 文字列の検索 「橋本くんのデータを取ってきて欲しい」と言われたらどのようなクエリを実行しますか。 SELECT name // nameの列を検索 FROM olinpians // olinpiansテーブルから WHERE name = '橋本' // nameが橋本という行を検索する で良さそうです。 olinpiansテーブル(一部変更) id name sport 1 大橋 競泳 2 橋本 体操 3 井本 卓球 4 高橋 柔道 「井という文字から始まるアスリートっていたっけ?ちょい調べて」と言われたら、前方の文字検索を行います。 SELECT * FROM olinpians WHERE name LIKE '井%'; // 井という文字から始まるnameカラムの情報を検索 id name sport 3 井本 卓球 % = 0文字以上の任意の文字列を表現してくれている 井%とすることで、井〜〜〜と続く文字列に対応 「橋という文字がつくアスリートを検索してほしい」と言われたら、部分一致の文字検索を行います。 SELECT * FROM olinpians WHERE name LIKE '%橋%'; //前後を%で挟んで検索を掛ける 「本で終わるアスリートは?」後方一致で検索を掛けます。 SELECT * FROM olinpians WHERE name LIKE '%本'; id name sport 2 橋本 体操 3 井本 卓球
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む