내용검색 때문에 서버가 늦어질 때 - 종결자 코드

불당   
   조회 12875   추천 0    

게시글이 어느정도 되고, 커뮤니티가 활성화 되면 게시판 검색을 빈번하게 하게 됩니다.
 
게시판의 검색이 시스템의 부하가 작을 때는 문제가 아니지만, 접속이 많을 때는 심각한 문제가 됩니다.
 
bbs/list.php의 아래 코드에서 tmp table을 만들고 하는 작업이 생기게 되는데,
tmp table 작업 중에는 해당 테이블에 대한 모든 작업이 중단(lock) 되기 때문이죠.
 
    $sql = " select distinct wr_parent from $write_table where $sql_search $sql_order limit $from_record, $board[bo_page_rows] ";
 
이 문제 때문에, 게시판의 인덱스도 바꿔보고 이런저런 삽질을 몇년간 했지만 마땅한 답을 못 얻고
할 수 있는 돈 질(disk를 raid로 바꾸고, 서버의 cpu를 바꾸고...)로 대응을 해 왔습니다. ㅠ.ㅠ...
 
그러다가 2010년 ibm sas 서버로 교체 했슴에도 불구하고 tmp table이 문제가 되어서 시스템이 엄청나게
lock 걸리고 버버버버벅~ 거려서 스트레스가 심했어요. 사실 운영자가 접속하기 힘들 정도였으니까요.
 
마지막 돈 질 (disk를 sas에서 ssd로 변경) 하기 전에, sql을 바꿀 수 없을까 생각을 한번 더 했습니다.
사실 워낙 단순한 SQL이라서 이것을 바꾼다는게 크게 의미가 있을거 같지도 않았지만 고민을 했어요.
 
구글링을 하다가 보니, mysql에도 temporary table을 만드는 것이 가능하더라구요.
 
그래서 위의 SQL을 temporary 테이블을 만들고
그 테이블에서 distinct를 하는 것으로 분리를 하면 어떨까 생각하게 됬습니다.
mysql이 db lock을 거는 것은 temporary 테이블을 만드는 단계 뿐이고,
이후에는 해당 테이블에 대해서 아무런 영향을 안미칠거 같더라구요 (완전히 제 맘대로 추정이었죠 ㅎㅎ)
 
바로 개발에 돌입해서, 어설프게 SQL을 만들고, 테스트 했습니다.
 
sql_query(" $sql_tmp"); // 임시 테이블 만들기
sql_query(" $sql_ord"); // distinct 하기
 
그런데, 이상하게 temporary 테이블이 없다고 우기는 겁니다. 왜??? 왜???
phpmyadmin에서도 2개의 SQL을 따로하면 2번째에서 temporary 테이블이 없다고 합니다.
 
한번 더 SQL을 디볐더니, connection이 유지될 동안만 temporary 테이블이 존재한다고 하네요.
temporary 테이블이 없다는건느 sql_query를 두번째 부를 때, mysql의 connection이 달라졌다는 거죠.
 
그래서 편법을 썼습니다.
 
sql_query(" $sql_tmp; $sql_ord ");
 
phpmyadmin에서는 되는데 안됩니다. ㅠ..ㅠ...
그래서, common.lib.php의 sql_query 함수를 보다가 생각없이 native 함수 그대로 2번 쓰기로 했습니다.
 
    @mysql_query($sql_tmp) or die("<p>$sql_tmp<p>" . mysql_errno() . " : " .  mysql_error() . "<p>error file : $_SERVER[PHP_SELF]");
    $result = @mysql_query($sql_ord) or die("<p>$sql_ord<p>" . mysql_errno() . " : " .  mysql_error() . "<p>error file : $_SERVER[PHP_SELF]");
그랬더니 되는 겁니다.
 
sql_query 함수는 접속 connection을 부를 때마다 다시 만들지만
native mysql_query 함수는 만들어진 connection을 계속 유지하는 것 입니다.
첨 알았어요. ㅠ.ㅠ...
 
결론은 ~ 더이상 내용검색 때문에 db lock 안걸린다는 겁니다~!!!!
 
수정 쉽습니다.
 
bbs/list.php에서 2곳을 수정 합니다.
 
(수정 1)
 
    // 원글만 얻는다. (코멘트의 내용도 검색하기 위함)
    /* 불당팩 - tmp table을 만들고, 거기서 distinct를 하는게 더 빠르다
    $sql = " select distinct wr_parent from $write_table where $sql_search ";
    $result = sql_query($sql);
    $total_count = mysql_num_rows($result);
    */
    $sql = " select wr_parent from $write_table where $sql_search ";
    $sql_tmp = " create TEMPORARY table list_tmp_count as $sql ";
    $sql_ord = " select distinct wr_parent from list_tmp_count ";
    @mysql_query($sql_tmp) or die("<p>$sql_tmp<p>" . mysql_errno() . " : " .  mysql_error() . "<p>error file : $_SERVER[PHP_SELF]");
    $result = @mysql_query($sql_ord) or die("<p>$sql_ord<p>" . mysql_errno() . " : " .  mysql_error() . "<p>error file : $_SERVER[PHP_SELF]");
    $total_count = mysql_num_rows($result);
 
(수정 2)
 
/* 불당팩 - tmp table을 만들고, 거기서 distinct를 하는게 더 빠르다
if ($sst)
    $sql_order = " order by $sst $sod ";
if ($sca || $stx)
{
    $sql = " select distinct wr_parent from $write_table where $sql_search $sql_order limit $from_record, $board[bo_page_rows] ";
}
else
{
    $sql = " select $list_select from $write_table where wr_is_comment = 0 $sql_order limit $from_record, $board[bo_page_rows] ";
}
$result = sql_query($sql);
*/
if ($sst)
    $sql_order = " order by $sst $sod ";
if ($sca || $stx)
{
    //$sql = " select distinct wr_parent from $write_table where $sql_search $sql_order limit $from_record, $board[bo_page_rows] ";
    $sql = " select wr_parent from $write_table where $sql_search $sql_order";
    $sql_tmp = " create TEMPORARY table list_tmp as $sql ";
    $sql_ord = " select distinct wr_parent from list_tmp limit $from_record, $board[bo_page_rows] ";
    @mysql_query($sql_tmp) or die("<p>$sql_tmp<p>" . mysql_errno() . " : " .  mysql_error() . "<p>error file : $_SERVER[PHP_SELF]");
    $result = @mysql_query($sql_ord) or die("<p>$sql_ord<p>" . mysql_errno() . " : " .  mysql_error() . "<p>error file : $_SERVER[PHP_SELF]");
}
else
{
    $sql = " select $list_select from $write_table where wr_is_comment = 0 $sql_order limit $from_record, $board[bo_page_rows] ";
    $result = sql_query($sql);
}
 
DISTINCT combined with ORDER BY may require a temporary table.
 
Some conditions prevent the use of an in-memory temporary table, in which case the server uses an on-disk table instead:
  • Presence of a BLOB or TEXT column in the table
  • Presence of any column in a GROUP BY or DISTINCT clause larger than 512 bytes
  • Presence of any column larger than 512 bytes in the SELECT list, if UNION or UNION ALL is used
 
 
You can use the TEMPORARY keyword when creating a table. A TEMPORARY table is visible only to the current connection, and is dropped automatically when the connection is closed. This means that two different connections can use the same temporary table name without conflicting with each other or with an existing non-TEMPORARY table of the same name. (The existing table is hidden until the temporary table is dropped.) To create temporary tables, you must have the CREATE TEMPORARY TABLES privilege.
- opencode.co.kr -
아마존 AWS 1년 무료체험
AWS 클라우드 서버 호스팅, 탄력적인 규모와 저렴한 비용! 1년 무료체험 신청
해외서버 IDCJP
DDOS 방어 만족도 으뜸 ! 기본 50G무료방어, 방어라인 200G이상 방어가능
HP서버 정데이타
HP서버 ML350 DL360 DL380 특가판매 빠른견적 기술지원 서버
파워링크 AD   클릭초이스등록
아닌데 2012-12
수정2는 어떻게 하라는 말이져?ㅠㅠ


제목Page 1/4
2010-04   10162   불당
2011-01   12876   불당
2010-06   9439   불당
2016-08   1611   불당
2016-08   1581   불당
2016-08   1595   불당
2016-08   12238   불당
2015-10   2992   불당
2014-02   6188   불당
2014-02   6048   불당
2014-02   6235   불당
2013-06   8868   불당
2013-05   10276   불당
2013-05   10055   불당
2013-01   12204   불당
2011-12   14780   불당
2011-12   11011   불당
2011-09   12213   불당
2011-09   10553   불당
2011-06   10833   불당
2011-01   10077   불당
2011-01   12873   불당
2011-01   12876   불당