當前位置:首頁 » 數據倉庫 » sqlite資料庫優化
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

sqlite資料庫優化

發布時間: 2022-09-27 19:03:21

A. android sqlite 對sqlite有哪些優化

關於 SQLite 的優化,首先是能用SQL語句的,就不要單筆操作,
Cursor 就更是能不用就不用。比如成批的
DELETE/UPDATE ,將條件組裝到
SQL 語句,會比使用 CURSOR
一條條的查再刪效率要高很多(
若干年前就曾使用存儲過程代替單筆操作,將一次批量計算時間從一晚上縮到了一小時以內
)。其次是對操作的優化:對於 INSERT/UPDATE
操作較多時使用事務,如果SELECT操作較多時,使用索引。

結合現在的工作,發現針對操作的優化,下面 這篇文章 可以翻譯出來歸檔。以下為正文:

SQLite 有一個簡潔的SQL介面,且以低內存佔用著稱。現如今,
SQLite 已經在 Android 及
iOS 開發中得到廣泛的應用。本文主要討論在 Android
應用如何優化 SQLite 的性能和資源佔用。

1, 使用事務( Transaction )

在默認情況下每一個SQL語句都被包一個全新的事務內,比如執行一個如INSERT這樣基本的資料庫操作,就會放到一個新創建的事務中執行。一次只需要操作一次資料庫操作時,讓SQLite自己來進行事務管理當然是明智的。但如果一次有大量的操作要做時,比如循環調用INSERT添加時,這樣就顯得開銷過大了,因為每一筆操作都要重新打開、寫入,最後再關閉journal文件,
這個文件是臨時用來保存數據操作的中間結果,詳細內容看這里( 參考 )。
如果明確地在一系列SQL語句前後以 BEGIN TRANSACTION 及
END TRANSACTION
這樣顯示地使用事務就可以避免上面的情況。對於那些不會改變數據的操作,這樣的方式也同樣可以提速(好似資料庫操作中單筆的操作效率將遠低於批次操作,如果用SQL語句可以搞定的事,就不可使用Cursor進行操作)。

註明:除了發起事務外,你必須還要負責對事務的提交和回滾操作。

在Android應用開發中可以使用類似如下的方式使用 BEGIN TRANSACTION
及 END TRANSACTION :
db.beginTransaction();
try{
for(int i =0; i< LENGTH ; i++,sequenceNum++)
{
// execute SQL
}
db.setTransactionSuccessful();// marks a commit
}
finally{
db.endTransaction();
}

2. 使用索引

如果沒有在資料庫使用索引,當你在一個沒有排序的數據表中使用映射查詢(projection
query)搜索時,無可避免的要執行一個全序列查找。這種情況通常並不是什麼問題,每種資料庫,包括SQLite都會為數據集執行索引來降低查找時間。

索引維護著一個表中某一列或某幾列的順序,這樣就可以快速定位到一組值,而不用掃遍全表。所有的索引信息會被保存在一個獨立的索引表中,所以會產生額外的空間佔用,不過絕對物超所值,特別是當你會在資料庫中進行大量的讀及搜索操作時。

SQLite會自動為每一個UNIQUE欄位創建索引,包括主鍵(Primary Key)欄位,另外也可以通過CREATE
INDEX進行顯示地創建。

注:如果你的查詢太復雜而無法使用所創建的索引,那你就要好好想想你資料庫的結構了。
3. 在Where分支中使用限定符

如果以字串拼接出SQL語句的Where,莫不如使用SQLite的query操作帶上'?'來編譯查詢。以下是它的好處:

a. 有利於SQLite緩存這些查詢。

b. 可以避免達到SQLite緩存的上限。使用字串拼接Where的查詢,每一個都被視為不同的查詢,這就容易達到緩存的上限。

c. 可以避免非法的SQL注入。
轉載

B. sqlite大資料庫怎樣進行性能優化

從上圖中我們會很清晰的看到通過普通方式插入 10000 條數據和開啟事務插入 10000 條數據之間的差異,整整差了 83 秒。下面我們來看測試代碼:

package cn.sunzn.sqlitedatabase;

import android.app.Activity;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;

C. 求sqlite資料庫索引創建語句或性能優化方案

第1條語句,跟create_time索引沒關系
第2條語句,應該不會使用create_time索引,因為即便用了索引最後還是要讀表數據,還不如直接全表讀數據然後在內存中排序快
第3條語句,不知道0到1383525367的create_time選出的記錄數相對於全表記錄數的比率有多大,太多了應該也不會使用索引,因為最後還是要讀一遍表數據,如果比率比較小應該會用上索引

D. ios 從哪些方面去做sqlite 資料庫的優化

先來看看.h文件

#import <Foundation/Foundation.h>
#import <sqlite3.h>

#define kFilename @"testdb.db"
@class sqlTestList;
@interface sqlService : NSObject {
sqlite3 *_database;

}

@property (nonatomic) sqlite3 *_database;
-(BOOL) createTestList:(sqlite3 *)db;//創建資料庫
-(BOOL) insertTestList:(sqlTestList *)insertList;//插入數據
-(BOOL) updateTestList:(sqlTestList *)updateList;//更新數據
-(NSMutableArray*)getTestList;//獲取全部數據
- (BOOL) deleteTestList:(sqlTestList *)deletList;//刪除數據:
- (NSMutableArray*)searchTestList:(NSString*)searchString;//查詢資料庫,searchID為要查詢數據的ID,返回數據為查詢到的數據
@end

@interface sqlTestList : NSObject//重新定義了一個類,專門用於存儲數據
{
int sqlID;
NSString *sqlText;
NSString *sqlname;
}

@property (nonatomic) int sqlID;
@property (nonatomic, retain) NSString *sqlText;
@property (nonatomic, retain) NSString *sqlname;

@end

再來看看.m文件

//
// sqlService.m
// SQLite3Test
//
// Created by fengxiao on 11-11-28.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "sqlService.h"

@implementation sqlService

@synthesize _database;

- (id)init
{
return self;
}

- (void)dealloc
{
[super dealloc];
}

//獲取document目錄並返回資料庫目錄
- (NSString *)dataFilePath{

NSArray *paths = (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSLog(@"=======%@",documentsDirectory);
return [documentsDirectory :@"data.db"];//這里很神奇,可以定義成任何類型的文件,也可以不定義成.db文件,任何格式都行,定義成.sb文件都行,達到了很好的數據隱秘性

}

//創建,打開資料庫
- (BOOL)openDB {

//獲取資料庫路徑
NSString *path = [self dataFilePath];
//文件管理器
NSFileManager *fileManager = [NSFileManager defaultManager];
//判斷資料庫是否存在
BOOL find = [fileManager fileExistsAtPath:path];

//如果資料庫存在,則用sqlite3_open直接打開(不要擔心,如果資料庫不存在sqlite3_open會自動創建)
if (find) {

NSLog(@"Database file have already existed.");

//打開資料庫,這里的[path UTF8String]是將NSString轉換為C字元串,因為SQLite3是採用可移植的C(而不是
//Objective-C)編寫的,它不知道什麼是NSString.
if(sqlite3_open([path UTF8String], &_database) != SQLITE_OK) {

//如果打開資料庫失敗則關閉資料庫
sqlite3_close(self._database);
NSLog(@"Error: open database file.");
return NO;
}

//創建一個新表
[self createTestList:self._database];

return YES;
}
//如果發現資料庫不存在則利用sqlite3_open創建資料庫(上面已經提到過),與上面相同,路徑要轉換為C字元串
if(sqlite3_open([path UTF8String], &_database) == SQLITE_OK) {

//創建一個新表
[self createTestList:self._database];
return YES;
} else {
//如果創建並打開資料庫失敗則關閉資料庫
sqlite3_close(self._database);
NSLog(@"Error: open database file.");
return NO;
}
return NO;
}

//創建表
- (BOOL) createTestList:(sqlite3*)db {

//這句是大家熟悉的SQL語句
char *sql = "create table if not exists testTable(ID INTEGER PRIMARY KEY AUTOINCREMENT, testID int,testValue text,testName text)";// testID是列名,int 是數據類型,testValue是列名,text是數據類型,是字元串類型

sqlite3_stmt *statement;
//sqlite3_prepare_v2 介面把一條SQL語句解析到statement結構里去. 使用該介面訪問資料庫是當前比較好的的一種方法
NSInteger sqlReturn = sqlite3_prepare_v2(_database, sql, -1, &statement, nil);
//第一個參數跟前面一樣,是個sqlite3 * 類型變數,
//第二個參數是一個 sql 語句。
//第三個參數我寫的是-1,這個參數含義是前面 sql 語句的長度。如果小於0,sqlite會自動計算它的長度(把sql語句當成以\0結尾的字元串)。
//第四個參數是sqlite3_stmt 的指針的指針。解析以後的sql語句就放在這個結構里。
//第五個參數是錯誤信息提示,一般不用,為nil就可以了。
//如果這個函數執行成功(返回值是 SQLITE_OK 且 statement 不為NULL ),那麼下面就可以開始插入二進制數據。

//如果SQL語句解析出錯的話程序返回
if(sqlReturn != SQLITE_OK) {
NSLog(@"Error: failed to prepare statement:create test table");
return NO;
}

//執行SQL語句
int success = sqlite3_step(statement);
//釋放sqlite3_stmt
sqlite3_finalize(statement);

//執行SQL語句失敗
if ( success != SQLITE_DONE) {
NSLog(@"Error: failed to dehydrate:create table test");
return NO;
}
NSLog(@"Create table 'testTable' successed.");
return YES;
}

//插入數據
-(BOOL) insertTestList:(sqlTestList *)insertList {

//先判斷資料庫是否打開
if ([self openDB]) {

sqlite3_stmt *statement;

//這個 sql 語句特別之處在於 values 裡面有個? 號。在sqlite3_prepare函數里,?號表示一個未定的值,它的值等下才插入。
static char *sql = "INSERT INTO testTable(testID, testValue,testName) VALUES(?, ?, ?)";

int success2 = sqlite3_prepare_v2(_database, sql, -1, &statement, NULL);
if (success2 != SQLITE_OK) {
NSLog(@"Error: failed to insert:testTable");
sqlite3_close(_database);
return NO;
}

//這里的數字1,2,3代表上面的第幾個問號,這里將三個值綁定到三個綁定變數
sqlite3_bind_int(statement, 1, insertList.sqlID);
sqlite3_bind_text(statement, 2, [insertList.sqlText UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 3, [insertList.sqlname UTF8String], -1, SQLITE_TRANSIENT);

//執行插入語句
success2 = sqlite3_step(statement);
//釋放statement
sqlite3_finalize(statement);

//如果插入失敗
if (success2 == SQLITE_ERROR) {
NSLog(@"Error: failed to insert into the database with message.");
//關閉資料庫
sqlite3_close(_database);
return NO;
}
//關閉資料庫
sqlite3_close(_database);
return YES;
}
return NO;
}

//獲取數據
- (NSMutableArray*)getTestList{

NSMutableArray *array = [NSMutableArray arrayWithCapacity:10];
//判斷資料庫是否打開
if ([self openDB]) {

sqlite3_stmt *statement = nil;
//sql語句
char *sql = "SELECT testID, testValue ,testName FROM testTable";//從testTable這個表中獲取 testID, testValue ,testName,若獲取全部的話可以用*代替testID, testValue ,testName。

if (sqlite3_prepare_v2(_database, sql, -1, &statement, NULL) != SQLITE_OK) {
NSLog(@"Error: failed to prepare statement with message:get testValue.");
return NO;
}
else {
//查詢結果集中一條一條的遍歷所有的記錄,這里的數字對應的是列值,注意這里的列值,跟上面sqlite3_bind_text綁定的列值不一樣!一定要分開,不然會crash,只有這一處的列號不同,注意!
while (sqlite3_step(statement) == SQLITE_ROW) {
sqlTestList* sqlList = [[sqlTestList alloc] init] ;
sqlList.sqlID = sqlite3_column_int(statement,0);
char* strText = (char*)sqlite3_column_text(statement, 1);
sqlList.sqlText = [NSString stringWithUTF8String:strText];
char *strName = (char*)sqlite3_column_text(statement, 2);
sqlList.sqlname = [NSString stringWithUTF8String:strName];
[array addObject:sqlList];
[sqlList release];
}
}
sqlite3_finalize(statement);
sqlite3_close(_database);
}

return [array retain];//定義了自動釋放的NSArray,這樣不是個好辦法,會造成內存泄露,建議大家定義局部的數組,再賦給屬性變數。
}

//更新數據
-(BOOL) updateTestList:(sqlTestList *)updateList{

if ([self openDB]) {
sqlite3_stmt *statement;//這相當一個容器,放轉化OK的sql語句
//組織SQL語句
char *sql = "update testTable set testValue = ? and testName = ? WHERE testID = ?";

//將SQL語句放入sqlite3_stmt中
int success = sqlite3_prepare_v2(_database, sql, -1, &statement, NULL);
if (success != SQLITE_OK) {
NSLog(@"Error: failed to update:testTable");
sqlite3_close(_database);
return NO;
}

附上出處鏈接:http://www.cnblogs.com/xiaozhu/archive/2012/12/07/2808170.html

E. sqlite如何優化

SQLite的資料庫本質上來講就是一個磁碟上的文件,所以一切的資料庫操作其實都會轉化為對文件的操作,而頻繁的文件操作將會是一個很好時的過程,會極大地影響資料庫存取的速度。

例如:向資料庫中插入100萬條數據,在默認的情況下如果僅僅是執行

sqlite3_exec(db, 「insert into name values 『lxkxf', 『24'; 」, 0, 0, &zErrMsg);

將會重復的打開關閉資料庫文件100萬次,所以速度當然會很慢。因此對於這種情況我們應該使用「事務」。

具體方法如下:在執行SQL語句之前和SQL語句執行完畢之後加上

rc = sqlite3_exec(db, "BEGIN;", 0, 0, &zErrMsg);

//執行SQL語句

rc = sqlite3_exec(db, "COMMIT;", 0, 0, &zErrMsg);

這樣SQLite將把全部要執行的SQL語句先緩存在內存當中,然後等到COMMIT的時候一次性的寫入資料庫,這樣資料庫文件只被打開關閉了一次,效率自然大大的提高。有一組數據對比:

測試1: 1000 INSERTs

CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));
INSERT INTO t1 VALUES(1,13153,'thirteen thousand one hundred fifty three');
INSERT INTO t1 VALUES(2,75560,'seventy five thousand five hundred sixty');
... 995 lines omitted
INSERT INTO t1 VALUES(998,66289,'sixty six thousand two hundred eighty nine');
INSERT INTO t1 VALUES(999,24322,'twenty four thousand three hundred twenty two');
INSERT INTO t1 VALUES(1000,94142,'ninety four thousand one hundred forty two');

SQLite 2.7.6:
13.061

SQLite 2.7.6 (nosync):
0.223

測試2: 使用事務 25000 INSERTs

BEGIN;
CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100));
INSERT INTO t2 VALUES(1,59672,'fifty nine thousand six hundred seventy two');
... 24997 lines omitted
INSERT INTO t2 VALUES(24999,89569,'eighty nine thousand five hundred sixty nine');
INSERT INTO t2 VALUES(25000,94666,'ninety four thousand six hundred sixty six');
COMMIT;

SQLite 2.7.6:
0.914

SQLite 2.7.6 (nosync):
0.757

F. 如果使用sqlite,大批量的插入數據,需要做哪些優化

在資料庫的sql語句前加:"begin;" 結束後加「commit;」;

string strSql;
strSql += "begin;\n";
for (unsigned int i = 0 ; i < v.Size(); ++i)
{
//unsigned int i = 0;

const rapidjson::Value &val = v[i];

auto month = new MothData();
month->initWithDictionary(val);

strSql += StringUtils::format("INSERT INTO Car_mqpfl(father_code, organ_code, organ_name, report_name, stat_month,mqpfl_dn,mqpfl_qn,mqpfl_sn,xh) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' , '%d');\n",month->father_code.c_str(),month->organ_code.c_str(),month->organ_name.c_str(),month->report_name.c_str(),month->stat_month.c_str(),month->mqpfl_dn.c_str(),month->mqpfl_qn.c_str(),month->mqpfl_sn.c_str(),month->xh);
}
strSql+= "commit;\n";
SqlDB::insertData(strSql);

void SqlDB::insertData(std::string sql)
{
result = sqlite3_exec(_db, sql.c_str(), nullptr, nullptr, &errMsg);

if (result != SQLITE_OK) {
log("insert error , code = %d, message = %s\n",result,errMsg);
}
}

G. 寫入密集的情況下.flask怎麼優化sqlite的性能

不限於flask, 很多應用都需要這樣的優化
1. 使用log而不是資料庫, 比如使用nginx的empty_gif, 然後記錄大量log, 用腳本批量導入資料庫或者運算好結果, 再存儲到資料庫
如果你的數據量足夠大, 那麼你應該不止一台web server, 你需要批處理好幾台機器上的log.
這些原始數據你可以保存在s3上, 以後作為數據倉庫使用.
2. 使用內存, queue server或者redis那樣的內存方案也同樣是批處理數據, 寫腳本. 不過這個受到內存大小限制, 比較貴, 需要經常跑腳本.

H. Android開發中的finish()與onDestroy()方法都是用來結束activity的吧兩個有什麼區別

Android開發中的finish()與onDestroy()方法都是用來結束activity的。

1、不同點區別:

finish()方法用於結束一個Activity的生命周期。而onDestory()方法則是Activity的一個生命周期。

其作用是在一個Activity對象被銷毀之前,Android系統會調用該方法,用於釋放此Activity之前所佔用的資源。finish會調用到onDestory方法。在onDestory里列印一句話,運行一下程序,會發現finish方法會把那句話列印出來。

2、方法區別:

Activity.finish()方法:

在你的activity動作完成的時候,或者Activity需要關閉的時候,調用此方法,當你調用此方法的時候,系統只是將最上面的Activity移出了棧,並沒有及時的調用onDestory()方法,其佔用的資源也沒有被及時釋放。因為移出了棧,所以當你點擊手機上邊的「back」 按鍵的時候,也不會再找到這個Activity.

Acitvity.onDestory()方法:

系統銷毀了這個Activity的實例在內存中占據的空間。在Activity的生命周期中,onDestory()方法是他聲明的最後一步,資源控制項等就被回收了。當重新進入此Activity的時候,必須重新創建,執行onCrate()方法。

(8)sqlite資料庫優化擴展閱讀

中介軟體

1、操作系統與應用程序的溝通橋梁,應用分為兩層:函數層(Library)和虛擬機(Virtual Machine)。 Bionic是 Android 改良libc的版本。Android 同時包含了Webkit,所謂的Webkit 就是Apple Safari 瀏覽器背後的引擎。Surface flinger 是就2D或3D的內容顯示到屏幕上。Android使用工具鏈(Toolchain)為Google自製的Bionic Libc。

2、Android採用OpenCORE作為基礎多媒體框架。Open CORE可分7大塊:PVPlayer、PVAuthor、Codec、PacketVideo Multimedia Framework(PVMF)、Operating System Compatibility Library(OSCL)、Common、OpenMAX。

3、Android 使用skia 為核心圖形引擎,搭配OpenGL/ES。skia與Linux Cairo功能相當,但相較於Linux Cairo, skia 功能還只是雛形的。2005年Skia公司被Google收購,2007年初,Skia GL源碼被公開,Skia 也是Google Chrome 的圖形引擎。

4、Android的多媒體資料庫採用SQLite資料庫系統。資料庫又分為共用資料庫及私用資料庫。用戶可通過ContentResolver類(Column)取得共用資料庫。

5、Android的中間層多以Java 實現,並且採用特殊的Dalvik 虛擬機(Dalvik Virtual Machine)。Dalvik虛擬機是一種「暫存器型態」(Register Based)的Java虛擬機,變數皆存放於暫存器中,虛擬機的指令相對減少。

6、Dalvik虛擬機可以有多個實例(Instance), 每個Android應用程序都用一個自屬的Dalvik虛擬機來運行,讓系統在運行程序時可達到優化。Dalvik 虛擬機並非運行Java位元組碼(Bytecode),而是運行一種稱為.dex格式的文件。