目前尚不清楚为什么要重写查询以消除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追捕你,惩罚你,公开羞辱你,并且打败你。
当你有一个常量列表时,'in'很好。性能问题是存在子查询时。 –
当“IN”子句在主键/索引列上选择时,它几乎尽可能快,因为该行可以直接从索引获得,索引应该可以通过二进制搜索进行排序。 – Smutje
“在”和“存在”不一定做同样的事情。有两个时间和一个地方。获得正确的结果应该是至关重要的。那么你可以担心速度。 –