我有一个如下所示的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
那么还有其他更好的办法吗?
首先,我同意@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;
请记住,这是快速而肮脏的伪代码。可能存在语法错误,但应该能让您了解我的意思