RSS구독하기:SUBSCRIBE TO RSS FEED
즐겨찾기추가:ADD FAVORITE
글쓰기:POST
관리자:ADMINISTRATOR
기술의 발전으로 인하여 저렴해지고 보다 성능은 뛰어나졌다.
요즘은 IaaS 같은 Cloud Service 들도 많기 때문에 비용적인 부담은 많이 줄어들었지만.

내가 가진 지갑도 홀~~~~~~~~~~쭉 하기 때문에 한정된 돈으로 싸게싸게 웹 서비스용 서버를
마련하기 위해서라면 어떻게 해야 할 까?

Cloud Service 를 쓰건 깡통을 사서 쓰건간에 큰 맥락에서 이해를 해주면 ...(땡큐 베리 감사 ..)

(여기서 Goal 은 Single box 를 굴린다는 전제하에 작성하는 것으로 한다.)


** 주의 **
본 글은 다분히 개인적 경험과 잡다구리한 지식을 기반으로 작성 되어음을 알려드립니다.
취사 선택에 주의를 요합니다.

보통 웹 서비스라고 하면 보통 다음과 같은 것들이 필요하다.



데이터 관리를 위한 DBMS
Server-Side language 를 위한 엔진(Engine)
Web Server


그리고 보통은


복잡하지 않은 DB 연산 , 다수의 Web application processors ...
매우 높은 CPU 연산 보단 매우 빈번한 I/O 를 사용하게 된다.


물론 이것은 사용하는 Web Application 에 따라서 달라질 가능성이 있지만 그것은 제껴 놓고 보자..


1. like a US beef .... (Cheap and delicious ...??)


(진짜 미국산 소고기가 그렇다는 것은 아니다...)

고성능 CPU 와 SSD 와 같은 장비를 샀으면 좋겠지만
그러하지 못하다면 어쩔수 없이 어떻게 써야 할지 고민이 될 것이다.
일단 우리가 이용하고자 하는 환경은
다수의 Application ( Web server + DB + Web Engine ...etc..) 이 동작하는 환경이 될 것이고.


각 Application 은 그다지 많은 CPU 성능을 요구하지는 않을 것이다.

이러한 환경에서는 고 클럭(Clock)  CPU 보다는
Core 수가 많은 혹은 HT 와 같이 Thread 성능을 늘릴수 있는 CPU 를 선택하는 것이 좋다.
고 클럭 Dual core CPU 보다는 조금 더 낮은 클럭의 Quad Core CPU 가
Multi Processes/Thread 에서는 좀 더 이득을 볼 수 있기 때문이다.


그리고 가급적이면 Main Memory 를 많이 꼽아라.
ECC 메모리가 아닌 이상 Memory 가격이 미친 듯 비싸지 않으니 많이 꼽아라 투자 한 만큼 돌아온다.


용량 대비 가격 면에서 SSD 는 현재 기준(2013. 10)  GB 당 1달러 (USD) 이상 된다.
일반용 SSD 임에도 불구 하고 말이다. 이는 고 용량 / Enterprise 급으로 넘어가게 되면 더 올라가게 된다.


그에 비하여 S-ATA 7200rpm HDD 의 경우 GB 당 0.05 달러 (USD) 정도 이니 약 20배 정도 차이가 난다.
HDD 도 사실 I/O 성능이 그다지 나쁘진 않는 편이다.
혹은 10K rpm 짜리 HDD 를 붙인다면 좀 더 나은 성능을 얻을 수 있겠다.

Disk I/O 가 매우 중요하다면 SSD 를 도입하되 데이터 영구 저장용으로 별도의 HDD 를 이용하는 것도 방법이다.
혹은 HDD+SDD Hybrid  방식의 디스크를 구매하는 것도 적절한 타협점이 될 수 있지 않을까?

그 외 NIC 나 Main board 와 같은 경우는 대부분 baseline 이상의 내구성을 보여주니
A/S 잘되는 녀석으로 고르면 된다.


2. 64 bit & Modern OS
64 bit 환경은 32 bit 시절 보다 향상된 연산능력과
광활한 어드레싱 (Addressing) 이 가능하게 만들기 때문에 보다 더 많은 메모리를 활용 할 수 있게 된다.


또한 몇몇 DBMS 의 경우 ( ex , MongoDB ) 에는 특정 필드의 데이터 타입의 한계가 다르기 때문에
앞으로 Web Application 개발을 감안한다면 굳이 32 bit 로 가야할 이유가 없을 것이다.


또한 epoll 이나 보다 향상된 File system ( ex, ext4 , zfs )  와 향상된 Scheduler 와 같이
내부적으로 최신 하드웨어에 맞는 최신 기술들이 적용되어있기 때문에
보다 효율적으로 하드웨어 자원을 활용 할 수 있게 된다.

그렇기 때문에 반드시! 최신 OS 는 항상 옳다고 봐야 한다.


3. Lightweight


Web 과 관련한 최신 기술들의 경향은 lightweight & Easy to use 라고 할 수 있다.
예전 LAPM 이라 불리웠던 Linux + Apache + PHP( 혹은 python , perl ) + MySQL 의 조합을 떠올리게 된다.


물론 이 모든 것들이 당시에는 가장 가볍게 저 비용으로 웹 서비스 환경을 구축하기 위한 조합이였다.


하지만 세월이 흐르면서 Lighttpd 나 Nginx 와 같이 성능은 월등히 뛰어나지만 시스템 자원을 적게 이용하는 경량 (light-weight) Web Server 들이 나왔고
FastCGI 나 PHP의 경우 PHP-FPM , WSGI 의 경우 Gunicorn 이나 uWSGI 와 같은 빠르지만 매우 가벼운 WSGI 모듈 과 같이 Web Server 에 의존적이던 형태에서 벗어나 보다 효율적으로 Web Engine (혹은 Web container )을 구동하기 위한 형태로 진화 해 왔다.

한발 더 나아가서 Node.JS 를 이용하여 아주 간단(?) 하게 Web Service 를 구축할 수 있는 방법도 생겼다.

이렇게 해서 실제 Web Application 을 효율적으로 처리하고 시스템 자원을 확보 하는 것이 필요하다.


4. Use more efficiently

2번 내용과 비슷한 맥락이 될 것이다. 최신 SW 기술은 항상 옳다.
예를 들자면 MySQL 의 경우 4.x 와 5.1 그리고 5.5+ 의 성능은 매우 차이가 크다.
MySQL 5.7 에 가서는 보다 빨라진 성능을 제공하기에 가급적 빨리 도입하는 것도 나쁘지 않은 선택이 될 수 있다.

MySQL project 에서 분리된 MariaDB 의 경우에는 MySQL 과 99% 호환이 되지만
MySQL Community Edition 에서 누락된 최신 기술들을 도입하여 보다 나은 성능을 보여준다.

물론 DBMS 특성상 최신 Engine 을 항상 도입하기에는 안전성의 문제로 인하여 쉽게 갈아타기 힘든 부분이 있기 마련이다.

하지만 적절한 시험(Testing) 을 통해서 빠른 시간내에 도입을 해보는 것도 방법이라고 할 수 있겠다.

또한 PHP 의 경우 기존의 mod_php 와 같이 Web Server 와 함께 동작하는 module 방식 보다는
독립적인 Process 형태의 FastCGI 나 PHP-FPM 과 같은 형태로 이용하게 되면
HTTP 요청(Request) 증가로 인한 Web Server 의  부하 와 상관 없이
PHP Application 의 요청에 따라 효율적으로 Process/resource 관리가 가능해질 수 있다.

특히 APC 를 이용하게 되는 경우 PHP-FPM 방식에서는 APC 데이터 영역을 공유하기 때문에
보다 효율적으로 메모리를 관리 할 수 있다.

혹은 호환성의 이슈가 있지만 Facebook 에서 이용하고 있는 HipHop VM (이하 HHVM ) 과 같은 것을 이용하게 되면
보다 빠르게 PHP Application 을 이용할 수 있게 된다.

Python 의 경우엔 mod_wsgi 보단 Gunicorn 이나 uWSGI 와 같은 고성능 Web Container 를 이용하는 편이 보다 나은 성능을 보장 할 수 있다.


I/O 성능을 극대화 하기 위해서 HDD 보단 Main Memory 를 활용하기 위해서
Redis 나 Memcached 와 같은 Engine 을 활용하게 되면 보다 빠른 I/O 성능을 뽑아 낼 수 있다.

여기에 tcmalloc 이나 jemalloc 과 같은 메모리 할당자를 이용하게 된다면 미묘하지만 성능상 잇점을 얻을 수 있고
메모리 사용량이 감소 되는 효과도 부수적으로 얻을 수도 있다.

하지만 이에 대해선 충분한 시험 후 적용하는 것이 좋다.

또한 Network 성능 향상을 위해서 epoll ,kqueue  혹은 IOCP 와 같은 library 를 활용 할 수 있는 솔루션을 선택하여
해당 library 를 이용할 수 있도록 하는 것이 좋다.


5. Configuration
이렇게 필요한 SW 들을 모두 완비를 하였다면
적절한 설정으로 해당 Application 들을 최적화 해야 할 필요가 있다.

하지만 적절한 설정 값 을 논하기엔 어려우니 큰 그림으로 보면서 이야기 하자면
기본적은 OS 와 관련된 parameter 들의 경우엔 현재 구비된 H/W 성능을 충분히 낼 수 있을 만큼의 조정이 필요하지만.

DBMS 나 Web Server / Container 와 같은 Application 은 적절하게 시스템 자원들을 활용 할 수 있도록 할당해줘야 한다.
보통 OS : DBMS : Web Container : Web Server 를 놓고 보자면 2: 5 :2:1 정도로 할 당해준다고 하면 얼추 잘 돌아갈 것이다.

물론 대략적으로 이야기 하지면 이렇다는 것이고.
DBMS 의 경우엔 CPU core 나 Memory 할당에 비중을 두고 설정을 하고 Main Memory 자원을 사용하는
Memcached 나 Redis 와 같은 DBMS 를 사용하게 되면 Memory 자원의 할당에 신경 써야 할 것이다.
Web Container(혹은 interpreter 와 같은 ) 의 경우엔 그 다음으로 CPU/Memory 자원을 할당한다.
그리고 Web Server 의 경우 비교적 적은 자원을 사용해도 무방 할 것이다.

하지만 FastCGI 를 사용한다 던지 Web Server 에 Plugin 등 을 사용한다던지 하면서
Memory 사용량이 급증 할 가능성이 있기 때문에 이에 따라 적절하게 설정을 변경해주는 것이 필요하다.




6. Keep eyes on ..
사용하다 보면 수 많은 변수들이 생기기 마련이다.
Application 이 변경 되면서 특정 자원을 제대로 사용하지 못한다거나 혹은 너무 과용하게 되서 다른 시스템에 영향을 미칠 수도 있다.

이런 일이 벌어졌을때 최악의 경우
DB 가 날라간다거나.
DB 가 소멸한다 거나..
DB 가 응답을 하지 않는 다거나...

하는 일이 벌어질 수도 있다.

또한 여기서는 언급이 되지 않았지만
보안적인 측면이나 혹은 시간이 지남에 따라 최신 기술들이 등장하기에
꾸준한 관심으로 시스템을 모니터링 해주면서 적절하게 그때 그때 최적화를 통하여
시스템을 유지하는 것이 최선이라고 할 수 있다.



Reference
http://www.php.net/manual/en/install.fpm.configuration.php

http://stackoverflow.com/questions/17141596/fastcgi-vs-php-fpm-using-nginx-web-server
http://php-fpm.org/about/
http://stackoverflow.com/questions/6330727/the-reason-why-mod-php-is-less-efficient-than-fastcgi-phpphp-fpm
http://stackoverflow.com/questions/1405656/apaches-mod-php-or-fastcgi-which-is-good-for-wordpress/1943706#1943706
https://github.com/facebook/hiphop-php/blob/master/hphp/doc/ir.specification
http://www.hhvm.com/blog/
http://www.canonware.com/jemalloc/
http://www.mysqlperformanceblog.com/2013/03/08/mysql-performance-impact-of-memory-allocators-part-2/
http://slashdot.org/topic/bi/mariadb-vs-mysql-a-comparison/
http://redis.io/
http://memcached.org/
http://nginx.org/
http://projects.unbit.it/uwsgi/
http://gunicorn.org/
http://nichol.as/benchmark-of-python-web-servers
http://www.kegel.com/c10k.html
http://www.slideshare.net/khanz2012/ijcse10-020562
2013/10/01 01:34 2013/10/01 01:34
이 글에는 트랙백을 보낼 수 없습니다
[로그인][오픈아이디란?]
오픈아이디로만 댓글을 남길 수 있습니다
Wordpress 를 사용하는 분 덕에 간단한 삽질...

PHP-FPM 과 NGINX 설치는 제끼고
핵심인 Nginx configuration 만 참조 바람.

server {
    server_name example.com www.example.com;

    access_log   /var/log/nginx/example.com.access.log;
    error_log    /var/log/nginx/example.com.error.log;

    root /var/www/example.com/htdocs;
    index index.php;

    location / {
            try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
            try_files $uri =404;
            include fastcgi_params;
            fastcgi_pass unix:/var/run/php5-fpm.sock;
    }
}


아래 참고 사이트를 이용하면 보다 다양한 내용을 자세하게 설명해줌.
끗.!

참고 : rtCamp ( http://rtcamp.com/wordpress-nginx/tutorials/ )
2013/09/18 01:10 2013/09/18 01:10
이 글에는 트랙백을 보낼 수 없습니다
[로그인][오픈아이디란?]
오픈아이디로만 댓글을 남길 수 있습니다

셋방살이 중인 서버의 대 격변(?) 에 발 맞춰서
기존의 Apache + mod_php 와 낮은 버전의 MySQL 로 인하여 이래저레 못해왔던 것들을 던져 버리고

신흥 문물(?) 들을 받아들여 보고자 하였는데.

설치 환경은 아래와 같다.

  • CentOS 6.x ( x86_64 )
    • MySQL 5.5.x
    • PHP 5.3.x
      • APC
      • PHP-FPM
    • Nginx 1.4.x
    • Memcached 1.4.x

오랜 숙원 사업이였던 탈 i686 의 꿈을 이루고 이것저것 삽질을 시작 하였는데.

여기서 설치와 관련된 내용은 모두 Yum 을 이용하여 설치를 하였다.
다음 Yum repository 를 추가 해주면 간단히 해결 됨.

이때 각 Yum Repository 마다 동일한 패키지 명의 중복으로 피곤해지는 일들이 발생 된다면
yum-plugin-priorities 을 설치하시면 Repo 별로 우선순위를 지정해서 처리가 가능하니 깔끔하게 해결!


이렇게 모든 패키지가 설치가 완료가 된다면.

PHP-FPM + Nginx 가 원활하게 구동 할 수 있도록 설정을 해줘야 하는데.

/etc/nginx/nginx.conf

location ~ \.php$
{
    fastcgi_send_timeout  5m;
    fastcgi_read_timeout 5m;
    fastcgi_connect_timeout 5m;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}


여기에 Textcube 를 위한 URL redirection 을 추가 한다.
( c.f /documents/setup_nginx.txt 을 참조하시길 바란다 )

location /tc/  {
    set $rewrite_base '/tc';
    if (!-f $request_filename) {
            rewrite ^(thumbnail)/([0-9]+/.+)$ cache/$1/$2;
    }
    if ($request_filename ~* ^(cache)+/+(.+[^/])\.(cache|xml|txt|log)$) {
            return 403;
    }
    if (-d $request_filename) {
            rewrite ^(.+[^/])$ $1/;
    }
    rewrite  ^(.*)$ $rewrite_base/rewrite.php last;
}


/etc/php-fpm.d/www.conf

[www]

listen = 127.0.0.1:9000

listen.backlog = -1
listen.allowed_clients = 127.0.0.1

user = nginx
group = nginx

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
request_terminate_timeout = 120s
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/www-slow.log
security.limit_extensions = .php .php3 .php4 .php5 .html
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on

/etc/php.d/memcache.ini
extension=memcache.so
memcache.default_port=11211

memcache.hash_function=crc32
memcache.hash_strategy=consistent
memcache.protocol=ascii
session.save_handler=memcache

session.save_path="tcp://127.0.0.1:11211?persistent=1&weight=1&timeout=1&retry_interval=15"



일단은 여기까지 설정을 마치고 PHP 가 정상적으로 구동되는지 확인을 한다.

정상적으로 동작을 한다면

Textcube 안정버전인 1.8.6 을 다운로드 받아서 설치를 하게 되는데
MySQL 5.5+ 에서의 호환 성을 위해 설치 전 미리 몇 가지 손을 좀 봐야 할 필요가 있다.

setup.php 의 1132 line. 의 TALBE 생성 시 'TYPE' 을 'ENGINE' 으로 바꿔 줘야 한다.
- $charset = 'TYPE=MyISAM DEFAULT CHARSET=utf8';
+ $charset = 'ENGINE=InnoDB DEFAULT CHARSET=utf8';


그리고 Textcube 를 설치를 진행 한다.

이때 Rewrite 관련 설정에 에러가 나는데 옵션을 끄고 진행 하더라도 무방하다.

여기까지는 Textcube 에서 제공하는 setup_nginx.txt 를 참조 하시면 좀 더 친절하게 안내 받을 수 있다.

여기서 한가지 고비가 오는데
Textcube 1.8.6 에서 PHP-APC 가 활성화 된 환경에서 Login 이 불가능하고 502 Error 를 뱉고
진행이 불가한 상황이 벌어지는데

PHP::Session class 와 session_write_close() 사이에 어떤 문제가 APC 모듈과 비 정상적인 동작을
일으켜서 생기는 문제라고 하는데

이때 PHP-APC 를 삭제 하거나 disable 하시면 되지만
왠지 아깝지 않은가? Textcube 때문에 APC 를 쓸 수가 없다니!!!!

이럴때 Texcube 가 설치된 디렉토리 아래의
./library/preprocessor.php 의 152번 째 줄 즈음에 다음 코드를 추가 한다.

+ register_shutdown_function("session_write_close");


이후엔 정상적으로 로그인이 가능해질 것이다.

Textcube 에 로그인 후 Memcache 를 활성화 시키기 위해서
"텍스트 큐브 관리" 메뉴로 이동한 뒤 "서비스 관리 > 서버" 메뉴에 진입을 한 뒤
"Memcached 사용" 메뉴에 Checkbox 에 Check 한 뒤 저장을 하게 된다면

보다 빠릿빠릿한 블로그를 이용 할 수 있게 된다.
2013/08/04 18:07 2013/08/04 18:07
이 글에는 트랙백을 보낼 수 없습니다
[로그인][오픈아이디란?]
오픈아이디로만 댓글을 남길 수 있습니다

MySQL 성능을 죽이는 15가지 방법이라는 아주 재미있는 내용의 프리젠테이션...

MySQL 을 기반으로 한 다양한 웹 서비스들을 만들어가고 또 운영되는데 있어서
항상 MySQL 이라서 느려...MySQL 이니까 이 정도도 감지덕지... 라고 하지 말고
제대로 알고 제대로 쓸 수 있도록 해보자.
원문 : Jay Pipes@MySQL, Inc
http://www.slideshare.net/techdude/how-to-kill-mysql-performance


#1. Thinking too small
시작은 미미했으나... 그 끝도 미미 하리라는 생각은 버려라.

분명 시스템은 처음에는 매우 단순한 구조로 이루어지겠지만
커져가면서 결코 한 군데에 다 때려박아서 커버하기가 불가능해진다.

다수의 웹 서버들과 어플리케이션 서버 , DNS 서버 등의 여러 서버(혹은 서비스)들이 존재하게 된다.

이러한 서비스들에서 오는 모든 요청들로 인한 부하들이 집중되면 아무리 짱짱한 시스템이 들어와도 이를 감당해내기 힘들어진다.
그래서 부하들을 매 단계별로 Proxies 과 Caching 을 해서 최종적으로 넘어오는 부하의 양을 최소화 해야 할 필요가 있다.

특히 Caching 을 적극적으로 활용하지 않는 대형 웹 사이트를 존립시킬 수 없다.

그리고 각 서비스 컴포넌트 나 어플리케이션을 적극적으로 분리를 하고
무리하게 집중시키지 마라...
Scale-Up 을 통해서 성능향상을 바라는 것은 금방 한계점에 달하고 비용도 매우 많이 소요된다.
그보다 효율적으로 분산해서 처리하는 것이 더 현명한 선택이 될 것이다.

그리고 닥치기 전에 복제(replication) 나 분할(Partitioning) 에 대한 계획을 미리 수립하는 것이 좋다.
세션데이터는 최소화 하여 관리한다.

하지만 너무 허황될 만큼 크게 생각하진 말길.

성능이 반드시 확장성을 가져오는 것은 아니다.

#2. Not using EXPLAIN
EXPLAIN 은 입력된 SQL 문장을 해석하여 옵티마이져의 실행 계획을 보여주는 명령어 이다.
입력된 SQL 을 해석한 뒤 테이블의 데이터/인덱스 등을 판단하여 어떻게 실행 할지 보여주게 되는데.

Extra 컬럼에 "Using Index" 라고 나온다면 제대로 돌아 가고 있다 라고 봐도 거~~의~~ 무방하다.

특히 MySQL 5.0 이전 버전에서는 단 하나의 Index 만을 이용 할 수 있었는데.
MySQL 5.0+ 버전에서는 Index Merge optimization 을 통해서 좀더 향상된 속도를 얻을 수 있다.
이는 곧 인덱스 수립 계획에도 큰 도움이 된다. ( 슬라이드 Page 13 참조 )


#3. Choosing the wrong date types
Index ( 혹은 데이터) 는 가급적이면 단일블럭(Single Block) 안에 들어갈 수 있게 하는 것이 좋다.
기본적으로 DBMS 는 데이터가 늘어가면서 I/O 가 많이 일어나고 그리고 성능에 매우 민감하게 영향을 미치게 된다.
특히 디스크 처럼 매우 느린장치(CPU 연산 과정에서 보자면  HDD 는 아직 한참 멀었다.)에 접근 횟수를 줄일 수 있다면 당연히 느려진다는 것이다.

반대로 말하자면 데이터를 가져올때 횟수를 최소화 할 수 있다면 곧 속도향상을 얻을 수 있다라는 이야기.

그렇기 때문에 Index (혹은 데이터) 를 저장함에 있어서 가급적이면 최소한의 컬럼을 유지하는 것이 I/O 횟수를 줄이는데 유리하다.
슬라이드에서는 IP 정보를 저장할때 Varchar 형을 사용하거나 UNSIGNED INT 형을 사용 하는 2가지 경우를 가지고 이야기를 한다.

일반적으로 Varchar 형을 이용하여 저장하는 경우가 많은데. INET_ATON()/INET_NTOA() 함수를 이용하여 변환하여 INT 형에 저장 할 수 있게 되는데.
저장하는 데이터 크기도 줄이고 또한 Index range scan 을 통한 성능 향상도 꾀 할 수 있다는 장점이 있다.

슬라이드에서는 설명하고 있지 않지만 굳이 음수형으로 데이터를 저장할 필요가 없다면 UNSIGNED INT 와 같이 선언을 하게 되면 SIGNED INT로 선언했을 때 보다 약 2배 가량 속도 향상을 얻을 수도 있다고 한다.
그러니 *반드시* 필요한 데이터형의 크기를 잘 정해서 설계하는 것이 중요하다.

#4. Using persistent connection in PHP
MySQL 연결 시간(Connection Time) 을 줄이기 위해 영구적인 연결(Persistent Connection) 을 이용하는 경우가 있다.

하지만 영구적인 연결(Persistent Connection) 인 경우 자원을 공유하지 않은 구조로 인하여
Apache 프로세서가 Zombie 상태에 빠지게 되면 그대로 자원을 낭비하게 된다.

애초에 MySQL 은 수명이 짧고 경량형 으로 디자인 되어있어서 Connection Time 은 Oracle 이나 PostgreSQL 에 비해서 10~100배 가량 빠르다고 하니 pconnon_* 계열 에 목 매지 맙시다.

#5. Using a heavy DB abstraction layer
이식성(Portability) 때문에  ADODB , MDB2  혹은 PearDB 같은 무거운(Heavy) 추상화 라이브러리(abstraction Library) 를 쓰는데
그것 보단 PDO 같은 경량형 라이브러리를 이용하는 것이 좋다.  거기에 Scale-out 을 위한 부분도 추가해주 면 좋다.

#6. Not understanding storage engines
MySQL 에서는 매우 다양한 DB Engine 을 가지고 있는데 각 Engine 의 특성에 따라서
장 단점이 있는데 이에 대한 이해를 통해 적절한 Storage Engine 을 활용하면 보다 나은 성능을 발 휘 할 수 있다.

반대로 그러한 이해가 없이 사용하면 오히려 성능저하의 원인이 되기도 한다.

예를 들어 웹 로그 기록 같이 한번 입력하면 변경은 이루어지지 않고 고속의 INSERT 성능이 필요한 경우엔 Archive Engine 을 쓰는 것이 낫다 더욱이 압축 효율 또한 우수하여 ( MyISAM 대비 6~8배 ) 디스크 관리에도 유리하다.

반대로 주간 베스트 와 같이 크지는 않지만 빠른 입출력이 필요한 경우 Memory Engine 을 사용하면 Disk based Engine 에 비하여
획기적으로 빠른 성능을 제공 할 수 있다.

이처럼 적절한 Engine 을 활용 하는 것이 보다 나은 성능을 보장해준다.
다시 한번 말하지만 InnoDB 는 어디에도 붙일 수 있지만 성능을 보장해주는 것은 아니다.


#7. Not understanding index layouts
INDEX 선정과 Storage Engine 을 선탁하는데 매우 중요한 부분이다.
모든 Engine 들 은 Data 와 Index 를 메모리(Memory) 와 디스크 ( Disk ) 에 저장 한다.

Clustered 방식은 Primary Key 를 기준으로 정렬된 Data 묶음 단위로 디스크에 저장을 하고
Non-Clustered 는 그렇지 않다.

Non-Clustered 의 경우에는 큰 영향은 없지만.
Clustered 의 경우 데이터를 검색 할 경우 Primary key 를 보고 실제 데이터로 이동하여 데이터를 검색 하기 때문에
데이터 조회시 가급적 PK 를 이용하여 데이터를 검색하는 것이 좋다.

그리고 Clustered  방식에서 생성되는 모든 Second Index 는 PK 를 참조하여 만드므로 PK 는 최대한 작게 만들어주는 것이 좋다.

#8. Not understanding how the query cache works
사용하는 Application 의 Read/Write 비율을 이해한 상황에서
CPU 사용율과 읽기 성능을 적절하게 조율해야 한다.

Query Cache 를 늘린다고 성능이 무작정 증가하지도 않는다.

Cache 검증하는데 매우 투박한 검증방식 을 채용했는데
이유는 Cache 된 데이터를 찾아서 저장하는데 너무 많은 CPU 자원을 사용을 방지 하기 위해서 이다.

이는 SELECT 할 때 Table 에 어떠한 변화가 생긴 경우 모든 Cache 정보들은 유효하지 않게 된다는 것이다.
결국 Table 에 매번 변화가 생길 경우 매번 Cache 갱신을 하게 되고
Query Cache 의 효율이 떨어지게 되는 것이다.

그래서 자주 업데이트 되는 컬럼들을 분리 할 필요가 있다.

#9. Using stored procedures improperly
모든 RDBMS 는 Connection thread 별로 컴파일(Compiled)된 Stored Procedure 의 실행 계획을 유지하게 되는데

이것은 PHP 로 만든 페이지에서 요청을 보내서 SP 를 이용하여 데이터를 가져온다면
매번 컴파일을 거친다는 것이고 이것은 매우 큰 낭비라는 것이다(7~8% 정도)

특별히 매우 복잡하고 요쳥 빈도수가 많지 않은 작업이거나...
한번에 매우 많은 횟수의 Query 를 요청하는 경우가 아니라면....말이다.

그냥 Prepared Statements 를 써라...

#10. Operating on an indexed column with a function
Index Column 을 펑션으로 변환해서 사용하게 되면 Index 를 사용할 수 없게 된다.
그러니 있는 그대로 Index Column 을 사용 할 수 있도록 하는 것이 중요하다.

#11. Having missing or useless indexes
Index 는 SELECT 할때 검색 속도 향상에 매우 도움이 크다.

하지만 사용하지 않는(혹은 빈도 수가 매우 적은) Index 는 INSERT/UPDATE/DELETE 할때 매우 부담이 된다.
필요 없는 Index 는 반드시 삭제해주는 것이 좋다.

혹시 대량의 데이터를 입력이 필요 할 경우 경우에 따라서는 INDEX 를 삭제한 뒤
입력을 완료하고 인덱스를 생성하는 것이 나을 것이다.

#12. Not being a join-fu master
최대한 단순하게
복잡한 SQL 문을 쪼개서 데이터 묶음(Sets)으로 생각하라.

반복된 작업(Subquery,loop) 가 아닌 데이터 묶음(Join)으로 생각 해야 한다.
데이터의 묶음으로 처리하기 때문에 보다 나은 성능을 얻을 수 있다.

( 46~48p 를 반드시 참조하라!)

#13. Not accounting for deep scans
정렬된 데이터(ordered set)에서 매우 깊숙한(Deep scan) 곳에 데이터의 일부를 가져오는 것은 비용이 매우 많이 든다.

보통 게시판의 Paging 을 하면서 LIMIT 를 이용하게 되는데

페이지 넘버가 커지면 커질 수록 느려지는 경험을 해봤을 것이다.

이유는  LIMIT 를 이용하여 목록을 가져 오는 경우
1. 데이터를 정렬하고
2. 검색에 필요한 위치(offset) 을 지정해서 목록을 가져 온다.

여기서 데이터를 가져오는 위치(offset) 이 크면 클 수록 그 만큼 scan 을 하는 비용이

Full scan 비용에 근접하게 된다.
이를 피하기 위해선 해당 정렬된 데이터(Ordered set)의 크기를 줄여서 가져오는 것이 보다 나은 성능을 보장 할 수 있다.

#14. Doing SELECT COUNT(*) without WHERE on an InnoDB table
InnoDB 는 SELECT count(*) 로 Table 전체 Row 개 수를 가져오는 작업은 매우 퍼포먼스가 느린 작업이다.


InnoDB 내부적으로 매우 복잡(?) 한 구조로 인하여 생긴 문제인데 ( MyISAM 에서는....괜찮았다...)

필요하다면 별도의 테이블을 생성하여 Table 마다 Trigger 를 작성하여 Table Row count 를 관리하도록 하는 것도 방법이 되겠다.

#15. Not profiling or benchmarking
시스템 성능의 Bottleneck 을 항상 관찰하고(Profiling)
어플리케이션의 성능이 어느정도 까지 버틸 수 있는지 얼만큼의 부하를 견딜 수 있는지 테스트(Benchmark) 해볼 필요가 있다.

(54~56p 참조)

#16. Not using AUTO_INCREMENT
MySQL 에서 AUTO_INCREMENT 는 매우 PK 에 최적화 되어있다.

복합적으로 진행 되는 매우 많은 INSERT 에도 고성능으로 처리가 가능하다.
(Lockless reading and appending)

#17. Not using ON DUPLICATE KEY UPDATE
Application 에서 해당 Row 가 존재하는지 보고 Update or INSERT 를 결정하는 경우가 있는데
DB Connection 을 오가면서 소모되는 비용을 줄 일 수 있다. ( 약 5~6% 정도 )
물론 많은 양의 데이터가 와도 가능하다.

http://joinfu.com/presentations/kill-mysql-performance/kill-mysql-performance.pdf
http://ppassa.wordpress.com/2011/05/15/mysql-optimization-with-indexing/
2012/02/14 00:36 2012/02/14 00:36
이 글에는 트랙백을 보낼 수 없습니다
[로그인][오픈아이디란?]
오픈아이디로만 댓글을 남길 수 있습니다

PHP4->PHP5로 변경되면서 많은 변화가 있었다.

하지만 실제적으로 크게 와 닿는 부분은 없었던거 같다.
(사실 그렇게 화려하게 -_- 코드를 짤 일이 없어서 그런가?..)

PHP5 가 정식 릴리즈한 2004년 7월 이후 만 3년 만에 PHP v6(이하 PHP6) 에 대한 이야기를 얻을수 있었다.

몇가지 변경사항이 발생 하였는데 그 내용은 다음과 같다.

  1. 향상된 Unicode 에 지원.
  2. Namespace 지원
  3. Web 2.0 관련 SOAP,XML 기능 강화
  4. 일부 함수(function) 및 일부 확장모듈 ( Freetype 1, GD 1) 삭제

이다.

1. 향상된 Unicode 지원
Unicode 에 대한 지원은 문자셋(charset)에서 해방(?)을 위해선
어쩔 수 없는 선택이 되가는 분위기라 '거스를 수 없는 대세' 이랄까?

PHP6 에서도 Unicode 를 처리하기 위한 코어 함수들의 성능 향상이 있었다고 한다.

2. Namespace 지원
co-work 을 하거나 혹은 개발 소스가 방대하다 보면 함수/클래스의 이름이 중복되는 경우가 발생한다.
그렇다 보니 이름을 지으면서 점점 이상한 함수명이 발생 하게 되면서
나중에는 코드를 분석하데 직관적이지 못했다.

이러한 문제를 해결하기 위하여 Namespace 를 통하여 해결 할 수 있도록 하였다.

Namespace 의 이용. (Language : php)
  1. <?php
  2. // XMLWriter라는 클래스를 생성하고 싶다.
  3. // 하지만 PHP 에 내장된 XMLWriter 라는 클래스명 과 중박되게 된다. 이를 피하기 위하여 NathanAGood 라는 Namespace 를 지정한다.
  4. namespace NathanAGood;
  5. class XMLWriter
  6. {
  7.     // Implementation here...
  8. }
  9.  
  10. $writer = new NathanAGood::XMLWriter();
  11.  
  12. ?>




3. Web 2.0 환경에서 SOAP,XML 지원 활성화.
SOAP 는 이기종간 데이터 전송을 위한 프로토콜로써 많이 알려져있다.

SOAP에 대한 것은 PHP4 에서부터 확장 모듈(PECL) 로 제공 되었었다.
이것이 PHP5 에서는 내장 되었으나 기본으로 설치되진 않았다. 이것이 PHP6 로 오면서 기본적으로 활성화 되어 이용 할 수 있도록 변경이 된것이다.

XMLReader/XMLWriter 의 제공을 통하여 XML 이용을 보다 수월하게 할 수 있게 되었다.
이 XML 확장 역시 SOAP 와 같이 기본으로 제공하게 되면서
XML 파싱(Parsing)에 대한 압박에서 해방를 ( --)/ 만세!!!!

새로 추가 되는것이 있는가 하면
반대로 사라지는 부분도 있다.

1. 기존에 포함 되었던 확장 모듈의 삭제(  GD 1 & Freetype 1 )
GD 1, Freetype 1 이 어떠한 역할을 하는지는 굳이 설명하지 않아도 되리라 믿는다.
이 모듈이 삭제 되는 이유는 GD1/FreeType1 에 대한 새 버전이 나와있는 상황이고 보다 나은 기능과 성능을 제공함으로 굳이 이것을 포함하고 있어야 할 이유가 없다는 판단으로 제거가 되는것 같다.

역시 구시대 유물은 정리하는게 좋은거 같다 ㅡㅡ;

2. php.ini 의 일부 설정값 삭제
magic_quotes
register_globals
register_long_arrays
safe_mode

magic_quotes 는 특수기호에 대한 회피(escape)를 위하여 자동으로 제공하였던 기능이다.
보통은 이러한 기능은 sql-injection 공격을 회피하기 위한 방법으로 이용 되었으나.

이렇게 데이터가 들어갔다 나왔다 하면서 addslashes(),stripslashes() 등의 뻘짓을 해왔던 분이라면 얼마나 고된 일인지 알 것이다. magic_quotes 가 편리함을 준건 사실이지만. 이것이 원본 데이터를 보존한다는 의미에선 올바른 선택이 아니며 또한 sql-injection 에 대해서 자유로운 것도 아니였다.

다른 방법으로 mysql_escape_string() 이나 pg_escape_string() 등 을 이용하거나.
아니면 SQL 문에 변수를 치환(Binding) 을 통한 쿼리 작성법을 권장하고 있다.

SQL Query 이용시. (Language : php)
  1. <?php
  2. // magic_quotes = on 일 경우
  3. $sql = "INSERT INTO USERS (USERNAME) VALUES $_GET['username']";
  4. ?>
  5.  
  6.  
  7.  
  8. <?php
  9. // 데이터 바인딩(Binding)을 통한 쿼리 이용
  10. $statement = $dbh->prepare("INSERT INTO USERS (USERNAME) VALUES ?");
  11. $statement->execute(array($_GET['username']));
  12. ?>


전자의 경우는 DBMS 에 의존적인 쿼리가 발생 할 수 있다. 물론 이는 의도하지 않는 동작을 할 가능성이 높으며 나중에 데이터 출력에도 부가적으로 데이터를 변조 해줘야 하는 수고 스러움이 따른다.

후자의 경우는 전자의 경우 처럼 문자열(String) 을 변경 하는 방식이 아닌 데이터 자체를 치환(Binding) 함으로 해서
전자의 경우보다 sql-injection 에 대한 위험도가 훨씬 나아질 수 있다.
성능 또한 query-cache 등을 이용 할 수 있기 때문에 훨씬 앞선다고 볼 수 있다.

register_globals
의 이슈는 끊임 없이 제기 되었다.
이전에 편리함이 지금의 독이 된 케이스가 아닌가 한다.
너무 편리한 나머지 Form 데이터 전송중 변조의 우려가 끊임없이 제기 되었고
실제로 이 때문에 의한 사고(?) 도 다수 발생 하였다.
이에 PHP.net 에선 PHP v4.2 부터 기본적으로 꺼져있는 기능으로 제공 된다.
하지만 여전히 옵션엔 존재하였다.

그랬던 것이 PHP6 에서는 아예 제거 된다.
그러니 앞으로 는 $_GET,$_POST,$_SESSION 등의 변수 이용을 필수라고 봐야 한다.

register_long_arrays 이 무엇인고 하니
$HTTP_*_VARS 에 이용과 관련된 옵션이라고 한다. 대해선 크게 이슈화 된것을 보지 못하였는데.

$HTTP_*_VARS 대신 $_* 형 함수($_GET,$_POST,$_SESSION 같은..)를 이용하도록 하려는 이유로 빠진거 같다..ㅡㅡ;

safe_mode 옵션 또한 삭제 된다.
safe_mode 옵션은 흔히 공용서버에서 php 이용시 활성화 하는데
이에 따라 몇몇 함수의 이용에 제약을 따르는 경우가 있다.( 예 : fopen() 함수 )
이것이 PHP6 에서는 사라지게 되면서 별다른 문제는 안될 것이지만
safe_mode 를 활성화 한 상태에서 한번쯤 테스트 해볼 필요성을 제기한다.

3. ASP 식 Script Tag 삭제

더불어 ASP 식의 Script Tag 옵션 ( <% ... %> ) 또한 더이상 지원하지 않는다.
사실상 있으나 마나한 옵션인데 이번 기회에 제거 하려는것 같다.

4. POSIX 정규식 지원 삭제
POSIX 정규식(POSIX regular expressions) 함수도 더이상 지원하지 않게 된다.
ereg(),eregi() 등의 함수가 이에 해당하며 이를 Perl 정규식( Perl regular expressions) 로 치환 해야 한다.
Perl 정규식 함수들이 POSIX 정규식 함수들 보단 빠른 것으로 대체적으로 나왔었는데.
정규식 문법도 유사하고 사실 두 함수를 혼용하는 경우도 없지 않아 있었다.

하지만 완벽하게 호환되는 문법도 아니고 eregi()->preg_match() 식으로 별칭(alias) 화 하기는 힘들듯 싶다.
그러니 직접 변경하는 수 밖에 없다 ㅡㅡ;

이와 같이 PHP6 에서는 많은 변화가 있었다.
물론 아직 Beta 버젼도 나오지 않은 개발단계이긴 하나 미리 대비한다고 나쁠건 없지 않는가?

Unicode 지원과 Namespace 관련된 내용은 PHP v5.3 에 추가 될 예정이다.

지금 당장 PHP6 를 쓰고 싶다면 지금도 받아 볼 수 있지만( PHP6 snepshot download ).
PHP6 로 이동하기엔 너무 부담이 크다면 PHP v5.3로 업그레이드를 해보는것도 어떤가?

출처 : IBM dW - The future of PHP

2008/05/09 14:52 2008/05/09 14:52
이 글에는 트랙백을 보낼 수 없습니다
방문객....  | 2008/07/01 16:05
난 php6개발자 홈페이지 찾으면서 이런걸 봤는데... 홈페이지도 검색엔진으로는 복잡하게 뒤꽁무니(?)속에 있고..... 많은양의 변화도 있고....
위에 적은것만있는게 아니라 앞으로 외서로 국내 출간되면 더 쇼킹한 내용이 더 있을법한...
[로그인][오픈아이디란?]
오픈아이디로만 댓글을 남길 수 있습니다
Dot:Where is ......
byDot
Where is ......
전체 (177)
주절거림 (60)
윈도우벽지 (2)
Shoveling.. (9)
주워들은것들.. (48)
요집이 괜찮더라!! (0)
찍사놀이 (7)
관심꺼리~ (4)
«   2024/03   »
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
  1. 내 맘대로 보는 세상  2009
    맘에 안드는 Internet Explorer 업데이트 방침!
  2. 시리니  2008
    브라우저 업데이트, 작지만 큰 실천입니다.
  3. Dinosur와 KM의 Blog  2007
    저도 보통 사람
  1. 2019/02 (1)
  2. 2018/07 (1)
  3. 2018/01 (11)
  4. 2017/12 (10)
  5. 2017/10 (1)