2013-05-31 2 views
3

나는 두 가지 테이블을 가지고있다 : 음식과 무언가.mySQL 삭제 쿼리 최적화

  • , FOOS는
  • MOOS는 외래 키

, FOOS로 foos.id (기록의 수백만) 매우 큰있다 시작일에 색인이 생성됩니다. 무스가 아닙니다 (100k 레코드).

나는 다소 간단한 작업이 필요합니다 : start_date가 < 인 foos에서 레코드를 삭제하고 moos에서 참조하지 마십시오. 나는 너무 특정 문제가 아니라 희망,하지만 난 그냥 (이 영원히 중단) 내가 될 것 "일반적인"방법을 생각했던 시도 동작하지 않습니다 :

delete foos FROM foos LEFT JOIN moos ON foos.id = moos.foo_id WHERE moos.foo_id is null AND foos.start_date < "2013-05-30"; 

delete foos FROM foos WHERE start_date < "2013-05-30" AND id NOT IN (select foo_id from moos where foo_id is not null); 

내가 추가해야을 :

  • 내가 시작일 < X와 MOOS의 수를 알 수 있도록 항상 X를 선택은

  • 몇 천 MOOS가 foo는 참조 (<> 200/300K 기록) 크지 않다

  • 나는 MySQL의 5.5에 그래서 내가 의해 교체 할 때이 "삭제"하지만 설명 MySQL을 내가 무슨 생각을하고있는 제안 "1 선택"설명 할 수없는 오전는 것 다음 START_DATE 지수

    • 처음 사용 올바른 FOOS
    • 을 찾을 수
    • 다음

이 작업을 수행 할 수있는 더 나은 방법이 있나요 ... 이 그래서 그런 "긴"거래 안 MOOS보고, 또는 뭔가를 놓친 거지?

감사합니다,

PJ에 대한

+0

moos.foo_id가 null입니까? 왜 null 필드에 합류하는지 –

+0

내가 따라 올지 모르겠다 - 왼쪽 조인이므로 문제가되지 않아야한다. – PJC

+0

start_date에 인덱스가 있습니까? – neutrino

답변

0

어떻게 ...

CREATE TABLE foos_new 
SELECT * 
FROM 
    foos 
LEFT JOIN moos on foos.id = moos.foo_id 
WHERE 
    moos.foo_id IS NOT NULL 
    OR 
    (
     moos.foo_id IS NULL AND 
     foos.start_date >= "2013-05-30" 
    ); 

그런 다음 원래 테이블을 삭제하고, FOOS에 새 이름을 바꿉니다. 물론 모든 인덱스를 추가하십시오.

+0

Thanks George. 하지만 그것은 훨씬 더 나아질 것이라고 확신하지 못합니다. - 수백만 개의 레코드를 복제하는 것을 의미합니다 ... – PJC

+0

실험 할 공간이 있다면,이 접근법으로 이해할 수있는 것처럼 무언가보다 더 많은 순차적 쓰기가 가능합니다. 빠르다. – George

0

또 다른 생각 : 경우와 계단식 삭제를하고있는 경우

외부 키는 문제가 될 수 그것은 또한 이제 고아 기록이 있는지 무을 확인해야합니다 foo는에서 삭제마다. 예, 일치하지 않는 항목 만 삭제할 필요는 없지만 쿼리 계획자는 그다지 똑똑하지 않을 수 있습니다.

+0

예, 쿼리 플래너에 뭔가 있어야합니다. 내가 삭제 쿼리를 설명하기 위해 5.6 설치를 시도하고 찾을 필요가 있다고 생각합니다. – PJC

0

은 NULL이 아니기 때문에 foos.id = moos.foo_id이 작동하기 때문에 쿼리 # 1이 작동하지 않습니다. NULL을 포함하는 것과 비교 된 NULL은 false입니다. 그리고 and moos.foo_id is null을 추가하면 조건과 일치하는 레코드가 생성되지 않습니다.

쿼리 # 2가 작동하지 않는 이유는 없습니다. select foo_id from moos where foo_id is not null은 얼마 동안 운영됩니까? 거기에 distinct BTW를 추가합니다.

쿼리 # 2는 또한 내가 foo_id에 Moos의 테이블에 인덱스를 추가 결국

delete foos FROM foos 
WHERE start_date < "2013-05-30" 
    AND exists (select foo_id from moos where foo_id = foos.id); 
+0

빅터에게 감사드립니다. 귀하의 첫 번째 의견 비록 : 그것은 꽤 있기 때문에 그것은 왼쪽 된 조인 작품 확신합니다. Cf 여기에 예 : http://www.w3schools.com/sql/sql_join_left.asp – PJC

+0

어, 네, 그것은 외부 조인을 위해 작동합니다. 하위 쿼리 실행 시간을 알려주고 쿼리가 제대로 작동했는지 확인하십시오. –

0

같이 다시 작성할 수 있으며 문제를 해결했다. 나는 왜 그것이 정직 할 필요가 있는지 확신하지 못한다. (Moos는 큰 테이블이 아니라고 생각한다.) ...

도움을 주셔서 감사합니다.

PJ