最近、SQLはひどい言語だとよく耳にします。太陽の下にあるすべてのフレームワークには、データベース抽象化レイヤーがあらかじめパッケージ化されているようです。
けれども私の経験では、SQLは多くの場合、データの入出力を管理するためのはるかに簡単で、より用途が広く、プログラマーに優しい方法です。私が使用したすべての抽象化レイヤーは、著しく制限されたアプローチであり、実際の利点はないようです。
SQLがこれほどひどいのはなぜですか。また、データベース抽象化レイヤーが重要なのはなぜですか。
最近、SQLはひどい言語だとよく耳にします。太陽の下にあるすべてのフレームワークには、データベース抽象化レイヤーがあらかじめパッケージ化されているようです。
けれども私の経験では、SQLは多くの場合、データの入出力を管理するためのはるかに簡単で、より用途が広く、プログラマーに優しい方法です。私が使用したすべての抽象化レイヤーは、著しく制限されたアプローチであり、実際の利点はないようです。
SQLがこれほどひどいのはなぜですか。また、データベース抽象化レイヤーが重要なのはなぜですか。
回答:
これは部分的に主観的です。だからこれは私の意見です:
SQLには、疑似自然言語スタイルがあります。発明者たちは、英語と同じように言語を作成でき、データベースクエリが非常に簡単になると考えていました。ひどい間違い。些細な場合を除いて、SQLの理解は非常に困難です。
SQLは宣言型です。データベースにどのように動作するかを伝えることはできません。結果として何をしたいかだけです。これは完璧で非常に強力です-パフォーマンスを気にする必要がない場合。つまり、SQLを書き、実行プランを読み、SQLを言い換えて実行プランに影響を与えようとすると、なぜ自分で実行プランを書けないのか不思議に思います。
宣言型言語のもう1つの問題は、いくつかの問題は命令型の方法で解決する方が簡単なことです。したがって、別の言語(標準SQLとおそらくデータアクセスレイヤーが必要です)で作成するか、ベンダー固有の言語拡張を使用して(たとえば、ストアドプロシージャなどを作成して)作成します。そうすることで、今まで見た中で最悪の言語の1つを使用していることに気付くでしょう。なぜなら、それは命令型言語として使用するように設計されていないからです。
SQLは非常に古いものです。SQLは標準化されていますが、遅すぎるため、多くのベンダーがすでに言語拡張を開発しています。SQLは何十もの方言になりました。これが、アプリケーションに移植性がない理由であり、DB抽象化レイヤーがある理由の1つです。
しかし、それは本当です-実行可能な代替手段はありません。したがって、今後数年間はすべてSQLを使用します。
言われたことはすべて別にして、テクノロジーは抽象化層を価値あるものにするために悪いものである必要はありません。
非常に単純なスクリプトまたはアプリケーションを実行している場合は、コード内でSQL呼び出しを好きな場所に混在させることができます。ただし、複雑なシステムを使用している場合は、データベース呼び出しを個別のモジュールに分離することをお勧めします。これにより、SQLコードが分離されます。コードの可読性、保守性、テスト容易性が向上します。これにより、すべての高レベルのものなどを分解することなく、システムをデータベースモデルの変更にすばやく適合させることができます。
SQLは素晴らしいです。その上の抽象化レイヤーはそれをさらに大きくします!
抽象化レイヤーの1つのポイントは、標準が少しあいまいであるため、またほとんどのベンダーが独自の(非標準)追加機能を追加しているため、SQL実装は互いに互換性がない傾向があるという事実です。つまり、MySQL DB用に作成されたSQLは、「必要がある」としても、たとえばOracle DBとまったく同様に機能しない可能性があります。
ただし、SQLは他のほとんどの抽象化レイヤーよりもはるかに優れていることに同意します。SQLが設計されていないものに使用されているのは、SQLのせいではありません。
SQLはいくつかのソースから悪口を付けられます:
1つのDBMS製品に固執する場合、少なくともモデルに内在するスケーラビリティの壁にぶつかるまで、SQL DBは競合製品よりも用途が広く、品質が高いことに間違いなく同意します。しかし、あなたは本当に次のTwitterを書こうとしているのでしょうか、それとも、いくつかの会計データを整理して一貫性を保とうとしているのでしょうか。
SQLに対する批判は、RDBMSに対する批判の代役となることがよくあります。RDBMSの批評家が理解していないように見えるのは、彼らが膨大なクラスのコンピューティング問題を非常にうまく解決していること、そして私たちの生活をより簡単にするためであり、困難ではないということです。
彼らがSQL自体を批判することに真剣であるならば、彼らはチュートリアルDやDataphorのような努力を後押しするでしょう。
SQLは、SETベースのデータの管理とクエリ用に設計されています。それはより多くを行うためにしばしば使用され、エッジのケースは時々欲求不満につながります。
SQLの実際の使用は、SQLが問題ではない可能性があるという基本データベース設計の影響を受ける可能性がありますが、設計が影響する可能性があります。また、悪い設計に関連するレガシーコードを投げると、変更の影響が大きくなり、実装にコストがかかります(戻って「機能する」ものや目標を達成するものを「修正」するのは好きではありません)
大工は、ハンマーで釘を、ノコギリで鋸で、平らな板で平面を叩くことができます。ハンマーや飛行機を使って「のこぎり」をすることは可能ですが、ぶらさがってイライラします。
ひどいとは言わない。一部のタスクには適していません。たとえば、SQLで適切な手続き型コードを記述することはできません。私はかつて、SQLでのセット操作を強制されました。それを理解するのに私はまるまる週末を要した。
SQLはリレーショナル代数用に設計されました-ここでSQLを使用する必要があります。
最近、SQLはひどい言語だとよく耳にします。太陽の下にあるすべてのフレームワークには、データベース抽象化レイヤーがあらかじめパッケージ化されているようです。
これらのレイヤーは独自のものを単にに変換することに注意してくださいSQL
。ほとんどのデータベースベンダーにとってSQL
、エンジンと通信する唯一の方法です。
けれども私の経験では、SQLは多くの場合、データの入出力を管理するためのはるかに簡単で、より用途が広く、プログラマーに優しい方法です。私が使用したすべての抽象化レイヤーは、著しく制限されたアプローチであり、実際の利点はないようです。
…上記で説明した理由。
データベースレイヤーは何も追加せず、制限するだけです。これにより、クエリが疑いなく単純になりますが、効率が上がることはありません。
定義上、データベースレイヤーにはにはないものはありませんSQL
。
何が
SQL
そんなにひどいのですか、そしてなぜデータベース抽象化レイヤーが貴重なのですか?
SQL
は素晴らしい言語ですが、それを使用するには多少の工夫が必要です。
理論的にSQL
は、宣言型です。つまり、取得したいものを宣言し、エンジンがそれを可能な限り最速の方法で提供します。
実際には、正しいクエリ(正しい結果を返すクエリ)を作成する方法はたくさんあります。
オプティマイザは、いくつかの事前定義されたアルゴリズム(そう、それらは複数です)からレゴ城を構築できますが、新しいアルゴリズムを作成することはできません。それでも、SQL
開発者がそれらを支援する必要があります。
ただし、一部の人々は、オプティマイザが「SQL
エンジンの特定の実装でこのクエリに使用できる最良の計画」ではなく、「可能な最良の計画」を作成することを期待しています。
そして、誰もが知っているように、コンピュータープログラムが人々の期待に応えられない場合、それは非難されるのはプログラムであり、期待ではありません。
ただし、ほとんどの場合、クエリを再構成することで、可能な限り最良の計画を作成できます。しかし、それが不可能であるときにタスクが存在しますが、SQL
これらのケースに対する新しくて成長している改善により、数はますます少なくなっています。
ただし、ベンダーが「インデックス範囲を取得する」、「行を取得するrowid
」などの関数への低レベルのアクセスを提供した場合、C
コンパイラーがアセンブリを言語に直接埋め込むことができるようになると便利です。
最近、私のブログにこれに関する記事を書いています。
私は大規模なORM擁護者であり、SQLは非常に有用であると私はまだ信じていますが、(他のものと同じように)それで恐ろしいことを行うことは確かに可能です。。
私はSQLを、コードの再利用や保守性/リファクタリングを優先事項としない、非常に効率的な言語と見なしています。
したがって、超高速処理が優先されます。そして、それは許容範囲です。あなたは、私にとってかなりのトレードオフを知っている必要があります。
美的観点から見ると、言語としては、OOの概念などがないため、いくつか欠けているように感じます。私には、非常に古い学校の手続き型コードのように感じます。しかし、それは遠く離れて特定のことを行う最も速い方法であり、それは強力なニッチです!
フレームワークに含まれているデータベースアブストラクションレイヤーは2つの非常に重要な問題を解決するので、良いことだと思います。
それはコードを明確に保ちます。 SQLを別のレイヤーに配置します。これは一般的に非常に薄く、クエリの基本と結果のハンドオフ(標準化された方法で)のみを実行する必要があるため、SQLの乱雑さからアプリケーションを解放できます。これは、Web開発者がCSSとJavaScriptを別々のファイルに配置する必要があるのと同じ理由です。回避できる場合は、言語を混在させないでください。
多くのプログラマーは、SQLの使い方がまったく得意ではありません。 何らかの理由で、多数の開発者(特にWeb開発者)は、SQLまたはRDBMSの一般的な使用が非常に非常に悪いようです。彼らは、データベース(および拡張機能によるSQL)を、データにアクセスするために経験しなければならない厄介な小さな仲介者として扱います。これにより、インデックスのない非常に不十分なデータベース、疑わしい方法でテーブルの上に積み重ねられたテーブル、および非常に不十分なクエリが作成されます。またはさらに悪いことに、彼らはあまりにも一般的すぎるようにしようとし(エキスパートシステム、誰か?)、意味のある方法でデータを合理的に関連付けることができません。
残念ながら、無知、頑固さ、またはその他の特性に関係なく、誰かが問題やツールを解決しようとする方法は、互いに直接対立しており、幸運にもこれを説得しようとしています。このように、データベースアブストラクションレイヤーは、SQLを貧しい開発者の目から遠ざけるだけでなく、コードを大幅にリファクタリングしやすくするため、データベースアブストラクションレイヤーを一種のセーフティネットと見なしています。すべてのクエリが1か所にあるため。
SQLは特定の種類のタスク、特にデータセットの操作と取得に最適です。
ただし、SQLには、変更と複雑さを管理するためのいくつかの重要なツールがありません(または一部しか実装されていません)。
カプセル化:SQLのカプセル化メカニズムは粗いです。SQLコードを作成するときは、データの実装に関するすべてを知る必要があります。これにより、達成できる抽象化の量が制限されます。
ポリモーフィズム:異なるテーブルで同じ操作を実行したい場合は、コードを2回記述する必要があります。(想像力に富んだビューを使用することで、これを軽減できます。)
可視性制御:コードの一部を互いに非表示にしたり、論理ユニットにグループ化したりするための標準SQLメカニズムがないため、望ましくない場合でも、すべてのテーブル、プロシージャなどに他のすべてからアクセスできます。
モジュール性とバージョン管理
最後に、SQLでCRUD操作を手動でコーディング(およびそれを他のアプリケーションに接続するコードを作成)は、反復的でエラーが発生しやすくなります。
最新の抽象化レイヤーはこれらの機能をすべて提供し、破壊的で反復的な実装の詳細を隠しながら、最も効果的な場所でSQLを使用できるようにします。オブジェクト指向のソフトウェア開発におけるデータアクセスを複雑にするオブジェクトリレーショナルインピーダンスの不一致を克服するのに役立つツールを提供します。
IMO、人々がSQLで抱えている問題は、リレーショナルデザインやSQL言語自体とは何の関係もありません。これは、データレイヤーのモデリングの分野と関係があり、多くの点で、ビジネスレイヤーやインターフェイスのモデリングとは根本的に異なります。プレゼンテーション層でのモデリングの間違いは、一般に、データベースを使用する複数のアプリケーションがあるデータ層よりもはるかに簡単に修正できます。これらの問題は、SOA設計でのサービスレイヤーのモデリングで発生する問題と同じであり、サービスの現在のコンシューマーと入出力コントラクトを考慮する必要があります。
SQLは、リレーショナルデータベースモデルと対話するように設計されています。しばらくの間存在していた他のデータモデルがありますが、データ層の設計に関する規律は、使用される理論モデルに関係なく適切に存在するため、開発者がSQLで通常持つ困難は、通常、非リレーショナルを課す試みに関連しています。リレーショナルデータベース製品へのデータモデル。
まず、パラメーター化されたクエリを使用するのは簡単で、SQLインジェクション攻撃からユーザーを保護します。この観点から、生のSQLを使用するとリスクが高くなります。つまり、セキュリティの観点から誤解を招きやすくなります。また、データベースにオブジェクト指向の視点を示すことも多く、この変換を行う必要がなくなります。
$dbh->do("DELETE FROM my_table WHERE some_value = ?", undef, $target_value);
そこ。できました。
経験豊富なSQLプログラマにとって、悪い面は
他の人にとっては、その理由は
SQLフレームワークの主な目的は、入力を減らすことです。彼らは何とかしますが、非常に単純なクエリに対してのみ頻繁に発生します。複雑なことをしようとすると、文字列を使ってたくさんタイプしなければなりません。SQL Alchemyのように可能な限りすべてを処理しようとするフレームワークは、他のプログラミング言語のように巨大になりすぎます。
[26.06.10の更新]最近、Django ORMモジュールを使用しました。これは私が目にした中で唯一価値のあるSQLフレームワークです。そして、これは多くのものを扱うことになります。ただし、複雑な集計は少し難しいです。
SQLはひどい言語ではありませんが、他の言語とうまく連携しないことがあります。
たとえば、すべてのエンティティをオブジェクト指向オブジェクトなどのオブジェクトとして表現したいシステムがある場合、これをSQLと抽象化レイヤーなしで組み合わせると、かなり面倒になる可能性があります。複雑なSQLクエリをOOの世界にマッピングする簡単な方法はありません。それらの世界間の緊張を緩和するために、抽象化の追加レイヤーが挿入されます(たとえば、OR-Mapper)。
SQLは、データ操作に最適な言語です。開発者の観点から見ると、データベースを変更してもコンパイル時にコードが壊れないというのが私が気に入らない点です。パフォーマンスを犠牲にしてSQL言語の表現力を犠牲にして、この機能を追加する抽象化を使用します。 、ほとんどのアプリケーションでは、SQLが持っているすべてのものは必要ないためです。
SQLが嫌われるもう1つの理由は、リレーショナルデータベースが原因です。
CAP定理は人気のようになります。
共有データシステムにどのような目標を設定したいですか?
- 強い整合性:更新がある場合でも、すべてのクライアントに同じビューが表示されます
- 高可用性:障害が発生している場合でも、すべてのクライアントがデータのレプリカを見つけることができます
- パーティショントレランス:システムがパーティション分割されている場合でも、システムプロパティが保持されます。
定理は、同時に3つのCAPプロパティのうち常に2つしか持てないことを述べています。
リレーショナルデータベースは、強い一貫性とパーティショントレランスに対応します。
したがって、リレーショナルデータベースが特効薬ではないことを理解する人が増え、高可用性により水平方向のスケーリングがより簡単になるため、高可用性を支持して拒否する人がますます増えています。ムーアの法則の限界に達したため、水平スケーリングは人気を博しましたの最良の方法はマシンを追加することです。
リレーショナルデータベースが拒否されると、SQLも拒否されます。
他の投稿者が指摘したように、SQLには多くの欠陥があります。それでも、「簡略化」は単純化することになっていたものよりも複雑になることが多いため、私は人々が代替手段として提供するツールの多くよりもSQLを使用することを好みます。
私の理論では、SQLは多数の象牙の塔の青いスキーヤーによって発明されたとしています。非手続き構造全体。素晴らしいですね。やりたいことではなく、やりたいことを教えてください。しかし、実際には、多くの場合、手順を示すだけの方が簡単です。多くの場合、これは、完了したときに車がどのように機能するかを説明することによって、車のメンテナンス指示を与えようとしているように見えます。はい、「車にもう一度ガロンあたり30マイルを取得し、このようなハミングサウンドで走りたい...うーん...など」と言うことができますが、誰にとっても簡単ではないでしょうか「スパークプラグを交換してください」と言ってください。また、複雑なクエリを非手続き的な用語で表現する方法を理解した場合でも、データベースエンジンは、そのための非常に非効率的な実行プランを思い付くことがよくあります。
そしてヌルの扱いは私を狂わせます!はい、理論的には、誰かが「nullが不明を意味する場合、既知の値に不明な値を追加すると、不明な値が得られるはずです。結局のところ、不明な値が何であるかはわかりません。 」理論的には、絶対に真実です。実際には、10,000の顧客がいて、9,999の借金が正確にわかっているが、最後の顧客が支払うべき金額についていくつかの質問があり、経営陣は「売掛金の合計はどのくらいですか?」と言っています。答えは「わからない」です。しかし、実際的な答えは「4,327,287.42ドルを計算しますが、1つのアカウントが問題であるため、数値は正確ではありません」です。私は、経営陣が空白の凝視よりも、特定の数ではないにしても、かなり近いものになると確信しています。
そうは言っても、SQLの上に構築されたいくつかのレイヤーではなくSQLを使用したいので、学習する必要のある別の完全なセットが作成され、最終的にこれがSQLに変換され、場合によっては私はそれを正しく効率的に翻訳するためにそれを信頼することができますが、物事が複雑になるとできないので、追加のレイヤーを知る必要があり、SQLを知る必要があり、それがどのように翻訳されるかを知る必要がありますレイヤーをだましてSQLをだまして正しいことをさせることができます。あー。
•すべてのベンダーがSQL構文を拡張して、ニーズに合わせています。したがって、かなり単純なことを行わない限り、SQLコードは移植できません。
•SQLの構文は直交していません。たとえば、select, insert, update,
and delete
ステートメントはすべて完全に異なる構文構造を持っています。
insert
とupdate
操作の間でより一般的な構文を持つように設計されている可能性があります。
私はあなたの点に同意しますが、あなたの質問に答えるために、SQLを「ひどい」ものにする1つのことは、データベースベンダー(SQL Server、Oracleなど)間のT-SQLの完全な標準化の欠如であり、SQLコードが完全にポータブル。データベースアブストラクションレイヤーは、パフォーマンスコスト(時には非常に深刻なもの)を伴いますが、この問題を解決します。
純粋なSQLを使用することは、実際にはメンテナンスの地獄です。私にとってORMの最大の利点は、面倒な「DBリファクタリング」手順なしでコードを安全にリファクタリングできることです。オブジェクト指向言語用の優れた単体テストフレームワークとリファクタリングツールがありますが、たとえば、Resharperの対応するSQLをまだ見ていません。
それでもすべてのDALには舞台裏でSQLがあり、データベースに何が起こっているかを理解するにはSQLを知る必要がありますが、優れた抽象化レイヤーでの日常の作業はより簡単になります。
SQLをあまり使用していない場合、大きな問題は優れた開発者ツールの不足だと思います。
SQLの経験が豊富な場合は、実行計画を制御できないことに不満を感じることがあります。これは、SQLをベンダーに指定する方法に固有の問題です。SQLは、基盤となるテクノロジー(非常に強力)を真に活用するために、より堅牢な言語になる必要があると思います。
MySQL、Oracle、MSSQL、PostgreSQL、DB2で機能するデータセットにページ番号を付けるSQLを書いてください。
そうです、標準SQLでは、返される結果の数と開始する行を制限する演算子を定義していません。
SQLは構文、セマンティクス、および現在の使用法が悪いため、SQLへの愛はありません。説明します:
SQLの有用性についての議論は主に主観的であるが、私はビジネスニーズの性質上、より主観的であると私はここのほとんどの投稿に同意します。
Stefan Steineggerが指摘したように、宣言型言語は、希望する方法を指定するのではなく、希望するものを指定するのに適しています。これは、SQLのさまざまな実装がハイレベルの観点から適切であることを意味します。つまり、必要なのはデータを取得するだけで、それ以外は何も問題ない場合は、比較的単純なクエリを記述し、SQLの実装を選択することで満足できます。それはあなたにぴったりです。
はるかに「低い」レベルで作業していて、そのすべてを自分で最適化する必要がある場合、それは理想からほど遠いです。抽象化の層をさらに使用すると効果的ですが、実際に実行しようとしているのがクエリを最適化するためのメソッドを指定する場合などは、最適化を試みるときに仲介者を追加するのは少し直観的ではありません。
SQLで私が抱えている最大の問題は、他の「標準化された」言語のようなもので、実際の標準はほとんどありません。2つの規則が混同されないように、SybaseとMySQLの間でまったく新しい言語を習得する必要があります。
SQLはその仕事を成し遂げる一方で確かに問題があります...
SQLは嫌いではありませんが、開発中のSQLの一部として記述したくありません。DALは、市場投入までの速度を重視するものではありません。実際には、コードからの直接クエリよりも高速なDAL実装があるとは思っていません。しかし、DALの目標は抽象化することです。抽象化にはコストがかかりますが、実装には時間がかかります。
ただし、メリットは非常に大きいです。表現力豊かなクラス、厳密に型指定されたデータセットなどを使用して、コードの周りにネイティブテストを記述します。C#でジェネリックを使用する純粋なDDD実装である、ソートの「DAL」を使用します。そのため、一般的なリポジトリ、作業単位の実装(コードベースのトランザクション)、および論理的な分離があります。少しの労力でデータセットのモックアウトなどを行うことができ、実際にデータベースの実装より先に開発することができます。そのようなフレームワークを構築するための先行費用がありましたが、それは非常にいいですが、ビジネスロジックがショーの。データをリソースとして消費し、コードでネイティブに使用している言語で処理します。このアプローチの追加の利点は、提供される明確な分離です。たとえば、Webページにデータベースクエリが表示されなくなりました。はい、そのページにはデータが必要です。はい、データベースが関係しています。しかし、今は、どこからデータを取得するかに関係なく、コードにアクセスして検索する場所が1つ(そして1つだけ)あります。小さなプロジェクトでは大したことではないかもしれませんが、サイトに数百のページがある場合や、デスクトップアプリケーションに数十のウィンドウがある場合は、本当にそれを評価できます。
開発者として、論理的および分析的スキルを使用してビジネスの要件を実装するために雇われました-そして、私たちのフレームワークの実装により、今はより生産的になることができます。私はマネージャーとして、SQLを作成するよりも、論理的および分析的なスキルを使用して問題を解決することを開発者に求めています。開発サイクルの終わりに近づくまで、データベースがなくてもデータベースを使用するアプリケーション全体を構築できるという事実は素晴らしいことです。これは、データベースの専門家をたたくためのものではありません。データベースの実装は、ソリューションよりも複雑な場合があります。SQL(特に私たちの場合、ビューとストアドプロシージャ)は、コードがサービスとしてデータを消費できる抽象化ポイントです。データチームと開発チームが明確に分かれているショップでは、これは、データベースの実装と変更を待つ保留パターンに留まることを排除するのに役立ちます。開発者はDBAにカーソルを合わせなくても問題のあるドメインに集中でき、DBAは開発者がそれを必要とせずに正しい実装に集中できます。今。