如何为 WHERE x > 0 创建一个高效的 MySQL 索引。

huangapple go评论68阅读模式
英文:

How to make an efficient mysql index for WHERE x > 0

问题

我有一个使用情况,我的表有几列:

CREATE TABLE stocks (
    id INT,
    warehouse_id INT,
    product_id INT,
    quantity INT,
    updated_at DATETIIME
);

几乎所有我的查询都包括WHERE quantity > 0ORDER BY updated_at
例如:

WHERE quantity > 0
AND warehouse_id = 11
ORDER BY updated_at DESC

或者

WHERE quantity > 0
AND product_id = 1200
ORDER BY updated_at ASC

我知道我可以简单地在quantity上添加一个索引,但这将阻止ORDER BY使用索引。
是否有一种方法可以创建一个仅存储两个值的索引:quantity = 0quantity > 0,以便我可以利用上面提到的两个规则?

例如,对于上面的查询:

CREATE INDEX idx_test1 ON stocks ("quantity > 0", product_id, updated_at)
CREATE INDEX idx_test2 ON stocks ("quantity > 0", warehouse_id, updated_at)
英文:

I have a use case where my table has a couple of columns:

CREATE TABLE stocks (
    id INT,
    warehouse_id INT,
    product_id INT,
    quantity INT,
    updated_at DATETIIME
);

Almost all of my queries include WHERE quantity > 0 and ORDER BY updated_at.
eg.

WHERE quantity > 0
AND warehouse_id = 11
ORDER BY updated_at DESC

or

WHERE quantity > 0
AND product_id = 1200
ORDER BY updated_at ASC

I know I can simply add an index on quantity, but that will prevent ORDER BY from using the index.
Is there a way to make an index that only stores 2 values: quantity = 0 and quantity > 0 so I can take advantage of it with both rules I mentioned above?

eg. for queries above:

CREATE INDEX idx_test1 ON stocks ("quantity > 0", product_id, updated_at)
CREATE INDEX idx_test2 ON stocks ("quantity > 0", warehouse_id, updated_at)

答案1

得分: 3

以下是翻译好的部分:

从MySQL 8.0.13开始,您可以创建[一个功能性索引](https://dev.mysql.com/doc/refman/8.0/en/create-index.html#create-index-functional-key-parts),该索引使用函数或表达式。

您的伪代码:

    CREATE INDEX idx_test1 ON stocks ("quantity > 0", product_id, updated_at);

将翻译为:

    CREATE INDEX idx_test1 ON stocks ( ( quantity > 0 ), product_id, updated_at);

表达式 `quantity > 0` 会产生一个取决于条件是否满足的 `1` 或 `0` - 这是索引所使用的。

目前尚不确定这是否会实际改善查询的性能;索引通常不适合对 `0`/`1` 值进行索引,因为只有两种可能的值。您*可能*想尝试更改索引中列的顺序,将更具区分度的条件放在首位,所以也许是:

    CREATE INDEX idx_test1 ON stocks ( product_id, updated_at, ( quantity > 0 ));

如果您的查询也使用了相反的排序方向,您可能还想使用带有 `updated_at desc` 的相同索引。
英文:

Starting MySQL 8.0.13, you can create a functional index, which makes use of a function or expression.

Your pseudo-code:

CREATE INDEX idx_test1 ON stocks ("quantity > 0", product_id, updated_at);

Would translate as:

CREATE INDEX idx_test1 ON stocks ( ( quantity > 0 ), product_id, updated_at);

Expression quantity > 0 yields 1 or 0 depending on whether the condition is fulfilled - which the index uses.

It is unsure whether this will actually improve the performance of the query; 0/1 values are typically inefficient to index, because there are just two possible values. You might want to try changing the order of the columns in the index, to put a more discriminating criteria first, so maybe:

CREATE INDEX idx_test1 ON stocks ( product_id, updated_at, ( quantity > 0 ));

You might also want to have the same index with updated_at desc, if your queries use that sort direction as well.

huangapple
  • 本文由 发表于 2023年6月29日 20:40:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76581161.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定