需要帮助优化查询性能

时间:2011-12-07 05:12:43

标签: mysql sql query-optimization

我有两个基本相同的查询:

旧“交易”查询

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”。

3 个答案:

答案 0 :(得分:2)

一般来说,您可以在JOIN字段和WHERE子句字段和ORDER BY字段中添加索引以提高性能。 请注意,这会影响插入记录时的插入性能,但只要这不重要,那么您应该没问题。

因此,要回答您的问题,您可以在以下位置添加索引:

mtg.group_id
p.status
p.member_id
mtg.member_id
m.member_id
m.isroot

修改

假设ID字段已经是主键字段,因此已经有了索引。

此外,您的is_rootstatus似乎是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.statusmember.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和状态列的索引。