2016-10-19 2 views
0

MySQL에서는 테이블 t1의 행과 일부 조건이 충족되는 테이블 t2의 모든 관련 행을 삭제하려고합니다 (어떤 종류의 상태라고 말하기).JOIN DELETE 대신 MySQL에서 다중 DELETE 사용하기

DELETE t1 FROM t1 INNER JOIN t2 
WHERE t1.some_id = t2.some_id 
AND t1.status=3; 

을하지만 T1에서 참조 T2의 일부 매달려 데이터가 내가 (그것의 오래된 타격을 DB) 그것도을 삭제하려면 :

는 내가이 작업을 수행 할 수 있습니다 알고 있습니다. 나는 이것에 대한 외부 조인과 내부 조인과의 UNION을 수행 할 수 있다고 생각한다. 하지만 ID가 관련있는 약 10 개의 테이블에서 행을 삭제해야하기 때문에 더 복잡해집니다. 최종 결과는 미친 큰 질문이었습니다.

그래서 나는이 일을 결과 : 등등 모든 테이블에 대한

DELETE FROM t1 
WHERE status=3; 

DELETE FROM t2 
WHERE some_id NOT IN (SELECT some_ID FROM t1) 

DELETE FROM t3 
WHERE some_id NOT IN (SELECT some_ID FROM t2) 

하고 있습니다. 그렇게하면 모든 참조되지 않은 데이터가 제거되고 더 읽기 쉽습니다. 외래 키가 없으므로 테이블을 변경할 수 없다는 점에 유의하십시오 ("계단식 삭제"는 잊어 버려야 함).

그래서 잘못 되었나요? 내가 그랬던 것처럼 그것을하는 단점은 무엇입니까?

편집

감사합니다 : 테이블이 크고, T1은 절반 만 행이, T2는 3 백만 행, 8 개 다른 테이블보다 절반 만이있다. 그러나 나는 또한 많은 데이터를 삭제하고 있는데, 약 75 %입니다.

편집 2 : Ok 예를 들어 설명하지 않고 실물을 보여 드리겠습니다. osTicket에서 250000 개의 오래된 티켓을 삭제 한 것입니다 (백업 한 후).

DELETE ticket, thread, event, cdata, user, email, email_info 
FROM  ost_ticket   AS ticket 
INNER JOIN ost_ticket_thread  AS thread 
INNER JOIN ost_ticket_event  AS event 
INNER JOIN ost_ticket__cdata  AS cdata 
INNER JOIN ost_user    AS user 
INNER JOIN ost_user_email  AS email 
INNER JOIN ost_ticket_email_info AS email_info 
WHERE ticket.ticket_id = thread.ticket_id 
AND ticket.ticket_id = event.ticket_id 
AND ticket.ticket_id = cdata.ticket_id 
AND ticket.user_id = user.id 
AND ticket.user_id = email.user_id 
AND thread.id  = email_info.thread_id 
AND ticket.status_id=3 
AND (ticket.closed < DATE_SUB(NOW(), INTERVAL 30 DAY)); 

만 7 개 테이블을 제거합니다 그건, 내가 적어도 2 ~ 3 개 테이블을 추가해야합니다 : VM을에서 작업

, 내가 먼저 시도. 아마도 더. 실행에 15 분이 걸리고 여기에 참조되지 않은 많은 데이터가 남습니다.

은 그럼 그것은 모든 데이터를 받아 실행 8 분 정도 걸립니다

START TRANSACTION; 
DELETE FROM ost_ticket WHERE status_id=3 AND (closed < DATE_SUB(NOW(), INTERVAL 30 DAY)); 
DELETE FROM ost_ticket_thread WHERE ticket_id NOT IN (SELECT ticket_id FROM ost_ticket); 
DELETE FROM ost_ticket_event WHERE ticket_id NOT IN (SELECT ticket_id FROM ost_ticket); 
DELETE FROM ost_ticket__cdata WHERE ticket_id NOT IN (SELECT ticket_id FROM ost_ticket); 
DELETE FROM ost_user WHERE id NOT IN (SELECT DISTINCT user_id FROM ost_ticket); 
DELETE FROM ost_user_email WHERE user_id NOT IN (SELECT id FROM ost_user); 
DELETE FROM ost_ticket_email_info WHERE thread_id NOT IN (SELECT id FROM ost_ticket_thread); 
COMMIT; 

(상쾌 VM에서)이 함께했다.

+0

마음에 오는 유일한 단점은 문제가되는 경우 원자 트랜잭션으로 처리하지 않는다는 것입니다. 데이터베이스의 나이/상태가 트랜잭션 무결성과 같은 것임을 감안할 때 make 또는 break가 아닙니다. 아마도 다른 사람들과 아이디어가있을 것입니다. – mba12

+0

그런 식으로 문제가 발생하지 않습니다. – CptMisery

+0

다중 테이블 삭제가 있습니다. [docs] (http://dev.mysql.com/doc/refman/5.7/en/delete.html) – Uueerdo

답변

0

3 개의 별도 DELETE 쿼리에서 잘못하지는 않습니다. 장점 :

  • (테이블이 큰 경우)이 무거운 할 어쩌려 구`t
  • 조인 더 읽기 - 경우에 따라서는 더 빨리

단점 실행할 수 있습니다 :

  • 을 테이블이 큰 경우 두 번째 및 세 번째 쿼리가 느려질 수 있습니다. 하위 쿼리 선택은 많은 데이터를 반환하기 때문에 ....
  • 삭제 될 수 있습니다. 하나가 아닌 3 단계 - 첫 번째 삭제 쿼리 후 t2 및 t3에 데이터가 있고 두 번째 삭제 후 t3에 데이터가 있음을 의미합니다.당신이 왼쪽 행보다 T1적은 행을 삭제하는 경우

    DELETE FROM t3 
    WHERE some_id IN (SELECT some_ID FROM t2 
    WHERE some_id IN (SELECT some_ID FROM t1 WHERE status=3)) 
    
    DELETE FROM t2 
    WHERE some_id IN (SELECT some_ID FROM t1 WHERE status=3) 
    
    DELETE FROM t1 
    WHERE status=3; 
    

    : 어떤 응용 프로그램에 따라하는 것은 좀 더 최적의 방법에 대한 조언을 할

좋은 또는하지 않을 수 있습니다 t1 (삭제 후)이 주문은 더 빠릅니다. 위의 삭제가 t1에 의존하기 때문에 마지막 쿼리의 t1에서 삭제하는 것을 잊지 마십시오. 그러나이 순서는 계단식 삭제 (t1 및 t2와 관련된 행이 t2 및 t3과 관련이있는 경우) 일 때만 유효합니다.

+1

나는 긍정적이지는 않지만 그 순서대로 질의를 수행 할 때't3' delete에서'NOT IN'을 원한다고 생각하지 않는다. 너? – Uueerdo

+0

예, 고맙습니다. 변경하는 것을 잊어 버렸습니다. 이제 괜찮습니다. – krasipenkov

+0

3 개의 테이블로 나쁘지는 않지만 약 10 개의 테이블로 무거워집니다. – SomeDudeWithCode

0

이 경우 다중 테이블 삭제 구문을 사용하는 것이 특히 잘못 되었습니까?

DELETE t1, t2, t3 
FROM t1 
INNER JOIN t2 ON t1.some_ID = t2.some_ID 
INNER JOIN t3 ON t2.some_ID = t3.some_ID 
WHERE t1.status=3 
; 

외래 키가있는 경우 행 참조 전에 참조 된 행을 삭제할 때 문제가 발생할 수 있음을 알고 있습니다. 그러나 당신은 당신이 그것들을 가지고 있지 않다고 말했다.