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.