Mysql delete operation with in will not go to the index

I encountered a performance problem today, and finally located a very slow delete operation.

delete  from t_policy where id in (select policyid from t_policy_user where userid = 1067919);

The statement is very simple. Explain that t_policy is not indexed.

mysql> explain delete  from t_policy where id in (select policyid from t_policy_user where userid = 1067919);   
+----+--------------------+---------------+----------------+-----------------+----------+---------+------+--------+-------------+
| id | select_type        | table         | type           | possible_keys   | key      | key_len | ref  | rows   | Extra       |
+----+--------------------+---------------+----------------+-----------------+----------+---------+------+--------+-------------+
|  1 | PRIMARY            | t_policy      | ALL            | NULL            | NULL     | NULL    | NULL | 101523 | Using where |
|  2 | DEPENDENT SUBQUERY | t_policy_user | index_subquery | policyid,userid | policyid | 302     | func |      1 | Using where |
+----+--------------------+---------------+----------------+-----------------+----------+---------+------+--------+-------------+

The same statement is changed to select very quickly, and explain finds that it will go to the index.

mysql> explain select *  from t_policy where id in (select policyid from t_policy_user where userid = 1067919);       
+----+--------------+---------------+--------+-----------------+---------+---------+----------------------+------+-------+
| id | select_type  | table         | type   | possible_keys   | key     | key_len | ref                  | rows | Extra |
+----+--------------+---------------+--------+-----------------+---------+---------+----------------------+------+-------+
|  1 | SIMPLE       | <subquery2>   | ALL    | NULL            | NULL    | NULL    | NULL                 | NULL | NULL  |
|  1 | SIMPLE       | t_policy      | eq_ref | PRIMARY         | PRIMARY | 302     | <subquery2>.policyid |    1 | NULL  |
|  2 | MATERIALIZED | t_policy_user | ref    | policyid,userid | userid  | 8       | const                |    1 | NULL  |
+----+--------------+---------------+--------+-----------------+---------+---------+----------------------+------+-------+

After a thorough search on the Internet, it is said that inner join can be used instead of in. Sure enough!

mysql> explain delete tp from t_policy tp inner join t_policy_user tpu on tp.id = tpu.policyid where tpu.userid = 1067919;
+----+-------------+-------+--------+-----------------+---------+---------+------------------+------+-------+
| id | select_type | table | type   | possible_keys   | key     | key_len | ref              | rows | Extra |
+----+-------------+-------+--------+-----------------+---------+---------+------------------+------+-------+
|  1 | SIMPLE      | tpu   | ref    | policyid,userid | userid  | 8       | const            |    1 | NULL  |
|  1 | SIMPLE      | tp    | eq_ref | PRIMARY         | PRIMARY | 302     | mdm.tpu.policyid |    1 | NULL  |
+----+-------------+-------+--------+-----------------+---------+---------+------------------+------+-------+

The following are examples of inner join:


  1. --Inquire  
  2. SELECT tp.tp_id, tp.tpmc, tp.leveid, tp.tpdz, tp.jgm, tp.scsj, tp.pbzyid, tp.ksbfsj, tp.jsbfsj, tp.status, tp.tpbz   FROM  qdgl_tupian tp INNERJOIN  qdgl_pqb  pq   
  3.  ON  tp.tp_id=pq.tpid  WHERE  pq.bfjgm='27010825'AND  ps_bfsj >= '2013-01'AND  ps_bfsj< 2013-05-31  ;     
[sql]  view plain copy  
  1. -- Revise  
  2.   UPDATE jx_lsjl jx INNERJOIN isa_gtxx gt ON jx.ckid=gt.gtbh  set jx.ckid=gt.gtid WHERE gt.jgm='27010825'AND jx.jgm='27010825' ;    
[sql]  view plain copy  
  1. --delete  
  2.  DELETE jx FROM  jx_lsjl jx INNERJOIN isa_gtxx gt ON jx.ckid=gt.gtbh    WHERE gt.jgm='27010825'AND jx.jgm='27010825' ;    

As for why mysql has such a problem, the explanation I found that I think is more reliable is:

The reason for the card
is that the operation of the subquery will definitely create a temporary table. Of course, it is not terrible to create a temporary table in memory,
but when you have a large amount of data and the single table size of the temporary table in memory is limited, the temporary table will be converted to write.

The two parameters of the physical memory table in the form of disk determine the size of your temporary table
tmp_table_size max_heap_table_size

You can check the changes of these two states to see if there is any problem with your database statement.
Created_tmp_disk_tables/Created_tmp_tables<5%   



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324824214&siteId=291194637