我需要让我的网站用户能够选择他们的国家,省和城市。所以我想显示一个国家/地区列表,然后是所选国家/地区的省份列表,然后是所选省份的城市列表(我现在不想要任何其他UI解决方案)。当然,每个名称都必须使用用户的语言,因此我需要额外的表格进行翻译。
让我们关注城市的情况。以下是两个表格:
CREATE TABLE `city` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`province_id` int(10) unsigned DEFAULT NULL
PRIMARY KEY (`id`),
KEY `idx_fk_city_province` (`province_id`),
CONSTRAINT `fk_city_province` FOREIGN KEY (`province_id`) REFERENCES `province` (`id`)
) ENGINE=InnoDB;
CREATE TABLE `city_translation` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`city_id` int(10) unsigned NOT NULL,
`locale_id` int(10) unsigned DEFAULT NULL,
`name` varchar(255) DEFAULT NULL
PRIMARY KEY (`id`),
KEY `idx_fk_city_translation_city` (`city_id`),
KEY `idx_fk_city_translation_locale` (`locale_id`),
KEY `idx_city_translation_city_locale` (`city_id`,`locale_id`),
CONSTRAINT `fk_city_translation_city` FOREIGN KEY (`city_id`) REFERENCES `city` (`id`),
CONSTRAINT `fk_city_translation_locale` FOREIGN KEY (`locale_id`) REFERENCES `locale` (`id`)
) ENGINE=InnoDB;
city
表包含4百万行,city_translation
表包含4百万x我网站上可用语言的数量。现在这是1200万。如果将来我想支持10种语言,那将是4千万......
所以我想知道:处理这个大小的表是一个坏主意(表现明智),还是一个很好的索引(在连接字段city_id
和locale_id
)足以使尺寸无关紧要?
如果没有,用于解决这个问题的常用解决方案有哪些 - 但我觉得常见问题?我只对表现感兴趣。我可以在必要时进行非规范化,如果它们更合适,甚至可以使用其他工具(ElasticSearch?)。
答案 0 :(得分:2)
摆脱city_translations中的id
。取而代之的是PRIMARY KEY(city_id, locale_id)
。使用InnoDB,由于在JOINs
中删除了不必要的步骤,因此速度可能会加倍。您还可以通过删除以city_id
开头的两个索引来缩小磁盘占用空间。
你认为你会超越16M城市吗?我对此表示怀疑。因此,通过将city_id
更改为MEDIUMINT UNSIGNED
来保存一个字节。
通过将locale_id
更改为TINYINT UNSIGNED
来保存3个字节。
这些节省量乘以提及它们的列数和索引数。
表格(GB)有多大? innodb_buffer_pool_size
的设置是什么?有多少内存?看看你是否可以使该设置大于总表大小,但不超过可用内存的70%。 (这是唯一的"可调和#34;值得检查。)
我希望您为中国用户设置默认值CHARACTER SET utf8mb4
。 (但这是另一个故事。)