關(guān)于ios本地大容量存儲sqlite優(yōu)化

隨著app信息量越來越大,每次從網(wǎng)絡(luò)獲取數(shù)據(jù)已經(jīng)不是很可取的方案了,本地?cái)?shù)據(jù)庫的運(yùn)用已經(jīng)越來越普遍了。
而說道移動端,不得不提的就是SQlite了,隨著本地?cái)?shù)據(jù)庫的大量運(yùn)用,F(xiàn)MDB也受到了很多程序員的關(guān)注。
FMDB是一個很棒的庫,對SQLite的進(jìn)行了一層更符合mvc的包裝,使得使用變得非常便捷和方便。
回過頭來說,移動DB的數(shù)據(jù)量也是越來越大,動輒10萬條的數(shù)據(jù)已經(jīng)不再稀奇,對于幾十萬條大量的數(shù)據(jù)來說,讀取,插入等的優(yōu)化對于用戶體驗(yàn)的優(yōu)化是很重要的。

優(yōu)化

對于沒有做任何優(yōu)化的DB來說,幾十萬的數(shù)據(jù)讀取,至少是幾十秒甚至可能需要更長的時間,即使使用loading頁面等的緩沖,這還是遠(yuǎn)遠(yuǎn)不夠的。

1)使用數(shù)據(jù)庫事務(wù)

FMDB默認(rèn)是對每一句sqlite語句執(zhí)行事務(wù)操作的。事務(wù)是為了對數(shù)據(jù)庫進(jìn)行操作失敗時,進(jìn)行數(shù)據(jù)回滾的一種安全機(jī)制。但是沒次執(zhí)行都執(zhí)行事務(wù)是一件非常耗時的操作,此時在進(jìn)行大量數(shù)據(jù)操作時,可以在全部語句執(zhí)行完成后,在做全面的事務(wù)操作。例:

-(void)shiwucaozuo
{
     [_dataBase inTransaction:^(FMDatabase *db, BOOL *rollback) {
        for (int i = 0; i<100000; i++) {
          //執(zhí)行sql語句
            BOOL a = [db executeUpdate:SQL];
            if (!a) {
                *rollback = YES;
                return;
            }
        }
    }];
}

這樣顯示的控制就可以有效的控制時間了,插入等操作優(yōu)化會有著一個數(shù)量級的增長優(yōu)化。
小技巧:在查詢出數(shù)據(jù)后,在數(shù)據(jù)量不大的情況下,可以加載到內(nèi)存中,避免每次進(jìn)行數(shù)據(jù)庫查詢操作。
比如,數(shù)據(jù)轉(zhuǎn)換成model以后可以以key-value的形式存儲在字典中

2)使用FMDB的Statement cache的機(jī)制

FMDB的cache機(jī)制就是在執(zhí)行DB操作結(jié)束后會根據(jù)sql作為key查詢cache。如果沒有cache就會加入cache中,會有兩次查詢操作。可以利用FMDB的cache緩存sql,這里推薦的做法是緩存不帶參數(shù)的sql,然后在準(zhǔn)備執(zhí)行使用時直接通過緩存時返回的id從cache中直接獲取sql語句,這樣只需要一次的查詢操作,在執(zhí)行大量sql語句時,大量的查詢還是會對性能有所損耗的,只緩存不帶參數(shù)的sql語句有助于提高查詢效率
例:

-(void)cacheSQl:(FMDatabase*) withSql:(NSString*)sql{
    id = [db cache:sql]'
    //上面的db需要緩存,下次可以通過該id找回sql.
}
可以通過
[db executeUpdataWithStatementID]方法直接獲取sql。

3)修改日志模式

日志模式

SQLite中日志模式主要有DELETE和WAL兩種,其他幾種比如TRUNCATE,PERSIST,MEMORY基本原理都與DELETE模式相同,不作詳細(xì)展開。DELETE模式采用影子分頁技術(shù)(Shadow paging),DELETE模式下,日志中記錄的變更前數(shù)據(jù)頁內(nèi)容;WAL模式下,日志中記錄的是變更后的數(shù)據(jù)頁內(nèi)容。事務(wù)提交時,DELETE模式將日志刷盤,將DB文件刷盤,成功后,再將日志文件清理;WAL模式則是將日志文件刷盤,即可完成提交過程。那么WAL模式下,數(shù)據(jù)文件何時更新呢?這里引入了檢查點(diǎn)概念,檢查點(diǎn)的作用就是定期將日志中的新頁覆蓋DB文件中的老頁,并通過參數(shù)wal_autocheckpoint來控制檢查點(diǎn)時機(jī),達(dá)到權(quán)衡讀寫的目的。
DELETE模式下,寫事務(wù)直接更新db-page,并將old-page寫入日志,讀事務(wù)則直接讀db-page,因?yàn)閐b-page中保存了提交的所有事務(wù)的更新。事務(wù)提交后,直接將日志文件刪除;若事務(wù)需要回滾,則將日志中old-page中的內(nèi)容覆蓋db-page,恢復(fù)原始內(nèi)容。WAL模式下,寫事務(wù)將更新寫到日志文件中,不更新db-page,事務(wù)提交時,也不影響db-page,只是將日志持久化而已。若事務(wù)回滾,則不將日志寫入文件即可。由于最新的數(shù)據(jù)在日志文件中,那么如何讀取到最新的數(shù)據(jù)呢?WAL模式通過end-mark(事務(wù)提交位點(diǎn))達(dá)到這一目的。具體而已,事務(wù)開始時,會首先掃描日志文件,獲取最近一個end-mark,在讀取數(shù)據(jù)時,首先會判斷page是否則在wal日志文件中存在,因?yàn)橥粋€page,一定是wal文件中的比db文件中的要新。如果存在,則使用,否則,再從db文件中獲取指定的page。從流程上來看,這個過程比較慢,因?yàn)闃O端情況下,每次讀都需要掃描wal文件和db文件。為了提高性能,WAL模式中有一個wal-index文件,這個文件記錄了頁號和該頁在WAL文件中的偏移,并且wal-index文件采用共享緩存實(shí)現(xiàn),從文件名也可以看到,后綴是.shm,因此判斷page是否在wal文件存在的操作實(shí)質(zhì)是一次內(nèi)存讀。wal-index采用hash表存儲,因此查詢效率也非常高。與傳統(tǒng)的DBMS不同,SQLite中記錄的日志,實(shí)質(zhì)是dirty-page,重做實(shí)質(zhì)是對利用WAL中的日志頁覆蓋db-page,這種實(shí)現(xiàn)方式比較簡單,同時也比較浪費(fèi)空間,因?yàn)橐粋€page是1k,即使只更新1byte,也會導(dǎo)致日志記錄1k。
我們可以在數(shù)據(jù)庫建立時就改變?nèi)罩灸J?br> WAL日志模式優(yōu)點(diǎn):
1) 讀寫可以并發(fā),不會阻塞
2)只有一個WAL文件,性能優(yōu)勢明顯。

4)調(diào)整數(shù)據(jù)變索引建立時間。

在創(chuàng)建表時,很多時候需要建立索引,索引可以提升搜索的效率,但是建立索引尤其是插入大量數(shù)據(jù)重新建立索引時需要耗費(fèi)大量的性能損耗。所以可以可以在全量拉取數(shù)據(jù)完成后手動添加index索引。

5)寫同步(synchronous)(不推薦)

在SQLite中,數(shù)據(jù)庫配置的參數(shù)都由編譯指示(pragma)來實(shí)現(xiàn)的,而其中synchronous選項(xiàng)有三種可選狀態(tài),分別是full、normal、off。這篇博客以及官方文檔里面有詳細(xì)講到這三種參數(shù)的設(shè)置。簡要說來,full寫入速度最慢,但保證數(shù)據(jù)是安全的,不受斷電、系統(tǒng)崩潰等影響,而off可以加速數(shù)據(jù)庫的一些操作,但如果系統(tǒng)崩潰或斷電,則數(shù)據(jù)庫可能會損毀。
SQLite3中,該選項(xiàng)的默認(rèn)值就是full,如果我們再插入數(shù)據(jù)前將其改為off,則會提高效率。如果僅僅將SQLite當(dāng)做一種臨時數(shù)據(jù)庫的話,完全沒必要設(shè)置為full。在代碼中,設(shè)置方法就是在打開數(shù)據(jù)庫之后,直接插入以下語句:

sqlite3_exec(db,"PRAGMA synchronous = OFF; ",0,0,0); 

當(dāng)synchronous設(shè)置為FULL (2), SQLite數(shù)據(jù)庫引擎在緊急時刻會暫停以確定數(shù)據(jù)已經(jīng)寫入磁盤。這使系統(tǒng)崩潰或電源出問題時能確保數(shù)據(jù)庫在重起后不會損壞。FULL synchronous很安全但很慢。
當(dāng)synchronous設(shè)置為NORMAL, SQLite數(shù)據(jù)庫引擎在大部分緊急時刻會暫停,但不像FULL模式下那么頻繁。 NORMAL模式下有很小的幾率(但不是不存在)發(fā)生電源故障導(dǎo)致數(shù)據(jù)庫損壞的情況。但實(shí)際上,在這種情況 下很可能你的硬盤已經(jīng)不能使用,或者發(fā)生了其他的不可恢復(fù)的硬件錯誤。
設(shè)置為synchronous OFF (0)時,SQLite在傳遞數(shù)據(jù)給系統(tǒng)以后直接繼續(xù)而不暫停。若運(yùn)行SQLite的應(yīng)用程序崩潰, 數(shù)據(jù)不會損傷,但在系統(tǒng)崩潰或?qū)懭霐?shù)據(jù)時意外斷電的情況下數(shù)據(jù)庫可能會損壞。另一方面,在synchronous OFF時 一些操作可能會快50倍甚至更多。但是這種操作還是有風(fēng)險(xiǎn)的。

6)關(guān)于查詢的優(yōu)化FTS

FTS虛擬表對于查詢的優(yōu)化是很明顯的。
FTS3 和FTS4 是一個SQLite 虛擬表的模塊, 允許用戶執(zhí)行全文搜索一組文檔從最常見()方法
但是在使用過程中發(fā)現(xiàn)有很多不一致的地方 如:

    CREATE VIRTUAL TABLE table1 USING fts4(content TEXT) */ FTS4 表/*
    CREATE TABLE IF NOT EXISTS table1(content TEXT); /* 普通表*/

當(dāng)然在FMDB中:

NSString *storePath = @"db路徑";
FMDatabase *db = [FMDatabase databaseWithPath:storePath];

[db open];

FMSimpleTokenizer *simpleTok = [[FMSimpleTokenizer alloc] initWithLocale:NULL];

[db installTokenizerModule];
[FMDatabase registerTokenizer:simpleTok withKey:@"simple"];

[db executeUpdate:@"CREATE VIRTUAL TABLE works_test USING fts4(id, title, title_tr, content, content_tr, dynasty, dynasty_tr, author, author_tr, tokenize=fmdb simple)"];

[db close];

插入等其他操作和原來一樣。
但是查詢的時候不是我們通常喜歡使用的#like#了 而是 #MATCH# 當(dāng)然據(jù)說比like查詢的速度快上1000倍(聽說)

SELECT * FROM works_test WHERE works_test MATCH 'something';

7)最后關(guān)于PRAGMA命令用法

PRAGMA語句是SQLITE數(shù)據(jù)的SQL擴(kuò)展,是它獨(dú)有的特性,主要用于修改SQLITE庫或者內(nèi)數(shù)據(jù)查詢的操作。它采用與SELECT、INSERT等語句一樣的形式來發(fā)出請求,但也有幾個重要的不同:

  1. 特定的PRAGMA語句可能被移走,新的PRAGMA語句可能在新的版本中添加。因此,后向兼容無法保證。
  2. 未知的PRAGMA命令不會有錯誤消息出現(xiàn),它只是簡單的忽略。
  3. 有些PRAGMA只在SQL的編譯階段起作用,而不是執(zhí)行階段。 這意味著如果使用C語言,sqlite3_prepare(), sqlite3_step(), sqlite3_finalize()這幾個API,pragma命令可能只在prepare()的調(diào)用里運(yùn)行,而不是在后兩個API當(dāng)中執(zhí)行。或者,pragma可能在sqlite3_step()執(zhí)行的時候運(yùn)行。到底在哪個階段執(zhí)行,取決于pragma從本身,以及是哪個sqlite的release版本。
  4. pragma命令是sqlite特有的,基本上不可能與其它數(shù)據(jù)庫保持兼容。

下面我們看看sqlite到底有些有用的pragma命令:
auto_vacuum
automatic_index
cache_size
case_sensitive_like
checkpoint_fullfsync
collation_list
compile_options
count_changes1
database_list
default_cache_size1
empty_result_callbacks1
encoding
foreign_key_list
foreign_keys
freelist_count
full_column_names1
fullfsync
ignore_check_constraints
incremental_vacuum
index_info
index_list
integrity_check
journal_mode
journal_size_limit
legacy_file_format
locking_mode
max_page_count
page_count
page_size
parser_trace2
quick_check
read_uncommitted
recursive_triggers
reverse_unordered_selects
schema_version
secure_delete
short_column_names1
synchronous
table_info
temp_store
temp_store_directory1
user_version
vdbe_listing2
vdbe_trace2
wal_autocheckpoint
wal_checkpoint
writable_schema
這里邊有幾個標(biāo)了右上標(biāo)為1的,似乎已經(jīng)被obsoleted掉了。標(biāo)為2的,只被用于debug,僅當(dāng)sqlite在預(yù)編譯宏SQLITE_DEBUG下build出來,才有用。

下面看看這些命令的具體用法:

  1. PRAGMA auto_vacuum;
    PRAGMA auto_vacuum = 0 或 NONE | 1 或 FULL | 2 或 INCREMENTAL;
    這里,0和NONE表示的含義相同。
    缺省值為0, 表示禁用auto vacuum. 除非SQLITE_DEFAULT_AUTOVACUUM宏在編譯的時候定義了。數(shù)據(jù)刪除的時候,數(shù)據(jù)庫大小不會改變。沒用的數(shù)據(jù)庫文件頁面會被添加到freelist里頭,用于將來重用。這時,使用VACUUM命令,可以重建整個數(shù)據(jù)庫,以回收無用的磁盤空間。
    值為1時,所有的freelist頁會被移動到文件末尾,每次事務(wù)提交的時候文件會被截短。注意,自動vacuum只是從文件是截?cái)鄁reelist頁,并沒有進(jìn)行碎片重整等操作,也就是說,它沒有VACUUM命令來得徹底。事實(shí)上,自動vacuum會讓碎片更多。
    只有在數(shù)據(jù)庫存儲某些附加信息的時候,它允許每個數(shù)據(jù)庫頁來跟蹤它的引用頁,自動vacuum才用得上。它必須在沒有創(chuàng)建任何表的情況下啟用。在一個表已經(jīng)創(chuàng)建了之后,是不能啟用和停用auto-vacuum的。
    值為2時,表示增量vacuum,意味著并不是在每次提交事務(wù)的時候自動vacuum,需要調(diào)用一個獨(dú)立的incremental_vacuum語句來觸發(fā)auto-vacuum。
    數(shù)據(jù)庫可以在1和2兩種vacuum模式下進(jìn)行切換。但是不能從none到full或incremental間切換。要想切換,要么數(shù)據(jù)庫是全新的數(shù)據(jù)庫(沒有任何表), 或者單獨(dú)運(yùn)行vacuum命令以后。改變自動vacuum模式,首先執(zhí)行auto_vacuum語句設(shè)置新的模式,然后調(diào)用VACUUM來重整數(shù)據(jù)庫。
    不帶參數(shù)的auto_vacuum語句返回當(dāng)前的auto_vacuum模式值。

  2. PRAGMA automatic_index;
    PRAGMA automatic_index = boolean;
    查詢,設(shè)置或者清除自動索引的功能。缺省值為true (1).

  3. PRAGMA cache_size;
    PRAGMA cache_size = <number of pages>;
    查詢或者修改打開的數(shù)據(jù)庫內(nèi)存里頭能容納的最多的數(shù)據(jù)庫頁數(shù)。缺省值是2000. 這樣設(shè)定只會改變當(dāng)前會話中的cache size,當(dāng)數(shù)據(jù)庫重新打開,又會恢復(fù)默認(rèn)值。你可以使用default_cache_size來設(shè)定所有會話中的cache size

  4. PRAGMA case_sensitive_like=boolean;
    默認(rèn)行為是忽略ascii字符的大小寫。'a' LIKE 'A'會是true. 當(dāng)禁用case_sensitive_like時,會用默認(rèn)的like行為。當(dāng)啟用它時,就會區(qū)分大小寫。

  5. PRAGMA checkpoint_fullfsync
    PRAGMA checkpoint_fullfsync=boolean;
    查詢或設(shè)置fullfsync的標(biāo)志值。如果設(shè)置了該值,則F_FULLFSYNC同步方法會在checkpoint操作時調(diào)用,默認(rèn)值是off。只有Mac OS-X操作系統(tǒng)支持F_FULLFSYNC。另外,如果設(shè)定了fullfsync值,那么F_FULLFSYNC同步方法會在所有sync操作里使用,也checkpoint_fullfsync標(biāo)志完全無關(guān)。

  6. PRAGMA collation_list;
    返回當(dāng)前數(shù)據(jù)庫連接定義的所有排序順序。

  7. PRAGMA compile_options;
    這個要贊,返回編譯SQLITE時使用的所有預(yù)編譯宏。當(dāng)然,以"SQLITE_"打頭的前綴會被忽略。實(shí)際上它是通過調(diào)用sqlite3_compileoption_get()方法返回的。

  8. PRAGMA count_changes;
    PRAGMA count_changes=boolean;
    該命令已經(jīng)停用. 只是為了保持后向兼容. 如果不設(shè)置此值,INSERT, UPDATE, DELETE語句不會返回多少行改變的數(shù)據(jù)。
    事實(shí)上,sqlite3_changes()可以獲取改變的行數(shù)。

  9. PRAGMA database_list;
    返回當(dāng)前數(shù)據(jù)庫連接關(guān)聯(lián)的數(shù)據(jù)庫列表.

  10. PRAGMA default_cache_size;
    PRAGMA default_cache_size = Number-of-pages;
    設(shè)置缺省的cache sie, 是以頁為單位。不幸的是,該命令也將被廢棄。

  11. PRAGMA empty_result_callbacks;
    PRAGMA empty_result_callbacks = boolean;
    僅作后向兼容用。如果將該標(biāo)志值清除,sqlite3_exec()提供的回調(diào)函數(shù)(返回0或多行數(shù)據(jù))將不被觸發(fā)。

  12. PRAGMA encoding;
    PRAGMA encoding = "UTF-8";
    PRAGMA encoding = "UTF-16";
    PRAGMA encoding = "UTF-16le";
    PRAGMA encoding = "UTF-16be";
    缺省值是utf-8。如果使用attach命令,則會要求使用與main數(shù)據(jù)庫相同的字符集編碼,如果新的數(shù)據(jù)庫編碼與main不同,則會失敗。

  13. PRAGMA foreign_key_list(table-name);
    返回外鍵列表

  14. PRAGMA foreign_keys;
    PRAGMA foreign_keys = boolean;
    查詢設(shè)置或者清除關(guān)于外鍵的限制, 外鍵限制只有在BEGIN或者SAVEPOINT不在PENDING狀態(tài)時設(shè)置才有效。
      改變該設(shè)置會影響所有已經(jīng)準(zhǔn)備好的SQL語句的執(zhí)行。
    從3.6.19開始,默認(rèn)的FK強(qiáng)制限制是OFF。也就是說,不會強(qiáng)制外鍵依賴。

  15. PRAGMA freelist_count;
    返回?cái)?shù)據(jù)庫文件中未使用頁的數(shù)目

  16. PRAGMA full_column_names;
    PRAGMA full_column_names = boolean;
    deprecated.

    1. 如果有AS子句,列名就會用AS后的別名
    2. 如果結(jié)果只是普通的表達(dá)式,而不是源表的列名,則采用表達(dá)式的文本
    3. 如果使用了short_column_names開關(guān)為ON,則采用源表列名,并且不帶表名前綴
    4. 如果兩個開關(guān)都設(shè)為OFF,則采用第2個規(guī)則。
    5. 結(jié)果列是學(xué)有源表源列的組合:TABLE.COLUMN
  17. PRAGMA fullfsync;
    PRAGMA fullfsync = boolean;
    缺省值為OFF,也只有MAC os支持F_FULLFSYNC

  18. PRAGMA ignore_check_constraints = boolean;
    是否強(qiáng)制check約束,缺省值為off

  19. PRAGMA incremental_vacuum(N);
    N頁從freelist中移除。用于設(shè)定此參數(shù)。每次截短相同的頁數(shù)。該命令必須是在auto_vacuum=incremental模式下才有效。如果freelist中的頁數(shù)少于N,或者N小于1,或者N被完全忽略,那么整個freelist會被清除。

  20. PRAGMA index_info(index-name);
    獲取具名的index信息。

  21. PRAGMA index_list(table-name);
    獲取與目標(biāo)表關(guān)聯(lián)的索引的的相關(guān)信息

  22. PRAGMA integrity_check;
    PRAGMA integrity_check(integer);
    執(zhí)行整個庫的完全性檢查,會查看錯序的記錄、丟失的頁,毀壞的索引等。

PRAGMA journal_mode;
PRAGMA database.journal_mode;
PRAGMA journal_mode = DELETE | TRUNCATE | PERSIST | MEMORY | WAL | OFF
PRAGMA database.journal_mode = DELETE | TRUNCATE | PERSIST | MEMORY | WAL | OFF
用于設(shè)置數(shù)據(jù)庫的journal_mode. DELETE是缺省的行為。在此模式下,每次事務(wù)終止的時候,journal文件會被刪除,它會導(dǎo)致事務(wù)提交。
TRUNCATE模式,通過將回滾journal截短成0,而不是刪除它。大多數(shù)情情況下,它要比DELETE模式速度快(因?yàn)椴挥脛h除文件)
PERSIST模式,每次事務(wù)結(jié)束時,并不刪除rollback journal,而只是在journal的頭部填充0,這樣會阻止別的數(shù)據(jù)庫連接來rollback. 該模式在某些平臺下,是一種優(yōu)化,特別是刪除或者truncate一個文件比覆蓋文件的第一塊代價高的時候。
MEMORY模式,只將rollback日志存儲到RAM中,節(jié)省了磁盤I/O,但帶來的代價是穩(wěn)定性和完整性上的損失。如果中間crash掉了,數(shù)據(jù)庫有可能損壞。
WAL模式,也就是write-ahead log取代rollback journal。該模式是持久化的,跨多個數(shù)據(jù)為連接,在重新打開數(shù)據(jù)庫以后,仍然有效。該模式只在3.7.0以后才有效。
(經(jīng)過實(shí)驗(yàn),發(fā)現(xiàn),它會生成兩個文件:.shm和.wal)
OFF模式,這樣就沒有事務(wù)支持了?!?br> 另外要注意的是,對于memory數(shù)據(jù)庫,只有兩種模式: MEMORY或者OFF。并且,當(dāng)前如果有活躍的事務(wù),則不允許改變事務(wù)模式。

  1. PRAGMA journal_size_limit
    PRAGMA journal_size_limit = N ;
    如果連接時,用了"exclusive mode(PRAGMA locking_mode=exclusive)或者(PRAGMA journal_mode=persist), 提交事務(wù)以后,journal文件會仍然在文件系系統(tǒng)當(dāng)中。這可能會提高了效率,但是也損耗了空間。一個大的事務(wù)(如VACUUM),會耗費(fèi)大量的磁盤空間。
    該設(shè)置會限制journal文件的大小。默認(rèn)值是-1。

  2. PRAGMA legacy_file_format;
    PRAGMA legacy_file_format = boolean;
    如果該值為ON,則會采用3.0.0文件格式,如果為off, 則會采用最新的文件格式,可能導(dǎo)致舊版本的sqlite無法打開該文件。
    第一次新文件格式的sqlite3數(shù)據(jù)庫打開時,該值為off.但是默認(rèn)值會是on.

  3. PRAGMA locking_mode;
    PRAGMA locking_mode = NORMAL | EXCLUSIVE
    缺省值是NORMAL. 數(shù)據(jù)庫連接在每一個讀或?qū)懯聞?wù)終點(diǎn)的時候放掉文件鎖。如果是EXCLUSIVE模式,連接永遠(yuǎn)不會釋放文件鎖。在此模式下,第一次執(zhí)行讀操作時,會獲取并持有共享鎖,第一次寫,會獲取并持有排它鎖。
    釋放排它鎖,僅當(dāng)關(guān)閉數(shù)據(jù)庫連接,或者將鎖模式改回為NORMAL時,再次訪問數(shù)據(jù)庫文件(讀或?qū)懀┎艜诺?。簡單的設(shè)置為NORMAL是不夠的,只有當(dāng)下次再訪問時才會釋放排它鎖。
    有下述三個理由,去設(shè)置鎖模式為EXCLUSIVE

    1. 應(yīng)用程序需要阻止其它進(jìn)程訪問數(shù)據(jù)庫文件
    2. 文件系統(tǒng)的系統(tǒng)調(diào)用數(shù)量減少了,導(dǎo)致些許性能下降
    3. WAL日志模式可以在EXCLUSIVE模式下使用,而不需要用到共享內(nèi)存
      當(dāng)指定數(shù)據(jù)庫名時,只能目標(biāo)數(shù)據(jù)庫生效。如:
      PRAGMA main.locking_mode=EXCLUSIVE; 不指定數(shù)據(jù)庫名時,則對所有打開的數(shù)據(jù)庫生效。temp或者memory數(shù)據(jù)庫總是使用exclusive鎖模式。
        第一次進(jìn)入WAL日志模式時,鎖模式使用的是exclusive,這以后,鎖模式也不能改變,直到退出WAL日志模式,如果鎖模式開始時使用的是NORMAL,第一次進(jìn)入WAL,這時鎖模式可以改變,并且不需要退出WAL模式。
  4. PRAGMA max_page_count;
    PRAGMA max_page_count = N;
    查詢或者設(shè)置數(shù)據(jù)庫文件的最大頁數(shù)

  5. PRAGMA page_count;
    返回?cái)?shù)據(jù)庫文件的頁數(shù)

  6. PRAGMA page_size;
    PRAGMA page_size = bytes;
    查詢或者設(shè)置數(shù)據(jù)庫文件的頁大小, 必須是2的乘方,并且介于512和65536之間。
    創(chuàng)建數(shù)據(jù)庫時,會給定一個缺省的大小。page_size命令會立即改變頁大?。ㄈ绻麛?shù)據(jù)庫是空的話,就是說在沒有創(chuàng)建任何表的情況下)。如果指定了新大小,是在運(yùn)行VACUUM命令之間,同時數(shù)據(jù)庫不是在WAL日志模式下,那么VACUUM命令會將頁大小調(diào)整到新的大小(這時應(yīng)該沒有是事創(chuàng)建表的限制)
    SQLITE_DEFAULT_PAGE_SIZE 缺省值是1024,最大的缺省頁大小是8192. windows下,有時候可能缺省頁大小大于1024,取決于GetDiskFreeSpace()來獲取真實(shí)的設(shè)置扇區(qū)大小。

  7. PRAGMA parser_trace = boolean;
    用在DEBUG的時候。

  8. PRAGMA quick_check;
    PRAGMA quick_check(integer)
    與integrity_check相像,但是略去了對索引內(nèi)容與表內(nèi)容匹配的校驗(yàn)。

  9. PRAGMA read_uncommitted;
    PRAGMA read_uncommitted = boolean;
    讀未提交開關(guān)。缺省的事務(wù)隔離級是:可串行化。任何進(jìn)程或線程都可以設(shè)置讀未提交隔離級,但是,SERIALIZABLE仍被使用,除了共享某頁和表模式的緩存的那些連接。

  10. PRAGMA recursive_triggers;
    PRAGMA recursive_triggers = boolean;
    會影響所有的語句執(zhí)行。3.6.18以前,這個開關(guān)是不支持的。缺省值是off.

  11. PRAGMA reverse_unordered_selects;
    PRAGMA reverse_unordered_selects = boolean;
    當(dāng)開啟此開關(guān)時,不帶order by的select語句,會輸出相反順序的結(jié)果。

  12. PRAGMA schema_version;
    PRAGMA schema_version = integer ;
    PRAGMA user_version;
    PRAGMA user_version = integer ;
    schema和user version是在數(shù)據(jù)庫文件頭40,60字節(jié)處的32位整數(shù)(大端表示)。
    schema版本由sqlite內(nèi)部維護(hù),當(dāng)schema改變時,就會增加該值。顯式改變該值非常危險(xiǎn)。
    user版本可以被應(yīng)用程序使用。

  13. PRAGMA secure_delete;
    PRAGMA database.secure_delete;
    PRAGMA secure_delete = boolean
    PRAGMA database.secure_delete = boolean
    設(shè)為ON時,刪除的內(nèi)容會用0來覆蓋。缺省值由宏SQLITE_SECURE_DELETE 決定。那就是OFF了。

  14. PRAGMA short_column_names;
    PRAGMA short_column_names = boolean;
    deprecated.

  15. PRAGMA synchronous;
    PRAGMA synchronous = 0 | OFF | 1 | NORMAL | 2 | FULL;
    查詢設(shè)置sync標(biāo)志值。缺省值是FULL.

  16. PRAGMA table_info(table-name);
    返回表的基本信息

  17. PRAGMA temp_store;
    PRAGMA temp_store = 0 | DEFAULT | 1 | FILE | 2 | MEMORY;
    查詢或設(shè)置temp_store參數(shù)值。
    SQLITE_TEMP_STORE PRAGMA temp_store Storage used forTEMP tables
    0 any file
    1 0 file
    1 1 file
    1 2 memory
    2 0 memory
    2 1 file
    2 2 memory
    3 any memory

  18. PRAGMA temp_store_directory;
    PRAGMA temp_store_directory = 'directory-name';
    設(shè)置或改變temp_store的目錄位置. deprecated.

  19. PRAGMA vdbe_listing = boolean;
    用于DEBUG

  20. PRAGMA vdbe_trace = boolean;
    用于DEBUG

  21. PRAGMA wal_autocheckpoint;
    PRAGMA wal_autocheckpoint=N;
    設(shè)置WAL自動檢查點(diǎn)的間隔(以頁為單位), 缺省值是1000。

  22. PRAGMA database.wal_checkpoint;
    PRAGMA database.wal_checkpoint(PASSIVE);
    PRAGMA database.wal_checkpoint(FULL);
    PRAGMA database.wal_checkpoint(RESTART);

  23. PRAGMA writable_schema = boolean;
    當(dāng)設(shè)為ON時,SQLITE_MASTER表可以執(zhí)行CUD操作。這樣做很危險(xiǎn)!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容