パート2
パート3
小さな紹介。
この記事は初心者プログラマ向けではありません。
SQLチュートリアルではありません。
彼女はSQLiteを使用するキャンペーンをしていません。
彼女は、SQLiteを使用しないようにキャンペーンをしていません。
この記事は、SQLiteの架空の新参者からの質問とそれらへの回答の形式で書かれています(多くの情報があり、少なくとも少し簡単に構成できるため)。
SQLiteとは何ですか?
SQLiteは、組み込みのクロスプラットフォームデータベースであり、SQLコマンドのかなり完全なセットをサポートし、ソースコード(C言語)で利用できます。
SQLiteのソースコードはパブリックドメインにあります。つまり、使用制限はまったくありません。
ウェブサイト(英語の優れたドキュメント付き): http : //sqlite.org
現在のバージョン:3.7.13
SQLiteは自分でコンパイルできますが、Windows DLLとしてすでにコンパイルされているものをダウンロードします。
ダウンロードページ: http : //sqlite.org/download.html
独自のアセンブリでは、いわゆる 「合併」 、
つまり C + sqlite3.hの単一ファイルとしてのSQLiteソース。
SQliteコードのサイズを小さくし、不要なnishtyakiを捨てるために、あらゆる種類のDEFINEが使用されます。
SQLiteの人気度は?
簡単に言うと、彼女はどこにでもいます。 少なくともどのスマートフォンでも。
信頼性はどのくらいですか?
とても。 このバージョンがリリースされると、いくつかの深刻な自動テストが実行され(〜200万テストが実行されます)、テストのコードカバレッジは100%です(2009年8月以降)。
開発者が提供する他のツールは何ですか?
データベースを操作するためのコンソールユーティリティが利用可能です(sqlite3.exe、「SQLiteデータベースにアクセスして変更するためのコマンドラインシェル」)。
それだけですか?
はい、メイン開発者から-それだけです。 しかし、他の人はあらゆる種類のマネージャーなどを書いています。
個人的には、完璧なものを見つけていないので、コンソールを使用しています。
「かなり完全なSQLのセット」とはどういう意味ですか?
ご存知のように、その開発では、SQLはさまざまな方向に急ぎました。 大手メーカーは、あらゆる種類の拡張機能をプッシュし始めました。 そして、あらゆる種類の標準が受け入れられていますが(SQL 92)、実際には、すべての大規模データベースは標準を完全にサポートしておらず、独自の何かを持っています。 そのため、SQLiteは「最小限の、しかし完全なセット」の原則に従って生きようとしています。 複雑なものはサポートしていませんが、多くの点でSQL 92に対応しています。
また、その機能のいくつかを紹介します。これらの機能は非常に便利ですが、標準ではありません。
SQLサポートで特に困惑することは何ですか?
テーブルの列を削除または変更することはできません(ALTER TABLE DROP COLUMN ...、ALTER TABLE ALTER COLUMN ...)。
トリガーはありますが、大規模なRDBMSほど強力ではありません。
外部キーがサポートされていますが、デフォルトでは無効になっています。
組み込みのUNICODEサポートはありません(ただし、一般的に簡単に実現できます)。
ストアドプロシージャはありません。
そして、何が良いまたは異常ですか?
a)各レコードには、64ビットの数値(テーブルに固有)と等しい仮想ROWID列が含まれています。
INTEGER PRIMARY KEY列を宣言すると、この列はROWIDになります(独自の名前で、ROWIDという名前は引き続き機能します)。
レコードを挿入するときに、rowidを指定するか、指定しないことを選択できます(システムは一意のレコードを挿入します)。
詳細: www.sqlite.org/autoinc.html
b)データベースをメモリ内で簡単に整理できます(これは非常に便利で、後で詳しく説明します)。
c)転送が簡単:デフォルトでは、データベースは単一のファイル(クロスプラットフォーム形式)です。
d)列のタイプは、このレコードフィールドに格納されている値のタイプを決定しません。つまり、任意の値を任意の列に入力できます。
e)多くの組み込み関数(SQLで使用可能): www.sqlite.org/lang_corefunc.html;
タイプの何が問題なのか理解できませんでしたか? なぜ列タイプが必要なのですか?
列のタイプによって、値の比較方法が決まります(たとえば、インデックス内で比較する場合、値を単一のタイプにする必要があります)。
ただし、このタイプの値を列に入力する必要はありません。 弱いタイピングのようなもの。
列を「A INTEGER」として宣言したとします。
SQliteでは、この列に任意のタイプの値を入力できます(999、「abc」、「123」、678.525)。
挿入された値が整数でない場合、SQliteはその値を整数にキャストしようとします。
つまり 文字列「123」は整数123に変わり、残りの値は「現状のまま」書き込まれます。
それでは、列のタイプをまったく指定できませんか?
これは非常に頻繁に行われます: CREATE TABLE foo(a、b、c、d) 。
建築はどうですか? サーバーはありませんか?
サーバーはなく、アプリケーション自体がサーバーです。 データベースへのアクセスは、データベースへの「接続」(OSファイルハンドルのようなもの)を介して行われ、対応するDLL関数の呼び出しを介して開きます。 開くと、データベースファイル名が表示されます。 存在しない場合は、自動的に作成されます。
同じアプリケーションまたは異なるアプリケーションで、同じデータベースへの(ファイル名を介した)複数の接続を開くことは許可されています。
システムは、OSレベルのファイルアクセスロックメカニズムを使用して、これを機能させます。
(これらのメカニズムは、通常、ネットワークドライブでは不十分に機能するため、ネットワーク上のファイルでSQliteを使用することはお勧めしません)。
当初、SQliteは「多数の読み取り-1つの書き込み」の原則に基づいていました。
つまり、一度に1つの接続のみがデータベースに書き込みます。 他の接続も書き込もうとすると、SQLITE_BUSYエラーをキャッチします。
ただし、操作のタイムアウトを入力できます。 次に、データベースのビジー状態に直面した接続は、SQLITE_BUSYエラーで落ちる前にN秒待機します。
そして何をすべきか?
1つの接続とそれを介したすべての要求、または可能なタイムアウトから続行して、SQLの繰り返し実行を提供します。
別の可能性があります:少し前に新しいタイプのSQliteログが登場しました:Write Ahead Log、 WAL 。
データベースに対してこのログモードを有効にすると、複数の接続が同時にデータベースを変更できます。
ただし、このモードでは、データベースはすでにいくつかのファイルを取得しています。
さて、SQLiteにはグローバルキャッシュがないため、SQLiteがひどいのはなぜですか?
実際、最新のRDBMSはすべて、コンパイルされたパラメーター化されたクエリのようなあらゆる種類のニシュティアキを格納できるグローバル共有キャッシュなしでは考えられません。 このサーバーはビジーであり、ここにはありません。 ただし、単一のアプリケーション内で、SQliteは複数の接続間でキャッシュを共有し(こちらをご覧ください: www.sqlite.org/sharedcache.html )、メモリを節約できます。
そして、なぜSQLiteが遅いと誰もが不満を言うのですか?
2つの理由。 最初はデフォルト設定です。 パフォーマンスではなく信頼性のために機能します。
2番目は、トランザクションを修正するメカニズムの誤解です。 デフォルトでは、コマンドの実行後、SQliteはトランザクションをコミットします(つまり、データベースが一貫した状態になるまで待機して電源をオフにします)。 パラノイアモードに応じて、SQLiteはこれに50〜300ミリ秒を費やします(ディスクへのデータ書き込みの終了を待機します)。
どうする? 10万件のレコードを高速で挿入する必要があります。
インデックスを削除し、同期モードをOFF(またはNORMAL)にし、各N千の部分を挿入します(N-ピックアップ、最初に5000を取得)。 部分を挿入する前に、-COMMITの後にBEGIN TRANSACTIONを作成します。
しかし、私は間違いを見つけました! 報告方法
まさか。
実際、SQLiteの人気は怖いです-どこでもあります。 これは冗談ではありません。
また、開発者は、誤解が原因であるか、機能の要求が隠されているというエラーメッセージが大量に発生していました。 実際、彼らはエラーのあるレポートの直接受信を閉じました。
そのため、メーリングリストを購読し、そこで問題を説明し、最善の結果を期待する必要があります。
個人的には、SQLIteの欠陥と解釈した状況がありました。 ニュースレターで説明しました。 次のバージョンでは、SQLiteの動作が修正されました。
SQLiteで遊ぶ便利なユーティリティ 。
継続する。