【问题标题】:MySQL new joined query taking too long with subqueryMySQL 新加入的查询与子查询耗时太长
【发布时间】:2014-10-16 19:58:22
【问题描述】:

我正试图弄清楚为什么我的查询需要这么长时间。每次查询通常需要大约 60 - 90 秒,并且会执行多次。

旧查询:

     "select * from $table where type = '".$type."' and transdate >= '".$begdate."' and 
      transdate<='".$enddate."' and customerin (select customer from master
      where targetaccount='Y') ";

新查询:

    $q = "SELECT * FROM activity  INNER JOIN custactivities ON 
    activity.activityID = custactivities.activityID  WHERE  type  = '$type'  AND  
    transdate BETWEEN '$begdate' AND '$enddate'  AND  custnum  IN 
    (SELECT customer FROM master WHERE targetaccount = 'Y')  
    GROUP BY custactivities.customer";

原始查询大约需要 0.15 秒,新查询每个查询大约需要 60-90 秒。

这里面确实有一些 PHP,但查询仍然是个问题。

非常感谢任何建议。

【问题讨论】:

  • 打印结果查询,我们不需要查看您的 PHP。此外,您可以通过使用说明了解您的查询是否正确使用索引,学习调试您的代码和查询,如果没有您的数据库结构,我们将无能为力。
  • 你为什么使用没有聚合函数的group byselect *
  • @DanyCaissy 我删除了大部分 PHP。它仍然需要在那里,以便提醒它它是一个变量。但是,在 custactivities 中也有一个键,我不能使用它们,因为有一个字段非常具体,我无法获取该数据。 @GordonLinoff 是的,Select * 我可以诚实地替换它。但我怀疑那会造成巨大的时差。没有聚合,因为没有一个函数符合我的需要。如果有的话,我只想替换select *。你想让我发show create table吗?

标签: php mysql sql


【解决方案1】:

向以下列添加索引(如果没有)

activityID on both table
type - if it's numeric, don't use the '
transdate
targetaccount - if you can, use numeric, or enum definition for that column for better indexing

如果您的主表在 where targetaccount = 'Y' 的情况下不太大,您可以将其分离到另一个查询中,使用 php 获取并使用 implode 将数组插入到您的查询中,而不是使用子查询。

并且永远不要使用 * ,正如 ChrisS 提到的那样。

这里是一段带有 php 和 mysql 的小代码 sn-p

$cust = array();
$sql = 'SELECT customer FROM master WHERE targetaccount = "Y"';
$query = mysql_query();
if ($query) {
    while ($row = mysql_fetch_row($query)) {
        $cust[] = $row[0]
    }
}

$sql = "select * from $table where type = '".$type."' and transdate >= '".$begdate."' and 
      transdate<='".$enddate."'" . (count($cust) ? ' AND custnum IN ('.implode(', ', $cust).')' : '');

我没有测试过,但我想你现在明白了。

【讨论】:

  • 我尝试将 master 分离到另一个查询中,但未能提供正确的信息。当查询不返回任何结果时,它有时也会引发错误。 (我知道这个错误应该由我自己处理,所以你知道)我同意targetaccount 是数字,但是,我没有设计这个数据库。我正在收拾残局。另外,是什么让select * 如此糟糕?我读过它据说会减慢查询速度,但我从未见过这种情况发生的迹象。
  • 它会减慢查询速度,是的。如果您只有几个访问者,每秒有几个查询,那并不算多,但如果您有一百万个访问者和数百万个查询,则需要太多时间
  • 当时肯定会注意到这一点。我很欣赏这些信息。
  • mysql_* 已弃用^_~。我没有考虑为查询做那个 if 语句。呃,想弄清楚这个问题,我的大脑就像死了一样。
  • 是的,从 PHP 5.5 开始不推荐使用 mysql,但是从代码 sn-p 您可以轻松地重写为其他任何内容,这只是一个示例。
【解决方案2】:

你能加入“大师”吗?我认为这会加快速度。你减速很可能是那个子选择。此外,仅仅为了内存管理,您可能不想只为您需要的列执行“SELECT *”,而是执行“SELECT col1, col2”。

【讨论】:

  • 虽然加入master 表可以工作并且大大缩短了查询时间,但是是什么让新查询在没有加入master 的情况下变慢?
  • 您将每一行与子查询返回的列表进行比较。当您加入时,您首先编译一个列表,然后使用 WHERE 缩小范围。基本上,您的查询将出去并抓取所有行而不在 master 上过滤然后检查每一行到列表 master 正在返回。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-08
  • 2011-02-07
  • 2015-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多