가끔씩 CPU 부하 100%

Extra Form
PHP PHP 7.2
CMS Rhymix 1.x

안녕하세요 가끔가다가 CPU100프로 튀는데 이게 정확하 원인을 모르겠습니다.

 

https://xetown.com/questions/1612676

여기 질문한대로 

1.공지제외 모든게시판 적용

2.오래된 글 열람시 페이지를 정확하게 계산하지 않는 옵션 이것도 켜놓은 상태입니다.

 

순간적으로 팍 튀다가 꺼져버리는데 뭐가 원인일까요?

 

1.PNG.jpg

2.PNG.jpg

3.PNG.jpg

5.PNG.jpg

 

  • profile

    첫 스샷에 17~18초씩 걸리는 쿼리들은 document_srl 값을 콕 찍어서 가져오는 것이라 이론상으로는 무척 빨라야하는데, ORDER BY list_order가 들어가는 바람에 DB의 쿼리 플래너가 엉뚱한 짓을 하고 있습니다. 어느 쿼리인지 찾아서 ORDER BY 부분을 삭제해야 합니다. 해당 글번호들을 찾아보시면 어느 자료에서 쓰고 있는 쿼리인지 추측할 수 있을 것 같네요. 예를 들어 모두 공지글 번호라면 공지와 관련된 애드온이나 위젯이 범인이겠지요.


    나머지 0~1초짜리 쿼리들은 위에 있는 쿼리들이 CPU를 다 잡아먹는 바람에 피해를 봤을 뿐, 문제의 원인은 아닌 것으로 보입니다.

  • profile profile
    그런데 정렬 순서를 정할 수 없다면 운영자가 원하는 기준으로 정렬을 할 수 없게 되는데요. 공지뿐 아니라 게시글 정렬에서도 흔히 사용하는 정렬부분이 왜 문제가 되는지 쉽게 이해가 되지 않네요. 제가 이해하지 못하는 부분이 있는거 같은데 그게 무엇인지 궁금하네요. 아마 저부분은 전체공지 애드온이 맞을 겁니다. 이전에 찾아주셨던 문제점은 list_count 값이 지나치게 크게 잡혀있는 것은 이해를 했고 아마 모두 삭제를 하거나 기본값을 작게 해 놓았을 겁니다.
  • profile profile

    MySQL(MariaDB)는 ORDER BY에 사용하는 인덱스를 WHERE에 사용하는 인덱스보다 더 우선순위에 둡니다. document_srl이 PK이기 때문에 document_srl로 검색하는 것이 훨씬 더 효율적임에도 불구하고, list_order 순으로 정렬하여 쭈~욱 스캔하면서 document_srl이 일치하는 것을 찾아내려고 한다는 뜻입니다.

    게다가 다소 오래된 버전의 라이믹스라면 XE의 잔재 때문에 ORDER BY list_order를 넣으면 WHERE list_order < 2100000000이라는 조건을 하나 더 붙여 버리곤 합니다. 이것도 list_order 인덱스를 타도록 하려는 의도입니다. 안 그래도 비효율적으로 실행될 가능성이 높은 쿼리인데, 무조건 비효율적으로 실행하라고 명령을 내려 버린 꼴이지요. 라이믹스 2.0은 이런 불필요한 조건을 임의로 추가하지 않습니다.

    document_srl과 같이 PK 컬럼의 특정 값을 콕 찍어서 가져오려고 하는 경우, 정렬은 MySQL(MariaDB)에게 맡기지 말고 PHP의 sort 기능을 이용하는 것이 좋습니다. 꼭 DB에서 정렬을 해야 한다면 index hint를 사용해서 list_order 인덱스가 아닌 PK 인덱스를 타도록 해야 합니다.

  • profile profile

    제가 이해하기는 어려운 부분이 많아 나중에 이해가 되는 날이 오길 기대해봅니다. 답변 감사합니다. db쪽도 공부해보면서 현재 언급해주신 문제가 무엇인지 이해하는 시간을 가질 수 있으면 좋겠네요.

    현재로서는 추천순,등록순,문서번호 순 등으로 정렬이 꼭 필요할텐데 이게 문제가 된다는게 이해하기 어려운 상황의 상태네요. 이부분이 이해가 가는 날이 오겠죠. 제가 db쪽을 이해하기 시작하는 순간이 되지 않을까 하네요.

     

    현재 상황이 콕 찍은 문서번호만 가지고 정렬을 시도하지 못하고 list_order 로 전체를 정렬한 후 거기서 문서번호를 찾는 다는 그런 말 같은데 이것도 명확히 이해는 가지 않습니다 ㅎ

  • profile profile

    도서관에 비유하면 PK 컬럼의 특정 값을 이용해 가져오는것은 책 번호를 이용해 가져오는 것이라면, 정렬후 스캔해서 찾는 것은 도서관의 모든 책을 한권씩 내림차순으로 확인해보며 책번호가 일치하는것을 찾는다는 것입니다.

    도서관은 책번호에 따라 책장에 가지런히 정리해 두니 그냥 찾을수 있는데도 불구 굳이 책장에서 책을 전부 뽑는다면 매우 비효율적일 것입니다.

  • profile profile
    대략적인 내용은 이해를 했습니다. 세부적인 기술적인 부분을 아직 알지 못해 이해를 못하는 상황이네요. 앞으로 공부를 해볼려고 합니다.

    인덱스 부분 우선순위에 의해 발생하는 문제로 보이며 기진곰님께서 말씀 하신대로 정렬 부분은 db에 요청하지 말고 php에서 별도로 정렬을 다시 해야 한다는 것으로 이해가 되네요.

    기존의 개발자분들께서 자료를 만드실때 이런 점에 유의해서 만들어주시면 동접이 굉장히 많은 곳에서 문제가 발생하지 않도록 예방할 수 있을 것 같습니다.
  • profile profile
    네, DB의 내부 구조나 특이한 작동 방식까지 모든 서드파티 개발자분들이 숙지하기는 어렵겠지만, 눈에 띄면 이렇게 피드백을 해드리고 있으니 조금씩이라도 개선이 되면 좋겠습니다.
  • profile profile

    흠... 결론은 두가지 문제가 있을수 있다는 뜻으로 해석되는 것 같은데요;

    1. document_srl로 검색하는데 (불필요한) ORDER BY list_order 를 추가해서 문제.
    2. 라이믹스 1.x를 써서 (라이믹스 2.x에서는 문제 없음) 생기는 문제 (WHERE list_order < 2100000000).

    이중에서 (2)는 라이믹스 2.x로 업그레이드 하면 될 것이고, (1)을 예방 하려면...

    • 이런 3rd party addon (혹은 3rd party module)만 안쓰면 코어 부분에서는 이런 문제를 유발하지 않는 것일까요, 아니면
    • 게시판이나 위젯등에서 이런 조건을 안주기 위해 어떤 추가적인 조치가 필요할까요?

    전자라면 질문자분만의 이슈일것 같고 (그래도 어떤 코드였는지는 궁금하기는 합니다. 호기심에), 후자라면 다른 사용자분들도 알아둬야 할 것이 있을것 같아서요~~~ㅎ

  • profile profile

    대부분의 게시판이나 위젯은 document_srl로 검색하는 것이 아니라 특정 조건에 맞는 글들을 운영자가 지정한 순서대로 보여주기 때문에 WHERE와 ORDER BY가 서로 다른 컬럼을 참조하는 것이 정상입니다. 인덱스를 타지 못하는 이상한 조건을 걸지 않는 이상, 웬만해서는 문제가 발생하지도 않습니다.

    전체공지 애드온에서 문제의 쿼리를 사용하는 것으로 알고 있습니다. 전체공지로 고정시킬 글번호를 운영자가 직접 입력하도록 되어 있으니까요. 라이믹스 2.0에서는 전체공지 기능을 기본 제공하므로 필요없는 애드온입니다.

    애드온이나 위젯의 쿼리 속도에 관심이 있으시다면 페이지 관련 변수도 확인해 보시기 바랍니다. 대부분의 애드온이나 위젯은 전체 글이 몇 개인지, 현재 글이 몇 페이지인지 알 필요 없고 단지 운영자가 지정한 순서대로 상위 n개만 보여주면 됩니다. 2~3페이지씩 넘어가는 목록을 보여주는 위젯이라도 쿼리를 2~3번 할 필요 없이 처음부터 2n~3n개를 불러오면 그만이고요. 이런 경우 XML 쿼리에서 <page> 부분에 default 값을 넣지 말고, 쿼리할 때 $args->page도 넣지 않는 것이 좋습니다. 페이지 관련 변수를 넣으면 코어에서 자동으로 전체 갯수를 카운트하고 현재 페이지를 계산하여 $output->page_navigation에 담아 주거든요. 불필요한 SELECT COUNT(*) 쿼리만 제거해도 웬만한 중대형 커뮤니티의 성능 문제는 대부분 해결됩니다.

  • profile profile
    아하~... 약간의 의문이 마저 풀립니다. 시간들여 답해주신것 감사드립니다. 라이믹스 2.0을 쓰고, 전체공지 애드온 쓰지말고, 기본 제공되는 것 쓰면 발생 안하는 문제겠네요.
  • profile profile
    전체공지 애드온은 제가 아래 듯글에 적어드린 정도로 하면 문제가 되는 부분이 제거가 될 겁니다.
    그리고 기본 list_count 값이 너무 높게 잡혀 있는 것은 이전에 한번 논의된 적이 있구요.
  • profile ?
    답변 감사합니다.
    게시글 번호로 조회했을때 공지가 아닌 일반적인 게시글로 확인됩니다.
    말씀하신 ORDER BY 부분을 삭제를 하려고 하는데 어디서 하는건지 알수있을까요??
  • ? profile

    어느 자료인지 찾는 것이 우선이겠지요.. 서버의 슬로우 로그에서 해당 쿼리 위치를 찾아보거나, 라이믹스의 디버그 기능을 써보세요.

  • profile

    전체공지 애드온의 경우 정렬 방법을 db에 요청하지 않게 삭제를 한다면,
    오래전에 작성된 문서가 위쪽으로 가게 되서 출력될 것입니다.

    만약 단순히 최근에 작성된 문서가 위쪽으로 배치되는 정도만 조치가 필요하다면 애드온 php 에서
    //if(!$addon_info->notice_sort_index) $args_notice->sort_index = 'list_order';
    //else $args_notice->sort_index = $addon_info->notice_sort_index;

    //if(!$addon_info->notice_order_type) $args_notice->order_type = 'asc';
    //else $args_notice->order_type = $addon_info->notice_order_type;


    이렇게 주석한 후

    foreach 문으로 지정된 문서를 공지 배열로 만들어 준 코드 아래에

    $notice_list = array_reverse($notice_list);

    이렇게 역순으로 순번을 바꿔주면 db에 정렬방법을 요청하지 않고 대략 목적에 달성할 수 있겠습니다.

     

    물론 쿼리 파일에서

     

            <index var="sort_index" default="list_order" order="order_type" />

     

    부분을 제거해야 합니다.

  • profile
    @기진곰 님
    화제의 애드온의 경우도 비슷한 구조의
    <index var="sort_index" default="documents.list_order" order="order_type" />

    코드가 사용되는데

    이 애드온의 경우는 정렬의 방법이 해당글의 추천수,댓글수,조회수 또는 게시물번호 순 으로 다양한 선택이 가능해야 하는 자료인데 결국 이 자료도 똑같은 문제가 되는 건지도 궁금하네요.
  • profile profile
    정렬 순서가 list_order가 아니라면 차라리 나을 수도 있습니다. 위에 적었듯이 list_order로 정렬하면 엉뚱한 조건이 추가되는 경우도 있어서요.
  • profile profile
    아.. 이자료는 보통은 추천수,댓글수 를 정렬기준으로 더 많이 삼는게 일반적이니 차리리 나을 정도는 피해가 좀 덜하다는 말씀 이시군요.
  • profile profile
    질문에 등장하는 자료처럼 특정한 document_srl값을 콕 찍어서 가져오면서 또다른 컬럼으로 정렬하는 경우가 최악입니다. document_srl을 지정하지 않고 그냥 어떤 조건을 충족하는 글 1위부터 5위까지 다 가져와~ 이런 경우는 훨씬 낫습니다.
  • profile profile
    아. 화제의 글은 또 글 번호를 콕 지정하지는 않습니다. 다른 조건에 맞는 글을 지정한 갯수로 뽑습니다. 화제의글 애드온은 그냥 사용해도 될 것 같네요.