Answers:
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`)
);
然后,在主表中添加三个触发器:
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,这些主表行包含由触发器更新的字符串“ ACTIVE”。
要将其用于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和STATUS这两个列上创建索引来完成您要执行的操作。这样可以有效地查询NAME ='SMITH'和STATUS ='ACTIVE'的位置
您可以通过在两个表之间拆分数据,在需要所有数据时使用视图将两个表合并并为该列上的一个表建立索引来实现此目的,但是我认为这会导致需要查询的性能问题运行整个表,除非查询计划程序比我认为的要聪明。本质上,您将手动对表进行分区(并将索引仅应用于其中一个分区)。
不幸的是,内置的表分区功能将无法为您提供帮助,因为您无法将索引应用于单个分区。
您可以维护带有索引的额外列,并且仅当您希望索引所基于的条件为true时,才在该列中具有值,但是这可能是劳动密集型的,并且在以下方面受限制(或负值)查询效率和节省空间。
MySQL现在具有虚拟列,可用于索引。
select count(*) from foo where id is null ;
使用索引吗?)
decode(status,'ACTIVE',name,null)
例如,虚拟列可能处于打开状态。