我有2张桌子。从这两个表我想尝试使用带连接的选择查询将记录插入第三个表。但是我发现选择查询时加入不使用索引并花费大量时间,因此插入速度很慢
我尝试按照几篇文章的建议创建多个索引,但没有用
MySQL with JOIN not using index
MySQL query with JOIN not using INDEX
以下是我的表结构:
CREATE TABLE master_table (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
field1 VARCHAR(50) DEFAULT NULL,
field2 VARCHAR(50) DEFAULT NULL,
field3 VARCHAR(50) DEFAULT NULL,
field4 VARCHAR(50) DEFAULT NULL,
PRIMARY KEY (id),
KEY mt_field1_index (field1)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
CREATE TABLE child_table (
c_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
m_id BIGINT(20) UNSIGNED NOT NULL ,
group_id BIGINT(20) UNSIGNED NOT NULL ,
status ENUM('Status1','Status2','Status3') NOT NULL,
job_id VARCHAR(50) DEFAULT NULL,
PRIMARY KEY (c_id),
UNIQUE KEY ct_mid_gid (m_id,group_id),
KEY Index_ct_status (status),
KEY index_ct_jobid (job_id),
KEY index_ct_mid (m_id),
KEY index_ct_cid_sts_tsk (group_id,status,job_id)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
查询:
SELECT m.id
, NULLIF(TRIM(m.field1),'')
FROM master_table m
JOIN child_table c
ON m.id = c.m_id
WHERE c.group_id = 2
AND c.status = 'Status3'
AND c.job_id = 0
ORDER
BY m.id
LIMIT 0, 1000;
解释:
+-------+-------------+-------+------------+----------+------------------------------------------------------------------------------+-----------------+---------+--------------+-------+----------+------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+-------+-------------+-------+------------+----------+------------------------------------------------------------------------------+-----------------+---------+--------------+-------+----------+------------------------------------------------+
| 1 | SIMPLE | c | (NULL) | ref | ct_mid_gid,Index_ct_status,index_ct_jobid,index_ct_mid,index_ct_cid_sts_tsk | Index_ct_status | 1 | const | 65689 | 0.00 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | m | (NULL) | eq_ref | PRIMARY | PRIMARY | 8 | r_n_d.c.m_id | 1 | 100.00 | (NULL) |
+-------+-------------+-------+------------+----------+------------------------------------------------------------------------------+-----------------+---------+--------------+-------+----------+------------------------------------------------+
答案 0 :(得分:1)
WHERE c.group_id = 2
AND c.status = 'Status3'
AND c.job_id = 0
ORDER BY c.m_id -- Note the change
需求
INDEX(group_id, status, job_id, -- in any order
m_id) -- last
你拥有的(单独的索引)不相同。
要获得LIMIT
,索引必须完全超过WHERE
和ORDER BY
。这样可以防止计算所有行(在LIMIT
之前)并进行排序,然后再执行LIMIT
。
所以,你获得了4次加速:
c
)ORDER BY
按顺序传递它们)c
的数据BTree之间来回反弹)当你在这里时,考虑摆脱AUTO_INCREMENT
。抛出c_id
并更改
PRIMARY KEY (c_id),
UNIQUE KEY ct_mid_gid (m_id, group_id)
- >
PRIMARY KEY(m_id, group_id)
巧合的是,如果你这样做了,你的KEY index_ct_cid_sts_tsk (group_id,status,job_id)
会偶然发现完美的索引。这是因为PK隐式添加到任何辅助索引上,但您需要m_id
,不 c_id
。无论如何,我更喜欢明确。
进行更改时,丢弃任何冗余索引。例如,KEY index_ct_mid (m_id)
是无用的,因为它是另一个索引的开头。
答案 1 :(得分:0)
您是否在where子句中使用的列上创建了索引? 通过在列上添加索引来检查查询。
但请记住,如果添加索引然后在表上插入,更新和删除操作可能会变慢。