2009-10-24 5 views
0

난 그냥 느린 로그 (+ 인덱스를 사용하지 않는)를 사용할 수 내가 (만 user 변경)MySQL을 사용하지 않는 인덱스

SELECT id 
    , name 
    FROM `all` 
WHERE id NOT IN(SELECT id 
        FROM `picks` 
        WHERE user=999) 
ORDER BY name ASC; 

는 EXPLAIN 쿼리의 같은 종류에 대한 항목의 수백을 얻고 있습니다 :

+----+--------------------+-------------------+-------+------------------+--------+---------+------------+------+------------------------------------------+ 
| id | select_type  | table    | type | possible_keys | key | key_len | ref  | rows | Extra         | 
+----+--------------------+-------------------+-------+------------------+--------+---------+------------+------+------------------------------------------+ 
| 1 | PRIMARY   | all    | index | NULL    | name | 156  | NULL  | 209 | Using where; Using index; Using filesort | 
| 2 | DEPENDENT SUBQUERY | picks    | ref | user,user_2,pick | user_2 | 8  | const,func | 1 | Using where; Using index     | 
+----+--------------------+-------------------+-------+------------------+--------+---------+------------+------+------------------------------------------+ 

이 쿼리를 최적화하는 방법에 대한 아이디어가 있으십니까? 여러 필드를 가지고 있지만 다른 인덱스는 사용하지 않았습니다.

답변

0

'존재하지 않음'과 '존재'가 항상 좋지 않은 성능 선택 사항이라는 것에 반드시 동의하지 않지만이 상황에있을 수 있습니다.

당신은 훨씬 단순 쿼리를 사용하여 결과를 얻을 수 있습니다

SELECT id 
    , name 
    FROM `all` 
    , 'picks' 
WHERE all.id = picks.id 
    AND picks.user <> 999 
ORDER BY name ASC; 
+0

999를 제외하고 모든 사용자에게 속한 모든 선택 항목이 표시됩니다. 맞습니까? 쿼리가 수행하는 작업 (효율적인 방법은 아님)은 '사용 가능한'선택 목록을 가져 오는 중이지만 사용자가 이미 선택한 항목은 제거하는 것입니다. –

+0

이 쿼리는 'picks'에 일치하는 항목이없는 행에 대해서는 아무것도 반환하지 않고 원래 쿼리는 반환하지 않습니다. –

+0

간단한 수정으로 외부에서 조인하면됩니다. – northpole

0

성능에있어 "안함"및 "존재"는 항상 잘못된 선택입니다. 찌르는와 함께 할 수 있습니다 "NULL"더 시도해보십시오.

0

이 아마 쿼리를 작성하는 가장 좋은 방법입니다. all에서 모든 항목을 선택하고 iduser을 공유하는 picks의 일치하는 행을 찾으려면 999입니다. 그러한 행이 존재하지 않으면 picks.id은 왼쪽 외부 조인을 사용하기 때문에 NULL이됩니다. 그런 다음 결과를 필터링하여 해당 행만 반환 할 수 있습니다.

SELECT all.id, all.name 
FROM 
    all 
    LEFT JOIN picks ON picks.id=all.id AND picks.user=999 
WHERE picks.id IS NULL 
ORDER BY all.name ASC 
관련 문제