MySQLでテキスト検索を書くとき、LIKEとREGEXPのどちらを使うか迷う場面があります。LIKEは%と_のワイルドカードで手軽に書けますが、REGEXPは正規表現でより柔軟なパターンを指定できます。この記事では両者の構文・動作の違い、インデックスが効くかどうかの性能差、そしてどの場面でどちらを選ぶべきかの判断基準を実例つきで整理します。MySQL 8.0を前提としています。
このシナリオで考える
ユーザー情報を管理する次のテーブルを使って説明します。
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL,
PRIMARY KEY (id),
INDEX idx_email (email)
);
INSERT INTO users (name, email) VALUES
('田中 太郎', 'taro.tanaka@example.com'),
('佐藤 花子', 'hanako.sato@gmail.com'),
('鈴木 一郎', 'ichiro@company.co.jp'),
('山田 二郎', 'jiro123@example.com'),
('高橋 三郎', 'saburo.takahashi@gmail.com'),
('伊藤 奈々', 'nana_ito@example.org');
このテーブルを使って、LIKEとREGEXPそれぞれのパターンマッチを確認していきます。
LIKEの基本:ワイルドカードで絞り込む
LIKEは2種類のワイルドカードでパターンを表現します。
| ワイルドカード | 意味 | 例 |
|---|---|---|
% |
0文字以上の任意の文字列 | LIKE 'taro%' |
_ |
任意の1文字 | LIKE 't_ro' |
代表的な3つのパターンを確認します。
-- 前方一致(taroで始まる)
SELECT name, email FROM users WHERE email LIKE 'taro%';
-- 後方一致(.jpで終わる)
SELECT name, email FROM users WHERE email LIKE '%.jp';
-- 部分一致(123を含む)
SELECT name, email FROM users WHERE email LIKE '%123%';
前方一致の結果はこのとおりです。
| name | |
|---|---|
| 田中 太郎 | taro.tanaka@example.com |
ワイルドカード自体(%や_)をリテラルとして検索したい場合は、ESCAPE句でエスケープ文字を指定します。
-- price_labelに「50%」という文字列が含まれる行を検索
SELECT * FROM products
WHERE price_label LIKE '%50\%%' ESCAPE '\';
LIKEは構文がシンプルで、SQLを読む側にも意図が伝わりやすい点が強みです。_は1バイトではなく1文字にマッチするため、MySQL 8.0では日本語でも意図どおりに動きます(例: LIKE '田_'は「田中」「田野」などにマッチ)。
REGEXPの基本:正規表現でマッチする
REGEXP(別名 RLIKE)は正規表現を使ったパターンマッチを行います。MySQL 8.0.4以降はICU(International Components for Unicode)ベースの実装に変わり、日本語などマルチバイト文字にも安全に対応しています。
よく使うメタ文字をまとめます。
| メタ文字 | 意味 | 例 |
|---|---|---|
. |
任意の1文字 | t.ro |
* |
直前の要素が0回以上 | ta*ro |
+ |
直前の要素が1回以上 | [0-9]+ |
^ |
文字列の先頭 | ^taro |
$ |
文字列の末尾 | \.jp$ |
[...] |
文字クラス | [a-z0-9] |
| |
いずれか(OR) | gmail|yahoo |
-- gmailまたはyahooを含むメールアドレス
SELECT name, email FROM users
WHERE email REGEXP 'gmail|yahoo';
-- ローカルパートに数字を含む
SELECT name, email FROM users
WHERE email REGEXP '[0-9]+@';
-- co.jpで終わる(ドットはエスケープ)
SELECT name, email FROM users
WHERE email REGEXP '\.co\.jp$';
最初のクエリの結果はこのとおりです。
| name | |
|---|---|
| 佐藤 花子 | hanako.sato@gmail.com |
| 高橋 三郎 | saburo.takahashi@gmail.com |
MySQL 8.0ではREGEXP_LIKE()関数も利用できます。第3引数にフラグを渡せるため、大文字小文字の区別を明示的に制御できます。
-- 'c'フラグ:大文字小文字を区別する
SELECT name FROM users WHERE REGEXP_LIKE(email, 'GMAIL', 'c');
-- 結果なし(gmailは小文字なのでマッチしない)
-- 'i'フラグ:大文字小文字を区別しない(デフォルト動作と同じ)
SELECT name FROM users WHERE REGEXP_LIKE(email, 'GMAIL', 'i');
-- 佐藤 花子 / 高橋 三郎 がマッチ
REGEXPとRLIKEは完全に同じ演算子です。どちらを使っても動作は変わりません。
インデックスと性能:前方一致LIKEが有利な理由
パターンマッチの性能を左右する最大の要因は、インデックスが使えるかどうかです。
| パターン | インデックス | スキャン方式 |
|---|---|---|
LIKE 'taro%'(前方一致) |
使える | 範囲スキャン(高速) |
LIKE '%example'(後方一致) |
使えない | フルテーブルスキャン |
LIKE '%word%'(部分一致) |
使えない | フルテーブルスキャン |
REGEXP 'pattern' |
使えない | フルテーブルスキャン(常に) |
EXPLAINで確認すると違いが明確です。
-- インデックスが効く(type: range)
EXPLAIN SELECT * FROM users WHERE email LIKE 'taro%';
-- インデックスが効かない(type: ALL = フルスキャン)
EXPLAIN SELECT * FROM users WHERE email LIKE '%example.com';
EXPLAIN SELECT * FROM users WHERE email REGEXP '@example';
前方一致LIKEのEXPLAIN出力(抜粋)は次のとおりです。type: rangeとなり、key: idx_emailが使われていることを確認できます。
+-------+---------------+-----------+------+
| type | possible_keys | key | rows |
+-------+---------------+-----------+------+
| range | idx_email | idx_email | 1 |
+-------+---------------+-----------+------+
テーブルが数百万行規模になると、フルスキャンとインデックス範囲スキャンの差は数十〜数百倍に広がることがあります。REGEXPは複雑なパターンを書けますが、常にフルスキャンになる点が最大のデメリットです。
よくある落とし穴と注意点
後方一致・部分一致はインデックスが使えない。LIKE '%suffix'やLIKE '%word%'はインデックスが効きません。大量データへの部分一致検索が必要な場合は、MySQLの全文検索(FULLTEXT INDEX + MATCH ... AGAINST)への移行を検討します。
REGEXPのデフォルトは大文字小文字を区別しない。列の照合順序(collation)が_ci(Case Insensitive)の場合、REGEXPも大文字小文字を区別しません。区別したい場合はREGEXP_LIKE(col, pattern, 'c')を明示します。
NOT LIKE / NOT REGEXPはNULLをスキップする。列の値がNULLのとき、NOT LIKEもNOT REGEXPも結果としてNULLを返します。NULLの行も結果に含めたい場合はOR col IS NULLを追加します。
-- NULLの行も拾いたい場合
SELECT * FROM users
WHERE email NOT LIKE '%@gmail.com'
OR email IS NULL;
LIKEとREGEXPの選択基準まとめ。パターンが単純で前方一致で済むならLIKE一択です。複数キーワードのOR条件(gmail|yahoo)や文字クラス([0-9]+)が必要な場合にREGEXPを選びます。ただしREGEXPはフルスキャンを前提とした小〜中規模テーブル向けの選択肢と捉えてください。
まとめ
LIKEとREGEXPの使い分けは「パターンの複雑さ」と「性能要件」の2軸で決まります。前方一致のシンプルな検索はLIKEでインデックスを活かすのが基本です。複数キーワードのOR検索や細かい文字クラスが必要なときにREGEXPを選び、フルスキャンになることを念頭に置いてください。大量データへの部分一致検索を避けられない場合は、全文検索(FULLTEXT INDEX)への移行が現実的な選択肢になります。
参考リンク
アイキャッチ画像: Photo by Jantine Doornbos on Unsplash
