mysqli는 뭔가? mysql보다 더 빠르고, 더 안전한 쿼리문이라는거
간단하게 말하면 지금까지 써오던 mysql이 대규모 연결부분에서 약간 문제가 있었다네요. mysql의 새로운 확장이라고 보면 되구요.
MySQLi라고도 부른다네요.. PHP5와 MySQL4.1 버전 이상에서만 지원하고 MySQLi는 MySQL보다 40배 정도 속도향상과 보안성을 향상시킬 수 있다네요.
BUT
MySQLi가 MySQL과 차별되는 점은 객체지향 인터페이스, Prepared Statement 지원, Transaction 처리 등이 될 수 있는데,
솔직히 이들 중에서 ‘속도’와 관련된 점은 Prepared Statement 정도라고 볼 수 있습니다.
하지만 이것이 속도 측면에서 영향을 끼치려면 쿼리 상에서 가변되는 부분이 많거나 쿼리의 조인 관계가 복잡하여 실행플랜을 결정하는데 매번 일정량 이상의 부하가 걸려야만 해당이 되는 이야기입니다.
‘보안’측면에서 좋다는 것은 SQL Injection과 관련된 이야기인데, Prepared Statement를 사용하면 구조적으로 인젝션이 불가능해지는 측면을 뜻하는 것입니다.
하지만 이 또한 철저하게 escape 처리를 한다면 사실 무관하다고 봐도 상관이 없고…
하지만 코드 예문에서 보이는 수준의 단순한 쿼리들만 실행하는 경우라면 그 차이는 미미하고, 오히려 속도 측면에서 대부분의 벤치마킹 상의 결과가 기존의 MySQL에 비해 MySQLi가 나은 부분을 보이지 않는 것을 나타내는 한, 단순히 성능이나 속도 면을 고려한 이주는 부정적이라고 볼 수 있을 겁니다.
실무적으로 말씀드리면 prepare stmt가 ‘일반적으로’ 빠르긴 빠릅니다만, 그게 빨라지는 수준이 막 두배, 세배 .. 이런 식으로 빨라지는게 절대 아닙니다.
prepare 했느냐 안했느냐의 차이는 결국 dbms의 optimizer가 query plan을 하는 시간 만큼이거든요.
sql 자체를 컴파일(?)해서 어떤 식으로 내부적인 동작을 하게 하느냐 하는 동작방식을 결정하는 부분인데, 사실 그 시간이라는게 굉장히 미미합니다.
물론 그 쿼리를 엄청나게 많이 사용하는 경우… 예를 들면 초당 수백 수천번 사용한다면 전체적인 서버의 성능에 영향을 끼칠 수는 있겠죠.
하지만 일반적으로 웹 환경의 서버환경에서 그 차이가 가시화될 수준이 되려면 상당히 특화(?)된 환경이라고 밖에는 볼 수 없을겁니다.
게다가 투자 대비 효과 측면도 고려해야 하죠. 방식을 변경한다는 것은 상당히 손품이 많이 들어가는 일임에 틀림 없는데, 얻어지는 성과는? 2% 향상? 막 이러면, 곤란해질 가능성이 농후하니까요.
다음 문으로 돌려봐도 mysql이 바른것 같네요.
<? function get_time() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } $start = get_time(); include_once("./inc/config.php"); $conn = @mysql_connect($dbhost, $dbuser, $dbpass) or die('DB ERROR'); @mysql_query("set names UTF8"); @mysql_select_db($dbname); $sql = "SELECT date,data FROM 테이블 WHERE date like '201312%' "; $result = mysql_query($sql); while ( $row = mysql_fetch_array($result) ) { //echo $row['date']; //echo $row['data']; } $end = get_time(); $time = $end - $start; echo ''.$time.'초 걸림'; ?> <? function get_time() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } $start = get_time(); include_once("./inc/config.php"); $mysqli = mysqli_connect($dbhost, $dbuser, $dbpass, $dbname) or die('DB Error'); mysqli_query($mysqli, 'set names utf8'); if (mysqli_connect_errno()) { printf("Connect failed: %s\n", mysqli_connect_error()); exit(); } // 미리 준비된 문장 if ($stmt = $mysqli->prepare("SELECT date,data FROM 테이블 WHERE date like ?")) { $stmt->bind_param("s", $code); $code = "201312%"; $stmt->execute(); /* 변수를 미리 준비된 문장에 결합, bind variables to prepared statement */ $stmt->bind_result($col1, $col2); // fetch values while ($stmt->fetch()) { //echo $col1." ".$col2; } // 문장 닫기 $stmt->close(); } // 접속 닫기 $mysqli->close(); $end = get_time(); $time = $end - $start; echo ''.$time.'초 걸림'; ?>
사용방법도 약간 틀리구. 책에서 발췌..해서 그런지…
그래서 이번 2014 6월 개표프로그램에 한번 써본 기본 SELECT문.
// 공통연결부분 $host="localhost"; $user="root"; $pw="apmsetup"; $db="dbtest"; $my_db=new mysqli($host,$user,$pw,$db); mysqli_query($my_db,"set names utf8"); if ( mysqli_connect_errno() ) { echo mysqli_connect_error(); exit(); }
// simple SELECT $rs = mysqli_query($my_db, "select no,name,email from shows limit 10"); while($data = mysqli_fetch_array($rs)){ echo $data['name']; }
//simple DELETE / UPDATE $my_db->query("update shows set name = '하하' where no='2'");
// 보안용 SELECT 사용 // 미리 준비된 문장 if ($stmt = $my_db->prepare("select no,name,email from shows WHERE no = ? ")) { $stmt->bind_param("s", $no); $no = "2"; $stmt->execute(); // 변수를 미리 준비된 문장에 결합 $stmt->bind_result($col1, $col2, $col3); while ($stmt->fetch()) { echo $col2; } // 문장 닫기 $stmt->close(); }
// 보안입력 $stmt = $my_db->prepare("INSERT INTO shows (name,email) VALUES (?, ?)"); $stmt->bind_param("ss", $name, $email); $name = '카라'; $email = 'kara@gmail.com'; // 미리준비된 문법 실행하기 $stmt->execute(); printf("%d Row inserted.n", $stmt->affected_rows); // 문법과 접속 닫기 $stmt->close();
// 접속 닫기 $my_db->close();
정리가 잘되어 있어 쉽게 이해가 되네요. ^^ 잘 읽어보구 갑니다.