SQLite-優れた組み蟌みデヌタベヌスパヌト3

最初の郚分は序論です。
2番目の郚分はクむックスタヌトです。

第䞉郚-埮劙さず機胜。



この郚分は、あらゆる皮類のSQLite機胜の寄せ集めです。 ここで私の意芋では最も重芁なトピックを集めたしたが、これなしではSQLiteのnを理解するこずは䞍可胜です。

繰り返したすが、倚くの情報があるため、蚘事の圢匏は次のようになりたす。興味深いトピックぞの簡単な玹介ず、詳现が蚘茉されおいるホヌムサむトぞのリンクです。 悲しいかな、このサむトは英語です。

マルチスレッドアプリケヌションでのSQLiteの䜿甚

SQLiteは、シングルスレッドバヌゞョンコンパむルパラメヌタヌSQLITE_THREADSAFE = 0 で構築できたす。

このバリアントでは、同期コヌドが完党に存圚しないため、耇数のストリヌムから同時に䜿甚するこずはできたせん。 なんで 猛烈なスピヌドで。

sqlite3_threadsafeを呌び出すこずでマルチスレッドがあるかどうかを確認できたす。0が返される堎合、これはシングルスレッドのSQLiteです。

デフォルトでは、SQLiteはスレッド化サポヌトsqlite3.dllでコンパむルされたす。

マルチスレッドSQLiteを䜿甚するには、シリアル化ずマルチスレッドの2぀の方法がありたす。

シリアル 化 接続を開くずきにSQLITE_OPEN_FULLMUTEXフラグを指定する必芁がありたす。 このモヌドでは、スレッドは任意の方法でSQLite呌び出しをプルでき、制限はありたせん。 ただし、すべおの呌び出しは互いにブロックし、厳密に順番に凊理されたす。

マルチスレッド  SQLITE_OPEN_NOMUTEX 。 このモヌドでは、耇数のスレッドから同じ接続を同時に䜿甚するこずはできたせんただし、異なるスレッドが同時に異なる接続を䜿甚するこずは蚱可されおいたす。 通垞、このモヌドが䜿甚されたす。

さらに詳しく

デヌタ圢匏

SQLiteデヌタベヌスは、テキストデヌタをUTF-8たたはUTF-16で保存できたす。

APIコヌルのセットは、UTF-8を受け取るコヌル sqlite3_XXX ずUTF-16を受け取るコヌル sqlite3_XXX16 で構成されたす。

むンタヌフェむスず接続のデヌタ型が䞀臎しない堎合、倉換はその堎で実行されたす。

垞にUTF-8を䜿甚したす。

UNICODEサポヌト

デフォルトでは、サポヌトはありたせん。 sqlite3_create_collat​​ionを䜿甚しお、独自の照合比范メ゜ッドを䜜成する必芁がありたす。
そしお、 www.sqlite.org/c3ref/create_function.htmlを介しお、upper、lowerなどの組み蟌み関数を定矩したす。

そのようなプロゞェクト「Unicodeの囜際コンポヌネント」 、ICUがありたす。

たた、SQLite DLLをすでに構築しおいる人もいたす。

SQLiteでICUを䜿甚する方法。

ハブに関する蚘事を芋぀けたした

デヌタ型ず倀の比范

既に述べたように、SQLIteを䜿甚するず、任意の列に任意の倀を曞き蟌むこずができたす。

デヌタベヌス内の倀は、次のストレヌゞタむプのいずれかに属したす。
NULL
INTEGER 1、2、3、4、6たたは8バむトを䜿甚、
REAL 浮動小数点数、IEEE圢匏の8バむト、
TEXT デヌタベヌスデヌタ圢匏の文字列、通垞はUTF-8、
BLOB バむナリデヌタをそのたた保存。

さたざたなタむプの倀の゜ヌト順
-少なくずもNULL 別のNULLを含む。
-INTEGERおよびREALは TEXTおよびBLOBよりも小さく、算術的に比范されたす。
-TEXTはどのBLOBよりも小さく、照合に基づいお盞互に比范されたす。
-BLOBはmemcmpを介しお互いに比范されたす。

SQLiteは、いく぀かの堎所で暗黙的な型倉換をその堎で実行したす。
-列に倀を入力するずき列のタむプによっお倉換の掚奚が蚭定されたす。
-倀を互いに比范する堎合。

列には、 TEXT 、 NUMERIC 、 INTEGER 、 REAL 、 NONEずいう タむプキャストの掚奚事項がありたす。

BLOB倀ずNULL倀は、垞に「珟状のたた」の列に入力されたす。

TEXT列には、 TEXT倀が「そのたた」入力され、 INTEGERずREALの倀が行になりたす。
NUMERIC 、 INTEGER列では、数倀は「そのたた」曞き蟌たれ、_mogut_の堎合、行は数倀になりたす぀たり、「ロスレス」逆倉換が蚱可されたす。
REAL列の堎合、ルヌルはINTEGER  NUMERIC に䌌おいたす。 違いは、すべおの数倀が浮動小数点圢匏であるこずです。
NONE列には、倀が「そのたた」入力されたす特に指定しない限り、このタむプがデフォルトで䜿甚されたす。

異なるタむプの倀を互いに比范する堎合、远加のタむプ倉換を実行できたす。

数倀を文字列ず比范するずきに、文字列を「ロスレス」数倀に倉換できる堎合、数倀になりたす。

さらに詳しく

ここで、SQLiteの䞀意のむンデックスには、任意の数のNULL倀が存圚する可胜性があるこずに泚意しおくださいOracleは同意し、MS SQLは同意したせん。

むンメモリデヌタベヌス

sqlite3_open呌び出しでファむル名を"memory"ずしお枡すず、SQLiteはメモリ内に新しいクリヌンなデヌタベヌスぞの接続を䜜成したす 。

この接続は、䜿甚ロゞックによるず、ファむル内のデヌタベヌスぞの接続ずたったく区別できたせん。同じSQLコマンドのセットを䜿甚できたす。

残念ながら、メモリ内の同じデヌタベヌスぞの2぀の接続を開く方法はありたせん。

UPDすでに刀明しおいたすが、メモリ内の1぀のデヌタベヌスぞの2぀の接続を開くこずができたす。

rc = sqlite3_open("file:memdb1?mode=memory&cache=shared", &db); 


 ATTACH DATABASE 'file:memdb1?mode=memory&cache=shared' AS aux1; 


詳现をご芧ください。

耇数のデヌタベヌスに同時に参加する

デヌタベヌスぞの接続を開くには、 sqlite3_open呌び出しを䜿甚したす。

い぀でも、SQL ATTACH DATABASEコマンドを䜿甚しお、開いおいる接続に最倧10個のデヌタベヌスを接続できたす。

 sqlite3_open('foo.sqlite3', &db); //       "foo.sqlite3" sqlite3_exec(&db, "ATTACH 'bar.sqlite3' AS bar", ... ); //  "bar.sqlite3" 


これで、db1.sqlite3ファむル内のすべおのデヌタベヌステヌブルが透過的に䜿甚可胜になりたした。

名前の競合を解決するには、添付ファむル名を䜿甚する必芁がありたすメむンベヌスは"main"ず呌ばれたす。

 SELECT * FROM main.my_table UNION SELECT * FROM bar.my_table 


メモリ内の新しいデヌタベヌスをデヌタベヌスに接続し、キャッシュなどに䜿甚するこずを劚げるものは䜕もありたせん。

 sqlite3_open('foo.sqlite3', &db); //       "foo.sqlite3" sqlite3_exec(&db, "ATTACH ':memory:' AS mem", ... ); //      


さらに詳しく

これは非垞に䟿利な機胜です。 接続されたデヌタベヌスは、メむンデヌタベヌスず同じデヌタ圢匏である必芁がありたす。そうでない堎合ぱラヌになりたす。

䞀時デヌタベヌス

sqlite3_openでファむル名の代わりに空の文字列を枡すず、ディスク䞊のファむルに䞀時デヌタベヌスが䜜成されたす。 さらに、デヌタベヌスぞの接続を閉じた埌、ディスクから削陀されたす。

PRAGMAコマンドによるデヌタベヌスの埮調敎

PRAGMA SQLコマンドは、接続たたはデヌタベヌス自䜓のすべおの皮類の蚭定を蚭定するために䜿甚されたす。

  PRAGMA name; //     name PRAGMA name = value; //   name  value 


接続のセットアップ圓然は、開いた盎埌ず䜿甚前に行う必芁がありたす。

すべおのパラメヌタの詳现な説明はこちらです。

私は最も重芁な事柄に぀いお説明したす。

 PRAGMA page_size = bytes; //   ;   -       ,       (  4096) PRAGMA cache_size = -kibibytes; //      ,     2000   PRAGMA encoding = "UTF-8"; //   ,   UTF-8 PRAGMA foreign_keys = 1; //   foreign keys,   -  PRAGMA journal_mode = DELETE | TRUNCATE | PERSIST | MEMORY | WAL | OFF; //   , .  PRAGMA synchronous = 0 | OFF | 1 | NORMAL | 2 | FULL; //   , .  


トランザクションのログずコミット

そのため、このトピックに぀いお説明したす。マスタヌするず、すぐにSQLiteのマスタヌの第3レベルに進みたす。

SQLiteは、デヌタベヌス ACID のデヌタの敎合性を泚意深く監芖し、 トランザクションを介しおデヌタを倉曎するメカニズムを実装したす。

トランザクションに぀いお簡単に説明するず、トランザクションは完党にロヌルアップされるか、完党にロヌルバックされたす。 䞭間状態はありたせん。

トランザクションを明瀺的に䜿甚しない堎合 BEGIN; ...; COMMIT; 、 暗黙的なトランザクションが垞に䜜成されたす。 コマンドを実行する前に開始し、盎埌にコミットしたす。

したがっお、぀いでに、SQLiteの「遅さ」に぀いおの苊情。 SQLiteは1秒あたり最倧5䞇件のレコヌドを挿入するこずもできたすが、1秒あたり最倧50件を超えるトランザクションを蚘録するこずはできたせん。

そのため、暗黙的なトランザクションを䜿甚しおレコヌドをすばやく挿入するこずはできたせん。

デフォルト蚭定では、SQLiteは操䜜䞭に電源がオフになった堎合でもデヌタベヌスの敎合性を保蚌したす。

この驚くべき動䜜は、 ロギング 特別なファむルず、ディスクぞの倉曎を同期するための独創的なメカニズムによっお実珟されたす。

デヌタベヌス内のデヌタを簡単に曎新するには、次のようにしたす。

-SQLiteは、デヌタベヌスを倉曎する前に、デヌタベヌスから倉曎したペヌゞを別のファむルログに保存したす。぀たり、単にそこにコピヌしたす。
-ペヌゞのコピヌが䜜成されたこずを確認するず、SQLiteはデヌタベヌスの倉曎を開始したす。
-デヌタベヌスぞのすべおの倉曎が「ディスクに到達」し、デヌタベヌスが完党になったこずを確認するず、SQLiteはログを消去したす。

トランザクションメカニズムの原子性はここで詳现に説明されたす 。

SQLiteがデヌタベヌスぞの接続を開き、ログが既に存圚するこずを確認するず、デヌタベヌスが䞍完党な状態にあるこずを認識し、最埌のトランザクションを自動的にロヌルバックしたす。

぀たり、実際には、障害埌のデヌタベヌス回埩メカニズムはSQLiteに組み蟌たれおおり、ナヌザヌにずっおシヌムレスに機胜したす。

デフォルトでは、ログは削陀モヌドになっおいたす。
 PRAGMA journal_mode = DELETE 


これは、トランザクションが完了した埌にログファむルが削陀されるこずを意味したす。 このモヌドでログファむルがあるずいう事実は、SQLiteにずっおトランザクションが完了しおいないこずを意味し、デヌタベヌスを埩元する必芁がありたす。 ログファむルには、「-journal」が远加されるデヌタベヌスファむルの名前が付けられたす。

TRUNCATEモヌドでは、ログファむルはれロに切り捚おられたす䞀郚のシステムでは、ファむルを削陀するよりも速く動䜜したす。

PERSISTモヌドでは、ログファむルの先頭がれロで詰たっおいたすサむズは倉曎されず、倚くのスペヌスを占有したす。

MEMORYモヌドでは、ログファむルはメモリに保持され、これは迅速に機胜したすが、障害が発生した堎合のデヌタベヌスの回埩を保蚌したせんディスク䞊にデヌタのコピヌはありたせん。

たたは、ゞャヌナルを完党に無効にするこずができたす PRAGMA journal_mode = OFF 。 この状況では、トランザクションのロヌルバック ROLLBACKコマンドが動䜜を停止し、プログラムがクラッシュした堎合にデヌタベヌスが砎損する可胜性がありたす。

メモリ内のデヌタベヌスの堎合、ログモヌドはMEMORYたたはOFFのいずれかのみです。

少し戻りたしょう。 SQLiteは、デヌタベヌスが垞に完党であるこずをどのように「確認」したすか

最新のシステムでは、巧劙なキャッシングを䜿甚しおパフォヌマンスが向䞊し、ディスクぞの曞き蟌みが遅れるこずがありたす。

SQLiteがデヌタベヌスぞの曞き蟌みを終了し、ログファむルを消去しおトランザクションをコミットしたこずを瀺したいずしたす。

デヌタベヌスが曎新される前にファむルが消去された堎合はどうなりたすか

この期間䞭に電源がオフになるず、ログはそこになく、デヌタベヌスはただ完党ではありたせん-デヌタ損倱

぀たり、独創的な倉曎コミットメカニズムは、ディスクシステムずOSからのいく぀かの保蚌に䟝存する必芁がありたす。

PRAGMA同期は、「パラノむア」SQLiteの床合いをこの効果に蚭定したす。

OFFモヌドたたは0は、SQLiteはデヌタをOSに転送した盎埌぀たり、察応するOS APIを呌び出した盎埌にディスク䞊で固定されおいるず芋なしたす。

぀たり、アプリケヌションがクラッシュした堎合 OSが匕き続き動䜜するためには敎合性が保蚌されたす が、OSのクラッシュや停電の堎合には保蚌されたせん。

NORMAL同期モヌドたたは1は、OSクラッシュ時およびほがすべおの停電時の敎合性を保蚌したす。 電力が最も䞍適切な瞬間に倱われるず、ベヌスが劣化する可胜性がれロではありたせん。 これは、パフォヌマンスず信頌性の点で、䞀皮の䞭皋床の劥協モヌドです。

FULLモヌドは、い぀でもどこでも、どんな事故でも完党性を保蚌したす。 しかし、特定の堎所では期埅の䞀時停止が行われるため、もちろん、よりゆっくりず動䜜したす。 そしお、これがデフォルトのモヌドです。

したがっお、 WALのような雑誌のトピックのみが未到達のたたでした。

WALログモヌド

デフォルトでは、デヌタベヌスログモヌドは垞にDELETEに 「戻りたす」。 デヌタベヌスぞの接続を開き、モヌドをPERSISTに蚭定したずしたす。 デヌタを倉曎し、接続を閉じたした。

ディスク䞊にログファむルがありたす最初はれロです。

デヌタベヌスぞの接続を再床開きたす。 この接続でログモヌドを蚭定しない堎合、再床DELETEで機胜したす。 デヌタを曎新するずすぐに、トランザクションコミットメカニズムによっおログファむルが消去されたす。

WALログモヌドの動䜜は異なりたす-「氞続的」です。 デヌタベヌスをWALモヌドにするずすぐに、デヌタベヌスが別のログモヌドに明確に倉曎されるたで、このモヌドのたたになりたす。

なぜそれが必芁なのですか

圓初、SQLiteは組み蟌みデヌタベヌスずしお蚭蚈されたした。 デヌタぞの同時アクセスを共有するアヌキテクチャは基本的なものでした。同時に、耇数の接続がデヌタベヌスを読み取るこずができたすが、䞀床に曞き蟌みできる接続は1぀だけです。 これは、少なくずも、曞き蟌み接続がデヌタベヌスがリヌダヌから「リリヌス」されるのを埅っおいるこずを意味したす。 「ビゞヌ」デヌタベヌスに曞き蟌もうずするず、アプリケヌションはSQLITE_BUSY゚ラヌを受け取りたす SQLITE_LOCKEDず混同しないでください 。 ファむルロックAPIを介しおアクセスを共有するためのこのメカニズムが実珟されたすネットワヌクドラむブではうたく機胜しないため、SQLiteは掚奚されたせん。 詳现

WAL 先行曞き蟌みロギング モヌドでは、デヌタベヌスの「リヌダヌ」ずデヌタベヌスの「ラむタヌ」が互いに干枉するこずはなくなりたした。぀たり、読み取り䞭にデヌタを倉曎できたす。 芁するに、これはすべおが存圚する倧芏暡で深刻なDBMSぞの䞀歩です。 たた、WALのSQLiteの方が高速であるず䞻匵されおいたす。

しかし、欠点もありたす
-OSからの远加のnishtyakiが必芁ですunixずWindowsにはこれらのnishtyakiがありたす。
-デヌタベヌスはいく぀かのファむルファむル"XXX-wal"および"XXX-shm" を取りたす。
-倧芏暡なトランザクションではうたく機胜したせん条件付きで、トランザクションが50 MBを超える堎合。
-このようなデヌタベヌスを読み取り専甚モヌドで開くこずはできたせん。
-远加のチェックポむント操䜜が発生したす。

実際、WALモヌドでは、デヌタベヌスデヌタはデヌタベヌスずログファむルの間で共有されたす。 チェックポむント操䜜は、デヌタをデヌタベヌスに転送したす。 デフォルトでは、ログが1000デヌタベヌスペヌゞを䜿甚しおいる堎合、これは自動的に行われたす。
぀たり、高速なCOMMITがあり、突然COMMITがそれに぀いお考え、チェックポむントを開始したした。 この動䜜が望たしくない堎合は、手動でチェックポむントを実行できたすすべおが萜ち着いおいる堎合。これは別のプロセスで実行できたす。

制限

SQLiteは、その小型化にもかかわらず、実際にはフィヌルド、テヌブル、たたはデヌタベヌスのサむズに深刻な制限を課しおいたせん。

デフォルトでは、BLOBたたは文字列倀は1 GBを占有でき、これは1レコヌドのサむズ制限ず同じです2 ^ 31-1、SQLITE_MAX_LENGTHパラメヌタヌに䞊げるこずができたす。

列数200032767たで䞊げるこずができたす、SQLITE_MAX_COLUMN。

SQLステヌトメントのサむズ1 MB1073741824バむト、SQLITE_MAX_SQL_LENGTH。

同時結合64テヌブル。

接続にベヌスを接続したす10最倧62、SQLITE_MAX_ATTACHED

デヌタベヌスの最倧ペヌゞ数1073741823最倧2147483646、SQLITE_MAX_PAGE_COUNT。

ペヌゞサむズを65,636バむトに蚭定した堎合、最倧デヌタベヌスサむズは玄14テラバむトになりたす。

テヌブル内の゚ントリの最倧数は2 ^ 64-1ですが、実際には、もちろん、サむズ制限は早くなりたす。

詳现sqlite.org/limits.html

UDPSQLite Optimization Links 1 2 android-1 android-2

続く

Source: https://habr.com/ru/post/J149635/


All Articles