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

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

優(yōu)化

對(duì)于沒(méi)有做任何優(yōu)化的DB來(lái)說(shuō)殿如,幾十萬(wàn)的數(shù)據(jù)讀取,至少是幾十秒甚至可能需要更長(zhǎng)的時(shí)間最爬,即使使用loading頁(yè)面等的緩沖涉馁,這還是遠(yuǎn)遠(yuǎn)不夠的。

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

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

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

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

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

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

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

3)修改日志模式

日志模式

SQLite中日志模式主要有DELETE和WAL兩種,其他幾種比如TRUNCATE入热,PERSIST拍棕,MEMORY基本原理都與DELETE模式相同晓铆,不作詳細(xì)展開。DELETE模式采用影子分頁(yè)技術(shù)(Shadow paging)绰播,DELETE模式下骄噪,日志中記錄的變更前數(shù)據(jù)頁(yè)內(nèi)容;WAL模式下蠢箩,日志中記錄的是變更后的數(shù)據(jù)頁(yè)內(nèi)容链蕊。事務(wù)提交時(shí),DELETE模式將日志刷盤谬泌,將DB文件刷盤滔韵,成功后,再將日志文件清理呵萨;WAL模式則是將日志文件刷盤奏属,即可完成提交過(guò)程。那么WAL模式下潮峦,數(shù)據(jù)文件何時(shí)更新呢囱皿?這里引入了檢查點(diǎn)概念,檢查點(diǎn)的作用就是定期將日志中的新頁(yè)覆蓋DB文件中的老頁(yè)忱嘹,并通過(guò)參數(shù)wal_autocheckpoint來(lái)控制檢查點(diǎn)時(shí)機(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ù)提交時(shí)沟突,也不影響db-page,只是將日志持久化而已捕传。若事務(wù)回滾惠拭,則不將日志寫入文件即可。由于最新的數(shù)據(jù)在日志文件中庸论,那么如何讀取到最新的數(shù)據(jù)呢求橄?WAL模式通過(guò)end-mark(事務(wù)提交位點(diǎn))達(dá)到這一目的今野。具體而已,事務(wù)開始時(shí)罐农,會(huì)首先掃描日志文件条霜,獲取最近一個(gè)end-mark,在讀取數(shù)據(jù)時(shí)涵亏,首先會(huì)判斷page是否則在wal日志文件中存在宰睡,因?yàn)橥粋€(gè)page,一定是wal文件中的比db文件中的要新气筋。如果存在拆内,則使用,否則宠默,再?gòu)膁b文件中獲取指定的page麸恍。從流程上來(lái)看,這個(gè)過(guò)程比較慢搀矫,因?yàn)闃O端情況下抹沪,每次讀都需要掃描wal文件和db文件。為了提高性能瓤球,WAL模式中有一個(gè)wal-index文件融欧,這個(gè)文件記錄了頁(yè)號(hào)和該頁(yè)在WAL文件中的偏移,并且wal-index文件采用共享緩存實(shí)現(xiàn)卦羡,從文件名也可以看到噪馏,后綴是.shm,因此判斷page是否在wal文件存在的操作實(shí)質(zhì)是一次內(nèi)存讀绿饵。wal-index采用hash表存儲(chǔ)欠肾,因此查詢效率也非常高。與傳統(tǒng)的DBMS不同拟赊,SQLite中記錄的日志刺桃,實(shí)質(zhì)是dirty-page,重做實(shí)質(zhì)是對(duì)利用WAL中的日志頁(yè)覆蓋db-page要门,這種實(shí)現(xiàn)方式比較簡(jiǎn)單虏肾,同時(shí)也比較浪費(fèi)空間廓啊,因?yàn)橐粋€(gè)page是1k欢搜,即使只更新1byte,也會(huì)導(dǎo)致日志記錄1k谴轮。
我們可以在數(shù)據(jù)庫(kù)建立時(shí)就改變?nèi)罩灸J?br> WAL日志模式優(yōu)點(diǎn):
1) 讀寫可以并發(fā)炒瘟,不會(huì)阻塞
2)只有一個(gè)WAL文件,性能優(yōu)勢(shì)明顯第步。

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

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

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

在SQLite中樊展,數(shù)據(jù)庫(kù)配置的參數(shù)都由編譯指示(pragma)來(lái)實(shí)現(xiàn)的呻纹,而其中synchronous選項(xiàng)有三種可選狀態(tài),分別是full专缠、normal雷酪、off。這篇博客以及官方文檔里面有詳細(xì)講到這三種參數(shù)的設(shè)置涝婉。簡(jiǎn)要說(shuō)來(lái)哥力,full寫入速度最慢,但保證數(shù)據(jù)是安全的墩弯,不受斷電吩跋、系統(tǒng)崩潰等影響,而off可以加速數(shù)據(jù)庫(kù)的一些操作最住,但如果系統(tǒng)崩潰或斷電钞澳,則數(shù)據(jù)庫(kù)可能會(huì)損毀。
SQLite3中涨缚,該選項(xiàng)的默認(rèn)值就是full轧粟,如果我們?cè)俨迦霐?shù)據(jù)前將其改為off,則會(huì)提高效率脓魏。如果僅僅將SQLite當(dāng)做一種臨時(shí)數(shù)據(jù)庫(kù)的話兰吟,完全沒(méi)必要設(shè)置為full。在代碼中茂翔,設(shè)置方法就是在打開數(shù)據(jù)庫(kù)之后混蔼,直接插入以下語(yǔ)句:

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

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

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

FTS虛擬表對(duì)于查詢的優(yōu)化是很明顯的窗宦。
FTS3 和FTS4 是一個(gè)SQLite 虛擬表的模塊, 允許用戶執(zhí)行全文搜索一組文檔從最常見()方法
但是在使用過(guò)程中發(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];

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

SELECT * FROM works_test WHERE works_test MATCH 'something';

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

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

  1. 特定的PRAGMA語(yǔ)句可能被移走沪摄,新的PRAGMA語(yǔ)句可能在新的版本中添加。因此纱烘,后向兼容無(wú)法保證杨拐。
  2. 未知的PRAGMA命令不會(huì)有錯(cuò)誤消息出現(xiàn),它只是簡(jiǎn)單的忽略擂啥。
  3. 有些PRAGMA只在SQL的編譯階段起作用哄陶,而不是執(zhí)行階段〔负 這意味著如果使用C語(yǔ)言屋吨,sqlite3_prepare(), sqlite3_step(), sqlite3_finalize()這幾個(gè)API,pragma命令可能只在prepare()的調(diào)用里運(yùn)行山宾,而不是在后兩個(gè)API當(dāng)中執(zhí)行至扰。或者资锰,pragma可能在sqlite3_step()執(zhí)行的時(shí)候運(yùn)行敢课。到底在哪個(gè)階段執(zhí)行,取決于pragma從本身绷杜,以及是哪個(gè)sqlite的release版本直秆。
  4. pragma命令是sqlite特有的,基本上不可能與其它數(shù)據(jù)庫(kù)保持兼容鞭盟。

下面我們看看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
這里邊有幾個(gè)標(biāo)了右上標(biāo)為1的圾结,似乎已經(jīng)被obsoleted掉了。標(biāo)為2的懊缺,只被用于debug,僅當(dāng)sqlite在預(yù)編譯宏SQLITE_DEBUG下build出來(lái)疫稿,才有用。

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

  1. PRAGMA auto_vacuum;
    PRAGMA auto_vacuum = 0 或 NONE | 1 或 FULL | 2 或 INCREMENTAL;
    這里鹃两,0和NONE表示的含義相同遗座。
    缺省值為0, 表示禁用auto vacuum. 除非SQLITE_DEFAULT_AUTOVACUUM宏在編譯的時(shí)候定義了。數(shù)據(jù)刪除的時(shí)候俊扳,數(shù)據(jù)庫(kù)大小不會(huì)改變途蒋。沒(méi)用的數(shù)據(jù)庫(kù)文件頁(yè)面會(huì)被添加到freelist里頭,用于將來(lái)重用馋记。這時(shí)号坡,使用VACUUM命令,可以重建整個(gè)數(shù)據(jù)庫(kù)梯醒,以回收無(wú)用的磁盤空間宽堆。
    值為1時(shí),所有的freelist頁(yè)會(huì)被移動(dòng)到文件末尾茸习,每次事務(wù)提交的時(shí)候文件會(huì)被截短畜隶。注意,自動(dòng)vacuum只是從文件是截?cái)鄁reelist頁(yè)号胚,并沒(méi)有進(jìn)行碎片重整等操作籽慢,也就是說(shuō),它沒(méi)有VACUUM命令來(lái)得徹底猫胁。事實(shí)上箱亿,自動(dòng)vacuum會(huì)讓碎片更多。
    只有在數(shù)據(jù)庫(kù)存儲(chǔ)某些附加信息的時(shí)候弃秆,它允許每個(gè)數(shù)據(jù)庫(kù)頁(yè)來(lái)跟蹤它的引用頁(yè)届惋,自動(dòng)vacuum才用得上。它必須在沒(méi)有創(chuàng)建任何表的情況下啟用菠赚。在一個(gè)表已經(jīng)創(chuàng)建了之后盼樟,是不能啟用和停用auto-vacuum的。
    值為2時(shí)锈至,表示增量vacuum晨缴,意味著并不是在每次提交事務(wù)的時(shí)候自動(dòng)vacuum,需要調(diào)用一個(gè)獨(dú)立的incremental_vacuum語(yǔ)句來(lái)觸發(fā)auto-vacuum峡捡。
    數(shù)據(jù)庫(kù)可以在1和2兩種vacuum模式下進(jìn)行切換击碗。但是不能從none到full或incremental間切換。要想切換们拙,要么數(shù)據(jù)庫(kù)是全新的數(shù)據(jù)庫(kù)(沒(méi)有任何表)稍途, 或者單獨(dú)運(yùn)行vacuum命令以后。改變自動(dòng)vacuum模式砚婆,首先執(zhí)行auto_vacuum語(yǔ)句設(shè)置新的模式械拍,然后調(diào)用VACUUM來(lái)重整數(shù)據(jù)庫(kù)突勇。
    不帶參數(shù)的auto_vacuum語(yǔ)句返回當(dāng)前的auto_vacuum模式值。

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

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

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

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

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

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

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

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

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

  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命令译蒂,則會(huì)要求使用與main數(shù)據(jù)庫(kù)相同的字符集編碼曼月,如果新的數(shù)據(jù)庫(kù)編碼與main不同,則會(huì)失敗柔昼。

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

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

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

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

    1. 如果有AS子句,列名就會(huì)用AS后的別名
    2. 如果結(jié)果只是普通的表達(dá)式勿决,而不是源表的列名乒躺,則采用表達(dá)式的文本
    3. 如果使用了short_column_names開關(guān)為ON,則采用源表列名低缩,并且不帶表名前綴
    4. 如果兩個(gè)開關(guān)都設(shè)為OFF嘉冒,則采用第2個(gè)規(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頁(yè)從freelist中移除。用于設(shè)定此參數(shù)玩般。每次截短相同的頁(yè)數(shù)银觅。該命令必須是在auto_vacuum=incremental模式下才有效。如果freelist中的頁(yè)數(shù)少于N坏为,或者N小于1究驴,或者N被完全忽略,那么整個(gè)freelist會(huì)被清除匀伏。

  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í)行整個(gè)庫(kù)的完全性檢查,會(huì)查看錯(cuò)序的記錄够颠、丟失的頁(yè)熙侍,毀壞的索引等。

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ù)庫(kù)的journal_mode. DELETE是缺省的行為履磨。在此模式下核行,每次事務(wù)終止的時(shí)候,journal文件會(huì)被刪除蹬耘,它會(huì)導(dǎo)致事務(wù)提交芝雪。
TRUNCATE模式,通過(guò)將回滾journal截短成0综苔,而不是刪除它惩系。大多數(shù)情情況下位岔,它要比DELETE模式速度快(因?yàn)椴挥脛h除文件)
PERSIST模式,每次事務(wù)結(jié)束時(shí)堡牡,并不刪除rollback journal抒抬,而只是在journal的頭部填充0,這樣會(huì)阻止別的數(shù)據(jù)庫(kù)連接來(lái)rollback. 該模式在某些平臺(tái)下晤柄,是一種優(yōu)化厌衔,特別是刪除或者truncate一個(gè)文件比覆蓋文件的第一塊代價(jià)高的時(shí)候狭吼。
MEMORY模式,只將rollback日志存儲(chǔ)到RAM中,節(jié)省了磁盤I/O恤左,但帶來(lái)的代價(jià)是穩(wěn)定性和完整性上的損失淑趾。如果中間crash掉了僵刮,數(shù)據(jù)庫(kù)有可能損壞递礼。
WAL模式,也就是write-ahead log取代rollback journal盾计。該模式是持久化的售担,跨多個(gè)數(shù)據(jù)為連接,在重新打開數(shù)據(jù)庫(kù)以后署辉,仍然有效族铆。該模式只在3.7.0以后才有效。
(經(jīng)過(guò)實(shí)驗(yàn)哭尝,發(fā)現(xiàn)骑素,它會(huì)生成兩個(gè)文件:.shm和.wal)
OFF模式,這樣就沒(méi)有事務(wù)支持了刚夺∠壮螅 
另外要注意的是,對(duì)于memory數(shù)據(jù)庫(kù)侠姑,只有兩種模式: MEMORY或者OFF创橄。并且,當(dāng)前如果有活躍的事務(wù)莽红,則不允許改變事務(wù)模式妥畏。

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

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

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

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

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

  6. PRAGMA page_size;
    PRAGMA page_size = bytes;
    查詢或者設(shè)置數(shù)據(jù)庫(kù)文件的頁(yè)大小, 必須是2的乘方,并且介于512和65536之間叙淌。
    創(chuàng)建數(shù)據(jù)庫(kù)時(shí)沥割,會(huì)給定一個(gè)缺省的大小耗啦。page_size命令會(huì)立即改變頁(yè)大小(如果數(shù)據(jù)庫(kù)是空的話机杜,就是說(shuō)在沒(méi)有創(chuàng)建任何表的情況下)帜讲。如果指定了新大小,是在運(yùn)行VACUUM命令之間椒拗,同時(shí)數(shù)據(jù)庫(kù)不是在WAL日志模式下似将,那么VACUUM命令會(huì)將頁(yè)大小調(diào)整到新的大小(這時(shí)應(yīng)該沒(méi)有是事創(chuàng)建表的限制)
    SQLITE_DEFAULT_PAGE_SIZE 缺省值是1024蚀苛,最大的缺省頁(yè)大小是8192. windows下在验,有時(shí)候可能缺省頁(yè)大小大于1024,取決于GetDiskFreeSpace()來(lái)獲取真實(shí)的設(shè)置扇區(qū)大小堵未。

  7. PRAGMA parser_trace = boolean;
    用在DEBUG的時(shí)候腋舌。

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

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

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

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

  12. PRAGMA schema_version;
    PRAGMA schema_version = integer ;
    PRAGMA user_version;
    PRAGMA user_version = integer ;
    schema和user version是在數(shù)據(jù)庫(kù)文件頭40圆凰,60字節(jié)處的32位整數(shù)(大端表示)。
    schema版本由sqlite內(nèi)部維護(hù)髓堪,當(dāng)schema改變時(shí)送朱,就會(huì)增加該值。顯式改變?cè)撝捣浅NkU(xiǎn)干旁。
    user版本可以被應(yīng)用程序使用驶沼。

  13. PRAGMA secure_delete;
    PRAGMA database.secure_delete;
    PRAGMA secure_delete = boolean
    PRAGMA database.secure_delete = boolean
    設(shè)為ON時(shí),刪除的內(nèi)容會(huì)用0來(lái)覆蓋争群。缺省值由宏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;
    查詢?cè)O(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自動(dòng)檢查點(diǎn)的間隔(以頁(yè)為單位), 缺省值是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時(shí),SQLITE_MASTER表可以執(zhí)行CUD操作复旬。這樣做很危險(xiǎn)!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末垦缅,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子驹碍,更是在濱河造成了極大的恐慌壁涎,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件志秃,死亡現(xiàn)場(chǎng)離奇詭異怔球,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)浮还,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門竟坛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人钧舌,你說(shuō)我怎么就攤上這事担汤。” “怎么了延刘?”我有些...
    開封第一講書人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵漫试,是天一觀的道長(zhǎng)六敬。 經(jīng)常有香客問(wèn)我碘赖,道長(zhǎng),這世上最難降的妖魔是什么外构? 我笑而不...
    開封第一講書人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任普泡,我火速辦了婚禮,結(jié)果婚禮上审编,老公的妹妹穿的比我還像新娘撼班。我一直安慰自己,他們只是感情好垒酬,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開白布砰嘁。 她就那樣靜靜地躺著,像睡著了一般勘究。 火紅的嫁衣襯著肌膚如雪矮湘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評(píng)論 1 285
  • 那天口糕,我揣著相機(jī)與錄音缅阳,去河邊找鬼。 笑死景描,一個(gè)胖子當(dāng)著我的面吹牛十办,可吹牛的內(nèi)容都是我干的秀撇。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼向族,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼呵燕!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起件相,我...
    開封第一講書人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤虏等,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后适肠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霍衫,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年侯养,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了敦跌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逛揩,死狀恐怖柠傍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辩稽,我是刑警寧澤惧笛,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站逞泄,受9級(jí)特大地震影響患整,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜喷众,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一各谚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧到千,春花似錦昌渤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至了赵,卻和暖如春潜支,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背斟览。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工毁腿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓已烤,卻偏偏與公主長(zhǎng)得像鸠窗,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胯究,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345