2012-10-04 5 views
0

4 억 개의 행을 가진 비표준 데이터베이스가 있습니다. 모든 반복 데이터를 새 정규화 데이터베이스로 이동 했으므로 ID로 나타낼 수 있습니다.거대한 비정규 화 된 mysql 데이터베이스 부분 2를 재구성하십시오.

이제 모든 데이터 항목을 이동하고 ID가있는 항목으로 변환해야합니다.

문제는 400m 행을 사용하면 다소 시간이 걸릴 것이므로 최적화하는 데 도움이 필요합니다.

이 쿼리는 행 당 0.4 초 소요, 그래서 몇 개월이 걸릴 것입니다 : 걸리는 것이이 방법을 좀 더 PHP를 사용하는 경우

INSERT IGNORE INTO normalized.entry (insDate, `date`, project, keyword, url, position, competition, serachEngine) 
SELECT 
CURDATE() as insDate 
, d.id as dateId 
, p.id as projectId 
, k.id as keywordId 
, z.id AS urlId 
, old.position 
, old.competition 
, s.id as searchEngineId 

FROM unnormalized.bigtable old 
INNER JOIN normalized.`date` d ON old.insDate = d.`date` 
INNER JOIN normalized.project p ON old.awrProject = p.project 
INNER JOIN normalized.searchEngine s ON old.searchEngine = s.searchEngine 
INNER JOIN normalized.keyword k ON old.keyword = k.keyword 
INNER JOIN normalized.urlHash z ON old.url = z.url 
WHERE old.id >= ".$start." AND old.id <= ".$stop.""; 

두 querys로 분할에만 0.07sec 항목 당하지만 여전히 걸립니다 또한 달의 :

$q = "SELECT tmp.id 
       , d.id as dateId 
       , p.id as projectId 
       , k.id as keywordId 
       , tmp.position 
       , tmp.competition 
       , s.id as searchEngineId 
       , tmp.url 
       , z.id AS urlId 
       FROM unnormalized.bigtable tmp 
     INNER JOIN normalized.`date` d ON tmp.insDate = d.`date` 
     INNER JOIN normalized.project p ON tmp.awrProject = p.project 
     INNER JOIN normalized.searchEngine s ON tmp.searchEngine = s.searchEngine 
     INNER JOIN normalized.keyword k ON tmp.keyword = k.keyword 
     INNER JOIN normalized.urlHash z ON tmp.url = z.url 
     WHERE tmp.id > ".$start." AND tmp.id < ".$stop.""; 
     // echo $q; 
      $result = mysql_query($q, $local); 
      if (mysql_num_rows($result) > 0) { 
      while ($row = mysql_fetch_array($result)) { 
      $q = "SELECT id FROM normalized.url WHERE url = '".$row["url"]."'"; 
      $resultUrl = mysql_query($q, $local); 
      $rowUrl = mysql_fetch_array($resultUrl); 

      $q = "INSERT IGNORE normalized.entry (insDate, `date`, project, keyword, url, position, competition, serachEngine) VALUES (NOW(), '".$row["dateId"]."', '".$row["projectId"]."', '".$row["keywordId"]."', '".$rowUrl["id"]."', '".$row["position"]."', '".$row["competition"]."', '".$row["searchEngineId"]."')"; 

나는 그것이 반년 복용하지 않고이 데이터거야 포트 얼마나 몰라! /모두 도움이 필요합니다.

사양 : RDS 아마존 서버에서 InnoDB를 사용하고 있습니다.

편집 :

ID, SELECT_TYPE, 테이블, 유형,이 possible_keys, 키,있는 key_len, 심판, 행 추가 1, SIMPLE, P, 인덱스, NULL, 프로젝트 이름, 42 : 첫 번째 쿼리의 SELECT를 EXPLAIN , NULL, 1346, "인덱스 사용" 1, SIMPLE, s, 인덱스, NULL, searchEngine, 42, NULL, 2336, "인덱스 사용, 조인 버퍼 사용" 1, SIMPLE, k, 인덱스, NULL, 키워드, 42 , NULL, 128567, "인덱스 사용, 조인 버퍼 사용" 1, SIMPLE, tmp, ref, "keyword_url_insDate, keyword, searchEngine, url, awrProject", keyword_url_insDate, 767, func, 115, "" 1, SIMPLE , d, eq_ref, 날짜, 날짜, 3, intradb.tmp.insDate, 1, "Where 사용, 색인 사용" 1, SIMPLE, z, ref, url, url, 767, bbointra db.tmp.(표를 rankingUrls201001 ( id INT (11) NOT NULL AUTO_INCREMENT, insDate 날짜 NOT NULL, keyword VARCHAR 만들기 ', 255

'rankingUrls201001 ': "인덱스를 사용하여'URL, 1,

SHOW CREATE TABLE을)) utf8_swedish_ci가 NULL NOT COLLATE) NULL NOT utf8_swedish_ci 대조) competition VARCHAR를 NULL NOT position INT (11 url VARCHAR (255 utf8_swedish_ci NOT NULL, searchEngine VARCHAR (25 부씩 (20) COLLATE utf8_swedish_ci은 NOT NULL이 awrProject VARCHAR (200) utf8_swedish_ci에게 NULL NOT 부씩 server VARCHAR (20) utf8_swedish_ci에게 NULL NOT 부씩 rank VARCHAR (40) utf8_swedish_ci에게 NULL NOT 부씩 PRIMARY KEY (id) keyword_url_insDate KEY (keyword, url, insDate) KEY keyword (keyword) KEY searchEngine (searchEngine) KEY url (url) KEY awrProject (awrProject) ) ENGINE = InnoDB AUTO_INCREMENT = 2266575 DEFAULT CHARSET = utf8 COLLATE = utf8_swedish_ci '

+0

테이블의 스키마는 무엇입니까? ('SHOW CREATE TABLE your_table'의 출력) – Jocelyn

+0

'EXPLAIN your_select_query' (질문에 첫 번째 INSERT 쿼리에서 사용 된 SELECT 쿼리)의 결과는 무엇입니까? – Jocelyn

+0

게시물 하단에 EXPLAIN 출력을 추가했습니다. –

답변

0

@Robin 데이터 전송 프로세스의 속도를 높이려면 모든 처리가 메모리 내에서 이루어 지도록 적절한 조치를 취해야합니다. 가능하면 디스크에 쓰기를하지 말아야합니다. 다음 단계를 수행하면 는 파일 전송 처리 시간을 단축해야합니다

  1. 첫째, 많은 임시 작업 공간이 가능한 할당하도록하여 DB 인스턴스를 구성합니다.

  2. 두 번째로, 프로세스를 여러 단계로 분할하여 각 단계가 최소 WRITE to disk 활동으로 완료되도록하십시오.

  3. 마지막으로 바이너리 로그를 비활성화하십시오. 이렇게하면 WRITE가 디스크 처리로 줄어들므로 대부분의 경우 쿼리 응답 시간을 최대 절반까지 줄일 수 있습니다.

이러한 단계를 수행하면 처리 속도가 빨라지지만 보유하고있는 데이터 행의 양을 고려하면 전송 및 처리하는 데 일정한 시간이 걸릴 수 있습니다.

관련 문제