我有两个基本相同的问题:
旧的“事务”查询
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'
第一个来自“事务”表,第二个来自称为“支付”的新表。基本上,我们每笔交易都有一张巨大的表格(付款、信用、收费、费用等),但它失控了,因为每一种类型都有很多不被使用的领域--所以我们把基本类型分开了。
由于某些原因,尽管更新的表系统(都在同一个数据库中,请注意)组织得更好,而且查询之间也有相似之处,但旧的“事务”查询运行得更快。"transaction“表在0.004秒内返回结果,而”支付“查询则需要0.303秒。在web应用程序的某些领域(例如,多个组的列表),这将转化为40秒的页面加载时间(而不是低于3)。
是否有一个字段(或多字段)索引我可能要使用?我可以进一步优化新的查询吗?
这在MySQL 5.0.92上运行
编辑1: i目前有关于“事务”(transaction_id,member_id)和“支付”(id,member_id)的单字段索引。不幸的是,我只能访问这个特定服务器上的PHPMYADMIN,并且解释输出不易复制。也就是说,我可以看到" transaction“查询的不同之处在于它在mtg表上写着”使用where;使用索引“,而"payment”事务只是说“使用where”。
发布于 2011-12-07 05:59:07
首先,我要把它改写为:
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'
然后,尝试使用解释语句比较这两个查询。这应该能告诉你区别在哪里。
接下来,我将查看这一行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
您可以使用WHERE
语句的顺序,但我认为应该已经通过数据库的内部查询优化来处理了。但谁知道呢,是mysql。
更新
如果EXPLAIN
说您没有在member_to_group
表上使用索引,那么您应该检查两个列(在该查询中使用的)的索引:group_id
和member_id
。其中至少有一个没有在member_to_group
中进行索引。
发布于 2011-12-07 05:36:57
一般来说,您可以在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)和status
,则会更好。如果需要获取文本表示形式,可以创建一个单独的表来映射这些值。
发布于 2011-12-07 05:27:16
您在支付表上有什么索引?考虑添加一个使用member_id和status列的索引。
https://stackoverflow.com/questions/8410716
复制相似问题