現在、リレーショナルデータベースでデータを操作したり照会したりする手段として、Structured Query Language(構造化問い合わせ言語)が標準的に使われていますが、製品によっては独自の拡張が行われています。
しかし、SQL は常にリレーショナル データベースの「ユニバーサル」な言語ではありませんでした。 当初(1980年頃)から、SQLには不利な点がありました。 私を含め、当時の多くの研究者や開発者は、SQL のオーバーヘッドにより、運用データベースでは実用的ではないと考えていました。
SQL の歴史
SQL が登場する前、データベースにはタイトでナビゲーショナルなプログラミング インターフェイスがあり、CODASYL データ モデルと呼ばれるネットワーク スキーマを中心に設計されていました。 CODASYL (Committee on Data Systems Languages) は、プログラミング言語のCOBOL (1959年に開始) とデータベース言語の拡張 (10年後に開始) を担当したコンソーシアムでした。 従来の階層型データベースでは、1つのレコードは1つのセットにしか所属できませんでした。
例えば、CS 101に在籍する学生をリストアップしたいとします。 まず、"CS 101"
Courses
Enrollees
Enrollees
ffm
Student
fnm
)を見つけ、それをリストアップします。
これは、データベース プログラマーにとっては大変な作業のように思えるかもしれませんが、実行時には非常に効率的でした。 カリフォルニア大学バークレー校のMichael Stonebraker氏やIngres社の専門家は、IDMSのようなCODASYLデータベースでこの種のクエリを実行した場合、SQLを使用したリレーショナル データベースで同じクエリを実行した場合と比べて、CPU時間は約半分、メモリは半分以下になると指摘しています。
比較のために、CS 101 のすべての学生を返す同等の SQL クエリは次のようになります。
SELECT student.name FROM courses, enrollees, students WHERE course.name ="CS 101"
この構文は、以下で説明するように、リレーショナル インナー ジョイン (実際には 2 つ) を意味し、ジョインに使用されるフィールドなどの重要な詳細が省かれています。
リレーショナル データベースと SQL
なぜ実行速度とメモリ使用量が 2 倍も向上することをあきらめるのでしょうか。 大きな理由は 2 つあり、開発のしやすさと移植性です。
つまり、ムーアの法則によって、CODASYLデータベースは廃止され、リレーショナル データベースが採用されたのです。
つまり、ムーアの法則により、CODASYLデータベースは廃止され、リレーショナルデータベースが採用されたのですが、結果的には、開発時間の改善は大きかったものの、SQLの移植性は夢のまた夢でした。 E.F. “Ted” Coddは、IBMサンノゼ研究所のコンピュータサイエンティストで、1960年代にリレーショナルモデルの理論を構築し、1970年に発表しました。 IBMは、CODASYLデータベースであるIMS/DBの収益を守るために、リレーショナルデータベースの導入を遅らせていた。 ようやくIBMが「System R」プロジェクトを開始したとき、開発チーム(Don ChamberlinとRay Boyce)はCoddの部下ではなかったので、Coddが1971年に発表したリレーショナル言語「Alpha」の論文を無視して、独自の言語「SEQUEL(Structured English Query Language)」を設計した。 1979年、まだIBMが製品をリリースする前に、ラリー・エリソンが自分のOracleデータベースにこの言語を組み込んだ(IBMの発売前のSEQUELの出版物を仕様として使用した)。
「SQLを求める声」(Michael Stonebraker氏の言葉)は、OracleやIBMだけでなく、顧客からも聞こえてきました。 CODASYLのデータベース設計者やプログラマーを雇ったり育てたりするのは簡単ではありませんでしたから、SEQUEL(とSQL)の方がずっと魅力的に見えたのです。
Coddが設計した純粋なリレーショナルデータベースは、関係にグループ化されたタプルを基に構築されており、一階の述語論理と一致しています。 現実のリレーショナルデータベースには、フィールド、制約、トリガーを含むテーブルがあり、テーブルは外部キーによって関連づけられています。
SQLには、スキーマを定義するためのサブ言語であるデータ定義言語(DDL)と、データを修正するためのサブ言語であるデータ操作言語(DML)があります。 これらはいずれも初期のCODASYL仕様がルーツとなっています。
SQL の SELECT 文
SELECT
文は、クエリ オプティマイザに、どのデータを返すか、どのテーブルを調べるか、どの関係をたどるか、返されたデータにどのような順序を課すかを指示します。 クエリ オプティマイザは、データベースがインデックス ヒントをサポートしていない限り、テーブル スキャンを回避し、クエリのパフォーマンスを向上させるために、どのインデックスを使用するかを自分で判断しなければなりません。 頻繁に使用するクエリのインデックスを省略すると、重い読み取り負荷がかかったときにデータベース全体が遅くなります。
もう 1 つの重要な技術は、すべてのテーブルに適切でユニークな主キーを選択することです。
水平シャーディングと呼ばれる、主キーの値に応じて異なるボリュームに分割されるデータベース テーブルの高度なケースでは、主キーがシャーディングにどのような影響を与えるかを考慮する必要があります。
SELECT
ステートメントの議論は、最初は簡単かもしれませんが、すぐに混乱してしまいます。
SELECT * FROM Customers;
シンプルですよね。 これは、Customers
Customers
テーブルには1億行と100個のフィールドがあり、そのうちの1つがコメント用の大きなテキストフィールドだったとします。 各行に平均 1 キロバイトのデータが含まれている場合、毎秒 10 メガビットのネットワーク接続で、すべてのデータを引き出すのにどれくらいの時間がかかるでしょうか。
おそらく、通信で送信する量を減らすべきでしょう。
SELECT TOP 100 companyName, lastSaleDate, lastSaleAmount, totalSalesAmount FROM Customers
WHERE state ="Ohio" AND city ="Cleveland"
ORDER BY lastSaleDate DESCENDING;
さて、あなたはかなり少ないデータを引き出すことになります。 データベースには、4 つのフィールドのみを提供し、Cleveland にある企業のみを考慮し、最新の売上がある 100 社のみを提供するよう依頼しました。 しかし、データベースサーバーで最も効率的にこれを行うには、次のようにします。 Customers
state+city
WHERE
Customers
state+city
lastSaleDate
ORDER BY
TOP 100
lastSaleDate
へのインデックスが必要です。
ところで、TOP 100
は、SQL ServerやSQL Azureでは有効ですが、MySQLやOracleでは有効ではありません。 MySQLでは、LIMIT 100
WHERE
節の後に使用します。 Oracleでは、ROWNUM
WHERE
です。
SQL joins
これまで、単一テーブルに対するSELECT
JOIN
句を説明する前に、外部キーとテーブル間の関係を理解する必要があります。 ここでは、SQL Server の構文を使用した DDL の例を使って説明します。
簡単に言うと、かなりシンプルです。 これは、単一のフィールドか、式で定義されたフィールドの組み合わせのいずれかです。 例えば、
CREATE TABLE Persons (
PersonID int NOT NULL PRIMARY KEY,
PersonName char(80),
...
Persons
Persons
の主キーに対応するフィールドを持つべきであり、関係の整合性を保つために、そのフィールドは外部キー制約を持つべきです。 例えば、
CREATE TABLE Orders (
OrderID int NOT NULL PRIMARY KEY,
...
PersonID int FOREIGN KEY REFERENCES Persons(PersonID)
);
両方のステートメントには、制約に名前を付けることができる CONSTRAINT
キーワードを使用したより長いバージョンがあります。
主キーは常にインデックスが付けられ、ユニーク(フィールドの値が重複しない)です。 他のフィールドはオプションでインデックスを付けることができます。 外部キー フィールドや、WHERE
ORDER BY
句に登場するフィールドにインデックスを作成することは、書き込みや更新によるオーバーヘッドが発生する可能性があるため、常にではありませんが、しばしば有用です。
John Doeが発注したすべての注文を返すクエリはどのように書きますか?
SELECT PersonName, OrderID FROM Persons
INNER JOIN Orders ON Persons.PersonID = Orders.PersonID
WHERE PersonName ="John Doe";
実際には、JOIN
INNER
OUTER
LEFT
RIGHT
INNER JOIN
INNER
LEFT JOIN
を使用します:
SELECT PersonName, OrderID FROM Persons
LEFT JOIN Orders ON Persons.PersonID = Orders.PersonID
ORDER BY PersonName;
2つ以上のテーブルを結合したり、式を使用したり、データ型を強制したりするクエリを実行し始めると、最初は構文が少々面倒になります。
SQL ストアド プロシージャ
SELECT
ステートメントの宣言的な性質では、行きたいところに行けない場合があります。
SQL Server では、ストアド プロシージャ (またはストアド プロシージャ) の初期の方言は Transact-SQL (通称 T-SQL)、Oracle では PL-SQL でした。 単純なT-SQLストアドプロシージャは、SELECT
ステートメントをパラメータ化しただけのものかもしれません。 ストアドプロシージャの利点は、使いやすさと効率の良さです。
より複雑な T-SQL ストアド プロシージャでは、複数の SQL ステートメント、入出力パラメーター、ローカル変数、BEGIN...END
IF...THEN...ELSE
条件、カーソル (セットの行ごとの処理)、式、一時テーブルなど、さまざまなプロシージャ構文が使用されます。 もちろん、ストアドプロシージャの言語がC#、Java、Rであれば、それらの手続き言語の関数や構文を使用することになります。
だからといって、昔のCODASYLデータベース プログラミングの時代に戻るわけではありませんが (カーソルはそれに近いですが)、SQLステートメントは標準化されるべきであり、パフォーマンスの問題はデータベース クエリ オプティマイザに任せるべきであるという考えからは脱却しています。
Learn SQL
以下のサイトは、SQL を学んだり、さまざまな SQL 方言の癖を発見したりするのに役立ちます。 SQLを学ぶ。 無料でインタラクティブに学べます。
SELECT
FROM
WHERE
)、Sachin Quickly Learns (SQL)などがあります。 データベースのドキュメント: