我有一个可以过滤的列表(多个过滤器),分页并且原始生成的sql是:
SELECT
b0_.id AS id0,
b0_.offset AS offset1,
b0_.title AS title2,
b0_.message AS message3,
b0_.type AS type4,
b0_.resolved_at AS resolved_at5,
b0_.operationImport_id AS operationImport_id6
FROM
bank_import_error b0_
INNER JOIN
bank_operation_import b1_ ON b0_.operationImport_id = b1_.id
INNER JOIN
bank_account b2_ ON b1_.account_id = b2_.id
WHERE
b2_.company_id = 1
AND (b1_.started_at LIKE '%03%'
OR b0_.title LIKE '%03%'
OR b2_.name LIKE '%03%'
OR b0_.offset LIKE '%03%')
ORDER BY b1_.started_at ASC
LIMIT 10 OFFSET 70
此请求需要3,5到4分钟,因此我尝试应用"后期行查找"技术:
SELECT b.id as id0, b.offset as offset1, b.title as title2, b.message as message3, b.type as type4, b.resolved_at as resolver_at5, b.operationImport_id as operationImport_id6 FROM
(SELECT
b0.id
FROM
(SELECT id, operationImport_id FROM bank_import_error WHERE title LIKE '%03%' OR offset LIKE '%03%') b0
LEFT JOIN
(SELECT id, account_id, started_at FROM bank_operation_import WHERE started_at LIKE '%03%') b1 ON b0.operationImport_id = b1.id
LEFT JOIN
(SELECT id from bank_account WHERE name like '%03%' AND company_id = 1) b2 ON b1.account_id = b2.id ORDER BY B1.started_at ASC
LIMIT 10 OFFSET 70
) o INNER JOIN bank_import_error b on b.id = o.id
但是这第二个请求并没有给出相同的结果。订购问题?一个逻辑问题?我该怎么做才能解决这个问题?
环境:Mysql,InnoDB。 SQLFiddle:http://sqlfiddle.com/#!9/a4157/1/0 但是这些信息非常敏感,所以我暂时不把数据放在表格中。
答案 0 :(得分:0)
后期行查找要求您编写一个有效的子查询,该子查询获取行子集的ID,并将其与查询的其余部分连接起来。
SELECT
b0_.id AS id0,
b0_.offset AS offset1,
b0_.title AS title2,
b0_.message AS message3,
b0_.type AS type4,
b0_.resolved_at AS resolved_at5,
b0_.operationImport_id AS operationImport_id6
FROM
bank_import_error b0_
INNER JOIN
bank_operation_import b1_ ON b0_.operationImport_id = b1_.id
INNER JOIN
bank_account b2_ ON b1_.account_id = b2_.id
INNER JOIN
(SELECT id
FROM bank_operation_import
ORDER BY started_at ASC
LIMIT 10 OFFSET 70) AS b3_ ON b1_.id = b3_.id
WHERE
b2_.company_id = 1
AND (b1_.started_at LIKE '%03%'
OR b0_.title LIKE '%03%'
OR b2_.name LIKE '%03%'
OR b0_.offset LIKE '%03%')
ORDER BY b1_.started_at ASC
但是,这不会返回与原始查询相同的数据,因为您在之后过滤选择了有限的行。
我认为在你的查询中很好地利用后期行查找,因为你需要在分页之前进行过滤,而过滤是昂贵的部分(因为LIKE '%03%'
可以'被索引)。