分离数据或使用 UNIQUE 索引进行优化
Segregating data or using UNIQUE index for optimization
我有一个table;
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
) 移动到不同的 table,因为当前打开的订单将比关闭的订单相对较小,从而最大限度地减少查找时扫描的行数
- 设置唯一键约束:
ALTER TABLE orders ADD CONSTRAINT UNIQUE KEY(id, userid);
我不知道后者的表现如何,我知道前者会有助于提高性能,但我不知道这是否是最佳实践的好方法。
任何其他想法将不胜感激。
在 id
和 user_id
上设置唯一索引不会给您带来任何好处,因为 id
已经被唯一索引为主键,并且无论如何都不会出现在您的查询中.
将关闭的订单移动到不同的 table 会带来一些性能提升,但由于关闭的订单可能分布在整个 table,性能提升不会像您想象的那么大预计。它还会产生管理开销,需要定期移动订单,并增加报告的复杂性。
您最好的解决方案可能是在 user_id
上添加索引,以便 MySQL 可以直接转到所需的用户 ID 并仅搜索那些行。通过在 user_id
和 is_open
上建立索引,您可能会得到进一步的提升,但额外的好处可能很小。
请记住,每次 table 更新时,每个额外的索引都会导致性能下降。如果您的 table 不忙,这不会有问题。
table属于orders
;每个 userid
.
可以有多个 open/closed orders
WHERE userid = ? AND is_open = 1
将从这些 'composite' 索引中受益:INDEX(userid, is_open)
或 INDEX(is_open, user_id)
。选择哪个更好取决于其他 查询可能比另一个查询更受益。
将“已关闭”订单移至另一个 table 当然是一个有效的选择。这将有助于提高性能。 (我通常不推荐它,只是因为在少数需要的情况下移动行 and/or 以搜索两个 table 需要笨拙的代码。)
我认为 UNIQUE(id, userid)
没有优势。大概 id
因为是 PRIMARY KEY
已经“独一无二”了?此外,在复合索引中,将首先检查第一列;这就是 PK 已经在做的事情。
另一种方法... AUTO_INCREMENT
PK 导致数据 BTree 大致按时间顺序排列。但是你平时伸手到table被userid
?为了提高效率,将 PRIMARY KEY(id), INDEX(userid)
更改为 PRIMARY KEY(userid, id), INDEX(id)
。 (但是...不知道 other 查询涉及这个 table,我不能说这是否会提供很多 overall 改进.)
这可能会更好:
PRIMARY KEY(userid, is_open, id), -- to benefit many queries
INDEX(id) -- to keep AUTO_INCREMENT happy
额外索引的成本(在写操作的性能上)通常被 Selects 的加速所补偿。
我有一个table;
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
) 移动到不同的 table,因为当前打开的订单将比关闭的订单相对较小,从而最大限度地减少查找时扫描的行数 - 设置唯一键约束:
ALTER TABLE orders ADD CONSTRAINT UNIQUE KEY(id, userid);
我不知道后者的表现如何,我知道前者会有助于提高性能,但我不知道这是否是最佳实践的好方法。
任何其他想法将不胜感激。
在 id
和 user_id
上设置唯一索引不会给您带来任何好处,因为 id
已经被唯一索引为主键,并且无论如何都不会出现在您的查询中.
将关闭的订单移动到不同的 table 会带来一些性能提升,但由于关闭的订单可能分布在整个 table,性能提升不会像您想象的那么大预计。它还会产生管理开销,需要定期移动订单,并增加报告的复杂性。
您最好的解决方案可能是在 user_id
上添加索引,以便 MySQL 可以直接转到所需的用户 ID 并仅搜索那些行。通过在 user_id
和 is_open
上建立索引,您可能会得到进一步的提升,但额外的好处可能很小。
请记住,每次 table 更新时,每个额外的索引都会导致性能下降。如果您的 table 不忙,这不会有问题。
table属于orders
;每个 userid
.
orders
WHERE userid = ? AND is_open = 1
将从这些 'composite' 索引中受益:INDEX(userid, is_open)
或INDEX(is_open, user_id)
。选择哪个更好取决于其他 查询可能比另一个查询更受益。将“已关闭”订单移至另一个 table 当然是一个有效的选择。这将有助于提高性能。 (我通常不推荐它,只是因为在少数需要的情况下移动行 and/or 以搜索两个 table 需要笨拙的代码。)
我认为
UNIQUE(id, userid)
没有优势。大概id
因为是PRIMARY KEY
已经“独一无二”了?此外,在复合索引中,将首先检查第一列;这就是 PK 已经在做的事情。另一种方法...
AUTO_INCREMENT
PK 导致数据 BTree 大致按时间顺序排列。但是你平时伸手到table被userid
?为了提高效率,将PRIMARY KEY(id), INDEX(userid)
更改为PRIMARY KEY(userid, id), INDEX(id)
。 (但是...不知道 other 查询涉及这个 table,我不能说这是否会提供很多 overall 改进.)这可能会更好:
PRIMARY KEY(userid, is_open, id), -- to benefit many queries INDEX(id) -- to keep AUTO_INCREMENT happy
额外索引的成本(在写操作的性能上)通常被 Selects 的加速所补偿。