Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何重写MySQL查询_Mysql_Performance - Fatal编程技术网

如何重写MySQL查询

如何重写MySQL查询,mysql,performance,Mysql,Performance,我有下面的问题,我试图重写它以提高性能,我可以使用什么方法来重写它 select notes.id, notes.name, notes.parent_type, notes.contact_id from notes JOIN ( SELECT contact_id as id from accounts_contacts where account_id = 'acct1876' and deleted = '0' union SELECT quot

我有下面的问题,我试图重写它以提高性能,我可以使用什么方法来重写它

select 
    notes.id, notes.name, notes.parent_type, notes.contact_id from notes 
JOIN 
    ( 
    SELECT contact_id as id from accounts_contacts where account_id = 'acct1876' and deleted = '0' union 
    SELECT quote_id as id from quotes_accounts where account_id = 'acct1876' and deleted = '0' union 
    SELECT opportunity_id as id from accounts_opportunities where account_id = 'acct1876' and deleted = '0' union 
    SELECT leads.id as id from leads where account_id = 'acct1876' and deleted = '0' union 
    SELECT  project_id as id from projects_accounts where account_id = 'acct1876' and deleted = '0' union 
    select 'acct1876' as id 
    ) A 
    ON A.id = notes.parent_id and deleted = '0' OR contact_id in 
    ( SELECT contact_id from accounts_contacts where account_id = 'acct1876' and deleted = '0' ) and deleted = '0' 

    group by notes.id;

为了回答您的问题并提高性能,我想建议一种乍一看似乎很奇怪的方法

如果您有一个合理的记录数量,请使用更多的选择,而不是单一的(和沉重的)一个。您可以在一个数组中收集id,或者(最好)在一个字符串中收集id,然后用逗号分隔的id列表进行另一个查询,等等。这(虽然听起来完全是胡说八道)与几乎没有缺点相比有许多优点:单独的选择运行得很快,然后让db服务器呼吸。当您执行一次选择时,其他表将不会被锁定(!!!),而一次较大的选择将在整个查询过程中锁定所有涉及的表。因此,这样做更容易,可读性更强:

$idlist = fetch_idlist("select id from users where name like 'John%'");
$result = fetch_all("select * from mails where userid in ($idlist)");
除此之外:

$result = fetch_all("select * from mails left join users on users.id=mails.userid ....")
尽管功能不存在,但我希望其含义是明确的。这只是原则。因此,在您的例子中,可能需要选择联系人,构建id列表,然后对注释进行单独的查询,等等,然后用php编写最终结果

同样,这只适用于少于一百万的记录计数,你不能以很高的数量消耗掉所有的内存。但关键是:在高负载情况下,单独处理耗时的查询并让其他进程参与其中比在(相对)长时间内锁定一整组表要好得多


抱歉,如果不是100%的答案,但我认为值得解释。

首先,您的最终OR是内部联接开始的副本,否则毫无意义

这部分

  ON A.id = notes.parent_id 
  and deleted = '0' 
  OR contact_id in ( SELECT contact_id 
                       from accounts_contacts 
                       where account_id = 'acct1876' 
                       and deleted = '0' ) 
  and deleted = '0' 
可能只是

  ON A.id = notes.parent_id 
接下来,您似乎正在尝试获取与给定帐户关联的所有ID,包括有问题的帐户。我会确保这些表中的每个表都有一个关于帐户ID和已删除列的索引。另外,对于这个查询,我会将其设置为独立的,以防止重复项被加入notes表。然后,我会交换订单(对我来说,在心里查询您想要的ID,然后获取相关的注释)。下面是UNION查询的每个表的索引,以及连接的父ID列旁边的notes表

table                  index
accounts_contacts      (account_id, deleted, contact_id)
quotes_accounts        (account_id, deleted, quote_id )
accounts_opportunities (account_id, deleted, opportunity_id )
leads                  (account_id, deleted, id
projects_accounts      (account_id, deleted, project_id )
notes                  (parent_id)
现在,次要的更新查询

select 
      notes.id, 
      notes.name, 
      notes.parent_type, 
      notes.contact_id 
   from 
         (SELECT DISTINCT contact_id as id 
             from accounts_contacts 
             where account_id = 'acct1876' and deleted = '0' 
          union 
          SELECT quote_id as id 
             from quotes_accounts 
             where account_id = 'acct1876' and deleted = '0' 
          union 
          SELECT opportunity_id as id 
             from accounts_opportunities 
             where account_id = 'acct1876' and deleted = '0' 
          union 
          SELECT leads.id as id 
             from leads 
             where account_id = 'acct1876' and deleted = '0' 
          union 
          SELECT project_id as id 
             from projects_accounts 
             where account_id = 'acct1876' and deleted = '0' 
          union 
          select 'acct1876' as id ) A 
         JOIN Notes
            ON A.id = notes.parent_id 
   group by 
     notes.id;

如前所述,您有一个group by,但列上没有求和或聚合,这将导致找到的第一个条目被包括在内,并且由于按自动递增的ID列显示,无论帐户“ID”来自何处,都将具有相同的值。

您可以了解连接,但现在还不清楚你到底想做什么!?!?!如果你能解释你的需求,而不是希望人们能正确地从你的查询中逆向工程它,这会有很大帮助。此外,您误用了
分组依据
;查询中没有聚合函数(如
SUM()
GROUP\u CONCAT()
),基本上查询速度较慢。索引是可以的,但总体性能并不好。我正在尝试重新构造查询以生成相同的输出。您可以从正确规范化数据库开始。