MySQLで条件付きインデックスを作成する方法は?
-
15-10-2019 - |
質問
MySQLのテーブルの特定の範囲またはサブセットをフィルタリングするインデックスを作成する方法は? AFAIK直接作成することは不可能ですが、この機能をシミュレートすることは可能だと思います。
例:インデックスを作成したい NAME
行の列だけ STATUS = 'ACTIVE'
この機能はaと呼ばれます フィルタリングインデックス SQL Serverおよびa 部分インデックス Postgresで。
解決
MySQLは現在、条件付きインデックスをサポートしていません。
あなたが尋ねていることを痛むために(あなたがそれをすべきではないというわけではありません;))あなたは補助テーブルの作成を開始できます:
CREATE TABLE `my_schema`.`auxiliary_table` (
`id` int unsigned NOT NULL,
`name` varchar(250), /* specify the same way as in your main table */
PRIMARY KEY (`id`),
KEY `name` (`name`)
);
次に、メインテーブルに3つのトリガーを追加します。
delimiter //
CREATE TRIGGER example_insert AFTER INSERT ON main_table
FOR EACH ROW
BEGIN
IF NEW.status = 'ACTIVE' THEN
REPLACE auxiliary_table SET
auxiliary_table.id = NEW.id,
auxiliary_table.name = NEW.name;
END IF;
END;//
CREATE TRIGGER example_update AFTER UPDATE ON main_table
FOR EACH ROW
BEGIN
IF NEW.status = 'ACTIVE' THEN
REPLACE auxiliary_table SET
auxiliary_table.id = NEW.id,
auxiliary_table.name = NEW.name;
ELSE
DELETE FROM auxiliary_table WHERE auxiliary_table.id = OLD.id;
END IF;
END;//
CREATE TRIGGER example_delete AFTER DELETE ON main_table
FOR EACH ROW
BEGIN
DELETE FROM auxiliary_table WHERE auxiliary_table.id = OLD.id;
END;//
delimiter ;
必要です
delimiter //
使用したいからです;
トリガー内。
そうすれば、補助テーブルには、トリガーによって更新される文字列「アクティブ」を含むメインテーブルの行に対応するIDが正確に含まれます。
それをaで使用します select
, 、通常を使用できます join
:
SELECT main_table.* FROM auxiliary_table LEFT JOIN main_table
ON auxiliary_table.id = main_table.id
ORDER BY auxiliary_table.name;
メインテーブルに既にデータが含まれている場合、または異常な方法でデータを変更する外部操作を行う場合(例:MySQL外)、これで補助テーブルを修正できます。
INSERT INTO auxiliary_table SET
id = main_table.id,
name = main_table.name,
WHERE main_table.status="ACTIVE";
パフォーマンスについては、おそらくインサート、更新、削除が遅くなるでしょう。これは、望ましい条件が陽性である場合に実際に対処する場合にのみ、ある程度理にかなっています。そのようにしても、おそらくテストするだけで、節約されたスペースが本当にこのアプローチを正当化するかどうかを確認できます(そして、あなたが本当にスペースをまったく節約しているかどうか)。
他のヒント
もしも 私は質問を正しく理解しています。あなたがやろうとしていることを達成することは、両方の列、名前、ステータスにインデックスを作成することだと思います。これにより、name = 'smith'およびstatus = 'Active'でクエリを効率的に使用できます。
条件付きインデックスを実行することはできませんが、例では、マルチコラムインデックスを追加できます(name
,status
).
これらの列のすべてのデータをインデックス化する場合でも、ステータス「アクティブ」で探している名前を見つけるのに役立ちます。
これは、2つのテーブル間でデータを分割し、すべてのデータが必要なときに2つのテーブルを結合するためにビューを使用して、その列のテーブルの1つのみをインデックスすることでこれを行うことができますが、これは必要なクエリのパフォーマンスの問題を引き起こすと思います。クエリプランナーが私が称賛するよりも賢い場合を除き、テーブル全体を実行してください。基本的に、テーブルを手動でパーティション化します(そして、インデックスをパーティションの1つだけに配置します)。
残念ながら 内蔵テーブルパーティション機能 単一のパーティションにインデックスを適用できないため、クエストに役立ちません。
インデックスを持つ追加の列を維持することができ、インデックスを基にしたい条件が真実である場合にその列にのみ値を持つことができますが、これは労働集約的であり、限られた(または否定的)値である可能性がありますクエリの効率と空間節約。
MySQLには仮想列があり、インデックスに使用できます。