英文:
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子句的联接,但我正在使用不支持UNIONS
或SUBQUERIES
的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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论