我们有一组用户
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(254) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED
每个用户可以拥有一个或多个域,例如
CREATE TABLE `domains` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` varchar(11) NOT NULL,
`domain` varchar(254) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `domain` (`domain`),
CONSTRAINT `domains_user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED
我们有一个包含某种数据的表,在这个例子中,它所包含的内容并不重要
CREATE TABLE `some_data` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content` TEXT NOT NULL,
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED
我们希望some_data
的某些元素只能由某些users
或仅某些domains
(白名单情况)访问。
在其他情况下,我们希望some_data
或某些users
的每个人都可以访问domains
的元素(黑名单)。
理想情况下,我们希望在单个查询中检索some_data
的给定元素可以访问的域的列表,理想情况下要进行反向操作(列出给定域可以访问的所有数据)
到目前为止,我们的方法是使用一张桌子
CREATE TABLE `access_rules` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rule_type` enum('blacklist','whitelist')
`some_data_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`domain_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `access_rules_some_data_id_fk` FOREIGN KEY (`some_data_id`) REFERENCES `some_data` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED
但是问题是,我们需要查询数据库两次(以确定给定的数据条目是在运行黑名单还是白名单(白名单具有更高的优先级))。 (编辑:可以在单个查询中完成) 另外,由于domain_id可为空(以允许将整个用户列入黑名单/将其列入白名单),因此加入并不容易
将使用该模式的API当前每秒达到4-5k次,因此性能至关重要。
users
表相对较小(超过5万行),domains
表大约有150万个条目。 some_data
也相对较小(不到10万行)
编辑:问题更多地围绕语义和最佳实践。通过上述结构,我相信我们可以使其正常运行,但是架构“感觉不对”,我想知道是否有更好的方法
答案 0 :(得分:1)
要考虑两个问题,规范化和管理。 传统上,要规范化,您将需要4个表。
设置3个主表USER,DOMAIN,OtherDATA。
使用User_Id,Domain_Id,OtherDATA_Id,PermissionLevel设置子表
这提供了最少的重复数据量。这也使在用户域级别的管理变得容易。您还可以在用户和域表中添加默认的白名单/黑名单字段。这样,脚本可以自动填充子表,然后经理可以进入并调整所需的一个值。
如果您有两个不同的表,一个表用于白名单,一个表用于黑名单,则您可能会偶然在两个列表中获得一个用户或域。实际上,它将是4个表,用户2个,域2个。管理会更复杂。