【问题标题】:SQL performance consideration when using joins for DB design使用连接进行数据库设计时的 SQL 性能注意事项
【发布时间】:2016-09-29 13:29:36
【问题描述】:

我有一张桌子

名称:orderidproduct_idcomment

现在我想添加一个状态

新表:order_state 1 -> finished 2 -> started

然后在表order中添加一个字段order_state_id

我必须以什么方式担心性能?

这是否总是表现良好,或者它不会的情况是什么?例如我的意思是当有很多订单进行连接等时,比如 200'000 个订单

我以前使用过 mysql 视图,它们是 horrible 我创建的视图显然包含多个连接。这不是一个相关的问题吗?

【问题讨论】:

  • 在这种特殊情况下,一个单独的表只存储 order_state 只能采用有限的一组值,这将是浪费且性能不高。相同的数据可以很容易地保存在订单列中。冗余级别将完全相同。
  • order_state_id 是一个低频率域。您可以将其实现为表(如您的问题)或 CHECK 约束,或作为真正的域(不知道 mysql 是否支持这些),或作为枚举(同上)。在所有情况下,存储要求通常是 sizeof int,域表版本可能意味着外键支持索引以加速级联。性能应该不是问题(低基数将启用哈希连接/查找)(如果 mysql 有这些)
  • @joop - MySQL 允许 CHECK 语法,但忽略它。

标签: mysql sql database-performance


【解决方案1】:

不是答案,评论太大了

除了已经说过的,考虑部分索引。

一些数据库,如 Postgres 和 SQL Server,允许您创建不仅指定列而且指定行的索引。

看来您最终会得到不断增长的 order_state_id 等于 finished (2) 的订单数量稳定的 order_state_id 等于 start (1) 的订单

如果您的企业使用这样的查询

SELECT id, comment
  FROM order
 WHERE order_state_id =  1
  AND product_id = @some_value

部分索引允许您限制索引,仅包括未完成的订单

CREATE INDEX Started_Orders
          ON order(product_id)
       WHERE order_state_id = 1

这个索引将小于未过滤的对立部分

【讨论】:

【解决方案2】:

不要规范化order_state。而是添加此列

order_state ENUM('finished', 'started') NOT NULL

然后这样使用(例如):

SELECT ...
    WHERE order_state = 'finished'
    ...

ENUM(最多 255 个选项)只占用 1 个字节。 INT 占用 4 个字节。 TINYINT 占用 1 个字节。

回到你的问题...JOIN 有很好的用途,也有不必要的用途。

【讨论】:

  • komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil 我在“3.无法添加其他属性或相关信息”时停止阅读。因为在此之前这对我来说已经是一个大杀手了
  • 如果您需要编写具有 Combobox 以选择 order_state 的客户端应用程序。如果添加了新状态(如“已取消”),那么在无需重新编译的情况下用值填充它的最佳方法是什么?
  • @Toskan - 您可以拥有另一个表,该表的枚举为PRIMARY KEY。在其中,您可以拥有其他包含“相关信息”的列。添加一个新选项曾经是一个代价高昂的选项。现在它几乎是瞬时的,不管桌子大小。
  • @Horaciux - 我已经有 15 年没有做过“重新编译”了。 PHP、Perl、Java、VB 等没有可见的“编译”阶段。您使用的是 C#、C++ 还是其他一些旧语言?不过,它可以“自动化”,请参阅下一条评论...
  • 通过额外的表或信息模式,您可以发现“order_states”列表并以编程方式构建组合框。
猜你喜欢
  • 2012-06-12
  • 2012-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-12
  • 1970-01-01
相关资源
最近更新 更多