SQL 問い合わせ計画 (SQL query plan)

URL: https://www.kkaneko.jp/tools/sqlitedb/6.html

演習で行うこと

SQLite 3 の SQL 演習に関連する部分

【SQLite 3 の主要なオペコード (Opcode) の要点】

* SQLite 3 のオペコードの説明は https://www.sqlite.org/opcode.html にある.

* SQLite 3の SQL の説明は https://www.sqlite.org/lang.html (English Web Page) にある.

* 命令列やアドレスの番号は SQLite 3 のバージョンによって異なるので,この Web ページの表示例と一致しないことがある.

郵便番号データベース (Japanese ZIP code database)

郵便番号データベースは zips, kens, shichosons の 3 つのテーブルから構成される.

データファイルの準備 (Prepare data files)

演習では,郵便番号データファイル (SQL 形式)を使う (Use Japanese ZIP code data file to construct larger database).

データファイル

  1. 郵便番号データファイル (SQL 形式) (Japanese ZIP code data file in SQL format) : zipsutf8.sql

    ファイル名は zipsutf8.sql.ファイルサイズは約 40 メガバイト.行数は 147499 行の SQL プログラム (The file name is 'zipsutf8.sql. The size of file is about 40 M-bytes. The number of rows are 147499.)

  2. 都道府県データファイル (SQL 形式) (Japanese Prefacture data file in SQL format) : kensutf8.sql

    ファイル名は kensutf8.sql.ファイルサイズは 4 キロバイト.行数は 49 行の SQL プログラム (The file name is 'kensutf8.sql. The size of file is about 4 K-bytes. The number of rows are 49.)

  3. 市町村データファイル (SQL 形式) (Japanese Prefacture data file in SQL format) : shichosonsutf8.sql

    ファイル名は shichosonsutf8.sql.ファイルサイズは 300 キロバイト.行数は 1943 行の SQL プログラム (The file name is 'shichosonsutf8.sql. The size of file is about 300 K-bytes. The number of rows are 1943.)

Sqliteman で既存のデータベースを開く

すでに作成済みのデータベースを,下記の手順で開くことができる.

以下の手順で,既存のデータベースファイルを開く. (Open an existing database file)

  1. File」→ 「Open
  2. データベースファイルを開く

    * Ubuntu での実行例(「/home/ubuntuuser/mydb」を開く場合)

    データベースファイル /home/ubuntuuser/mydb を選び, 「開く」をクリック (Click '開く' after choosing the database file "/home/ubuntuuser/mydb")

    * Windows での実行例(「C:\SQLite\mydb」を開く場合)

    データベースファイル C:\SQLite\mydb を選び, 「開く」をクリック (Click '開く' after choosing the database file "C:\SQLite\mydb")

SQL を用いたテーブル定義と一貫性制約の記述

SQL を用いて,kens, shichosons, zips テーブルを定義し,一貫性制約を記述する. (Define 'kens', 'shichosons' and 'zips' tables and specify integrity constraints using SQL)

* 全てのテーブルに主キーがある (All tables have a primary key)

  1. kens, shichosons, zips テーブルの定義 (Define three tables)

    次の SQL を入力 (Write the following SQL to define tables)

    create table kens (
        id        integer primary key autoincrement not null,
        ken_kanji text UNIQUE not null,
        ken_kana  text UNIQUE not null );
    
    create table shichosons (
        jiscode         integer primary key not null check (jiscode >= 1000 AND jiscode <= 50000),
        ken_kanji       text not null,
        shichoson_kanji text not null,
        shichoson_kana  text not null);
    
    create table zips (
        id           integer primary key autoincrement not null,
        zipcode      integer not null,
        zip_old      integer not null,
        jiscode      integer not null REFERENCES shichosons(jiscode),
        choiki_kanji text not null,
        choiki_kana  text not null,
        flag10       text    not null,
        flag11       integer not null check ( flag11 >= 0 AND flag11 <= 1 ),
        flag12       integer not null check ( flag12 >= 0 AND flag12 <= 3 ),
        flag13       integer not null check ( flag13 >= 0 AND flag13 <= 1 ),
        info14       integer check ( info14 >= 0 AND info14 <= 1 ),
        info15       integer check ( info15 >= 0 AND info15 <= 5 ) );
    

    * 「SQL Editor」のウインドウには,SQL プログラムを書くことができる. In the 'SQL string' window, you can write down SQL program(s).

  2. 複数の SQL 文の一括実行

    複数の SQL 文を一括実行するので,カーソルを先頭行に移動した後に,「Run multiple SQL statements ...」のボタンをクリックする. (Move the cursor to the top statement. Click "Run multiple SQL statements from current cursor position in one batch" icon)

  3. 「Script Output」ウインドウの確認(Inspect "Script Output" window)

    エラーメッセージが出ていないことを確認

    * エラーメッセージが出たときは,kens, shichosons, zips テーブルを作り直す. テーブルを作りなおすときは, 最初に,次の手順で,テーブル定義を消去する (try to drop tables)
    1. 次の SQL を入力 (Write the following SQL to drop tables)

      * 「SQL Editor」のウインドウには,SQL プログラムを書くことができる. In the 'SQL string' window, you can write down SQL program(s).

      DROP TABLE zips;
      DROP TABLE kens;
      DROP TABLE shichosons;
      
    2. 複数の SQL 文の一括実行

      複数の SQL 文を一括実行するので,カーソルを先頭行に移動した後に,「Run multiple SQL statements ...」のボタンをクリックする. (Move the cursor to the top statement. Click "Run multiple SQL statements from current cursor position in one batch" icon)

      * kens, shichosons, zips テーブルを作成済みでない場合には,上記の操作を行うとエラーメッセージが出る.

データベースの生成 (Generate Database)

  1. 次の操作に移る前に,起動していた Sqliteman を終了しておく
  2. SQLite 3の起動 (Execute the SQLite. The database name 'mydb' is specified.)

    * Ubuntu の場合

    1. 端末を起動する
    2. SQLite を起動する.

      このとき,データベース名として mydb を指定する.(The logical database name is 'mydb').

      「sqlite」ではなく「sqlite3」であることに注意.

      sqlite3 mydb
      

    * Windows の場合

    Windowsコマンドプロンプトで,次の操作を行う.(Use the Windows command prompt, and do the following).

    まず,SQLite 3 のデータベース・ディレクトリ C:\SQLite に移る.

    cd /d C:\SQLite
    

    その後,SQLite を起動する.

    このとき,データベース名として mydb を指定する.(The logical database name is 'mydb').

    cd /d C:\SQLite
    .\sqlite3.exe mydb
    
  3. kensutf8.sql と shichosonsutf8.sql と zipsutf8.sql の実行 (Execute the kensutf8.sql, shichosonsutf8.sql and zipsutf8.sql)
    .read kensutf8.sql
    .read shichosonsutf8.sql
    .read zipsutf8.sql
    

    数秒待つ (Wait a several seconds).

    * 「cannot open "zipsutf8.sql"」のようなエラーメッセージは「ファイルが無い」という意味である. SQLite ディレクトリに zipsutf8.sql と kensutf8.sql と shichosonsutf8.sql の 3 つのファイルを置いてから,上の操作をやりなおす.
  4. (オプション)各テーブルの行数の確認 (the number of rows)
    select count(*) FROM kens;
    select count(*) FROM shichosons;
    select count(*) FROM zips;
    
  5. SQLite 3の終了

    .exit」で終了.

Sqliteman で既存のデータベースを開く

以下の手順で,既存のデータベースファイルを開く. (Open an existing database file)

  1. File」→ 「Open
  2. データベースファイルを開く

    * Ubuntu での実行例(「/home/ubuntuuser/mydb」を開く場合)

    データベースファイル /home/ubuntuuser/mydb を選び, 「開く」をクリック (Click '開く' after choosing the database file "/home/ubuntuuser/mydb")

    * Windows での実行例(「C:\SQLite\mydb」を開く場合)

    データベースファイル C:\SQLite\mydb を選び, 「開く」をクリック (Click '開く' after choosing the database file "C:\SQLite\mydb")

  3. 「Tables」を展開すると,テーブルの一覧 (List of Tables) が表示されるので確認する (List of tables appears by clicking 'Tables')
  4. 「System Catalogue」を展開し,「sqlite_master」をクリックすると,データベース・スキーマ (database schema) が表示されるので,kens, shichosons, zips の行を確認する (Database schema appears by clicking 'sqlite_master')

    * 「55735」, 「65950」, 「66052」 の部分は別の数値になる. これらは,テーブルのデータが置かれるページ番号 (rootpage) であり, SQLite 3 が自動で決める値である.

Sqliteman を用いたデータのブラウズ

SQL 問い合わせの発行と評価結果の確認

テーブル kens に関する条件検索 (SQL queries about the table 'kens')

テーブル kens を使用.都道府県名(ken_kanji)による条件検索などを行う. (Use the table 'kens'. Several SQL programs are issued)

テーブル shichosons に関する条件検索 (SQL queries about the table 'shichosons')

テーブル zips に関する条件検索 (SQL queries about the table 'zips')

テーブル kens とテーブル shichosons の結合問い合わせの例

データベースの構造の確認 (Database Structure)

  1. sqlite_master をクリック (Click 'sqlite_master')
  2. テーブルと二次索引のルート・ページ番号が分かる (Root page number of each table and secondary index)

zips, kens, shichosons の 3 つのテーブルのルートページ (root page) は,この資料では次の値として説明する.

* ルート・ページ番号は SQLite 3 が決める値なので, 実際には上とは違う値になる.

(The number is automatically decided by the database management system)

Sqliteman を用いた SQL 問い合わせ計画の表示

ここでは,SQL 問い合わせ計画の表示例を示す.

データベース管理システムは, SQL 文をコンパイルし,SQL 問い合わせ計画を作る. SQL 問い合わせ計画とは,データベースに関する基本的なオペレータの並びである. (Database management system compiles a SQL statement into a SQL query plan. SQL query plan is a sequence or a tree of database operations).

SQLite 3の問い合わせ計画については,SQLite Virtual Machine Opcodes の Web ページを参照.(please refer to https://www.sqlite.org/opcode.html for SQLite opcodes)

* テーブルの全ての行の表示 (List all rows of a table)

【表示された問い合わせ計画の要点】

アドレス (addr) オペコード 主なオペランド  
2 OpenRead P2 = 7 ルート・ページが 7 であるテーブル (この場合は,テーブル zips) のカーソルを作る (Open table 'zips' for read, and make a cursor)
3 Rewind P2 = 18 カーソルをテーブルの先頭行に位置づける.テーブルが空の場合には,アドレス 18 (Close)にジャンプする (Use the first row. If the table is empty then jump to '18')
4 Rowid P2 = 1 主キーの値を,レジスタ1に格納する (Primary key is #0 value. The value is stored into register)
5〜15 Column P2 = 1〜11, P3 = 2〜12 列番号1から11の値を,それぞれレジスタ2から12に格納する. (#1, #2, #3, #4, #5, #6, #7, #8, #9, #10 and #11 values are stored into registers)
16 ResultRow P1 = 1, P2 = 12 レジスタ 1 からレジスタ 12 までの値を1行として出力する (Generate output using registers)
17 Next P2 = 4 もし,カーソルが指し示すレコードが末端レコードならば,次の命令に進む. もし,カーソルが指し示すレコードが末端レコードでなければ,カーソルを1つ進めて,アドレス4 (Rowid のところ) にジャンプする. (Advance cursor to the next row. If there are more rows, then jump to the address '4')

二次索引がないとき,テーブルの本体が1行ずつ処理される.テーブルの全ての行について処理が繰り返される. (このことを「tuple at a time」ともいう)

* 列の絞込み

【表示された問い合わせ計画の要点】

「SELECT * FROM zips; 」と「SELECT zipcode, choiki_kanji FROM zips;」の違いを説明する.

アドレス (addr) オペコード 主なオペランド  
4 Column P2 = 1, P3 = 1 列番号1の値を,レジスタ1に格納する. (#1 value is stored into registers)
5 Column P2 = 4, P3 = 2 列番号4の値を,レジスタ2に格納する. (#4 value is stored into registers)

この場合も,テーブルの本体が1行ずつ処理される.テーブルの全ての行について処理が繰り返される.

* 条件を満足する行のみの表示 (List the rows which satisfy a given condition)

最初,カーソルは先頭行にセットされる. アドレス 6 の「Ne 1 10 2 collseq(BINARY) 6c」は条件付きジャンプであり,もとの SQL で指定した選択条件「jiscode = 40135」の処理を行う. (true の時に限り,新しい行が評価結果に追加される) その後,カーソルは次の行へ動く. このようにして,zips テーブルの全ての行が精査される.

Sqliteman を用いた二次索引の削除

二次索引がないときと,二次索引があるときの SQL 問い合わせ計画を比べるため, 下記の手順で,zips テーブルの二次索引を確認し,二次索引を全て削除する. (Inspect a secondary index of table 'zips' and delete all secondary indices of the table).

DROP INDEX を用いた二次索引の削除

SQL でも二次索引を削除できる (remove the secondary index using 'DROP INDEX')

DROP INDEX idx2;