【问题标题】:Segregating data or using UNIQUE index for optimization隔离数据或使用 UNIQUE 索引进行优化
【发布时间】:2021-10-06 09:49:29
【问题描述】:

我有一张桌子;

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);

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

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

【问题讨论】:

    标签: mysql optimization query-optimization


    【解决方案1】:

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

    • 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)。 (但是......在不知道 other 查询涉及此表的情况下,我不能说这是否会提供很大的整体改进。)

    • 这可能会更好:

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

    【讨论】:

    • 这是一个orders 表。一个用户可以有 2 个未结订单,因此 user_idis_open 的组合不是唯一的。这是一个封闭的“订单”而不是“用户”。这就像一个已完成的电子商务交易。我在UNIQUE KEY(id, userid) 背后的想法是,如果搜索按userid 分组,那么可以运行二进制搜索来找出给定userid 的第一次出现,然后可以将其过滤为is_open = 1
    • GROUP BY 不能使用索引 (id, userid),除非它已被单个 id 过滤 (WHERE)。
    • @Ozichukwu - 我根据每个user 的多个orders 清理了我的答案。
    【解决方案2】:

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

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

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

    请记住,每个附加索引都会在每次表更新时导致性能损失。如果您的餐桌不忙,这将不是问题。

    【讨论】:

      猜你喜欢
      • 2016-08-25
      • 1970-01-01
      • 1970-01-01
      • 2011-08-11
      • 2012-04-09
      • 1970-01-01
      • 1970-01-01
      • 2013-02-21
      • 1970-01-01
      相关资源
      最近更新 更多