1. 程式人生 > >sqlite 優化 之 ANALYZE 與 VACUUM 命令

sqlite 優化 之 ANALYZE 與 VACUUM 命令



 資料清理:

    和PostgreSQL中的VACUUM命令相比,他們的功能以及實現方式非常相似,不同的是PostgreSQL提供了更細的粒度,而SQLite只能將該命令作用於資料庫,無法再精確到資料庫中指定的資料表或者索引,然而這一點恰恰是PostgreSQL可以做到的。
    當某個資料庫中的一個或多個數據表存在大量的插入、更新和刪除等操作時,將會有大量的磁碟空間被已刪除的資料所佔用,在沒有執行VACUUM命令之前,SQLite並沒有將它們歸還於作業系統。由於該類資料表中的資料儲存非常分散,因此在查詢時,無法得到更好的批量IO讀取效果,從而影響了查詢效率。
    在SQLite中,僅支援清理當前連線中的主資料庫,而不能清理其它Attached資料庫。VACUUM命令在完成資料清理時採用了和PostgreSQL相同的策略,即建立一個和當前資料庫檔案相同大小的新資料庫檔案,之後再將該資料庫檔案中的資料有組織的匯入到新檔案中,其中已經刪除的資料塊將不會被匯入,在完成匯入後,收縮新資料庫檔案的尺寸到適當的大小。該命令的執行非常簡單,如:


sqlite> VACUUM;

- (void)vacuumDB {

NSArray *databaseInfos;

@synchronized(_databaseInfos) {

        databaseInfos = _databaseInfos.allValues;

    }

for (GYDatabaseInfo *databaseInfo in databaseInfos) {

        [databaseInfo.databaseQueuesyncInDatabase:^(FMDatabase *db) {

if (databaseInfo.timer) {

dispatch_suspend(databaseInfo.timer);

                [db commit];

                databaseInfo.needCommitTransaction = NO;

            }

            [db executeStatements:@"VACUUM"];

if (databaseInfo.timer) {

                [db beginTransaction];

dispatch_resume(databaseInfo.timer);

            }

        }];

    }

}

 資料分析:

    和PostgreSQL非常相似,SQLite中的ANALYZE命令也同樣用於分析資料表和索引中的資料,並將統計結果存放於SQLite的內部系統表中,以便於查詢優化器可以根據分析後的統計資料選擇最優的查詢執行路徑,從而提高整個查詢的效率。見如下示例:
    --如果在ANALYZE命令之後沒有指定任何引數,則分析當前連線中所有Attached資料庫中的表和索引。
    sqlite> ANALYZE;
    --如果指定資料庫作為ANALYZE的引數,那麼該資料庫下的所有表和索引都將被分析並生成統計資料。
    sqlite> ANALYZE main;
    --如果指定了資料庫中的某個表或索引為ANALYZE的引數,那麼該表和其所有關聯的索引都將被分析。
    sqlite> ANALYZE main.testtable;
    sqlite> ANALYZE main.testtable_idx2;

- (void)synchronizeDB:(NSString *)dbName {

@synchronized(_databaseInfos) {

GYDatabaseInfo *databaseInfo = [_databaseInfosobjectForKey:dbName];

        [databaseInfo.databaseQueuesyncInDatabase:^(FMDatabase *db) {

if (databaseInfo.timer) {

dispatch_source_cancel(databaseInfo.timer);

                databaseInfo.timer = nil;

                [db commit];

            }

if (databaseInfo.writeCount >= 500) {

                [db executeStatements:@"ANALYZE"];

                databaseInfo.writeCount = 0;

            }

        }];

@synchronized(databaseInfo.updatedTables) {

            [databaseInfo.databaseQueueclose];

            [databaseInfo.updatedTablesremoveAllObjects];

        }

        [self.writeCountssetObject:@(databaseInfo.writeCount)forKey:dbName];

NSData *data = [NSPropertyListSerializationdataWithPropertyList:self.writeCounts

format:NSPropertyListBinaryFormat_v1_0

options:0

error:nil];

        [data writeToFile:[GYDBRunnerpathForAnalyzeStatistics] atomically:YES];

    }

}

參考 :(1) http://www.cnblogs.com/stephen-liu74/archive/2012/01/14/2322335.html

      (2) GYDataCenter