SQL查询在Symfony中非常慢,但在PhpMyAdmin中速度非常快

时间:2015-06-17 15:18:51

标签: sql performance symfony doctrine-orm

我正在开发商业智能应用程序。我在Symfony存储库中运行以下查询:

public function countSubscribers()
{
    $sql = "SELECT COUNT(DISTINCT(a.id))
    FROM account a
    INNER JOIN customer c ON c.account = a.id
    INNER JOIN payment p ON p.customer = c.id
    WHERE p.init != 1
    AND p.cancel_date IS NULL
    AND p.unpaid != 1
    AND p.abo = 1
    AND p.value != 0
    AND c.date_next_payement > NOW()";

    $connection = $this->getEntityManager()->getConnection();
    $statement = $connection->prepare($sql);
    $statement->execute();
    $result = $statement->fetchColumn();

    return $result;
}

页面加载速度很慢,根据symfony profiler,查询执行时间超过15秒:

SELECT COUNT(DISTINCT(a.id)) FROM account a INNER JOIN customer c ON c.account = a.id INNER JOIN payment p ON p.customer = c.id WHERE p.init != 1 AND p.cancel_date IS NULL AND p.unpaid != 1 AND p.abo = 1 AND p.value != 0 AND c.date_next_payement > NOW() Parameters: { }
[Hide runnable query]
Time: 14553.83 ms [ - Explain query ]
Explanation:
id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  c   ALL     PRIMARY,UNIQ_81398E097D3656A4               179226  Using where
1   SIMPLE  a   eq_ref  PRIMARY     PRIMARY     8   evotest.c.account   1   Using index
1   SIMPLE  p   ref     IDX_6D28840D81398E09    IDX_6D28840D81398E09    9   evotest.c.id    1   Using where

所以我尝试在PhpMyAdmin中运行此查询,并且查询在不到1秒的时间内执行。知道为何如此差异?我的网页执行了许多其他查询,但这是几乎使用所有总加载时间的查询。

更新的查询:

SELECT COUNT(DISTINCT(c.id)) 
FROM customer c 
INNER JOIN payment p ON p.customer = c.id 
WHERE p.init != 1 
AND p.cancel_date IS NULL 
AND p.unpaid != 1 
AND p.abo = 1 
AND p.value != 0 
AND c.date_next_payement > NOW()

此查询仍然很慢。有没有办法优化它?我想用给定的过滤器计算至少有1笔付款的客户数量。关系在c.id = p.customer

1 个答案:

答案 0 :(得分:0)

我会尝试使用EXISTS而不是完整联接的子查询。

SELECT COUNT(1) 
FROM customer c
WHERE c.date_next_payement > NOW()
AND EXISTS (
  SELECT 1
  FROM payment p 
  WHERE p.customer = c.id 
  AND p.init != 1 
  AND p.cancel_date IS NULL 
  AND p.unpaid != 1 
  AND p.abo = 1 
  AND p.value != 0
);