안녕하세요 가끔가다가 CPU100프로 튀는데 이게 정확하 원인을 모르겠습니다.
https://xetown.com/questions/1612676
여기 질문한대로
1.공지제외 모든게시판 적용
2.오래된 글 열람시 페이지를 정확하게 계산하지 않는 옵션 이것도 켜놓은 상태입니다.
순간적으로 팍 튀다가 꺼져버리는데 뭐가 원인일까요?
PHP | PHP 7.2 |
---|---|
CMS | Rhymix 1.x |
안녕하세요 가끔가다가 CPU100프로 튀는데 이게 정확하 원인을 모르겠습니다.
https://xetown.com/questions/1612676
여기 질문한대로
1.공지제외 모든게시판 적용
2.오래된 글 열람시 페이지를 정확하게 계산하지 않는 옵션 이것도 켜놓은 상태입니다.
순간적으로 팍 튀다가 꺼져버리는데 뭐가 원인일까요?
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 인덱스를 타도록 해야 합니다.
제가 이해하기는 어려운 부분이 많아 나중에 이해가 되는 날이 오길 기대해봅니다. 답변 감사합니다. db쪽도 공부해보면서 현재 언급해주신 문제가 무엇인지 이해하는 시간을 가질 수 있으면 좋겠네요.
현재로서는 추천순,등록순,문서번호 순 등으로 정렬이 꼭 필요할텐데 이게 문제가 된다는게 이해하기 어려운 상황의 상태네요. 이부분이 이해가 가는 날이 오겠죠. 제가 db쪽을 이해하기 시작하는 순간이 되지 않을까 하네요.
현재 상황이 콕 찍은 문서번호만 가지고 정렬을 시도하지 못하고 list_order 로 전체를 정렬한 후 거기서 문서번호를 찾는 다는 그런 말 같은데 이것도 명확히 이해는 가지 않습니다 ㅎ
도서관에 비유하면 PK 컬럼의 특정 값을 이용해 가져오는것은 책 번호를 이용해 가져오는 것이라면, 정렬후 스캔해서 찾는 것은 도서관의 모든 책을 한권씩 내림차순으로 확인해보며 책번호가 일치하는것을 찾는다는 것입니다.
도서관은 책번호에 따라 책장에 가지런히 정리해 두니 그냥 찾을수 있는데도 불구 굳이 책장에서 책을 전부 뽑는다면 매우 비효율적일 것입니다.
흠... 결론은 두가지 문제가 있을수 있다는 뜻으로 해석되는 것 같은데요;
이중에서 (2)는 라이믹스 2.x로 업그레이드 하면 될 것이고, (1)을 예방 하려면...
전자라면 질문자분만의 이슈일것 같고 (그래도 어떤 코드였는지는 궁금하기는 합니다. 호기심에), 후자라면 다른 사용자분들도 알아둬야 할 것이 있을것 같아서요~~~ㅎ
대부분의 게시판이나 위젯은 document_srl로 검색하는 것이 아니라 특정 조건에 맞는 글들을 운영자가 지정한 순서대로 보여주기 때문에 WHERE와 ORDER BY가 서로 다른 컬럼을 참조하는 것이 정상입니다. 인덱스를 타지 못하는 이상한 조건을 걸지 않는 이상, 웬만해서는 문제가 발생하지도 않습니다.
전체공지 애드온에서 문제의 쿼리를 사용하는 것으로 알고 있습니다. 전체공지로 고정시킬 글번호를 운영자가 직접 입력하도록 되어 있으니까요. 라이믹스 2.0에서는 전체공지 기능을 기본 제공하므로 필요없는 애드온입니다.
애드온이나 위젯의 쿼리 속도에 관심이 있으시다면 페이지 관련 변수도 확인해 보시기 바랍니다. 대부분의 애드온이나 위젯은 전체 글이 몇 개인지, 현재 글이 몇 페이지인지 알 필요 없고 단지 운영자가 지정한 순서대로 상위 n개만 보여주면 됩니다. 2~3페이지씩 넘어가는 목록을 보여주는 위젯이라도 쿼리를 2~3번 할 필요 없이 처음부터 2n~3n개를 불러오면 그만이고요. 이런 경우 XML 쿼리에서 <page> 부분에 default 값을 넣지 말고, 쿼리할 때 $args->page도 넣지 않는 것이 좋습니다. 페이지 관련 변수를 넣으면 코어에서 자동으로 전체 갯수를 카운트하고 현재 페이지를 계산하여 $output->page_navigation에 담아 주거든요. 불필요한 SELECT COUNT(*) 쿼리만 제거해도 웬만한 중대형 커뮤니티의 성능 문제는 대부분 해결됩니다.
어느 자료인지 찾는 것이 우선이겠지요.. 서버의 슬로우 로그에서 해당 쿼리 위치를 찾아보거나, 라이믹스의 디버그 기능을 써보세요.
전체공지 애드온의 경우 정렬 방법을 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" />
부분을 제거해야 합니다.
첫 스샷에 17~18초씩 걸리는 쿼리들은 document_srl 값을 콕 찍어서 가져오는 것이라 이론상으로는 무척 빨라야하는데, ORDER BY list_order가 들어가는 바람에 DB의 쿼리 플래너가 엉뚱한 짓을 하고 있습니다. 어느 쿼리인지 찾아서 ORDER BY 부분을 삭제해야 합니다. 해당 글번호들을 찾아보시면 어느 자료에서 쓰고 있는 쿼리인지 추측할 수 있을 것 같네요. 예를 들어 모두 공지글 번호라면 공지와 관련된 애드온이나 위젯이 범인이겠지요.
나머지 0~1초짜리 쿼리들은 위에 있는 쿼리들이 CPU를 다 잡아먹는 바람에 피해를 봤을 뿐, 문제의 원인은 아닌 것으로 보입니다.