2014-02-16 26 views
1

我怎么能“转换”这个查询中未使用,我读到的是缓慢比较它存在如何使用EXIST,而不是在使用MySQL的

SELECT * FROM kx_examenes_diagnostico.examenes t1 WHERE NOT EXISTS (
SELECT * FROM kx_examenes_diagnostico.examenes_aplicados t2 WHERE t2.alumno_id=812 AND t2.examen_id=t1.examen_id 
) AND t1.examen_id IN (1,2,3,4,5,10,11,12,13,,50,159,635,456,780,12,63,45); 

使用MySQL的IM,我不知道如何我可以使用存在与我比较的价值(在子句内)我必须使用OR's吗?有可能吗?

谢谢

+5

当你有一个常量列表时,'in'很好。性能问题是存在子查询时。 –

+1

当“IN”子句在主键/索引列上选择时,它几乎尽可能快,因为该行可以直接从索引获得,索引应该可以通过二进制搜索进行排序。 – Smutje

+0

“在”和“存在”不一定做同样的事情。有两个时间和一个地方。获得正确的结果应该是至关重要的。那么你可以担心速度。 –

回答

2

目前尚不清楚为什么要重写查询以消除IN列表。该查询可以被重写以取代col IN (literal list)谓词,但这不会提高性能。


如果您正在寻找提高性能,它更可能你会想消除

NOT EXISTS (correlated_subquery) 

谓词,并使用“反连接”模式取代它,这样的事情:

SELECT t1.* 
    FROM kx_examenes_diagnostico.examenes t1 
    LEFT 
    JOIN kx_examenes_diagnostico.examenes_aplicados t2 
    ON t2.examen_id=t1.examen_id 
    AND t2.alumno_id=812 
WHERE t1.examen_id IN (1,2,3,4,5,10,11,12,13,50,159,635,456,780,12,63,45) 
    AND t2.examen_id IS NULL 

“抗连接”模式是一个外连接(包括来自t1行不具有在t2任何匹配的行)与predic组合ate(WHERE子句)消除了确实匹配的行。

对于这个特定的查询的最佳性能,你很可能要指标

... ON examenes (examen_id) 

... ON examenes_aplicados (examen_id, alumno_id) 

根据alumno_id列的基数,该指数可能会更好:

... ON examenes_aplicados (alumno_id, examen_id) 

无论是那些examenes_aplicados上的两个索引是“覆盖索引”,这意味着MySQL可以通过访问索引页满足查询,而不需要访问基础表中的页面。我们预计MySQL EXPLAIN会显示“Using index”来访问该表。


UPDATE:

我避而不答你提出的问题,并回答了完全不同的问题。回答您提问的问题:

问:我必须使用OR吗?

不,您不必使用OR关键字。 IN列表可以替换为不使用任何OR关键字的等效谓词。

问:有可能吗?

是的,可以用EXISTS子句替代IN (list)谓词。但是你做而不是想要这样做,除非你的目标是可怕的表现,而且你有渴望让DBA追捕你,惩罚你,公开羞辱你,并且打败你。