我有以下查询,显示具有特定 margin 水平的账户列表:
SELECT
crm_margincall.id,
crm_margincall.CreationTime,
ba.name AS crm_bankaccount_id,
crm_margincall.name,
crm_margincall.MarginCallLevel,
crm_margincall.UseOfEquityForMargin,
crm_margincall.MarginRequired,
crm_margincall.NetEquityForMargin,
crm_margincall.MarginDeficit,
crm_margincall.balance,
crm_margincall.deposited,
crm_margincall.prefunded,
crm_margincall.required
FROM
crm_margincall
LEFT JOIN
crm_bankaccount ba ON crm_margincall.crm_bankaccount_id = ba.id
WHERE
crm_margincall.name = 'MarginCall'
AND
crm_margincall.MarginCallLevel >= 100
AND
crm_margincall.crm_account_id NOT IN
(
SELECT
x.crm_account_id
FROM
crm_margincall x
WHERE
x.crm_account_id = crm_margincall.crm_account_id
AND
x.name = 'LevelDrop'
AND
x.MarginCallLevel < 100
AND
x.id > crm_margincall.id
)
ORDER BY
id
DESC
此查询在约 22.500 条记录的表上运行需要 >10 秒,这是由定义 NOT IN 部分的子查询引起的(尝试过 NOT EXISTS,速度并不快)。我怎样才能加入这个表本身来达到同样的效果?
最佳答案
This query, on a table of ~22.500 records takes >10 seconds to run, this is caused by the subquery defining the NOT IN section (tried NOT EXISTS, isnt much faster). How can I join this table on itself to achieve the same effect?
这可以通过多种方式完成,但扫描 22500 条记录需要 10"意味着硬件问题或非常低效的 JOIN。
后者最可能的原因是索引缺失或索引配置错误,要对此进行调查,您需要发出 EXPLAIN:
EXPLAIN SELECT ...
完全在黑暗中拍摄,从所使用的选定列来看,我会尝试
CREATE INDEX test_index ON crm_margincall(name, crm_account_id, MarginCallLevel, id)
其他改进可能是可能的,但您需要在 SQLfiddle 中准备一个包含一些假数据的示例结构,以真正允许调试。
关于MYSQL 删除表本身的 NOT IN 子查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41167575/