如何重写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()
),基本上查询速度较慢。索引是可以的,但总体性能并不好。我正在尝试重新构造查询以生成相同的输出。您可以从正确规范化数据库开始。