(mysql) multiple fields need subquery for optimization

to ask a question, (MySQL) table A has code_name,code_id,code_field at the end, and table B of another table has many attributes, such as nationality, place of origin, and so on. The nationality subquery method is select code_name form A table where code_id= B table. GJ _ id and code_field = "gj".
the difficulty encountered now is that the subquery is too slow, and there are other attributes such as place of origin in addition to nationality. If all subqueries are used, it will be estimated for a few minutes at a time. Can we use a contingency table in this case?
is there any good solution?

the writing style is not good. You can look directly at the following code to see how to optimize

.
select
B.code_name,C.code_name
FROM
A
JOIN B 
ON
B.code_id = A.GJ AND B.field_name = "GJ"
JOIN B as C
ON
C.code_id = A.MZ AND C.field_name = "MZ"

this way of writing nested join is even longer than a subquery. What is the reason for this? if you know it, you can also say ha

.
Jun.07,2022

first of all, let's assume that the indexes that should be added in both AB tables are added (it should not be so slow if table B is added with a federated index). Since you said in your comments that you don't have permission to touch their tables, don't consider this problem yet.

Let's start with why nested join is slower: multiple layers of join are used in the statement, and a join is a Cartesian product. When there is a large amount of data, the amount of Cartesian product is astronomical. With subqueries, in the worst case, the amount of computation is a Cartesian product.

solution, of course, the best way is to write a python script to load the data of table B into memory at one time, and then assemble the data of table A by yourself, so that you don't have to query table B every time.

if the conditions do not allow, try adding limit 1 to the subquery to reduce the number of rows for some full table scans:

select 

(select code_name from B where code_id = A.GJ and field_name = 'GJ' limit 1) as GJ
(select code_name from B where code_id = A.MZ and field_name = 'MZ' limit 1) as MZ
(select code_name from B where code_id = A.JG and field_name = 'JG' limit 1) as JG

FROM

A;

explain take a look at the execution plan


B table to establish a joint index idx_code_id_field_name (code_id,field_name)
if you don't have permission to modify the table, you can always create a temporary table of your own. The temporary table is indexed and associated with Table A

.
MySQL Query : SELECT * FROM `codeshelper`.`v9_news` WHERE status=99 AND catid='6' ORDER BY rand() LIMIT 5
MySQL Error : Disk full (/tmp/#sql-temptable-64f5-1b2be79-2b24c.MAI); waiting for someone to free some space... (errno: 28 "No space left on device")
MySQL Errno : 1021
Message : Disk full (/tmp/#sql-temptable-64f5-1b2be79-2b24c.MAI); waiting for someone to free some space... (errno: 28 "No space left on device")
Need Help?