索引用于OR查询,其中值在两列上相同。

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

Index for OR query where value is the same on both columns

问题

我有以下使用案例:

我的表(重要部分):

CREATE TABLE transfers (
    id int,
    product_id int,
    source_location_id int,
    destination_location_id int,
    quantity int,
    created_at datetime
);

现在我的查询是:

SELECT * 
FROM transfers 
WHERE (source_location_id = 123 OR destination_location_id = 123)
ORDER BY created_at DESC
LIMIT 100 OFFSET 400

目前,该表包含2000万行数据,这个查询需要2-3分钟才能完成。

是否有办法为这个OR子句创建一个索引,因为在这个SELECT中,这个特定的id将始终相同于这两个位置。

我看到一些人提到了OR子句的联接,但我正在使用不支持UNIONSSUBQUERIES的ORM,而且联接在分页上不起作用。

英文:

I have following use case:

My table (significant parts):

CREATE TABLE transfers (
    id int,
    product_id int,
    source_location_id int,
    destination_location_id int,
    quantity int,
    created_at datetime
);

Now my query is:

SELECT * 
FROM transfers 
WHERE (source_location_id = 123 OR destination_location_id = 123)
ORDER BY created_at DESC
LIMIT 100 OFFSET 400

At the moment that table contains 20 million rows and this query takes 2-3 minutes to finish)

Is there a way to create an index for that OR clause since this specific id will always be the same for both locations in that SELECT.

I have seen some people mentioning unions for OR clause, but I am using an ORM that does not support UNIONS nor SUBQUERIES, plus unions will not work with pagination.

答案1

得分: 1

以下是翻译好的部分:

"No, there is no index that will help this. To have this query indexed, you need a union, optimally like:

SELECT transfers.*
FROM transfers
JOIN (
(
SELECT id, created_at
FROM transfers
WHERE source_location_id = 123
ORDER BY created_at DESC
LIMIT 500
)
UNION DISTINCT
(
SELECT id, created_at
FROM transfers
WHERE destination_location_id = 123
ORDER BY created_at DESC
LIMIT 500
)
) ids USING (id)
ORDER BY ids.created_at DESC
LIMIT 100 OFFSET 400

If source and destination are never the same, UNION ALL should be used instead.

Alternatively, add another table like:

CREATE transfer_locations (
transfer_id int,
location_id int,
created_at datetime,
primary key (location_id, transfer_id)
)

with rows for the source and destination for each transfer, and select from that, joining transfers."

英文:

No, there is no index that will help this. To have this query indexed, you need a union, optimally like:

SELECT transfers.* 
FROM transfers 
JOIN (
    (
        SELECT id, created_at
        FROM transfers 
        WHERE source_location_id = 123
        ORDER BY created_at DESC
        LIMIT 500
    )
    UNION DISTINCT
    (
        SELECT id, created_at
        FROM transfers 
        WHERE destination_location_id = 123
        ORDER BY created_at DESC
        LIMIT 500
    )
) ids USING (id)
ORDER BY ids.created_at DESC
LIMIT 100 OFFSET 400

If source and destination are never the same, UNION ALL should be used instead.

Alternatively, add another table like:

CREATE transfer_locations (
    transfer_id int,
    location_id int,
    created_at datetime,
    primary key (location_id, transfer_id)
)

with rows for the source and destination for each transfer, and select from that, joining transfers.

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

发表评论

匿名网友

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

确定