憂国なプログラマ

背景を地味なパターンに直してみました。これはこれでいいかも!

MySQL

[ リスト | 詳細 ]

記事検索
検索

全2ページ

[1] [2]

[ 次のページ ]

データベースと都市伝説といえば オラクル都市伝説 が一部で有名である。
この記事を巡り、MicroSoft と Oracle の間で熱いバトルが繰り広げられているようだが、
Sun のサポートエンジニアである奥野さんが、両社の争いを横目に見つつ、自身のブログで


という記事をぶち上げた!以下、一つ目の都市伝説を引用させていただくと

都市伝説1. トランザクションが使えない???


な、わけねーだろ!!


などといきなり切り捨ててはいけない。未だに MySQL ではトランザクションが使えないと信じて止まない人が未だに居る。以前のバージョンでは MyISAM もしくはその前身となった ISAM がメインのストレージエンジンとして使われており、なおかつそれらが非常に高速であったため MySQL = MyISAM = トランザクションに非対応といったイメージがあったのは否めない。しかしそのような時代は遙か彼方原生代の出来事であり、現在デファクトとして使われている InnoDB では ACID に準拠したトランザクションが利用可能である。InnoDB 以外にも NDB、PBXT、TokuDB など様々なストレージエンジンでトランザクションが利用可能になっている。


そのような都市伝説には喝!!である。

DBエンジニアなら一見の価値があると思う。ぜひご覧あれ!!

この記事に

開く コメント(0)

DBチューニング

以前の現場では、数十万件に及ぶテーブル同士を結合してすべての列を取ってきたり、頻繁に数千から数万件の更新が発生していたため、システム導入の初期段階からパフォーマンスが遅くなるという問題が発生した。

その時のシステムだが、サーバーは Windows 2003 Server、DB が SQLServer2005 だったと記憶している。
最終的に、以下の方法を組み合わせてパフォーマンス問題を解決したことを覚えている。
・頻繁に大量のデータの更新を繰り返すため、インデックスが断片化していた。
 対策のため、毎晩夜間バッチを走らせてインデックスを貼り直すようにした。
・埋め込みクエリをストアド化した。
 ストアド化すると実行プランがキャッシュ化されるためか、
 埋め込みクエリに比べてパフォーマンスが劇的に向上した。
・更新系の複雑なストアド内で一時テーブルを使用するようにしたところ、
 更新処理のパフォーマンスが著しく改善された
・画面遷移ごとに DB に接続してデータを取ってくるのを止め、
 画面初期化時にデータセットを取得し、遷移時はデータセットを使いまわすようにした。
・顧客とよく話し合ったところ、表示系画面は最新データを表示する必要なしと明言してくれたため
 表示系クエリのトランザクション分離レベルを READ UNCOMMITTED に統一した。
これで、更新系で一時間かかっていたクエリが10秒を切り、表示系で3分かかっていたクエリが一秒を切るまでになった。

しかしいまから考えると、オプティマイザの挙動まで考慮したクエリであったか、本当にインデックスの貼り方が適切であったか、そもそもテーブル設計が本当に適切であったのか?
・・・もっとも私が現場に入った時点でテーブル設計が完了済であったため、手を付ける術もなかったのだが・・・
今頃になって色々な面で気にかかる。


そんなことを考えながら「漢(オトコ)のコンピュータ道」を覗いてみたら、非常に面白い記事が公開されていた。
同ブログの主である Okuno さんと MySQLのコンサルタントの松信さんのインタビュー記事である。。お題は


これを読むと「餅は餅屋」という諺が頭に浮かぶ。興味のある方は是非覗いてみるといいだろう。


あと関連ページも紹介しておく。MySQL に特化した内容だが、他のDBにも応用できることは多いだろう。

MySQLパフォーマンスチューニング TIPS
http://sdc.sun.co.jp/news/2009/04/feature01.html

MySQLを高速化する10の方法
http://nippondanji.blogspot.com/2009/02/mysql10.html

さらにMySQLを高速化する7つの方法
http://nippondanji.blogspot.com/2009/03/mysql7.html


なぜMySQLのサブクエリは遅いのか。
http://nippondanji.blogspot.com/2009/03/mysql_25.html

 

この記事に

開く コメント(0)

本日の打ち合わせでサーバーチームから聞いた話。

以下のような「請求」に関するテーブルが存在したとする。
CREATE TABLE d_account (
    id int unsigned NOT NULL auto_increment COMMENT 'ID',
    account_code varchar(11) NOT NULL       COMMENT '請求コード',

    submit_date date     NOT NULL COMMENT '請求日(発行日)',
    begin_date datetime  NOT NULL COMMENT '請求期間開始日',
    end_date datetime    NOT NULL COMMEN  '請求期間終了日',
    pay_date date        NOT NULL COMMENT '支払予定日',
    price decimal        NOT NULL COMMENT '請求金額'

    PRIMARY KEY  (id),
    KEY i_account_I1 (price)
) 
ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED;
このテーブルには「price」という請求金額を格納する列があり、マイナス値を設定できる。
また列「price」は検索で使うので、インデックスを貼っておく必要がある。

このテーブルから請求金額が 0 以外の行を抽出するなら、普通は以下のようなクエリを考える。
SELECT * FROM  price != 0
しかし「!=」(ノットイコール)では、せっかく用意したインデックスが有効にならない。

請求テーブルは稼働期間に従ってデータ量が膨大になるため、
DB のパフォーマンスを維持するためにもインデックスを有効にしておく必要がある。

そこでインデックスを有効に使うには、以下のようにするとよい。
SELECT * FROM (price > 0)
UNION ALL
SELECT * FROM (price < 0)
クエリは二重になるが、これならインデックスが有効になるとのこと。
EXISTS とサブクエリを組み合わせれば UNION ALL を使わなくても済むが、
UNION ALL を使った方がはるかにクエリが読みやすくなるのでこれでいくとのこと。

これを受けてチーム内のある人は「OR を使ったらどうか?」と言ったが、
以下の例だとインデックスが効かなくなり遅くなるそうだ。
SELECT * FROM ( price > 0 ) OR ( price < 0 )

この仕様は MySQL に限らずどの RDBMS でも同じであるとのこと。

この記事に

開く コメント(0)

MySQL サーバーのクエリログを参照するには、以下の手順で行うとよい。

まず、PuTTy 等を使って MySQLサーバーに接続する。PuTTy ごった煮版とかは、日本語環境が初期設定されるので非常に使いやすいと思う。


PuTTy を起動~サーバーにログインしたら、tail コマンドを実行する。
tail -f /var/log/mysql/mysqld-query.log
これでクエリがサーバーに送られるたびに、コマンドラインにログが表示される。
コマンドを終了するときは CTRL+C。その後 exit でログアウト。

この記事に

開く コメント(0)


Fatal error encountered during command execution.

というメッセージを吐く場合があります。クエリにパラメータを設け MySqlParameter クラスでパラメータを設定しない場合、この例外が発生します。例えば
Dim query AS String = "SELECT * FROM customer WHERE id = @id"
Dim command As New MySqlCommand(query, con)
command.ExecuteNonQuery()
このクエリの場合、パラメータ id には値が割り当てられてないため、MySqlCommand クラスはこの例外を発生します。以下のようにパラメーターを設定すれば、例外は発生しません。 (´∀`)
Dim query AS String = "SELECT * FROM customer WHERE id = @id"
Dim command As New MySqlCommand(query, con)
command.Parameters.Add(New MySqlParameter("id", 10))
command.ExecuteNonQuery()
また気をつけなければいけないのは、以下のケース。

select @data := 3, @data * 4

この場合、クエリ内でパラメータに値を設定してるから phpMyAdmin や Navicat では正常に実行されます。
しかし MySQL Connector/NET では
Dim query AS String = "select @data := 3, @data * 4"
Dim command As New MySqlCommand(query, con)
command.ExecuteNonQuery()
Fatal error encountered during command execution.

・・・例外が発生します。(-ω-)

MySQL Connector/NET の仕様ということで注意が必要です。
ちなみに SQLClient の場合は・・・・・・・・・忘れた!(^ω^)


あと、どのパラメータが設定されてないのか調べるには、例外をウオッチして InnerException プロパティを見れば判ります。このケースでは ?id というパラメータが設定されてないのが判ります。(-ω-)

イメージ 1




 
 

この記事に

開く コメント(3)

全2ページ

[1] [2]

[ 次のページ ]


.
hilapon
hilapon
男性 / AB型
人気度
Yahoo!ブログヘルプ - ブログ人気度について
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

過去の記事一覧

 今日全体
訪問者52190228
ブログリンク010
コメント0201
トラックバック012

開​設日​: ​20​09​/6​/1​8(​木)​


みんなの更新記事