質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

解決済

2回答

5383閲覧

MySQLのLIKEとREGEXP、RLIKEの速度の違いについて

hanlio

総合スコア14

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

1クリップ

投稿2018/10/29 23:33

編集2018/10/30 06:51

素朴な疑問なのですが、結果は同じになるようにLIKEとREGEXP、RLIKEを実行したら速度差が出ました。
先頭文字マッチのみLIKEの方が速度が早いのは何故でしょうか。
ただの誤差の範囲なのでしょうか。

  • 先頭文字マッチの場合、LIKE(0.01sec) < RLIKE(0.08sec) < REGEXP(0.16sec)
  • 末尾文字マッチの場合、RLIKE(0.01sec) = REGEXP(0.01sec) < LIKE(0.07sec)
  • 任意文字マッチの場合、RLIKE(0.00sec) < REGEXP(0.01sec) < LIKE(0.09sec)

MySQL

1使用したデータ 2mysql> SELECT * FROM Address; 3+-----------+---------------+--------------+-----+-----+ 4| name | phone_nbr | address | sex | age | 5+-----------+---------------+--------------+-----+-----+ 6| 井上 | NULL | 福島県 | 女 | 55 | 7| 佐々木 | 080-5848-XXXX | 千葉県 | 女 | 19 | 8| 佐藤 | 090-1922-XXXX | 三重県 | 女 | 25 | 9| 前田 | 090-0000-XXXX | 東京都 | 女 | 21 | 10| 小川 | 080-3333-XXXX | 東京都 | 男 | 30 | 11| 松本 | NULL | 千葉県 | 女 | 20 | 12| 林 | 080-3333-XXXX | 福島県 | 男 | 32 | 13| 森 | 090-2984-XXXX | 東京都 | 男 | 45 | 14| 鈴木 | 090-0001-XXXX | 和歌山県 | 男 | 32 | 15+-----------+---------------+--------------+-----+-----+ 169 rows in set (0.03 sec)

###先頭文字マッチ

MySQL

1LIKEの場合 2mysql> SELECT * FROM Address WHERE phone_nbr LIKE "090%"; 3+--------+---------------+--------------+-----+-----+ 4| name | phone_nbr | address | sex | age | 5+--------+---------------+--------------+-----+-----+ 6| 佐藤 | 090-1922-XXXX | 三重県 | 女 | 25 | 7| 前田 | 090-0000-XXXX | 東京都 | 女 | 21 | 8| 森 | 090-2984-XXXX | 東京都 | 男 | 45 | 9| 鈴木 | 090-0001-XXXX | 和歌山県 | 男 | 32 | 10+--------+---------------+--------------+-----+-----+ 114 rows in set (0.01 sec) 12 13REGEXPの場合 14mysql> SELECT * FROM Address WHERE phone_nbr REGEXP "^090"; 15~中略~ 164 rows in set (0.16 sec) 17 18RLINKの場合 19mysql> SELECT * FROM Address WHERE phone_nbr RLIKE "^090"; 20~中略~ 214 rows in set (0.08 sec)

###末尾文字マッチ

MySQL

1mysql> SELECT * FROM Address WHERE name LIKE "%木"; 2+-----------+---------------+--------------+-----+-----+ 3| name | phone_nbr | address | sex | age | 4+-----------+---------------+--------------+-----+-----+ 5| 佐々木 | 080-5848-XXXX | 千葉県 | 女 | 19 | 6| 鈴木 | 090-0001-XXXX | 和歌山県 | 男 | 32 | 7+-----------+---------------+--------------+-----+-----+ 82 rows in set (0.07 sec) 9 10mysql> SELECT * FROM Address WHERE name REGEXP "木$"; 11~中略~ 122 rows in set (0.01 sec) 13 14mysql> SELECT * FROM Address WHERE name RLIKE "木$"; 15~中略~ 162 rows in set (0.01 sec)

###任意文字マッチ

MySQL

1mysql> SELECT * FROM Address WHERE phone_nbr LIKE "%2%"; 2+--------+---------------+-----------+-----+-----+ 3| name | phone_nbr | address | sex | age | 4+--------+---------------+-----------+-----+-----+ 5| 佐藤 | 090-1922-XXXX | 三重県 | 女 | 25 | 6| 森 | 090-2984-XXXX | 東京都 | 男 | 45 | 7+--------+---------------+-----------+-----+-----+ 82 rows in set (0.09 sec) 9 10mysql> SELECT * FROM Address WHERE phone_nbr REGEXP "2"; 11+--------+---------------+-----------+-----+-----+ 12| name | phone_nbr | address | sex | age | 13+--------+---------------+-----------+-----+-----+ 14| 佐藤 | 090-1922-XXXX | 三重県 | 女 | 25 | 15| 森 | 090-2984-XXXX | 東京都 | 男 | 45 | 16+--------+---------------+-----------+-----+-----+ 172 rows in set (0.01 sec) 18 19mysql> SELECT * FROM Address WHERE phone_nbr RLIKE "2"; 20+--------+---------------+-----------+-----+-----+ 21| name | phone_nbr | address | sex | age | 22+--------+---------------+-----------+-----+-----+ 23| 佐藤 | 090-1922-XXXX | 三重県 | 女 | 25 | 24| 森 | 090-2984-XXXX | 東京都 | 男 | 45 | 25+--------+---------------+-----------+-----+-----+ 262 rows in set (0.00 sec)

##(追記)

###先頭文字マッチのEXPLAINの実行結果

MySQL

1mysql> EXPLAIN SELECT * FROM Address WHERE phone_nbr LIKE "090%"; 2+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+ 3| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 4+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+ 5| 1 | SIMPLE | Address | NULL | ALL | NULL | NULL | NULL | NULL | 9 | 11.11 | Using where | 6+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+ 71 row in set, 1 warning (0.00 sec) 8 9mysql> EXPLAIN SELECT * FROM Address WHERE phone_nbr REGEXP "^090"; 10+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+ 11| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 12+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+ 13| 1 | SIMPLE | Address | NULL | ALL | NULL | NULL | NULL | NULL | 9 | 100.00 | Using where | 14+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+ 151 row in set, 1 warning (0.00 sec)

###ついでのSHOW INDEX

MySQL

1mysql> SHOW INDEX FROM Address; 2+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 3| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 4+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 5| address | 0 | PRIMARY | 1 | name | A | 9 | NULL | NULL | | BTREE | | | 6+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/10/30 00:39

これって複数回やった結果なんでしょうか?誤差の範囲な気もします。
hanlio

2018/10/30 06:01

改めて実行したところ、全て0.00secになりました。誤差の範囲だったのかも知れません。
guest

回答2

0

ベストアンサー

先頭文字マッチのみLIKEの方が速度が早いのは何故でしょうか。

先頭マッチの場合、LIKEではインデックスを利用可能、とのことです。RLIKEの場合は「先頭一致でインデックスを見る」という最適化がどうやらなされていないようです。

…といっても推測に過ぎないので、EXPLAINしてみましょう。インデックスを使っているかはそれで判別できます。

投稿2018/10/30 00:36

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hanlio

2018/10/30 06:02

ありがとうございます。EXPLAINという構文があるのですね。 知りませんでした。調べてみます。
hanlio

2018/10/30 06:55

インデックスというものを私は知らなかったのですが、EXPLAINの実行してみました。 filteredがLIKEは11.11。REGEXPは100ということはインデックスで絞られて検索されているということでしょうか。
maisumakun

2018/10/30 07:08

両方ALLとなれば、テーブルスキャンは共通なので、「先頭一致だと明示した検索」と、「正規表現で同じ意味を指定した検索の差」がメインになるのかと思います(同じ意味でも正規表現で実現すると遅いことはよくあります)。 filteredは、テーブルをJOINする際に行数を見積もるためのものなので、JOINしないときには特に関係なさそうです。 https://dev.mysql.com/doc/refman/5.6/ja/explain-output.html#explain_filtered
hanlio

2018/10/30 07:19

ご丁寧にご教授いただき、ありがとうございました。 正規表現かどうかで速度差が出ることもあることも覚えておきます。
sazi

2018/10/30 07:23

検索対象の項目にそもそもインデックスが作成されていないので、どちらの方法にしてもALLにしかならないと思いますけど。
guest

0

先頭からの場合、検索文字数分しか走査する必要がなく、走査対象となった文字数が、一番小さくなるからでしょう。

投稿2018/10/30 00:29

sazi

総合スコア25173

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hanlio

2018/10/30 06:07

ありがとうございます。 LIKEとRLIKEでは、記述だけでなく検索の手法も異なるということでしょうか。
sazi

2018/10/30 06:15 編集

内部的な話なので推測にしかすぎません。また、インデックスの有無とは別な話です。 ただ、前方検索でないとインデックスも適用されないことと同様に、検索方法によって検索対象の文字列の扱いに違いがある事は、ほぼ確実だと思います。
sazi

2018/10/30 06:23

尚、RLIKEはREGEXPのシノニム(別名)なので、性能差があってもそれは誤差として扱うしか無いかと思います。
hanlio

2018/10/30 06:59

ありがとうございます。 インデックスを今回初めて知りました。 LIKEの場合でも前方検索でしかインデックスが適用されないんですね。 ちなみに、インデックスが適用されているかどうかは、EXPLAINのfilteredカラムの数値で確認するのでしょうか。 RLIKEがシノニムである件は理解できました。
sazi

2018/10/30 07:08 編集

>インデックスが適用されているかどうかは、EXPLAINのfilteredカラム typeですね。`ALL`になっていたらインデックスは使用されていません。
sazi

2018/10/30 07:11

そもそも、対象となるphone_nbrにインデックスは作成されていないという事ですね。
hanlio

2018/10/30 07:16

typeカラムでしたか。 色々と詳しくご教授いただき、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問