インデックスの生成・削除。
成果物
情報源
インデックスとは
データを高速に取得する方法。B木など何らかのアルゴリズムを用いる。
インデックス用データを保存するディスクスペースが必要。また、データ挿入時にインデックス用データを更新する処理も必要。
公式からは説明を見つけられなかった。
メリット
- 検索が速くなる
デメリット
- 挿入が遅くなる
- ファイルサイズ肥大化
Index操作
create index
create unique index
create index if not exists
create index where
drop index
drop index if exists
やってみる
create table T(A int);
sqlite3 :memory: \ "create table T(A int);" \
create index
0.sql
create table T(A int); create index idx_T_A on T(A); .indexes
インデックスの生成を確認した。
sqlite3 :memory: ".read 0.sql"
idx_T_A
なぜか以下だと出ない。
sqlite3 :memory: < 0.sql
対話モードでも確認できた。
sqlite3
sqlite> create table T(A int); sqlite> create index idx_T_A on T(A); sqlite> .indexes idx_T_A
create unique index
1.sql
create table T(A int); create unique index idx_T_A on T(A); .indexes
idx_T_A
インデックスの生成を確認した。
UNIQUE制約エラー確認
1_unique.sql
create table T(A int); create unique index idx_T_A on T(A); insert into T values(0); insert into T values(0); .indexes
Error: near line 4: UNIQUE constraint failed: T.A
テーブルの列にunique
制約を付与したときと同じ反応。
もしかして、テーブルの列にunique
制約をつけるより、unique
インデックスを作ったほうがいいのかな? drop
可能だし、検索の高速化に使えるし。
後からUNIQUE制約追加
1_unique_add.sql
create table T(A int); insert into T values(0); insert into T values(0); create unique index idx_T_A on T(A); .indexes
Error: near line 4: UNIQUE constraint failed: T.A
重複データがある状態で、その後にUNIQUE制約つきインデックスを追加してみた。追加後にエラーが出た。
rm -f a.db sqlite3 a.db \ "create table T(A int);" \ "insert into T values(0);" \ "insert into T values(0);" \ "create unique index idx_T_A on T(A);" \ ".indexes" \ "select * from T;"
sqlite3 a.db "select * from T;" rm -f a.db
0 0
だが、当然テーブルには重複したデータが残っている。
create index if not exists
2.sql
create table T(A int); create index if not exists idx_T_A on T(A); .indexes
idx_T_A
インデックスの生成を確認した。
存在時にエラーにならないことを確認
2_exists.sql
create table T(A int); create index if not exists idx_T_A on T(A); create index if not exists idx_T_A on T(A); .indexes
idx_T_A
インデックスの生成を確認した。
存在時にエラーになることを確認
if not exists
を使わずに同名のインデックスを作成する。
2_error.sql
create table T(A int); create index idx_T_A on T(A); create index idx_T_A on T(A); .indexes
Error: near line 3: index idx_T_A already exists
だから作成するときはif not exists
つけたほうがいい。
create index where
3.sql
create table T(A int); create index idx_T_A on T(A) where is idx_T_A not null; .indexes
idx_T_A
インデックスの生成を確認した。
部分インデックスとは、条件に一致したレコードだけを対象にしたインデックス。たとえば上記コードにて、ほとんどの行のA
の値がNULL
だとしたら、ディスクスペースがかなり節約できるらしい。
drop index
4.sql
create table T(A int); create index idx_T_A on T(A); .indexes drop index idx_T_A; .indexes
idx_T_A
インデックスの削除を確認した。
drop index if exists
5.sql
create table T(A int); create index idx_T_A on T(A); .indexes drop index if exists idx_T_A; .indexes
インデックスの削除を確認した。
存在しないのに削除しようとしてもエラーなし
5_not_exists.sql
create table T(A int); .indexes drop index if exists idx_T_A; .indexes
存在しないのに削除しようとするとエラー
if exists
を使わずにやるとエラー。
5_error.sql
create table T(A int); .indexes drop index idx_T_A; .indexes
Error: near line 3: no such index: idx_T_A
だから削除するときはif exists
つけたほうがいい。
まとめ
create | drop | 効果 |
---|---|---|
if not exists |
if exists |
定義存在エラー回避 |
unique |
一意制約追加(drop 可) |
|
where |
対象データの選別 |
速さについて
古いけどDBMSの速さについて以下のような検証をみつけた。SQLite3が圧倒な大差をつけてトップ。これをみるともうSQLite3以外ありえない。Oracleは許可なくベンチマーク公開禁止とか怖い。論外。
どうすれば速くなる?
思うのだが、select
で1000件返すときに非同期で10件ずつ返すように実装できないのだろうか? プログラミング言語ならできるのだが、SQLにも欲しい。あれば体感速度があがる。
時間かかるのはそこじゃないのかな? 件数が増えると最低限必要な時間が長くなるのが問題なのかな?
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 4.4.12(1)-release
- SQLite 3.29.0
- MeCab 0.996ユーザ辞書
$ uname -a Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux
前回まで
- SQLite3学習 俯瞰まとめ
- SQLite3学習 環境構築まとめ
- SQLite3学習 インタフェースまとめ(C言語、CLI、対話モード、Tcl...)
- SQLite3学習 ドットコマンドまとめ
- SQLite3学習 JSON拡張まとめ
- SQLite3学習 FTSまとめ(ICU, MeCab)
- SQLite3学習 再帰クエリ(WITH RECURSIVE)
- SQLite3学習 R-Treeモジュール
- SQLite3学習 Geopoly(2次元ベクタ画像の生成)
- SQLite3学習 拡張関数(generate_series)
- SQLite3学習 拡張ライブラリ数学関数(extension-functions.c)
- SQLite3学習 謎と名前
- SQL文の分類(DDL,DML,TCL,DCL)
- SQL構文 alter(rename)
- SQL構文 alter(add column)概要
- SQL構文 alter(add column)制約
- SQL構文 alter(add column)sqlite_master変更しても反映されない
- SQL構文 alter(add column)スキーマ再定義(テーブル再作成による定義変更)
- SQL構文 analyze
- SQL構文 attach/detach
- SQLite3構文 begin,end,commit,rollback,savepoint(deferred,immediate,exclusive)
- SQLite3構文 コメント
- SQLite3構文 create/drop