2016-05-18 39 views
1

考虑到analisi_campo_free是一个包含大约100万行的表, 有没有一种比较简单的方式来为mysql写这个查询?有多个子查询优化的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'); 

感谢


查询

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%'); 

需要与此有关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 

查询

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; 

需要约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) 

的指标是:

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  

我还没有考虑过情侣的查询,因为现在我知道我需要一个像。 最后,也许我会使用我的第一个查询,因为在querydsl中进行翻译更简单。 感谢您的帮助

+0

性能问题应该包括'EXPLAIN ANALYZE'和一些关于表格大小,索引,当前时间表现,期望时间等的信息。'Slow'是一个相对术语,我们需要一个真正的值来比较。 [** MySQL **](http://dba.stackexchange.com/questions/15371/how-do-i-get-the-execution-plan-for-a-view) –

+0

@JuanCarlosOropeza所以你是告诉我,如果不查看解释中的值,就无法找到更好的方式来编写有问题的查询? *讽刺地鼓掌* –

+0

@RahulSharma优化最重要的部分是指数。所以你可以花80%的时间来解决5%的问题。但我宁愿有效地工作。你可以检查'Lad'答案,这是一个很好的解决方案,但是如果索引不合适,仍然会有不好的性能。 –

回答

1

你可以使用:

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; 
+0

这不会返回相同的结果,因为它将外部“与”更改为“或”。 – Uueerdo

+0

@Uueerdo好点,固定。 – lad2025

1

在子查询的WHERE子句通常是在MySQL中表现不佳,特别是相关子查询。这将查找关联的campo_free记录并计算与条件匹配的不同的posizone,valore对。 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 
; 

COUNT中没有DISTINCT;如果是posizone,则valore对对于每个id_campo_free值都不唯一,具有两个(1,'6/11/2015')或(3,'vvvvvv')匹配的ID_ANALISI也可以包含在最终结果中。