隔离数据或使用 UNIQUE 索引进行优化

我有一张桌子;

Orders
* id INT NN AN PK
* userid INT NN
* is_open TINYINT NN DEFAULT 1
* amount INT NN
* desc VARCHAR(255)

以及我经常运行的查询 SELECT * FROM orders WHERE userid = ? AND is_open = 1;。我想为此查询优化数据库,目前我有两个选择;

  • 将关闭的订单 (is_open = 0) 移至不同的表,因为当前未结订单将相对小于已关闭订单,从而最大限度地减少查找时要扫描的行
  • 设置唯一键约束:ALTER TABLE orders ADD CONSTRAINT UNIQUE KEY(id,userid);

我不知道后者的表现如何,我知道前者有助于提高表现,但我不知道这是否是最佳实践的好方法。

任何其他想法将不胜感激。

nh8341 回答:隔离数据或使用 UNIQUE 索引进行优化

表是orders;每个 orders 可以有多个打开/关闭的 userid

  • WHERE userid = ? AND is_open = 1 将受益于以下任一“复合”索引:INDEX(userid,is_open)INDEX(is_open,user_id)。选择哪个更好取决于其他查询可能从哪个查询中受益更多。

  • 将“关闭”的订单移到另一个表当然是一个有效的选择。这将有助于提高性能。 (我通常不推荐它,只是因为在少数情况下需要移动行和/或搜索两个表所需的笨拙代码。)

  • 我认为 UNIQUE(id,userid) 没有优势。大概 id 因为是 PRIMARY KEY 已经“独一无二”了?此外,在复合索引中,将首先检查第一列;这就是PK已经在做的事情。

  • 另一种方法... AUTO_INCREMENT PK 导致数据 BTree 大致按时间顺序排列。但是您通常通过 userid 进入桌子?为了提高效率,请将 PRIMARY KEY(id),INDEX(userid) 更改为 PRIMARY KEY(userid,id),INDEX(id)。 (但是……在不知道涉及此表的其他查询的情况下,我不能说这是否会提供很大的整体改进。)

  • 这可能会更好:

      PRIMARY KEY(userid,is_open,-- to benefit many queries
      INDEX(id)   -- to keep AUTO_INCREMENT happy
    
  • 额外索引的成本(关于写操作的性能)通常可以通过 Selects 的加速来补偿。

,

iduser_id 上设置唯一索引不会给您带来任何好处,因为 id 已经被唯一索引为主键,并且无论如何都不会出现在您的查询中。

将关闭的订单移动到不同的表会带来一些性能改进,但由于关闭的订单可能分布在整个表中,因此性能改进不会像您预期的那样大。它还带来了管理开销,需要定期移动订单,以及报告的额外复杂性。

您最好的解决方案可能是在 user_id 上添加索引,以便 MySQL 可以直接转到所需的用户 ID 并仅搜索那些行。通过在 user_idis_open 上建立索引,您可能会得到进一步的提升,但额外的好处可能很小。

请记住,每个额外的索引都会导致每次表更新时的性能损失。如果您的桌子不忙,这不会成为问题。

本文链接:https://www.f2er.com/7078.html

大家都在问