2012-01-24 3 views
0

두 개의 테이블이 있는데, 하나는 사용자 세션을 저장하고 다른 하나는 장바구니 데이터를 저장합니다. sessions에는 테이블의 해당 id과 일치하는 cart_id 열이 있습니다. 내 데이터베이스 기반 세션에서 가비지 수집을 실행하려고합니다. 그 cart_id이 하나와 일치하는 세션이 없습니다,슬로우 가비지 수집 쿼리

DELETE FROM sessions WHERE expires < NOW(); 

그리고, 지금 즉, 고아 카트를 삭제 : 우선 내가 만료 세션을 삭제합니다.

DELETE `carts` 
FROM `carts` 
LEFT OUTER JOIN `sessions` 
ON `carts`.`id` = `sessions`.`cart_id` 
WHERE `sessions`.`cart_id` IS NULL 

이 마지막 쿼리는 종류가 느린 60 초를 초과하는 매우 느립니다. 내가 대신 일을 시도했습니다

:

또한 느린
DELETE `cart` 
FROM `cart` 
WHERE `cart`.`id` NOT IN (SELECT `cart_id` FROM `sessions`) 

. 어떤 포인터?

+0

'sessions.cart_id'에 대한 색인이 있습니까? –

+0

색인이 없습니다. 그게 내 문제 일세, 응? * 쉰 목소리로 물러서서 인덱스에 대한 설명서를 읽으십시오 * – Rob

+0

조인을 위해 (정기적으로) 사용하는 열에 인덱스가 꼭 필요합니다. –

답변

1

sessions.expires 및 sessions.cart_id 열의 색인이 생성되었는지 확인하십시오.

트래픽이 많은 사이트가 있고 많은 카트/세션을 추가하는 경우 병행 성으로 인해 삭제 작업이 느려집니다.

당신은 항상 당신이 세션의 많은 경우 매우 느려질 수 게시 한 마지막 작업합니다 (IN 가까이 한 각 ID를 하나씩 비교해야합니다.)

엄지 손가락의 규칙을 IN 문을 사용하는 경우 : IN 값은 상대적으로 작아야합니다.

+0

그의 쿼리가 좋습니다. 왜 다르게 생각하니? –

+0

MySQL 삭제 쿼리 명세 ('DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name' ...)는 FROM 문 앞에 테이블 이름을 나열하지 않습니다. –

+0

오, 내 나쁜 ypercube, 그냥 내가 대답에서 참조했던 쿼리를 지정하지 않았다. –

2

주위를 뒤집을 수 있습니다. 각각 장바구니을 통해 참조하고 ON DELETE CASCADE을 설정하자. 이렇게하면 세션에있는 행을 삭제하면 해당 장바구니도 삭제됩니다.

CREATE TABLE session (session_id INT NOT NULL, 
         expires DATE NOT NULL, 
        PRIMARY KEY (session_id), 
        INDEX expires_index (expires) 
) ENGINE=INNODB;       

CREATE TABLE cart (id INT, 
        session_id INT, 
        INDEX session_index (session_id), 
        FOREIGN KEY (session_id) REFERENCES session(session_id) ON DELETE CASCADE 
) ENGINE=INNODB; 

당신이제한와 더 자주 더 작은 삭제를 할 모든 카트 만료 삭제하려면 너무 많은 시간이 걸리는 것을 발견합니다.

DELETE FROM session WHERE expires < NOW() ORDER BY expires LIMIT 10;