2017-01-27 9 views
0

공유 호스트 서버에서 AWS 설정 (Apache/PHP의 경우 EC2, MySQL의 경우 RDS)으로 전환 할 계획입니다.MyISAM -> InnoDB 후 AWS로 이동

공유 서버에서 1 년 이상 베타 버전의 php/mysql 사이트를 실행했습니다. 특히 한 페이지는 항상 브라우저에서 빠르게 실행되었습니다 (아마 < 3 초가 완전히로드 됨).

이동을 준비하면서 데이터베이스와 모든 테이블을 MyISAM에서 InnoDB로 변경했습니다. 또한 기본 문자 집합을 utf8mb4 (latin-1 또는 뭔가)로 설정하고 데이터 정렬을 utf8mb4_unicode_ci로 전환했습니다. varchar2 (400)와 같은 몇 가지 열이 있는데 이는> 191 문자 오류가있는 색인이 생성되었습니다 (utf8mb4로 3byte -> 4byte에서 이동했기 때문입니다). 들어가서 수동으로 열을 UTF-8/utf_unicode_ci로 전환했습니다. EVerything ok (명백한 오류 없음)

이제 사이트/DB의 복사본을 AWS로 옮겼습니다. 대부분의 페이지가 잘로드됩니다. 특히이로드는 영원히로드됩니다 (> 5 분). 꽤 작은 EC2 인스턴스와 RDS 인스턴스가 있으므로 문제가 될 수 있다는 것을 알았지 만 사이트를 사용하는 유일한 쿼리이며 전체 데이터베이스는 < 70MB입니다.

Explain plan을 실행하면 대부분의 경우 키 (인덱스)가 사용되며 74K 행을 가진 하나의 "derived"테이블이 사용됩니다. 74k는 매우 작은 데이터 세트입니다. 필자는 오라클이 계획을 설명하는 것에 훨씬 더 익숙하므로 어떤 일이 일어나고 있는지 파악하기가 어렵습니다.

공유 호스팅 서버에서 원본 페이지를 실행하려고 시도했지만 속도가 너무 느려졌습니다! 따라서 AWS 문제라고 생각할 이유가 없습니다.

간단한 시나리오에서 MyISAM이 조금 더 빠르다는 것을 알고 있지만 InnoDB를 새로 사용했을 때보 다 10000000000000x 빠를 방법이 없습니다.

191 자 이상의 varchars를 색인화하려고 시도한 변환에 문제가 있습니까? 시스템/테이블이 어떻게 든 부러 졌을 가능성이 있습니까? 당신이 그들에게 많은 시간을 주면 질의가 끝나 겠지만, 천천히해야 할 길은 없습니다. 나는 인덱스가 튀겨 지더라도 74K 줄에서 전체 테이블 스캔을하고 있었지만 땀을 흘리지 않아야한다고 생각했습니다.

생각하십니까?

편집 : 이 https://dba.stackexchange.com/questions/75091/why-are-simple-selects-on-innodb-100x-slower-than-on-myisam 포스터가 비슷한 둔화 경험을 갖고있는 것 같아요 : 이 스레드를 발견. 나는 그/그녀와 같은 해결책을 사용할 수 없다. 내가 반환하고자하는 모든 열을 색인에 넣어야한다고 생각하는 것은 정신 나간다. 이것이 모든 사람들이 받아들이는 어떤 방법도 아닙니다.

+0

[_ 많은 전환 도움말 _] (https://mariadb.com/kb/en/mariadb/converting-tables-from-myisam-to-innodb/). –

답변

0

좋아, 알아 냈어. 내 잘못이었습니다 (놀라운 것은 아닙니다). 나는 내가 무엇을하고 있는지를 정말로 알기도 전에 오랜 시간 전에 질의를 썼다. 나는 그것이 존재한다면 기본적으로 A의 위치를 ​​사용하지만,없는 경우는 다시 B의 위치에 떨어 원

TableA (main table of focus) 
    aID (pk) 
    bID (fk) 
    locationID (fk) 
    rowTitle 

TableB 
    bID (pk) 
    locationID (fk) 

TableLocations 
    locationID (pk) 
    locationName 

: 쿼리 같은 것을 보았다

개선의 여지가 ... 확실히 있었다. (A는 항상 B와 연결됩니다).

내가

SELECT 
    rowTitle, 
    locationName 
FROM 
    TableA a, TableB b, TableLocations loc 
WHERE 
    a.bID = b.bID 
    AND 
    (a.locationID = loc.locationID 
    OR 
    (a.locationID IS NULL AND b.locationID = loc.locationID) 
) 

과 같은 몇 가지를하고 있었는데 그것은 괜찮 았는데 항상의 MyISAM을 사용하면 내가 원하는 것을 돌려 보냈다. 그리고 그것은 매우 빨랐습니다.그러나, 어떤 이유로 InnoDB로 옮겼을 때 sh $ &이 벽에 부딪쳤다. 이 쿼리에 대한 계획을 실행할 때 엔진이 어떻게 다른지에 대한 단서가 없습니다. 어느 시점에서 데이터 세트가 충분히 커지면 MyISAM은 막혔을 것입니다. 그러나 아직 데이터가 작기 때문에 데이터가 작습니다.

내가 있기 때문에 더 나은처럼 구조적으로 뭔가로 이동했습니다

SELECT 
    rowTitle 
    CASE WHEN loc1.locationID IS NOT NULL THEN loc1.locationName 
     WHEN loc2.locationID IS NOT NULL THEN loc2.locationName 
    END as locationName 
FROM 
    TableA a 
JOIN TableB b ON a.bID = b.bID 
LEFT OUTER JOIN TableLocations loc1 ON a.locationID = loc1.locationID 
LEFT OUTER JOIN TableLocations loc2 ON b.locationID = loc2.locationID 

그리고 모든 것이 잘 작동합니다! 내 주요 논리적/물리적 문제에 집중하기 위해 많은 쿼리와 다른 테이블을 잘라 냈습니다.

쿼리는 약 10MS로 예상됩니다.

그건 내가 MySQL에 대해 좋아하고 싫어하는 것 중 하나입니다. 때로는 "효과가 있습니다"라고 말하면서 자신의 부족한 부분을 보자. 처음에 제대로하지 못했다는 나의 잘못은 ...

추가 질문 : MyISAM과 InnoDB가 첫 번째 (잘못된) 쿼리를 평가 한 방법과 성능이 너무 다른 이유를 아는 사람이라면, 나는 정말로 그것을 듣고 싶다!

감사합니다.

+0

그래서 ...'innodb_buffer_pool_size'의 값은 뭔가요? 128 MB를 추측 해 보시겠습니까? :) 확인 방법 :'SHOW VARIABLES LIKE '% innodb_buffer_pool %'; ' – Mjh

+0

buffer_pool을 사용 가능한 RAM의 70 %로 변경하고,'key_buffer_size'를 30M으로 낮추십시오. –

+0

innodb_buffer_pool_size = 625999872 (AWS/RDS에서 설정 한 기본값). – user3249281