MySQLテーブルがあり、非常に頻繁にSELECT x, y, z FROM table WHERE x LIKE '%text%' OR y LIKE '%text%' OR z LIKE '%text%'
クエリ。どんな種類のインデックスも物事をスピードアップするのに役立ちますか?
テーブルには数百万のレコードがあります。検索を高速化するものがある場合、データベースファイルによるディスク使用量とINSERT
およびDELETE
ステートメントの速度に深刻な影響がありますか? (UPDATE
は実行されません)
更新:投稿後すぐに、クエリでLIKE
が使用される方法に関する多くの情報と議論を見ました。私は解決策を指摘したいと思います しなければならない 使用する LIKE '%text%'
(つまり、探しているテキストの先頭に%ワイルドカードが追加されます)。また、セキュリティを含む多くの理由で、データベースはローカルでなければなりません。
テキスト列のインデックスは、左からN文字のインデックスを作成することで機能するため、インデックスを作成してもクエリの速度は上がりません。 LIKE '%text%'を実行すると、テキストの前に可変数の文字が存在する可能性があるため、インデックスを使用できません。
すべきことは、そのようなクエリをまったく使用しないことです。代わりに、MyISAMテーブルでMySQLがサポートするFTS(全文検索)のようなものを使用する必要があります。また、MyISAM以外のテーブル用にこのようなインデックスシステムを自分で作成するのは非常に簡単です。実際のテーブルに単語とその関連IDを保存する別のインデックステーブルが必要です。
インデックスはnotを使用して、検索条件がワイルドカードで始まるクエリを高速化できます。
LIKE '%text%'
インデックスは、次の形式の検索語に使用できます(選択性に応じて使用される場合があります)。
LIKE 'text%'
場合によっては、表示しているフィールドが頻繁に空であるか、定数が含まれている場合、like/rlikeとともにインデックスを使用してクエリを高速化できることを追加します。
その場合、固定値の「and」句を追加することにより、インデックスを使用してアクセスされる行を制限できるようです。
私は通常、多くのタグを含まない巨大なテーブルで「タグ」を検索するためにこれを試しました。
SELECT * FROM objects WHERE tags RLIKE("((^|,)tag(,|$))" AND tags!=''
タグにインデックスがある場合、検索されている行を制限するために使用されることがわかります。
Mysql5.1をmysql5.7にアップグレードしてみてください。
約70,000件のレコードがあります。そして、次のSQLを実行します。
select * from comics where name like '%test%';
Mysql5.1では2000msかかります。そして、mysql5.7またはmysql5.6では200msが必要です。
別の方法:
これらの文字列をREVERSEdにして計算列を保持し、使用することができます
SELECT x, y, z FROM table WHERE x LIKE 'text%' OR y LIKE 'text%' OR z LIKE 'text%' OR xRev LIKE 'txet%' OR yRev LIKE 'txet%' OR zRev LIKE 'txet%'
保存された永続列を追加する方法の例
ALTER TABLE table ADD COLUMN xRev VARCHAR(N) GENERATED ALWAYS AS REVERSE(x) stored;
xRev
、yRev
などにインデックスを作成します。
全表スキャンを回避する別の代替方法は、サブストリングを選択してhavingステートメントでチェックすることです。
SELECT
al3.article_number,
SUBSTR(al3.article_number, 2, 3) AS art_nr_substr,
SUBSTR(al3.article_number, 1, 3) AS art_nr_substr2,
al1.*
FROM
t1 al1
INNER JOIN t2 al2 ON al2.t1_id = al1.id
INNER JOIN t3 al3 ON al3.id = al2.t3_id
WHERE
al1.created_at > '2018-05-29'
HAVING
(art_nr_substr = "FLA" OR art_nr_substr = 'VKV' OR art_nr_subst2 = 'PBR');