tombo2-progress’s diary

できるだけ毎日1時間を切り取ってここに晒す。誤字脱字気にしない。日本語が崩壊するのも気にしない。最終的にまとめて本ブログに書く

prepared_statementの投げ方とMySQLからの確認の仕方

以前書いたような気がするのだが、検索してもなかったので書く。 Prepared statementを使ってcom_stmt_prepareが流れるか見てみる。

結論:流れた。

実際のサービスでは使われないらしいがどうなのだろうか?prepareしてidとパラメータ指定の2往復になってしまうため、1 session中に複数回同じstatementを投げない限りパフォーマンスが落ちるというのはわかるが、、、

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "log"
    "time"
)

func generalQuery() {
    db, error := sql.Open("mysql", "root:root@tcp(127.0.0.1:13306)/sakila")
    if error != nil {
        log.Fatal(error)
    }

    rows, err := db.Query("SELECT film_id FROM film limit 3")
    if err != nil {
        log.Fatal(err)
    }

    var id int
    var c1 int
    for rows.Next() {
        err = rows.Scan(&id)
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(id, c1)
    }
}

func preparedStatements() {
    db, error := sql.Open("mysql", "root:root@tcp(127.0.0.1:13306)/sakila")
    if error != nil {
        log.Fatal(error)
    }

    stmtSelect, err := db.Prepare("SELECT film_id FROM film WHERE film_id = ?")
    if err != nil {
        panic(err.Error()) // proper error handling instead of panic in your app
    }
    defer stmtSelect.Close()
    time.Sleep(3 * time.Second)

    var squareNum int

    // Query id = 1
    err = stmtSelect.QueryRow(1).Scan(&squareNum)
    if err != nil {
        panic(err.Error()) // proper error handling instead of panic in your app
    }
    fmt.Println(squareNum)

    // Query id = 2
    err = stmtSelect.QueryRow(2).Scan(&squareNum)
    if err != nil {
        panic(err.Error()) // proper error handling instead of panic in your app
    }
    fmt.Println(squareNum)

}

func main() {
    generalQuery()
    preparedStatements()
}

ついでにMySQL側でPreparedされたクエリを取得するにはperformance_schema.prepared_statements_instancesテーブルを参照する. 5.7.4で導入されたようなことが書いてあるので要確認.

https://mysqlserverteam.com/mysql-performance-schema-prepared-statements-instrumentation/

上記のコードでprepareされたクエリのサンプル

mysql> select * from prepared_statements_instances\G
*************************** 1. row ***************************
      OBJECT_INSTANCE_BEGIN: 140545020190976
               STATEMENT_ID: 1
             STATEMENT_NAME: NULL
                   SQL_TEXT: SELECT film_id FROM film WHERE film_id = ?
            OWNER_THREAD_ID: 42
             OWNER_EVENT_ID: 1
          OWNER_OBJECT_TYPE: NULL
        OWNER_OBJECT_SCHEMA: NULL
          OWNER_OBJECT_NAME: NULL
              TIMER_PREPARE: 170553000
            COUNT_REPREPARE: 0
              COUNT_EXECUTE: 0
          SUM_TIMER_EXECUTE: 0
          MIN_TIMER_EXECUTE: 0
          AVG_TIMER_EXECUTE: 0
          MAX_TIMER_EXECUTE: 0
              SUM_LOCK_TIME: 0
                 SUM_ERRORS: 0
               SUM_WARNINGS: 0
          SUM_ROWS_AFFECTED: 0
              SUM_ROWS_SENT: 0
          SUM_ROWS_EXAMINED: 0
SUM_CREATED_TMP_DISK_TABLES: 0
     SUM_CREATED_TMP_TABLES: 0
       SUM_SELECT_FULL_JOIN: 0
 SUM_SELECT_FULL_RANGE_JOIN: 0
           SUM_SELECT_RANGE: 0
     SUM_SELECT_RANGE_CHECK: 0
            SUM_SELECT_SCAN: 0
      SUM_SORT_MERGE_PASSES: 0
             SUM_SORT_RANGE: 0
              SUM_SORT_ROWS: 0
              SUM_SORT_SCAN: 0
          SUM_NO_INDEX_USED: 0
     SUM_NO_GOOD_INDEX_USED: 0
1 row in set (0.00 sec)