sqlite 源碼編譯,并寫一個 sqlite_demo程序。
環(huán)境介紹:
ubuntu 系統(tǒng)
cmake (cmake 安裝) (可以手動下載源碼,編譯安裝,也可以 使用系統(tǒng)最新的 cmake 安裝)
一、下載源碼并編譯
https://github.com/sqlite/sqlite/tree/vesion-3.45.1
下載 3.45.1 的源碼 sqlite-vesion-3.45.1.zip
解壓 sqlite-vesion-3.45.1 到當前目錄
在 sqlite-vesion-3.45.1 同級目錄,創(chuàng)建 bld 文件夾,并進入這個文件夾
mkdir bld ;# Build will occur in a sibling directory cd bld ;# Change to the build directory
chmod 755 ../sqlite-vesion-3.45.1/configure ../sqlite-vesion-3.45.1/configure
make -j4
二、創(chuàng)建一個cmake工程
project_directory/ │ ├── CMakeLists.txt ├── main.cpp └── sqlitelib/ # 創(chuàng)建一個 sqlitelib 文件夾 ├── sqlite3.h # 將 sqlite3.h文件拷貝過來 ├── libsqlite3.a # 將 libsqlite3.a 靜態(tài)庫拷貝過來
CMakeLists.txt
cmake_minimum_required(VERSION 3.10) project(SQLiteCppDemo) # Set C++ standard set(CMAKE_CXX_STANDARD 11) # Add executable add_executable(sqlite_demo main.cpp) # Include the path to the SQLite3 headers and link to the SQLite3 static library target_include_directories(sqlite_demo PRIVATE ${CMAKE_SOURCE_DIR}/sqlitelib) target_link_libraries(sqlite_demo PRIVATE ${CMAKE_SOURCE_DIR}/sqlitelib/libsqlite3.a) # Set the output directory for the built executable set_target_properties(sqlite_demo PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
main.cpp
1.如果 henry.db數(shù)據(jù)庫不存在,則創(chuàng)建;
2.創(chuàng)建 Userinfo表;
3.插入 若干條測試數(shù)據(jù);
4.查詢 Userinfo表所有的數(shù)據(jù),并打印輸出;
#include <iostream> #include <sqlite3.h> void executeSQL(sqlite3* db, const char* sql) { char* errMsg = nullptr; int rc = sqlite3_exec(db, sql, nullptr, nullptr, &errMsg); if (rc != SQLITE_OK) { std::cerr << "SQL error: " << errMsg << std::endl; sqlite3_free(errMsg); } } int main() { sqlite3* db; const char* dbName = "henry.db"; // Open the database (creates if not exists) int rc = sqlite3_open(dbName, &db); if (rc) { std::cerr << "Can't open database: " << sqlite3_errmsg(db) << std::endl; return rc; } std::cout << "Opened database successfully" << std::endl; // SQL statement to create Userinfo table const char* createTableSQL = R"( CREATE TABLE IF NOT EXISTS Userinfo ( uid INTEGER PRIMARY KEY, uname VARCHAR(64), age INTEGER ); )"; executeSQL(db, createTableSQL); std::cout << "Table created successfully" << std::endl; // Insert 10 rows of sample data for (int i = 1; i <= 10; ++i) { std::string insertSQL = "INSERT INTO Userinfo (uname, age) VALUES ('User" + std::to_string(i) + "', " + std::to_string(20 + i) + ");"; executeSQL(db, insertSQL.c_str()); } std::cout << "Inserted 10 rows successfully" << std::endl; // Query and print all records const char* selectSQL = "SELECT * FROM Userinfo;"; sqlite3_stmt* stmt; rc = sqlite3_prepare_v2(db, selectSQL, -1, &stmt, nullptr); if (rc != SQLITE_OK) { std::cerr << "Failed to fetch data: " << sqlite3_errmsg(db) << std::endl; return rc; } std::cout << "Querying data..." << std::endl; while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { int uid = sqlite3_column_int(stmt, 0); const unsigned char* uname = sqlite3_column_text(stmt, 1); int age = sqlite3_column_int(stmt, 2); std::cout << "UID: " << uid << ", Name: " << uname << ", Age: " << age << std::endl; } sqlite3_finalize(stmt); sqlite3_close(db); return 0; }
到此,一個sqlite 的 demo工程已開發(fā)完成。
編譯了sqlite庫之后,只需要 sqlite3.h頭文件, libsqlite3.a庫文件,接口在 demo工程里面 使用sqlite3的 若干api操作數(shù)據(jù)庫。
基本介紹完成。
其他擴展知識:
在 SQLite 的 C++ API 中,`sqlite3_step` 是用于逐條獲取查詢結(jié)果的確實設計如此,SQLite 本身并不直接提供所謂的“批量查詢”功能。原因在于它是一個輕量級的數(shù)據(jù)庫引擎,設計目標之一是盡可能保持簡單。
不過,雖然沒有直接的批量查詢接口,但可以通過一些優(yōu)化手段來提高查詢大數(shù)據(jù)量時的效率。以下是一些建議:
### 1. 使用事務來優(yōu)化批量查詢
當查詢大量數(shù)據(jù)時,可以嘗試使用事務來減少 SQLite 的 I/O 操作頻率,這通常能顯著提高查詢速度。雖然在讀取時不需要顯式開啟事務,但是在一些操作系統(tǒng)上(尤其是寫操作),事務機制對效率提升有幫助。
### 2. 緩存查詢結(jié)果
SQLite 提供了內(nèi)存中的緩存功能,你可以通過設置 `PRAGMA cache_size` 來調(diào)整緩存大小。默認的緩存大小可能不足以容納大量數(shù)據(jù),通過增加緩存大小,可以減少硬盤的 I/O 次數(shù),從而提高查詢性能。
例如:
```cpp
sqlite3_exec(db, "PRAGMA cache_size = 10000;", nullptr, nullptr, nullptr);
```
這個語句可以將 SQLite 的緩存大小設置為 10000 個頁面(每個頁面的大小由 `PRAGMA page_size` 決定,通常是 4096 字節(jié))。
### 3. 批量處理結(jié)果
雖然 `sqlite3_step` 是逐條獲取結(jié)果的,但你可以將結(jié)果緩存到內(nèi)存中,再進行批量處理。這是較為常見的做法,比如將 `sqlite3_step` 獲取的每一行數(shù)據(jù)先存到一個 `std::vector` 中,然后再一次性處理。
```cpp
std::vector<std::tuple<int, std::string, int>> results;
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
int uid = sqlite3_column_int(stmt, 0);
const char* uname = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
int age = sqlite3_column_int(stmt, 2);
results.emplace_back(uid, std::string(uname), age);
}
// 批量處理 results
```
通過這種方式,雖然你仍然是逐條讀取數(shù)據(jù),但數(shù)據(jù)讀取后可以一次性批量處理,避免了逐條處理的開銷。
### 4. 索引優(yōu)化
如果查詢的速度仍然不理想,可以考慮為頻繁查詢的字段創(chuàng)建索引。尤其是當你要查詢20萬條數(shù)據(jù)時,索引可以顯著減少查詢時間。
```sql
CREATE INDEX idx_userinfo_uid ON Userinfo(uid);
```
為 `Userinfo` 表的 `uid` 列創(chuàng)建索引可以加速通過 `uid` 進行的查詢。
### 5. 限制每次查詢返回的數(shù)據(jù)量
如果 20 萬條數(shù)據(jù)確實太多,你可以考慮分頁查詢,也就是分批次獲取數(shù)據(jù)。例如,在每次查詢時使用 `LIMIT` 和 `OFFSET` 關鍵字,這樣可以避免一次性處理過多數(shù)據(jù):
```sql
SELECT * FROM Userinfo LIMIT 10000 OFFSET 0;
```
每次只查詢 10000 條,減少單次查詢的內(nèi)存占用,從而提升性能。
### 6. 并行處理
如果你的應用程序運行在多核處理器上,并且你可以將查詢分塊處理,那么可以考慮使用多線程或多進程并行查詢不同的數(shù)據(jù)塊。雖然 SQLite 本身不支持多線程寫入,但可以通過分批查詢不同的部分數(shù)據(jù)來進行并行處理,從而優(yōu)化整體查詢時間。
### 總結(jié)
- SQLite 沒有原生的批量查詢接口,但可以通過批量處理結(jié)果、增加緩存、使用索引等方法提升查詢性能。
- 如果你需要查詢大量數(shù)據(jù),適當?shù)姆猪摬樵?、事務管理、并行處理也可以顯著提升查詢速度。
針對你查詢 20 萬條數(shù)據(jù)的情況,以上優(yōu)化方法應該會有所幫助。如果有更具體的查詢或性能問題,可以進一步討論如何根據(jù)實際情況優(yōu)化。

浙公網(wǎng)安備 33010602011771號