요즘 사이트 DB Query 최적화 작업을 하던 중 워드프레스 3.4부터 포함된 멋진 기능 + Hook을 발견했습니다.

대형 사이트 혹은 메모리 할당량이 아주 작은 임대 호스팅에서 posts(wp_posts)테이블의 크기가 점점 커져가게 되면, 카테고리 목록 등 JOIN 과 ORDER BY 가 혼합된 Query에서 각 테이블의 Index를 잘 활용하지 못하고 TMP 테이블을 사용하게 됩니다.

이 경우 아무리 USE INDEX (FOR JOIN)을 쑤셔 넣어 보아도 TMP테이블에 쓰고 읽는데 많은 시간을 써 버리게 되어 페이지 로딩이 많이 늦어질 수 있게 됩니다.

mysql> SHOW PROFILE;
+———————-+———-+
| Status | Duration |
+———————-+———-+
| starting | 0.000250 |
………
| preparing | 0.000095 |
| Creating tmp table | 0.000388 |
| Sorting for group | 0.089872 |
| executing | 0.000154 |
| Copying to tmp table | 1.594660 |
| Sorting result | 0.097977 |
| Sending data | 0.106168 |
| end | 0.000142 |
| removing tmp table | 0.042374 |
………


이를 해결 해 보기위해 여려방안을 찾아 보던 중, SELECT 단계에서 우선은 posts 의 ID들만 가져온 뒤 해당 아이디의 posts만 따로 불러오면 Index를 충분히 활용해서 단번에 결과를 가져오는 아주 적절한 방법을 찾게 되었습니다. 실제로 SQL_NO_CACHE를 적용해서 테스트 해 보면 5~10배 가량 속도에 향상이 있는것을 확인 할 수 있었죠.

‘됐다!’ 하면서 플러그인을 만들어 적용 해 볼 요량으로 wp-includes/query.php 파일의 hook 부분들을 슬쩍 둘러보려다 보니 왠걸… 이미 적용이 되어 있네요 ㅎㅎㅎ

$split_the_query = ( $old_request == $this->request && “$wpdb->posts.*” == $fields && !empty( $limits ) && $q[‘posts_per_page’] < 500 ); $split_the_query = apply_filters( 'split_the_query', $split_the_query, $this ); if ( $split_the_query ) { // First get the IDs and then fill in the objects

주석에도 당당히 적혀있네요 “// First get the IDs and then fill in the objects

워드프레스 SVN 저장소를 둘러보니 이번 3.4버전부터 이눔이 적용되어 있더군요. 3.4 적용 전에 이 방법을 적용하려 했다면 완전 삽질을 할 뻔 했더군요…. 헐 다행입니다!

아직 3.4 버전을 사용하지 않는 사이트를 운영중인 분들 중에 Posts DB가 커져만 가고, 목록 페이지 로딩이 점점 느려지는 현상을 겪고 계신 분들께서는 3.4로 업그레이드를 한 번 시도해 보세요 🙂

저는 또 다른 삽질을 하러 이만 사라지겠습니다~~

Responses

이메일 주소는 공개되지 않습니다.

+

  1. 박태환

    홈페이지 주소는 nteongs.com 입니다
    어제 저녁부터 에러메세지가 뜨면서 아무것도 할 수가 없습니다.
    에러 메세지는 다음과 같습니다.

    WordPress database error: [Unknown column ‘day_no_time’ in ‘field list’]
    INSERT INTO netongs_popularpostsdatacache (id, day, day_no_time) VALUES (12166, ‘2012-09-03 08:41:35’, ‘2012-09-03’) ON DUPLICATE KEY UPDATE pageviews = pageviews + 1, day = ‘2012-09-03 08:41:35’, day_no_time = ‘2012-09-03’;

    1. 082net Post author

      질문글은 내용과 상관없는 글 말고 포럼쪽에 올려주시길 부탁드릴께요~

      오류내용은 popular posts 와 관계된 문제로서, 데이터베이스에 입력하는 과정에서 day_no_time 이라는 컬럼이 없어 발생한 오류로 보입니다. 보통 새로운 컬럼이 플러그인 버전이 업그레이드 되면서 생기는데, 정상적인 플러그인 업그레이드 과정을 거치지 않은면 이와 같은 문제가 발생하기도 합니다. 해당플러그인을 비활성화 > 활성화 시켜보시고 그래도 문제가 해결되지 않는다면, 우선은 플러그인을 비활성화 시켜 사용하지 않는 방법밖에는 없겠군요.