如何优化大列表中的sql?

问题描述 投票:0回答:1

我有一个如下所示的sql。

SELECT * FROM payment
WHERE is_deleted = 0
    AND is_privacy = 0
    AND ou_code IN ('A1', 'A2', ..., 'W1', 'W2'...)
LIMIT 0, 20

in
后面的元素很多,大约有3000个。
payment
表有5000万条数据。我尝试了以下方法:

1、使用临时表:新建一个临时表,将ou_code列表插入表中并创建索引,然后使用inner join。但是我的Java应用程序被禁止在程序中使用DDL语句,所以我无法尝试这个方法。

2、 所以我尝试用sql语法创建一个临时表:如下:

SELECT * FROM 
(VALUES ROW('A1'), ROW('A2')... ROW('W1'), ROW('W2')...) tem(`code`)
inner join 
payment
on payment.`ou_code` =  tem.`code`
WHERE is_deleted = 0
    AND is_privacy = 0
LIMIT 0, 20

但是这个表好像不能创建索引,所以效率没有提高,反而更慢。

3、use contains:我尝试过,但是这个方法也不能创建索引,而且速度还慢

SELECT *
FROM 
payment
WHERE is_deleted = 0
    AND is_privacy = 0
    AND exists (select 1 from (SELECT 'WA1' AS `code`
UNION ALL  
SELECT 'WA2'  
UNION ALL  
SELECT 'WA3') tem where tem.code = payment.ou_code)
LIMIT 0, 20

那么还有其他更好的办法吗?

sql mysqli
1个回答
0
投票

首先,我同意@Jonas Metzler 的观点,如果您没有 DDL 权限,您应该与能够修复数据库结构的人交谈。

这是解决您问题的最佳方法。但是,作为临时解决方法,您可以尝试对 IN 子句进行批处理。这可以帮助你,但只有一点点,不要期望太多。

对于批处理,我的意思是这样的

    SELECT * FROM payment
WHERE is_deleted = 0
    AND is_privacy = 0
    AND ou_code IN ('A1', 'A2', ..., 'A500')
LIMIT 0, 20;

-- Next batch...
SELECT * FROM payment
WHERE is_deleted = 0
    AND is_privacy = 0
    AND ou_code IN ('A501', 'A502', ..., 'A1000')
LIMIT 0, 20;

请记住,这是快速而肮脏的伪代码。可能存在语法错误,但应该能让您了解我的意思

© www.soinside.com 2019 - 2024. All rights reserved.