简体   繁体   中英

Optimize mysql subquery containing self-join to reduce CPU Usage

I understand that mysql query involving self-join table might lead to slow query and/or CPU spike, but have been struggling to come up with ways to improve it.

CREATE TABLE `tool` (
  `tool_id` char(32) NOT NULL,
  `provider` varchar(36) NOT NULL,
  PRIMARY KEY (`tool_id`),
)

CREATE TABLE `edata` (
  `e_data_id` char(32) NOT NULL,
  `tool_id` char(32) DEFAULT NULL,
  `ref_e_data_id` char(32) DEFAULT NULL,
  PRIMARY KEY (`e_data_id`),
  KEY `e_ref_e_data__06a0c1a7_fk` (`ref_e_data_id`),
  KEY `edata_tool_id_61d6bb9b` (`tool_id`),
  CONSTRAINT `e_tool_id_61d6bb9b` FOREIGN KEY (`tool_id`) REFERENCES `tool` (`tool_id`),
) 

here is the query in question

mutdata
LEFT JOIN (SELECT e1.edata_id as m_id, a1.provider as m_cp from edata e1 INNER JOIN tool a1 on e1.tool_id=a1.tool_id WHERE a1.deleted=0) as mapping 
on mutdata.ref_e_data_id=mapping.m_id or mutdata.e_data_id=map.m_id

in short, first the subquery is constructed as a lookup table like a dictionary or map, then mutdata tries to use the lookup table to determine the corresponding provider (this query is part of even larger query). Is there a way to optimize this part?

These indexes may help:

mutdata:  INDEX(ref_e_data_id,  e_data_id)
map:  INDEX(m_id)
e1:  INDEX(tool_id,  edata_id)
a1:  INDEX(deleted, tool_id,  provider)

Try not to use the construct JOIN ( SELECT... ) ; instead try to bump that up a level.

Do you really need LEFT in either place?

OR is terrible for performance. Sometimes it is practical to use two SELECT connected by UNION DISTINCT as a workaround. That way, each SELECT may be able to take advantage of a different index.

Where is map in the query?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM