作为一个简单的例子,假设我正在销售小部件。我在全国范围内销售它们(在美国和加拿大)但有一些只能在某些地区(一个或多个美国或加拿大省份)出售。
我想要一种存储此信息的好方法,以及快速查询给定用户可用的小部件的方法。 “美国,50个州和D.C.”是最常见的值,所以我宁愿不插入51行。
MySQL不支持位图索引,因此排除了。
以下是一些组合:
我的用户将为我们的州/省和国家/地区提供一个值。
您能否建议一个提供良好存储和快速匹配的架构?
谢谢!
答案 0 :(得分:1)
您应该构建预定义的值集并将此集存储到项目中。 使用值可以检索匹配集和匹配项。
CREATE TABLE `valuesets` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `valueset_items` (
`valueset_id` int(11) unsigned NOT NULL,
`value` varchar(20) NOT NULL DEFAULT '',
PRIMARY KEY (`valueset_id`,`value`),
CONSTRAINT `fk_valueset_items_valueset` FOREIGN KEY (`valueset_id`) REFERENCES `valuesets` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `items` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL DEFAULT '',
`valueset_id` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_items_valueset` (`valueset_id`),
CONSTRAINT `fk_items_valueset` FOREIGN KEY (`valueset_id`) REFERENCES `valuesets` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
选择与特殊值匹配的所有项目
SELECT *
FROM items
WHERE
valueset_id IN ( SELECT valueset_id
FROM valueset_items
WHERE `value` = 'A' )
答案 1 :(得分:0)
这是一个MySQL SET类型,假设您可以将数据集保持为64个项目(或者根据其他条件使用多个集合)。
我以为我会扩展我的答案,因为我认为有些人根本不理解该集的力量。示例表:
CREATE TABLE `Test` (
`setid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`setname` varchar(64) NOT NULL,
`setstate` set('AK','AL','AR','AZ','CA','CO','CT','DC','DE','FL','GA','HI','IA','ID','IL','IN','KS','KY','LA','MA','MD','ME','MI','MN','MO','MS','MT','NC','ND','NE','NH','NJ','NM','NV','NY','OH','OK','OR','PA','RI','SC','SD','TN','TX','UT','VA','VT','WA','WI','WV','WY') NOT NULL,
PRIMARY KEY (`setid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
insert into `Test` values('1','test','AZ,CA,NJ,NM,NY,VA,VT');
请注意,我们对状态使用单个字段。更复杂的用途可能需要使用多个集合,但是每个记录稍微更加水平的qword可能比在查找表上添加大量额外的连接操作更便宜,这些操作可以轻松地在其上打开大量的记录。 / p>
下面是3个(功能上)等效拉力。请注意,位掩码是提取此数据的最快方法:
SELECT * FROM Test WHERE setstate & 1000;
对于测试#1,我们使用1000作为位掩码,因为这对应于列表(AZ)中的项目#4。到目前为止,这是最快的方法......并且存储这些数据的方法很少,这将为您提供更快的结果潜力。
SELECT * FROM Test WHERE setstate LIKE '%AZ%';
此方法可以使用索引,但由于模糊匹配会稍微缓慢。
SELECT * FROM Test WHERE FIND_IN_SET('AZ',setstate);
这种方法比模糊匹配更快,但其性质几乎需要在大多数实际使用中使用临时表。