我正在尝试如下优化查询,我已经研究了如何添加索引以提高性能,但结果仍然很慢。下面的查询需要20秒才能运行,Transaction包含大约100万条记录,并且连接表TransactionDetail包含大约500k条记录。
SELECT Transaction.id ....
FROM Transaction
INNER JOIN Agent ON Agent.id = Transaction.agent_id
INNER JOIN Distributor ON Distributor.id = Transaction.distributor_id
INNER JOIN TransactionDetail ON Transaction.id = TransactionDetail.transaction_id
WHERE TransactionDetail.type = 'Admin'
AND Transaction.status IN ('pending', 'processing', 'success', 'rejected')
ORDER BY issued_date DESC LIMIT 0 , 10
从上面的查询中我尝试应用我对索引的理解
由于内部连接,我添加了3个索引, 交易(agent_id,distributor_id)和交易(transaction_id)
从where子句我添加了Transaction(status)
但是,我从EXPLAIN
得到的结果并没有显示出任何改进
这是来自phpmyadmin的截图,显示了表Transaction
的索引
有没有办法改进这个查询?或者它已经优化,我应该专注于mysql配置?
答案 0 :(得分:1)
您的查询
SELECT Transaction.id ....
FROM Transaction
INNER JOIN Agent ON Agent.id = Transaction.agent_id
INNER JOIN Distributor ON Distributor.id = Transaction.distributor_id
INNER JOIN TransactionDetail ON Transaction.id = TransactionDetail.transaction_id
WHERE TransactionDetail.type = 'Admin'
AND Transaction.status IN ('pending', 'processing', 'success', 'rejected')
ORDER BY issued_date DESC LIMIT 0 , 10
现在你已经在表上应用了索引,但是in clause
更像是or
这会产生真正的性能问题。如果数据集较小,则无法观察到,但在大型数据集中
性能将大幅下降。
优化它的一种方法是将in clause
转换为union
,其效果优于or
in
(
SELECT Transaction.id ....
FROM Transaction
INNER JOIN Agent ON Agent.id = Transaction.agent_id
INNER JOIN Distributor ON Distributor.id = Transaction.distributor_id
INNER JOIN TransactionDetail ON Transaction.id = TransactionDetail.transaction_id
WHERE TransactionDetail.type = 'Admin'
AND Transaction.status = 'pending'
)
union
(
SELECT Transaction.id ....
FROM Transaction
INNER JOIN Agent ON Agent.id = Transaction.agent_id
INNER JOIN Distributor ON Distributor.id = Transaction.distributor_id
INNER JOIN TransactionDetail ON Transaction.id = TransactionDetail.transaction_id
WHERE TransactionDetail.type = 'Admin'
AND Transaction.status = 'processing'
)
union
(
SELECT Transaction.id ....
FROM Transaction
INNER JOIN Agent ON Agent.id = Transaction.agent_id
INNER JOIN Distributor ON Distributor.id = Transaction.distributor_id
INNER JOIN TransactionDetail ON Transaction.id = TransactionDetail.transaction_id
WHERE TransactionDetail.type = 'Admin'
AND Transaction.status = 'success'
)
union
(
SELECT Transaction.id ....
FROM Transaction
INNER JOIN Agent ON Agent.id = Transaction.agent_id
INNER JOIN Distributor ON Distributor.id = Transaction.distributor_id
INNER JOIN TransactionDetail ON Transaction.id = TransactionDetail.transaction_id
WHERE TransactionDetail.type = 'Admin'
AND Transaction.status = 'rejected'
)
order by issued_date DESC LIMIT 0 , 10
要解决订单,您可能需要将索引添加为
alter table Transaction add index status_created_idx(status,issued_date);
答案 1 :(得分:1)
添加所有INDEXes
是徒劳的,因为优化器(几乎总是)只使用一个索引。
原始查询可能受益于INDEX(issue_date)
。添加该索引,然后向我们显示EXPLAIN SELECT ...
的输出,看它是否正在使用它。
如果它正在使用它,那只会避免使用" filesort"这通常只占总时间的一小部分。它也可能因LIMIT
因停止而受益。但是,它可能必须读取超过10行,因为WHERE
包括其他表。
由于TransactionDetail.type = 'Admin'
,它必须在决定要保留哪些行之前通过JOINs
。
可能导致其他选项的两个问题:
在进行实验时,发布(1)索引和(2)EXPLAIN。