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:
- --Inquire
- 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
- ON tp.tp_id=pq.tpid WHERE pq.bfjgm='27010825'AND ps_bfsj >= '2013-01'AND ps_bfsj< 2013-05-31 ;
- -- Revise
- 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' ;
- --delete
- 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%