2011-03-13 4 views
1

각각 1 천만 개가 넘는 행을 가진 두 개의 테이블에 액세스하는 MySQL 쿼리를 어떻게 최적화 할 수 있습니까?1 천만 개가 넘는 행을 가진 MySQL 테이블 액세스 = 오류 : 너무 많은 연결

아래의 쿼리는 'guests'테이블에 존재하지 않는 'users'테이블의 모든 ID를 가져옵니다. 결과적으로 수십만 개의 행이 반환되므로 실행 당 최소한 5000 개의 ID를 얻도록 제한 할 것입니다. 이 작업을 더 효과적으로 수행 할 수 있도록 실행 당 더 많은 작업을 수행 할 수 있습니다.

$before = date here before in time; 
$now = date now; 

$query="SELECT users.id 
    FROM users 
    LEFT JOIN guests ON guests.id = users.id  
    WHERE guests.id IS NULL AND (users.in >= '$before' AND users.in <= '$now') 
    LIMIT 0,5000"; 

손님 테이블에 어떤 ID가 없는지 알게 된 후 사용자 테이블에서 해당 행을 삭제해야합니다. 즉, 이는이 ID를 모두 삭제하기 위해 또 다른 5000 개의 삭제 쿼리를 실행한다는 의미입니다.

10million 이상의 행이 포함 된 두 테이블 모두에서이 프로세스를 실행하면 서버가 연결이 너무 많아서 MySQL 서버를 다시 시작할 때까지 더 이상 액세스 할 수 없다는 오류가 반환됩니다. 그러나 몇 천 개의 행을 포함하는 두 테이블 모두에서 동일한 프로세스를 실행하면이 문제가 발생하지 않지만 여전히 약간의 시간이 걸립니다.

왜 이런 일이 발생하며 왜이 문제를 피하면서 동시에이 프로세스를 최적화 할 수 있습니까?

답변

1

2 가지 - 소프트웨어가 MySQL 연결을 처리하는 방법을 확인하십시오. 그것은 지속적인 연결을 연 다음 다시 사용하지 않는 것처럼 보이며 모든 쿼리 전에 새로운 연결이 있습니다.

두 번째 - 각 사용자에 대해 별도의 쿼리를 실행하는 대신 하나의 문에서 쿼리를 수정할 수 있습니다. 그런 식으로 단 하나의 연결이 필요하며, 모든 처리가 MySQL 측에서 이루어 지므로이를 더 이상 최적화 할 수 있습니다.

편집 : 확인할 수있는 또 다른 사항은 쿼리에 EXPLAIN을 실행하여 모든 적절한 인덱스가 설정되어 있는지 확인합니다 (선택 부분이 느리게 실행되는 경우).

+0

영구 연결을 사용하지 않습니다. boggles는 MySQL의 프로세스 목록에서 위에서 언급 한 주요 SQL 쿼리 다음에 많은 SELECT 쿼리가 있다는 것을 알 수 있습니다. 이 선택 쿼리는 게스트 테이블에서 ID를 선택합니다. LEFT JOIN 또는 JOIN 문이 하위 선택 쿼리를 수행합니까? LEFT JOIN이 "너무 많은 연결"오류의 원인 일 수 있습니까? – officeboi101

+0

@officeboi - 아니, 가능하지 않을 것입니다. 어떤 소프트웨어/언어/라이브러리를 사용하고 있습니까? 그것은 당신의 도서관이 별도의 선택을 통해 추가 정보를 검색하고있을 수 있습니다 ... 그리고 그것은 같은 lib 디렉토리가 여분의 연결을 일으킬 수 있습니다 ... – Sergey

0

경고 : 라이브 데이터를 실행하기 전에이 쿼리를 테스트하십시오. 나는 모든 데이터에 대한 책임은 귀하의 질문의 핵심에 관해서는

DELETE 
    u 
FROM 
    users AS u 
LEFT JOIN 
    guests AS g 
ON g.id = u.id 
WHERE 
    g.id IS NULL 
    AND (users.in >= '$before' AND users.in <= '$now') 

을 잃은 주장하지 않습니다 (너무 많은 연결) 나는 당신의 PHP 스크립트가 삭제 될 이제까지 ID에 대한 루프의 새로운 연결을 시작 생각한다.

+0

난 그냥 사용자 테이블에있는 ID를 얻을 간단한 PHP 테스트 스크립트를 만들지 않습니다 게스트 테이블에 존재하지 않습니다. 이것은 정상입니다 - 정상적인 연결 (지속성이 아님)을 사용하여 연결 한 다음 위의 SQL 쿼리를 사용하여 연결 한 다음 연결을 끊고 PHP를 사용하여 결과를 출력하십시오. 나는 여전히 "너무 많은 연결"오류를주는 동일한 문제가 발생했습니다. 나는 심지어 결과를 2500으로 제한했으며 여전히 동일합니다. 또한 스크립트가 실행되는 동안 아무도 MySQL DB에 액세스 할 수 없습니다. JOIN 문이 너무 많은 연결 오류를 일으키는 하위 선택을 수행 할 수 있습니까? – officeboi101

+0

아니요 하나의 쿼리는 하나의 연결 내에서 실행됩니다. 하위 쿼리 등에 대한 추가 연결을 만들지 않습니다. – Mchl

관련 문제