[英]mysql query with several subquery optimization
Considering that analisi_campo_free is a table with about 1 million rows, is there a lighter way to write this query for mysql? 考虑到analisi_campo_free是一个约有100万行的表,是否有更简便的方法来编写针对mysql的查询?
select distinct ID_ANALISI from analisi_campo_free
where 1=1
and ID_ANALISI IN ( select ID_ANALISI from analisi_campo_free acf inner join campo_free cf on acf.id_campo_free = cf.id_campo_free where posizione = 1 and valore = '06/11/2015')
and ID_ANALISI IN ( select ID_ANALISI from analisi_campo_free acf inner join campo_free cf on acf.id_campo_free = cf.id_campo_free where posizione = 3 AND valore='vvvvvv');
Thanks 谢谢
The query 查询
select distinct ID_ANALISI from analisi_campo_free
where 1=1
and ID_ANALISI IN ( select ID_ANALISI from analisi_campo_free acf inner join campo_free cf on acf.id_campo_free = cf.id_campo_free where posizione = 1 and valore like 'irene%')
and ID_ANALISI IN ( select ID_ANALISI from analisi_campo_free acf inner join campo_free cf on acf.id_campo_free = cf.id_campo_free where posizione = 3 AND valore like 'antonio%');
require about 2.3 seconds with this explain 大约需要2.3秒
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE cf index PRIMARY ID_LABORATORIO 4 6 16.67 Using where; Using index; Using temporary; Start temporary
1 SIMPLE cf index PRIMARY ID_LABORATORIO 4 6 16.67 Using where; Using index; Using join buffer (Block Nested Loop)
1 SIMPLE acf ALL ID_ANALISI,FK_ANALISI_CAMPO_FREE_CAMPO_FREE 1054163 11.11 Using where; Using join buffer (Block Nested Loop)
1 SIMPLE acf eq_ref ID_ANALISI,FK_ANALISI_CAMPO_FREE_CAMPO_FREE ID_ANALISI 5 elettroforesi.acf.ID_ANALISI,elettroforesi.cf.ID_CAMPO_FREE 1 11.11 Using where
1 SIMPLE analisi_campo_free ref ID_ANALISI ID_ANALISI 4 elettroforesi.acf.ID_ANALISI 1 100 Using index; End temporary
The query 查询
SELECT acf.ID_ANALISI, COUNT(DISTINCT cf.posizione, acf.valore) AS matches
FROM analisi_campo_free AS acf
INNER JOIN campo_free AS cf ON acf.id_campo_free = cf.id_campo_free
WHERE (posizione = 1 AND valore like 'irene%')
OR (posizione = 3 AND valore like 'antonio%')
GROUP BY acf.ID_ANALISI
HAVING matches = 2;
requires about 1.3 seconds with this explain 大约需要1.3秒
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE cf index PRIMARY ID_LABORATORIO 4 6 30.56 Using where; Using index; Using temporary; Using filesort
1 SIMPLE acf ALL ID_ANALISI,FK_ANALISI_CAMPO_FREE_CAMPO_FREE 1054163 20.99 Range checked for each record (index map: 0x6)
The index are: 索引是:
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
analisi_campo_free 0 PRIMARY 1 ID_ANALISI_CAMPO_FREE A 1054159 BTREE
analisi_campo_free 0 ID_ANALISI 1 ID_ANALISI A 1049622 BTREE
analisi_campo_free 0 ID_ANALISI 2 ID_CAMPO_FREE A 1049622 BTREE
analisi_campo_free 1 FK_ANALISI_CAMPO_FREE_CAMPO_FREE 1 ID_CAMPO_FREE A 1 BTREE
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
campo_free 0 PRIMARY 1 ID_CAMPO_FREE A 6 BTREE
campo_free 0 DESCRIZIONE 1 DESCRIZIONE A 6 BTREE
campo_free 0 ID_LABORATORIO 1 ID_LABORATORIO A 1 BTREE
campo_free 0 ID_LABORATORIO 2 POSIZIONE A 6 BTREE
campo_free 0 ID_LABORATORIO 3 UTILIZZATO A 6 YES BTREE
I have not considered the query with couples because now I know I need a like. 我没有考虑过夫妇的问题,因为现在我知道我需要一个喜欢的人。 At the end maybe I will use my first query because is simplier to translate in querydsl. 最后,也许我将使用我的第一个查询,因为这样可以更轻松地在querydsl中进行翻译。 Thanks for your help 谢谢你的帮助
You could use: 您可以使用:
SELECT ID_ANALISI
FROM analisi_campo_free acf
JOIN campo_free cf
ON acf.id_campo_free = cf.id_campo_free
WHERE (posizione,valore) IN ((1,'06/11/2015'),(3,'vvvvvv'))
GROUP BY ID_ANALSI
HAVING SUM(posizione = 1 AND valore = '06/11/2015') > 0
AND SUM(posizione = 3 AND valore='vvvvvv') > 0;
Subqueries in WHERE clauses are usually poor performers in MySQL, especially CORRELATED subqueries. WHERE子句中的子查询通常在MySQL中表现不佳,尤其是CORRELATED子查询。 This finds the associated campo_free
records and counts the distinct posizone, valore pairs that match the criteria. 这将找到相关的campo_free
记录,并计算与条件匹配的不同的posizone,valore对。 The HAVING insures only the ID_ANALISI that have both are in the results. HAVING确保仅ID_ANALISI都包含在结果中。
SELECT acf.ID_ANALISI, COUNT(DISTINCT cf.posizone, cf.valore) AS matches
FROM analisi_campo_free AS acf
INNER JOIN campo_free AS cf ON acf.id_campo_free = cf.id_campo_free
WHERE (posizione = 1 AND valore = '06/11/2015')
OR (posizione = 3 AND valore='vvvvvv');
GROUP BY acf.ID_ANALISI
HAVING matches = 2
;
Without the DISTINCT in COUNT; COUNT中没有DISTINCT; if posizone, valore pairs are not unique for each id_campo_free values, ID_ANALISI with two (1,'6/11/2015') or (3,'vvvvvv') matches could also be included in the final results. 如果对于每个id_campo_free值,posiozone,valore对不是唯一的,则具有两个(1,'6/11/2015')或(3,'vvvvvv')匹配的ID_ANALISI也可以包含在最终结果中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.