2014-02-16 84 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追捕你,懲罰你,公開羞辱你,並且打敗你。