アプリケーション開発者による一般的なデータベース開発の間違いは何ですか?
1。適切なインデックスを使用していません
これは比較的簡単な方法ですが、それでも常に発生します。外部キーはそれらにインデックスを持つべきです。 WHERE
の中でフィールドを使っているのであれば、おそらくそれにインデックスがあるはずです。そのようなインデックスは、実行する必要があるクエリに基づいて複数の列をカバーする必要があります。
2。参照整合性を強制しない
データベースはここでは異なる場合がありますが、データベースが参照整合性をサポートしている場合、つまりすべての外部キーが存在するエンティティを指すことが保証されている場合は、それを使用する必要があります。
MySQLデータベースでこの失敗が発生することはよくあることです。 MyISAMがそれをサポートしているとは思わない。 InnoDBは行います。 MyISAMを使用している人、またはInnoDBを使用しているが使用していない人が見つかります。
もっとここ:
3。代理(技術的)主キーではなく自然な主キーを使用する
自然キーは、(表面的には)一意の、外部的に意味のあるデータに基づくキーです。一般的な例としては、製品コード、2文字の州コード(US)、社会保障番号などがあります。代理または技術的な主キーは、システム外ではまったく意味がないものです。これらは純粋にエンティティを識別するために考案されたもので、通常は自動インクリメントフィールド(SQL Server、MySQLなど)またはシーケンス(最も注目すべきはOracle)です。
私の意見では、常に代理キーを使うべきです。この問題はこれらの質問に現れました:
これはやや物議を醸しているトピックで、あなたは普遍的な合意を得ることはできません。自然なキーは状況によっては問題ないと考える人もいるかもしれませんが、代用キーについての批判は、おそらく不必要であること以外には見つかりません。あなたが私に尋ねるならば、それはかなり小さい欠点です。
覚えておいて、 国は存在しなくなることができます (例えば、ユーゴスラビア)。
4。 DISTINCT
が動作するのに必要なクエリを書く
これはORMで生成されたクエリでよく見られます。 Hibernateからのログ出力を見ると、すべてのクエリが次のように始まっていることがわかります。
SELECT DISTINCT ...
これは、重複する行を返さないようにして重複するオブジェクトを取得するための、ちょっとした近道です。あなたも時々人々がこれをやっているのを見るでしょう。あなたがそれを見すぎるなら、それは本当の赤い旗です。 DISTINCT
が悪い、または有効なアプリケーションを持っていないということではありません。それは(両方の点で)そうですが、それは正しいクエリを書くための代用物ではありません。
から なぜ私はDISTINCTが嫌い :
私の考えで物事が酸っぱくなり始めるのは、開発者がかなりのクエリを作成し、テーブルを結合し、そして突然彼がそれが見えていることに気づいた時です彼が重複した(あるいはそれ以上の)行を受け取ってすぐに対応しているような...この「問題」に対する「解決策」はDISTINCTキーワードとPOOF彼の問題はすべて解決しました。
5。結合よりも集約を優先する
データベースアプリケーション開発者によるもう1つの一般的な間違いは、結合と比較して、どれほど高価な集計(つまりGROUP BY
句)を比較できるのかわからないことです。
これがどれほど広範囲に及んでいるかについての考えを与えるために、私はこのトピックについて何度かここで書いて、それについて多くの投票を下されました。例えば:
From SQLステートメント - 「join」vs「group by and having」 :
最初のクエリ:
SELECT userid FROM userrole WHERE roleid IN (1, 2, 3) GROUP by userid HAVING COUNT(1) = 3
クエリ時間:0.312 s
2番目のクエリ:
SELECT t1.userid FROM userrole t1 JOIN userrole t2 ON t1.userid = t2.userid AND t2.roleid = 2 JOIN userrole t3 ON t2.userid = t3.userid AND t3.roleid = 3 AND t1.roleid = 1
問い合わせ時間:0.016秒
そのとおり。私が提案した結合バージョンは、集約バージョンよりも20倍高速です。
6。ビューで複雑なクエリを単純化しない
すべてのデータベースベンダがビューをサポートしているわけではありませんが、ビューをサポートしている場合は、慎重に使用すればクエリを大幅に簡略化できます。例えば、あるプロジェクトで私はCRMに generic Party model を使いました。これは非常に強力で柔軟なモデリング手法ですが、多くの結合につながる可能性があります。このモデルではありました:
例:
そのため、テッドと彼の雇用主を結び付けるために5つのテーブルが結合されています。あなたはすべての従業員が(組織ではなく)個人であると想定し、このヘルパーの見解を提供します。
CREATE VIEW vw_employee AS
SELECT p.title, p.given_names, p.surname, p.date_of_birth, p2.party_name employer_name
FROM person p
JOIN party py ON py.id = p.id
JOIN party_role child ON p.id = child.party_id
JOIN party_role_relationship prr ON child.id = prr.child_id AND prr.type = 'EMPLOYMENT'
JOIN party_role parent ON parent.id = prr.parent_id = parent.id
JOIN party p2 ON parent.party_id = p2.id
そして突然、あなたは欲しいデータの非常に単純なビューを持っていますが、非常に柔軟なデータモデルの上にあります。
7。入力をサニタイズしない
これは巨大なものです。今、私はPHPが好きですが、自分が何をしているのかわからない場合は、攻撃に対して脆弱なサイトを作成するのは本当に簡単です。 小さなボビーテーブルの物語 ほど良く要約されているものはありません。
URL、フォームデータ、およびクッキーを介してユーザーから提供されたデータは、常に敵対的なものとして扱われ、サニタイズされます。期待通りのものになっていることを確認してください。
8。準備済みステートメントを使用しない
準備済みステートメントは、挿入、更新、およびWHERE
文節で使用されているデータを除いた照会をコンパイルしてから後でそれを提供するときです。例えば:
SELECT * FROM users WHERE username = 'bob'
vs
SELECT * FROM users WHERE username = ?
または
SELECT * FROM users WHERE username = :username
プラットフォームによって異なります。
こうすることでデータベースがひざまずいたのを見たことがあります。基本的に、最近のデータベースは新しいクエリに遭遇するたびにそれをコンパイルしなければなりません。それが以前に見られたクエリに遭遇するならば、あなたはデータベースにコンパイルされたクエリと実行プランをキャッシュする機会を与えています。クエリを大量に実行することで、データベースにそれを把握し、それに応じて最適化する機会が与えられます(たとえば、コンパイルされたクエリをメモリに固定することによって)。
準備済みステートメントを使用すると、特定の照会が使用される頻度に関する有意義な統計も得られます。
プリペアドステートメントはSQLインジェクション攻撃からあなたをよりよく保護するでしょう。
9。十分に正規化されていません
データベースの正規化 は、基本的にデータベース設計を最適化するプロセス、またはデータをテーブルに編成する方法です。
今週、私は誰かが配列を分解し、それをデータベースの単一のフィールドに挿入したいくつかのコードに出くわしました。それを正規化することは、その配列の要素を子テーブル内の別々の行として扱うことです(つまり、1対多の関係)。
これもまた思いついた ユーザーIDのリストを保管するための最良の方法 :
私は他のシステムでリストが直列化されたPHP配列に格納されていることを見ました。
しかし、正規化の欠如はさまざまな形で起こります。
もっと:
10。正規化し過ぎ
これは前の点と矛盾するように思われるかもしれませんが、正規化は多くのことと同様にツールです。それは目的を達成するための手段であり、それ自体の目的ではありません。多くの開発者はこれを忘れて「手段」を「終わり」として扱い始めていると思います。単体テストはその代表的な例です。
私はかつて次のようなクライアントのための巨大な階層構造を持つシステムに取り組みました。
Licensee -> Dealer Group -> Company -> Practice -> ...
意味のあるデータを取得するには、11個のテーブルを結合しなければならなかったためです。正規化が行き過ぎた例です。
さらに重要なことには、慎重かつ考慮された非正規化はパフォーマンスに大きな利点をもたらす可能性がありますが、これを行うときは本当に慎重になる必要があります。
もっと:
11。排他的アークを使用する
排他アークは、テーブルが2つ以上の外部キーで作成され、そのうち1つのみがNULL以外になる可能性がある一般的な間違いです。 大きな間違いです。データの整合性を維持するのが難しくなります。結局、参照整合性があっても、これらの外部キーのうちの2つ以上が設定されるのを妨げるものは何もありません(複雑なチェック制約にもかかわらず)。
From リレーショナルデータベース設計のための実践的なガイド :
コードを書くのが面倒でメンテナンスがさらに困難になる可能性があるという正当な理由から、私たちは可能な限り排他的なアークの作成に対して強く助言しました。
12。クエリのパフォーマンス分析をまったく行わない
実用主義は、特にデータベースの世界では最高に支配します。彼らが教義になったという点まで原則に固執しているなら、あなたはかなり間違いを犯したでしょう。上記の集計クエリの例を見てください。集約バージョンは "Nice"に見えるかもしれませんが、そのパフォーマンスはひどいものです。パフォーマンスの比較で議論は終わったはずですが(ただし、それは終わりではありませんでしたが)、もっとまずいことに言っておきます。
13。 UNION ALL、特にUNION構成要素への過度の依存
SQL用語でのUNIONは、一致するデータセットを単に連結するだけです。つまり、それらは同じ型と数の列を持ちます。両者の違いは、UNION ALLは単純な連結であり、可能な限り推奨されるべきですが、UNIONは重複したタプルを削除するために暗黙的にDISTINCTを実行するという点です。
DISTINCTのように、UNIONにはその場所があります。有効なアプリケーションがあります。しかし、特にサブクエリで自分自身で多くのことをしているのに気づいた場合は、おそらく何か問題があるでしょう。それは、不十分なクエリ構築または不適切に設計されたデータモデルのケースである可能性があります。
UNIONは、特に結合または従属副問合せで使用されると、データベースを無効にする可能性があります。可能な限りそれらを避けるようにしてください。
14。クエリでOR条件を使用する
これは無害に思えるかもしれません。結局のところ、ANDはOKです。 ORは問題ないでしょうか。違う。基本的にAND条件はデータセットを制限しますが、OR条件は大きくなりますしかしそれは最適化に向いているという意味ではありません。特に、さまざまなOR条件が交差する可能性があるため、オプティマイザは結果に対して効果的にDISTINCT操作を実行する必要があります。
悪い:
... WHERE a = 2 OR a = 5 OR a = 11
より良い:
... WHERE a IN (2, 5, 11)
これで、SQLオプティマイザは最初のクエリを事実上2番目のクエリに変えることができます。しかしそうではないかもしれません。しないでください。
15。高性能のソリューションに適したデータモデルを設計していない
これは定量化するのが難しい点です。それは通常その効果によって観察される。比較的単純なタスクに対して大雑把なクエリを書いている場合や、比較的単純な情報を見つけるためのクエリが効率的ではない場合は、おそらくデータモデルがまずいでしょう。
ある意味でこの点は以前のものをすべて要約していますが、クエリ最適化のようなことをすることは、しばしば最初に行われるべきであるが、次に行われるべきであるということをより警告的な物語です。まず第一に、パフォーマンスを最適化しようとする前にあなたが良いデータモデルを持っていることを確認するべきです。クヌースが言ったように:
時期尚早の最適化はすべての悪の根源です
16。データベーストランザクションの誤った使用
特定のプロセスに対するすべてのデータ変更はアトミックです。すなわち操作が成功すると、それは完全に成功します。失敗した場合、データは変更されません。 - 「途中で」変更される可能性はないはずです。
理想的には、これを達成するための最も簡単な方法は、システム設計全体が単一のINSERT/UPDATE/DELETEステートメントを介してすべてのデータ変更をサポートするように努めることです。この場合、データベースエンジンが自動的に行うので、特別なトランザクション処理は必要ありません。
ただし、データを一貫した状態に保つために1つの単位として複数のステートメントを実行する必要があるプロセスがある場合は、適切なトランザクション制御が必要です。
また、データベース接続層とデータベースエンジンがこの点でどのように相互作用するかの細部に注意を払うことをお勧めします。
17。セットベースのパラダイムを理解していない
SQL言語は、特定の種類の問題に適した特定のパラダイムに従います。ベンダー固有のさまざまな拡張機能にもかかわらず、この言語はJava、C#、Delphiなどの言語では些細な問題に対処するのに苦労しています。
この理解の欠如は、いくつかの点で表れています。
明確な責任分担を決定し、それぞれの問題を解決するために適切なツールを使用するように努めます。
開発者による重要なデータベース設計とプログラミングの間違い
利己的なデータベース設計と使用法開発者は、データ内の他の利害関係者のニーズを考慮せずに、データベースを個人用の永続オブジェクトストアとして扱うことがよくあります。これはアプリケーションアーキテクトにも当てはまります。データベース設計とデータの整合性が悪いと、第三者がデータを扱うことが難しくなり、システムのライフサイクルコストが大幅に増加する可能性があります。レポーティングとMISは、アプリケーション設計においては従兄弟である傾向があり、後付けとしてのみ行われます。
非正規化データの悪用非正規化データをやり過ぎてアプリケーション内で維持しようとすると、データの整合性の問題が発生します。非正規化は控えめに使用してください。結合をクエリに追加したくないということは、非正規化の言い訳ではありません。
SQLを書くのが怖いSQLはロケットサイエンスではなく、実際にはその仕事をするのが得意です。 O/Rマッピングレイヤは、単純でそのモデルによく適合する95%のクエリを実行するのに非常に優れています。 SQLが仕事をするための最善の方法です。
教義的な「ストアドプロシージャはありません」ポリシーストアドプロシージャが悪いと信じるかどうかにかかわらず、この種の教義的な考え方はソフトウェアプロジェクトには意味がありません。
データベース設計を理解していません。正規化はあなたの友人です、それは ロケット科学ではありません 結合と濃度はかなり単純な概念です - あなたがデータベースアプリケーションの開発に関わっているのであれば、理解していないという言い訳はまったくありません。
ストアドプロシージャの使いすぎや依存。
一部のアプリケーション開発者は、ストアドプロシージャを中間層/フロントエンドコードの直接の拡張と見なしています。これは、Microsoftのスタック開発者にはよく見られる特性であり(私は1つですが、それから成長してきました)、複雑なビジネスロジックとワークフロー処理を実行する多くのストアドプロシージャを生成します。これは他のところでもっとよくできています。
ストアドプロシージャは、実際の技術的要因によってその使用が必要であることが実際に証明されている場合(たとえば、パフォーマンスとセキュリティ)に役立ちます。たとえば、大きなデータセットの集約/フィルタリングを「データに近づける」など。
私は最近、ビジネスロジックとルールの70%が1400のSQL Serverストアドプロシージャ(残りのUIイベントハンドラ)に実装されている大規模なDelphiデスクトップアプリケーションの保守と強化を手助けしなければなりませんでした。これは、主にTSQLに効果的な単体テストを導入することの困難さ、カプセル化の欠如、および貧弱なツール(デバッガ、編集者)による悪夢でした。
過去にJavaチームと仕事をしていたとき、私はすぐにその環境には全く反対のことが成り立つことを知りました。 Javaアーキテクトがかつて私に言った: "データベースはコード用ではなくデータ用です"。
最近では、ストアドプロシージャをまったく考慮しないのは間違いだと思いますが、有用な利点がある場合は(デフォルトではなく)控えめに使用する必要があります(他の回答を参照)。
一番の問題?彼らは唯一のおもちゃのデータベースでテストします。そのため、データベースが大きくなったときにSQLがクロールされることはわかりません。後で誰かが一緒に行って修正する必要があります(このような音は私の歯を磨くものです)。
インデックスを使用しません。
相関サブクエリによるパフォーマンス低下
ほとんどの場合、相関副照会を避けたいです。サブクエリ内に、外側のクエリからのカラムへの参照がある場合、サブクエリは相関します。この場合、副照会は返される行ごとに少なくとも1回実行され、相関副照会を含む条件が適用された後に他の条件が適用されると、さらに複数回実行される可能性があります。
この例とOracleの構文をご容赦ください。ただし、1日に最後の1万ドル未満の売上を達成してから、いずれかの店舗に雇用されているすべての従業員を見つけたいとします。
select e.first_name, e.last_name
from employee e
where e.start_date >
(select max(ds.transaction_date)
from daily_sales ds
where ds.store_id = e.store_id and
ds.total < 10000)
この例の副問合せは、store_idによって外部問合せと関連付けられており、システム内のすべての従業員に対して実行されます。このクエリを最適化できる1つの方法は、副問合せをインラインビューに移動することです。
select e.first_name, e.last_name
from employee e,
(select ds.store_id,
max(s.transaction_date) transaction_date
from daily_sales ds
where ds.total < 10000
group by s.store_id) dsx
where e.store_id = dsx.store_id and
e.start_date > dsx.transaction_date
この例では、from句の問合せはインライン・ビュー(Oracle固有の構文)になり、一度だけ実行されます。データモデルによっては、このクエリの実行速度がはるかに速くなる可能性があります。従業員数が増えるにつれて、最初のクエリよりもパフォーマンスが向上します。最初のクエリは、従業員が少なく店舗数が多い(そしておそらく店舗の多くに従業員がいない)場合、およびdaily_salesテーブルがstore_idでインデックス付けされている場合、実際にはパフォーマンスが向上します。これは一般的なシナリオではありませんが、相関クエリが代替方法よりも優れたパフォーマンスを発揮する可能性があることを示しています。
私はジュニア開発者がサブクエリを何度も相関させるのを見ました、そしてそれは通常パフォーマンスに深刻な影響を与えました。ただし、相関副照会を除去するときは、前後の Explain plan を必ず見て、パフォーマンスが低下していないことを確認してください。
私の経験では:
経験豊富なDBAと連絡を取りません。
「実際の」データベースの代わりにAccessを使用する。 SQL Express 、 MySQL 、および SQLite のような、小規模で無料のすばらしいデータベースがたくさんあります。アプリは予想外の方法で拡張する必要があることがよくあります。
テーブル間の関係を設定するのを忘れる。私が現在の雇用主で働き始めたときに、これを片付けなければならなかったのを覚えています。
私は追加したいと思います。高性能のコードよりも「優雅な」コードを支持すること。データベースに対して最もよく機能するコードは、アプリケーション開発者の目には醜いものです。
時期尚早の最適化についてはナンセンスだと思います。データベースは、元の設計およびその後の開発におけるパフォーマンスを考慮する必要があります。私の考えでは、パフォーマンスはデータベース設計の50%です(40%がデータの整合性、最後の10%がセキュリティです)。最初から最後まで構築されていないデータベースは、実際のユーザーと実際のトラフィックがデータベースに対して配置されるとパフォーマンスが低下します。時期尚早の最適化は最適化がないという意味ではありません。それはあなたがそれを容易に見つけるので、ほとんどいつもひどく悪い結果を出すであろうコードを書くべきであるという意味ではありません(例えば、他のすべてが失敗しない限り本番データベースで決して許されるべきではないカーソル)。それはあなたがする必要があるまでパフォーマンスの最後の少しを絞り出すのを見る必要がないことを意味します。設計上および開発上でこれを無視するために、データベースで何がより良く機能するかについて多くのことが知られていますが、せいぜい近視眼的です。
大量のデータの保存にExcelを使用する。
私は何千もの行を持ち、複数のワークシートを使っている企業を見たことがあります(以前のバージョンのExcelでは65535行に制限されていたため)。
Excelは、レポート、データ表示、その他の作業に最適ですが、データベースとして扱うべきではありません。
パラメータ化クエリを使用しません。停止するのにかなり便利です SQLインジェクション 。
これは、別の回答で述べたように、入力データをサニタイズしないことの具体例です。
開発者がネストしたSELECT文を使用したり、クエリの "SELECT"部分の中にSELECT文の結果を返すような関数さえも使用するとき、私はそれが嫌いです。
@ adamにも同様の問題が指摘されていますが、ここで他の場所でこれを見ていないのであれば、私は実際に驚いています。
例:
SELECT
(SELECT TOP 1 SomeValue FROM SomeTable WHERE SomeDate = c.Date ORDER BY SomeValue desc) As FirstVal
,(SELECT OtherValue FROM SomeOtherTable WHERE SomeOtherCriteria = c.Criteria) As SecondVal
FROM
MyTable c
このシナリオでは、MyTableが10000行を返す場合、最初のクエリと他の各テーブルに対するクエリを結果の各行に1回ずつ実行する必要があるため、クエリは20001クエリを実行したかのようになります。
開発者は、数行のデータしか返さず、サブテーブルには通常少量のデータしか含まれていない開発環境でこの作業をやめることができますが、実稼働環境では、この種のクエリーは指数関数的にコストがかかりますデータがテーブルに追加されます。
より良い(必ずしも完璧ではない)例は次のようなものです。
SELECT
s.SomeValue As FirstVal
,o.OtherValue As SecondVal
FROM
MyTable c
LEFT JOIN (
SELECT SomeDate, MAX(SomeValue) as SomeValue
FROM SomeTable
GROUP BY SomeDate
) s ON c.Date = s.SomeDate
LEFT JOIN SomeOtherTable o ON c.Criteria = o.SomeOtherCriteria
これにより、データベースオプティマイザーはメインテーブルの各レコードを再クエリするのではなく、データをまとめてシャッフルすることができます。この問題が発生したコードを修正する必要がある場合がよくあります。同時にCPUとメモリの使用量を削減しながら、より多くの。
SQLベースのデータベースの場合
本番データベース内の問題を修正する前にバックアップを取らないでください。
ストアドプロシージャ内のストアドオブジェクト(テーブル、ビューなど)に対してDDLコマンドを使用する。
ストアドプロシージャを使用することへの恐怖、またはORMクエリを使用することがより効率的で適切な場合はいつでもORMクエリを使用することへの恐怖。
データベースプロファイラの使用を無視すると、ORMクエリが最終的にどのように変換されているのかを正確に知ることができるため、ORMを使用しない場合はロジックを検証したり、デバッグしたりできます。
1 - where句内の値に対して関数を不必要に使用しているため、そのインデックスが使用されていません。
例:
where to_char(someDate,'YYYYMMDD') between :fromDate and :toDate
の代わりに
where someDate >= to_date(:fromDate,'YYYYMMDD') and someDate < to_date(:toDate,'YYYYMMDD')+1
そして、それほどではありませんが、それらを必要とする値に機能インデックスを追加しないでください。
2 -データの有効性を保証するためにチェック制約を追加しません。制約はクエリオプティマイザによって使用されることができます、そして、それはあなたがあなたの不変式を信頼できるのを確実にするのを本当に助ける。使用しない理由はまったくありません。
-純粋な怠惰や時間のプレッシャーから、テーブルに正規化されていない列を追加する。物事は通常このように設計されていませんが、これに進化します。最終的な結果は、間違いなく、将来の進化で失われたデータの整合性に悩まされたときの混乱を一掃しようとする大量の作業です。
これを考えて、データのないテーブルは再設計するのがとても安いです。整合性のない数百万のレコードを含むテーブル...再設計するのはそれほど安価ではありません。したがって、列または表を作成するときに正しい設計をすることはスペードで償却されます。
4 -データベース自体についてはそれほど多くはありませんが、実際には面倒です。 SQLのコード品質を気にする必要はありません。あなたのSQLがテキストで表現されているという事実は、文字列操作アルゴリズムの集まりにロジックを隠すことを許さないのです。他のプログラマが実際に読める形式でSQLをテキストで書くことは完全に可能です。
正しいレベルの 正規化 をしていません。データが重複していないこと、そして必要に応じてデータを別のデータに分割していることを確認します。また、正規化にも従わないようにする必要があります。
データベースを単なる格納メカニズム(つまり、コレクションコレクションライブラリ)として扱い、そのアプリケーションに従属する(データを共有する他のアプリケーションを無視する)
これは以前にも言われていますが、インデックス、インデックス、インデックス。私は、(どのテーブルが多くヒットしているのかを確認するために)少しプロファイリングを行い、それらのテーブルにインデックスを追加することによって解決された、パフォーマンスの悪いエンタープライズWebアプリケーションの例をたくさん見ました。これはSQLの知識を書くのにはそれほど必要ではなく、その見返りは膨大です。
ペストのようにデータの重複を避けます。一部の人々は、少しの重複でも問題はなく、パフォーマンスも向上すると主張しています。こんにちは、私はあなたが自分のスキーマをThird Normal Formに拷問しなければならないと言っているのではありません。一連の名前、郵便番号、または配送コードを複製すると、コピーが最終的に互いに同期しなくなることを理解してください。それは起こるでしょう。そして、毎週のメンテナンススクリプトを実行しているうちに、あなた自身が蹴られることになります。
そして最後に、明確で一貫した直感的な命名規則を使用してください。よく書かれたコードが読めるように、良いSQLスキーマやクエリも読めなければならないのと同じように、実際に教えてくださいコメントなしでも。あなたがテーブルの上のメンテナンスをしなければならないとき、あなたは6ヶ月であなた自身に感謝するでしょう。 "SELECT account_number, billing_date FROM national_accounts"
は "SELECT ACCNTNBR、BILLDAT FROM NTNLACCTS"よりも無限に扱いが簡単です。
DELETEクエリを実行する前に対応するSELECTクエリを実行しないでください(特に本番データベースで)。
私が20年間で見た中で最も一般的な間違い:前もって計画していない。多くの開発者はデータベースとテーブルを作成し、その後アプリケーションを構築するときにテーブルを継続的に変更および拡張します。その結果、多くの場合、混乱して非効率的になり、後でクリーンアップまたは単純化するのが困難になります。
a)文字列でのクエリ値のハードコーディング
b)Windowsフォームアプリケーションの "OnButtonPress"アクションにデータベースクエリコードを追加する
私は両方を見ました。
アプリケーションでデータベース接続を管理することに十分な注意を払っていない。それからあなたは、アプリケーション、コンピュータ、サーバーを見つけ出し、そしてネットワークは詰まっています。
これらの分野に正式な教義がない場合、それらはDBAおよびデータモデラー/デザイナーであると考えます。
彼らのプロジェクトはDBAを必要としないと考えていますが、それはすべて簡単で簡単なためです。
データベースで行われるべき作業と、アプリで行われるべき作業とを正しく識別できない。
バックアップを検証しない、またはバックアップしない。
生のSQLをコードに埋め込む。
Scott Walzによる「 古典的なデータベース開発の間違いとそれを克服するための5つの方法 」と呼ばれるビデオへのリンクはここにあります
データベースの並行性モデルと、これが開発に与える影響について理解していない。事後にインデックスを追加したりクエリを微調整したりするのは簡単です。ただし、ホットスポット、リソースの競合、正しい操作を考慮しないで設計されたアプリケーション(先ほど読んだものがまだ有効であると仮定して)は、後で修正するためにデータベースとアプリケーション層内で大幅な変更が必要になります。
さて、アプリケーション開発者が犯す最大の間違いは、データベースを適切に正規化しないことです
私はアプリケーション開発者として、適切なデータベース構造、正規化、およびメンテナンスの重要性を認識しています。データベースの構造と管理について自分自身を教育するために無数の時間を費やしました。私の経験では、別の開発者と仕事を始めるときはいつも、データベース全体を再構築し、通常は不正な形式であるためにアプリを更新する必要がありますそして欠陥があります。
たとえば、新しいプロジェクトで作業を開始し、開発者からFacebook Connectをサイトに実装するように依頼されました。データベースをクラックして開き、作業内容を確認したところ、特定のユーザーに関するあらゆる情報が1つのテーブルに詰め込まれていることがわかりました1つのテーブルテーブルを4つまたは5つの別々のテーブルに整理するスクリプトを書くのに6時間かかり、アプリがそれらのテーブルを使用するようにするには2時間かかりました。データベースを正規化してください!それは他のすべてを頭痛の少ないものにします。
DBMSが内部でどのように機能するのか理解していません。
クラッチの仕組みを理解していないと、スティックを正しく動かすことができません。そして、あなたが本当にハードディスク上のファイルに書き込んでいるだけであるということを理解しなければ、データベースの使い方を理解することはできません。
具体的には:
クラスタ化インデックスが何であるか知っていますか。スキーマを設計するときにそれについて考えましたか?
あなたはインデックスを正しく使う方法を知っていますか?インデックスを再利用する方法Covering Indexとは何ですか?
とても素晴らしい、あなたはインデックスを持っています。インデックスの1行はどれくらいの大きさですか?大量のデータがある場合、インデックスはどのくらい大きくなりますか?それは容易に記憶に収まるでしょうか?そうでない場合は、インデックスとしては意味がありません。
MySQLでEXPLAINを使用したことがありますか?すばらしいです。今正直に言ってください:あなたはあなたが見たものの半分さえ理解しましたか?いいえ、あなたはおそらくしませんでした。それを修正してください。
クエリキャッシュを理解しましたか。クエリがキャッシュ不可能になる原因を知っていますか?
MyISAMを使っていますか?あなたが全文検索を必要とするなら、MyISAMはとにかくがらくたです。 Sphinxを使ってください。次にInnoに切り替えます。
15 - 単純なCOALESCEの代わりにクレイジーな構造とアプリケーションロジックを使う。
非常に大きなトランザクション。大量のデータを挿入/更新してから再ロードする。基本的に、これはデータベースが動作するマルチユーザー環境を考慮していないためです。
関数の使い過ぎ、特にselectやwhere句の中で、結果に対して関数が何度も呼び出される原因となります。これは、SQLを最大限に活用するよりも慣れ親しんだ手続き的な方法で作業しようとしているという一般的なケースに当てはまると思います。
最大の間違いは、単純なセットベースの解決策でトリックがはるかに速く、はるかに単純になるときに、コードの更新またはデータの挿入にループがあることです。
私は、すべての開発者やデータベース管理者が犯している最大の過ちは、慣習を信じすぎることだと思います。それは私が意味しているのは、慣例はほとんどの場合にうまくいくガイドラインであり、必ずしもそうではないということです。私の良い例は正規化と外部キーです。私はほとんどの人がこれを好まないことを知っていますが、正規化は複雑さを引き起こしパフォーマンスも低下させるので、電話番号を電話テーブルに移動する理由がないのならそれ。外部キーについては、ほとんどの場合これは素晴らしいことですが、必要に応じて自分自身で機能できるようなものを作成しようとすると、将来的に外部キーが問題になり、またパフォーマンスが低下します。とにかく、私は悲しい規則や慣習を導くためにそこにあります、そしてそれらは常に考えられるべきですが必ずしも実行される必要はありません、それぞれのケースの分析は常に行われるべきものです。
あなたの開発マシン上であまりに速く走ったクエリが爆発したときにdbエンジンを非難し、あなたがアプリケーションでいくらかのトラフィックを投げたらチョークします。
多くの開発者はデータベースに対して複数のクエリを実行し(多くの場合1つか2つのテーブルをクエリします)、結果を抽出してJava/c/c ++で簡単な操作を実行します。
多くの開発者は、開発環境ではデータベースとアプリケーションサーバーがラップトップ上にあることに気付かないことが多くありますが、本番環境ではデータベースとアプリケーションサーバーは異なるマシン上にあります。したがって、すべてのクエリに対して、データがアプリケーションサーバーとデータベースサーバーの間で受け渡されるための追加のn/wオーバーヘッドがあります。 1ページをユーザーに表示するために、アプリケーションサーバーからデータベースサーバーへのデータベース呼び出しの数を調べて驚きました。
私が付け加えるかもしれないことが1つあります。それは、PARTITION BY、RANK、DENSE_RANK(Oracle用)のような分析関数の使い方を学ぶことです。それらは複雑なクエリには絶対に不可欠です。
可能であれば、SQL、データベースモデリング、チューニングなどの専門家である開発チームに専用のデータベース開発者を配置することをお勧めします(ただしDBAではありません)。そのようなスキルは素晴らしい資産です。
レプリケーション(MySQL)を使用している場合は、行ベースのレプリケーションを使用していない限り、以下の関数は安全ではありません。
USER(), CURRENT_USER() (or CURRENT_USER), UUID(), VERSION(), LOAD_FILE(), and Rand()
参照してください: http://dev.mysql.com/doc/refman/5.1/en/replication-features-functions.html
1)Javaとデータベース間の適切な対話方法に関する理解が不十分。
2)SQLの解析が過剰、不適切、または再利用されていない
3)BIND変数を使用しない
4)SQLがデータベース内のロジックを設定するときにJavaで手続き型ロジックを実装する(より良い)。
5)本番に入る前に妥当なパフォーマンスまたはスケーラビリティのテストを行わなかった
6)Crystal Reportsを使用していてレポートでスキーマ名を正しく設定できていない
7)実行計画を無視しているため、デカルト積を使用してSQLを実装する(EXPLAIN PLANを見たこともありますか?)