Oracleでは、関数に基づいてインデックスを作成することが可能であることを思い出しますSUBSTRING(id,1,8)
。
MySQLはこれをサポートしていますか?そうでない場合、代替手段はありますか?
いいえ、一般的な意味ではありませんが、5.6(この回答が最初に書かれたときの最新バージョン)でさえこの機能を備えているとは思いません。8.0.13以降で機能インデックスがサポートされるようになり、以下で説明するトリガーメソッドなしで必要なものを実現できるようになったことは注目に値します。
古いバージョンのを実行している場合はmysql
、列の先頭部分のみを使用できます(この機能は長い間使用されています)が、2番目以降の文字で始まる部分やその他のより複雑な関数は使用できません。 。
たとえば、次の例では、名前の最初の5文字を使用してインデックスを作成します。
create index name_first_five on cust_table (name(5));
より複雑な式の場合は、インデックス可能なデータを含む別の列を作成し、挿入/更新トリガーを使用して正しく入力されていることを確認することで、同様の効果を得ることができます。
冗長データのための無駄なスペースを除けば、それはほとんど同じことです。
また、技術的には3NFに違反しますが、トリガーを使用してデータの同期を維持することで軽減されます(これは、パフォーマンスを向上させるためによく行われることです)。
MySQLは8.0.13以降これをサポートしています
https://dev.mysql.com/doc/refman/8.0/en/create-index.html#create-index-functional-key-parts
MySQL 8.0.13以降は、列または列のプレフィックス値ではなく式の値にインデックスを付けるファンクションキー部分をサポートしています。ファンクションキーパーツを使用すると、テーブルに直接保存されていない値のインデックスを作成できます。例:
CREATE TABLE t1 (col1 INT, col2 INT, INDEX func_index ((ABS(col1))));
CREATE INDEX idx1 ON t1 ((col1 + col2));
CREATE INDEX idx2 ON t1 ((col1 + col2), (col1 - col2), col1);
ALTER TABLE t1 ADD INDEX ((col1 * 40) DESC);
複数のキーパーツを持つインデックスは、非機能キーパーツと機能キーパーツを混在させることができます。
8.0.13より前のバージョンには、次の選択肢があります。
1.MySQL5.7.6以降
自動生成された列を使用して、インデックス付きのサブストリングを保持できます。
CREATE TABLE SomeTable (
id CHAR(10),
sub_id CHAR(8) AS SUBSTRING(id, 1, 8) STORED, INDEX(sub_id)
)
Benjaminが指摘したように、InnoDBは仮想列のセカンダリインデックスをサポートしているため、STOREDキーワードを省略できます。実際、仮想列のセカンダリインデックスが望ましい場合があります。詳細はこちら:セカンダリインデックスと生成された列
2.MySQL5.7.6より前
インデックスが付いたトリガーによって更新された列を使用できます。
CREATE TABLE SomeTable (
id CHAR(10),
sub_id CHAR(8) , INDEX(sub_id)
);
CREATE TRIGGER TR_SomeTable_INSERT_sub_id
BEFORE INSERT
ON SomeTable FOR EACH ROW
SET NEW.sub_id = SUBSTRING(NEW.id, 1, 8);
CREATE TRIGGER TR_SomeTable_UPDATE_sub_id
BEFORE UPDATE
ON SomeTable FOR EACH ROW
SET NEW.sub_id = SUBSTRING(NEW.id, 1, 8);
これは、MySQL 5.7.5以降、新しい生成列を使用して可能です。
はい、MySQLで機能インデックスを作成できます。この機能はMySQL8.0.13から利用できます。(他のRDBMSは以前のリリースでこの機能を備えていますが、MySQLはリリース8.0.13でこの機能を導入しました)。機能インデックス
ここでは、MySQL8.0で機能インデックスを作成する例を示しました。
これはクエリです
SELECT * FROM app_user WHERE month(createdOn) = 5;
mysql> SELECT * FROM app_user WHERE month(createdOn) = 5;
7e9e2b7bc2e9bde15504f6c5658458ab - 74322 rows in set (5.01 sec)
createdOn列にインデックスがある場合でも、74322レコードをフェッチするために5秒以上実行されています(createdOn列のインデックスは、month()関数によってマスクされているため、オプティマイザーでは使用されません)
これで、次の構文を使用して列に機能インデックスを作成しました。
mysql> ALTER TABLE app_user ADD INDEX
idx_month_createdon((month(createdOn)));
Query OK, 0 rows affected (1 min 17.37 sec) Records: 0 Duplicates: 0
Warnings: 0
mysql> SELECT * FROM app_user WHERE month(createdOn) = 5;
7e9e2b7bc2e9bde15504f6c5658458ab - 74322 rows in set (0.29 sec)
機能インデックスを作成した後、0.29秒で実行されます。
MysqlのWebサイトでファンクションインデックスドキュメントを見つけるのは困難です。これはファンクションキーパーツの名前です。
また、機能インデックスのある列は削除できません。達成するには、最初に機能インデックスを削除する必要があります。
mysql> ALTER TABLE app_user DROP COLUMN createdOn;
Cannot drop column 'createdOn' because it is used by a functional
index. In order to drop the column, you must remove the functional
index.
MySQL> 5.7.5を使用している場合は、生成された列を使用して同じことを実現できます。