2012-04-28 2 views
2

나는 700,000 개의 mysql 쿼리를 반복하지 않고도 데이터 집합을 수집하는 방법을 찾으려고합니다.제한된 그룹화 된 서브 세트를 모으기위한 서브 쿼리

내가

ip unique varchar(20), 
most_recent datetime, 
count (int) 

users

id autoincrement, 
time timestamp, 
username varchar(200), 
email varchar(100), 
ip varchar(20) 

uniq_ip 두 테이블

users이 25 개 백만 행을 가지고 있으며, 그들이 사이트에서 작업하는 사용자의 활동을 기록합니다. uniq_ip에는 모든 IP 번호 목록과 사용자에게 나열되는 횟수 (트리거 업데이트시)가 있습니다.

백일향 코드를 코딩하는 동안 uniq_ip에서 모든 IP 목록을 가져 와서 반복하여 각 IP에 대해 최신 2000 레코드를 얻습니다. uniq_ip가 70 개 행이,이 루프는 내가 IP를 각각 가장 최근의 2000 목록을 사로 잡고 단일 쿼리를 얻으려고

select * from users where ip = '$outerloopip' order by `time` desc limit 2000; 

사용, 70 만 쿼리가 총 제작, 정말 불쾌한입니다. 1.2.3.4가 10,000 번 나열되면 시간 필드를 기준으로 가장 최근의 2000을 원합니다.

아이디어 하나의 쿼리에서 어떻게 할 수 있습니까?

답변

1

이전 답변에 대해 사과하고 업데이트 된 질문을 다시 읽고 적용했습니다. 내가보고 싶었던 가장 최근의 2000 IP 주소만을 원한다고 생각했습니다. 어쨌든,이 사람은 모든 IP 주소를 수행하고 IP 당 총 레코드 수를 가장 최근에 2,000 개의 항목으로 제한합니다. 난 당신이 그런

에 대한 인덱스 (IP, TIME DESC)

을 보장 것,이 쿼리를 시도합니다. 내가 분명히 놓쳤던 중요한 것. HAVING 절은 group-by 또는 order-by 절 다음에 적용됩니다. 따라서 데이터는 IP 주소와 날짜/시간 DESCENDING 순서로 미리 반환되고 @sql 변수가 적용됩니다. 레코드가 수식되고 READY가 최종 결과 집합에 추가되면 HAVING 절이 적용됩니다. 그 순간에 시퀀스 카운터를보고 2000보다 큰 경우 던져 버리고 다음 레코드로 넘어갑니다.

내 원래의 쿼리를 통해 모든 것을 저장하고 두 번째 사이클을 반복하며 디스크 공간을 날려 버리는 이유 인 2000보다 큰 파일을 쫓아 냈습니다.

select 
     U.*, 
     @LastSeq := IF(@LastIP = U.IP, @LastSeq +1, 1) as IPSequence, 
     @LastIP := U.IP as carryForNextRecord 
    from 
     (select @LastIP := '', @LastSeq := 0) sqlvars, 
     Users U 
    order by 
     U.IP, 
     U.time DESC 
    having 
     IPSequence <= 2000 
+0

나는 MySQL의에 아이들이 내 모든 음식을 먹고 마친 순간이 떨어질 수 있습니다. 이 테이블은 1 년 넘은 모든 데이터를 삭제하므로 문제가되지 않습니다. 이 테이블은 현재 2 천 5 백만 행 (약 8 천만 명으로 줄어들 것입니다)이지만, Redis ZSET 데이터 세트를 업데이트하기 위해 일주일에 한 번만 실행됩니다. – pedigree

+0

몇 가지 추가 드라이브 공간을 넣고 다시 시도해야합니다 .- 질문 : tmp 드라이브가 고갈되기 전에 쿼리가 11GB 사용자 테이블에서 80GB의 임시 SQL 파일을 생성 할 수있었습니다. – pedigree

+0

@pedigree, 소리가 나지 않습니다. 맞아 ... 웃음 소리 만 들으면 시나리오를 테스트하고 2000 카운트를 바꾸어서 50 또는 100을 말하면서 그 개념을 테스트합니다. – DRapp

0
SELECT ip as IP , 
    (SELECT GROUP_CONCAT(time)  FROM users WHERE ip = IP ORDER BY time DESC LIMIT 2000) as Time, 
    (SELECT GROUP_CONCAT(username) FROM users WHERE ip = IP ORDER BY time DESC LIMIT 2000) as UserName, 
    (SELECT GROUP_CONCAT(email) FROM users WHERE ip = IP ORDER BY time DESC LIMIT 2000) as Email 
FROM uniq_id 
+0

이것은 각 ip에 대해 1 행이지만 쉼표로 구분 된 시간, 사용자 이름 및 전자 메일 –