【问题标题】:Performance of joins on multi-million-row tables数百万行表的连接性能
【发布时间】:2016-05-02 03:34:43
【问题描述】:

我需要让我的网站用户能够选择他们的国家、省和市。所以我想显示一个国家列表,然后是所选国家的省份列表,然后是所选省份的城市列表(我现在不需要任何其他 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 表包含 400 万行,city_translation 表包含 400 万行 × 我网站上可用语言的数量。现在是1200万。如果以后我要支持10种语言,那就是4000万……

所以我想知道:使用这种大小的表是一个坏主意(性能方面),还是一个好的索引(在连接字段上,city_idlocale_id)足以使大小不重要?

如果不是,用于解决这个特定问题的常用解决方案是什么——但我猜是常见的——问题?我只对性能感兴趣。如有必要,我可以进行非规范化,甚至可以使用其他更合适的工具(ElasticSearch?)。

【问题讨论】:

  • 接受的答案here 有一些很好的信息
  • Paris 在多种语言中是“巴黎”。您可以实现一个备用系统,如果 city.name 没有翻译,则使用备用
  • “所以我想知道:使用这种大小的表是一个坏主意(性能方面),还是连接字段上的一个好的索引?”您为什么不尝试一下,让我们知道结果如何。

标签: mysql database performance join database-design


【解决方案1】:

去掉 city_translations 中的id。取而代之的是PRIMARY KEY(city_id, locale_id)。使用 InnoDB,这可能会使速度翻倍,因为在 JOINs 中删除了不必要的步骤。您还可以通过删除以city_id 开头的两个索引来缩小磁盘占用空间。

你认为你会超越 1600 万个城市吗?我对此表示怀疑。因此,通过将(在所有表中)city_id 更改为 MEDIUMINT UNSIGNED 来节省一个字节。

locale_id 更改为TINYINT UNSIGNED 可节省3 个字节。

这些节省乘以提及它们的列和索引的数量。

表有多大 (GB)? innodb_buffer_pool_size的设置是什么?有多少内存?看看您是否可以使该设置大于总表大小,但不超过 可用 内存的 70%。 (这是唯一值得检查的“可调参数”。)

为了中国用户,我希望你默认CHARACTER SET utf8mb4。 (但那是另一回事了。)

【讨论】:

  • 感谢@Rick 的提示。但是,我的问题是,使用这么大的桌子是否是一个坏主意,或者尝试另一种方式通常是否更好。我需要的是一个或另一个模型设计的元素,权衡利弊的标准,等等。或者甚至是一些基本的东西:“从 x 记录开始,忘记它”;-) 我很想阅读你的建议在你的答案中的这些点。
  • “十亿条记录,令人兴奋。”不,我没有说“忘记它”。我没有说的是“你的 40M 行很好”。我只是开始列出一些让它更好地工作的技巧。你所描述的(到目前为止)是中等体积,但“简单”。
猜你喜欢
  • 2013-11-27
  • 1970-01-01
  • 2011-02-14
  • 2018-12-26
  • 1970-01-01
  • 2023-01-05
  • 2012-07-10
  • 2021-11-06
  • 2012-07-27
相关资源
最近更新 更多