我有两个基本相同的查询:
旧“交易”查询
SELECT t.payment_method, t.amount, t.commission
FROM `transactions` t, `member_to_group` mtg, `member` m
WHERE mtg.`group_id`='37'
AND t.`is_deleted`='No'
AND t.`member_id`=mtg.`member_id`
AND m.member_id=mtg.member_id
AND m.`is_root`='No'
AND t.`type` IN ('Payment','Credit')
新“付款”查询
SELECT p.method, p.amount, p.commission
FROM `payments` p, `member_to_group` mtg, `member` m
WHERE mtg.`group_id`='37'
AND p.`status`='Active'
AND p.`member_id`=mtg.`member_id`
AND m.member_id=mtg.member_id
AND m.`is_root`='No'
第一个来自“交易”表,第二个来自一个名为“付款”的新表。基本上我们为每笔交易(支付,信用,收费,费用等)都有一张巨大的桌子,但由于每种类型都没有使用大量的字段,所以它已经失去控制 - 所以我们分开了基本的打字。
出于某种原因,尽管更好的组织了更新的表系统(所有在同一个数据库中,请注意),以及查询之间的相似性,旧的“事务”查询运行得更快。 “交易”表以0.004秒的形式返回结果,而“付款”查询则为0.303。在Web应用程序的某些区域(例如,多个组的列表),这转换为40秒的页面加载时间(而不是3以下)。
我可能想要使用单个字段(或多字段)索引吗?我可以进一步优化新查询吗?
这是在MySQL 5.0.92上运行
编辑1:我目前在“交易”(transaction_id,member_id)和“付款”(id,member_id)上都有单字段索引。不幸的是,我只能访问此特定服务器上的PHPMYADMIN,并且EXPLAIN输出不易复制。也就是说,我可以看到“交易”查询的区别在于它在mtg表上显示“使用where; using index”,而“payment”事务只是说“使用where”。
答案 0 :(得分:2)
一般来说,您可以在JOIN
字段和WHERE
子句字段和ORDER BY
字段中添加索引以提高性能。
请注意,这会影响插入记录时的插入性能,但只要这不重要,那么您应该没问题。
因此,要回答您的问题,您可以在以下位置添加索引:
mtg.group_id
p.status
p.member_id
mtg.member_id
m.member_id
m.isroot
修改强>
假设ID字段已经是主键字段,因此已经有了索引。
此外,您的is_root
和status
似乎是varchar字段,如果它们分别是tinyint(1)和整数,则会更好。
如果需要获取文本表示,可以创建一个映射这些值的单独表
答案 1 :(得分:2)
首先,我会将其重写为:
SELECT
payments.method,
payments.amount,
payments.commission
FROM payments
LEFT JOIN member_to_group ON payments.member_id = member_to_group.member_id
LEFT JOIN member ON member.member_id = member_to_group.member_id
WHERE member_to_group.group_id = '37'
AND payments.status = 'Active'
AND member.is_root = 'No'
然后,尝试使用 EXPLAIN 语句比较两个查询。这应该会告诉你差异在哪里。
接下来我会看一下这一行WHERE member_to_group.group_id = '37'
,并确保我将INT
值而不是VARCHAR
的列与所有拟合索引进行比较。
对于payments.status
和member.is_root
,两列都应编入索引( AFAIK ,MySQL仍然不支持部分索引)。
我假设以下列是主键/外键并相应地编入索引:
payments.member_id
member_to_group.member_id
member.member_id
P.S。您可以使用WHERE
语句的顺序,但我认为应该已经由数据库的内部查询优化处理..但谁知道,它是mysql。
<强>更新强>
如果EXPLAIN
表示您没有在member_to_group
表上使用索引,那么您应该检查两个列(在该查询中使用的列)的索引:group_id
和{ {1}} .. member_id
中至少有一个未编入索引。
答案 2 :(得分:0)
您在付款表上有哪些索引?考虑添加一个带有member_id和状态列的索引。