• 締切済み

Recordsetの処理時間について

現在VC++を用いてSQL Server Express 2005のデータベースに対してSQL文を実行しています。 そこで、下記のような現象が発生し、解決できずに困っています。 [現象] 複数のデータベースが存在する(約300)環境に対して、masterデータベースに接続し、個々のデータベースに対してデータベース名を明示的に記述したSQLを実行。 データベース接続したデータベースと異なるデータベースに対するSQLの処理は1ms~500msと処理時間がばらつきます (SQL文はSELECT data1 FROM Db1.dbo.table1 where data1=1;という感じで各テーブルには約3000レコード、SQLの結果は300件程度。Recordset Openメソッドの引数はCursorType:adOpenForwardOnly,Options:adLockReadOnly,LockType:adCmdTextです。)。 まったく同一のSQL文なので、データベース接続後、1回目は時間がかかるのは理解できますが、それ以降の処理を連続で繰返しているだけなので2回目以降処理時間が大きくばらつくことが不明です。 これは同一データベースに対して繰返しても、別々のデータベースに対して繰返してもほぼ同様の現象が発生します。 [確認したこと] - Windows認証、SQL Server認証いずれにおいても同様の傾向。 - 自プロセスあるいは他プロセスからターゲットとなるデータベースに先に接続した状態のままで実行すれば、処理時間のばらつきが1ms~80ms程度 本来、データベース毎に接続-->SQL実行-->解放を繰返せばよいのですが、Vistaにおいてはメモリリークが発生するため、この方法は採用できません。 現状、別プロセスでSQL文を実行するデータベースだけ、先に接続し、処理が完了すればこのプロセスを終了することで回避を考えているのですが、この方法では、SQLServerの負荷をかけてしまうため、よりよい方法が無いか教えてください。 よろしくお願い致します。

みんなの回答

  • AKARI0418
  • ベストアンサー率67% (112/166)
回答No.3

>再利用されるためにはストアドプロシージャにしておく必要があるのでしょうか? ストアドに登録したとしても、 提示したクエリは再利用されないと思います。 なぜなら、実行するたびに対象となるリソース(テーブル)が変わるため、 効率の良いアクセス方法を再度計画しなおす必要があるためです。 提示したクエリであれば、 ストアドにすることの利点はSQLとして送信する文字列長の短縮、 そのSQLのコンパイルにかかる時間の短縮程度です。 >ユニオンクエリを行なうために、各データベースのテーブルの存在チェックでこのようなクエリを必要としています。 他のクエリと同様の方法でパラメータ化し効率化できればと考えています。 SQLだけで処理をすることが、 効率的であるかどうか判断が必要かもしれません。 CLR SQLの使用を検討されてみてはどうでしょうか?

  • AKARI0418
  • ベストアンサー率67% (112/166)
回答No.2

DECLARE @SQL nvarchar(1024) SET @SQL = N'SELECT * FROM ' + @TableName + ';' EXECUTE sp_executesql @SQL こんな感じです。 ただし、実行計画が再利用されなくなると思うので、 処理にばらつきは出ると思いますよ。 どこまでのばらつきを許容できるか判断してください。 あまりに遅いテーブルがある場合は、 非クラスタインデックスが正しく設定されているかなどをチェックしてください。 後はインデックスの断片化を解消しておくことも大事です。

andong
質問者

お礼

AKARI0418様、回答ありがとうございます。 教えて頂いた方法を試し、処理時間のばらつきがどれくらいか確認してみます。 再利用されるためにはストアドプロシージャにしておく必要があるのでしょうか? ユニオンクエリを行なうために、各データベースのテーブルの存在チェックでこのようなクエリを必要としています。 他のクエリと同様の方法でパラメータ化し効率化できればと考えています。

  • AKARI0418
  • ベストアンサー率67% (112/166)
回答No.1

SQL Server の使用しているメモリ(キャッシュおよび実行プラン)の状態による差異じゃないですか? 特に、ページングファイルを利用している場合は差が出ても不思議ではありません。 実行プランがアドホックなクエリとしてあつかわれているか、 もしくは再利用されているのか。 データの断片化具合も考えられますね、 ページ数が多いテーブルと少ないテーブルでは、 取得に時間がかかってもおかしくありません。 状況がわからないので、的を射ていないかもしれませんが、 参考までに。

andong
質問者

お礼

AKARI0418様、回答ありがとうございます。 自動パラメータ化されているかと考えていましたが、実際に発行しているSQL文においてTOP句、GROUP BY句、共通テーブル式を含むものがあり、自動パラメータ化の対象から外れていました。 (http://www.microsoft.com/japan/sqlserver/2005/ssj/tips/04.mspx#EKB参照) これらをsp_executesqlを用いてパラメータ化することで、処理時間のばらつきが対象データベースに接続した場合とあまり変わらない状況まで改善しました。 ただし、データベースやテーブル名を切り替えるパラメータはsp_executesqlではSQL文をうまく表現できないため、まだ試せていません。 例えば、SELECT Field1 FROM [DB1].[dbo].[TBL1] WHERE Field1 = 0; というようなSQL文においてDB1やTBL1をパラメータ化するにはどのように明記すればよいでしょうか? あるいはsp_executesqlでは、データベースやテーブル、フィールド名はパラメータ化できないのでしょうか? (このような場合は、ストアド プロシージャあるいはParameterクラスを使う必要がありますか?) よろしくお願い致します。

関連するQ&A

  • VBAからaccessへの接続で、RecordsetのCursorTypeが勝手に変更される

    エクセルVBAからaccessへの接続で、RecordsetのCursorTypeが勝手に変更されてしまいます。 Dim rst As New ADODB.Recordset rst.CursorType = adOpenStatic と「adOpenStatic」に設定したいのですが、 Set rst = con.Execute(sql_str, , adCmdText) のようにクエリを実行した直後にCursorTypeを調べると、「adOpenForwardOnly」に変わってしまっています。 (設定直後に調べると、ちゃんとadOpenStaticになっています) 「CursorType」を何に設定しても、Execute直後に「adOpenForwardOnly」になってしまっていまうようです。 CursorTypeをadOpenStaticにして、RecordCountを使いたいのですが、、、 CursorTypeが変わってしまう原因をお知りの方は、教えていただけるとありがたいです。 Dim rst As New ADODB.Recordset Dim con As New ADODB.Connection con.Open "Provider=Microsoft.jet.OLEDB.4.0;" & "Data Source=" & ThisWorkbook.Path & "\" & mdb_file & ";" rst.CursorType = adOpenStatic rst.LockType = adLockReadOnly MsgBox "前 = " & rst.CursorType Set rst = con.Execute(sql_str, , adCmdText) MsgBox "後 = " & rst.CursorType

  • 処理時間について

    今、仕事で既存の処理のレスポンス調査をしているのですが、 行き詰ってしまったので質問させていただきます。 本番環境とテスト環境で全く同じ処理を実行した所、テスト環境では 1分程度で処理が正常終了するのに本番環境だと 2時間経過しても処理が終わらず、なぜ同じ処理なのに本番環境と テスト環境で処理時間に違いがありすぎるのか分からず困っています。 処理としては25万件程あるデータ(テキストベース)を PL/SQLで読み込みTable_AにInsert または キーが同じデータが 存在しているならUpdateをし、 それと同時にトリガーで更新前と更新後の値を Log_TableにInsertします。 検証したときの手順としては、 (1)Table_AとLog_TableをCreate (2)トリガーのコンパイル (3)Table_Aのインデックスの作成 (4)PL/SQLのコンパイル (5)Table_AとLog_Tableの統計情報の取得 となっております。 ちなみに、テスト環境と本番環境の両方について、 実行されたSQLの実行計画を取得し比較したのですが、 同じ実行計画になっていました。 また、統計情報を取らずに処理を実行した場合は、テスト環境でも 2時間経過しても処理が終わりませんでした。

  • Visual Basic SQL文の結果表示

    質問させていただきます。 VBからSQL文を送信し、データベースから結果を持ってくるという処理がしたいです。 ボタンを配置し、ボタンを押下したらSQL文を実行→ラベルやDataGridViewなどに表示 が理想です。 データベースの接続に苦戦しましたが、それはできているようで、SQL文を間違いはないようですが、実行しようとすると型があっていないとエラーがでてしまいます。 ご教示お願いします。

  • SQL実行時の負荷、処理時間確認

    oracle 10g Release 10.2.0.2.0を使用しています。 SQLにてDELETE文実行時のサーバ負荷、処理時間を確認したく、 次のSQLを実行しましたが、「V$SQLが無い」と怒られました。 SELECT * FROM V$SQL; oracleのバージョンを確認するSQL(select * from v$version;)は 問題なく実行できます。 V$SQLが使用できない理由、もしくは別の方法で処理負荷、処理時間を 確認できる方法とうあれば教えていただきたいです。 宜しくお願いします。

  • oracle8.1iでSQL文処理時間について

    Oracle8.1iでの質問です。 クライアントからサーバへなんらかのSQL文を 投げた場合、サーバで処理をし、クライアントに 結果を返すと思いますが。 サーバ側でのSQL文の処理開始時刻と処理終了時刻を知りたいのですが、どのような システムテーブルを見ればよいのかご存知の方 教えてください。SQL文まで、分かれば助かります。

  • Oracle SQL実行時間について

    Oracle初心者です。 あるテーブル(レコード数:100万件程度)に対してSelectするSQLの実行時間を、Oracleのset timing on, set autotrace onlyで計測しました。 結果は1000ms程度だったのですが、 同じSQL文を実行するプログラム(java)を作成し、pstmt.executequery()してresultsetからデータをgetするまでの時間をログに出力させたところ、400ms程度でした。 プログラムの性能目標として、set timing on の値を設定していたため、実際の結果(javaプログラムが出力した処理時間)の評価に困っています。 差がでる原因をご教示いただけませんでしょうか。 宜しくお願いします。

  • マルチプロセスの処理時間

    今、シングルプロセス処理としては開始から終了までA(sec)かかるとします。 これを、一定間隔でプロセス発生させ、マルチプロセスとして処理する場合、 多重実行時の処理速度は、単純に(A / 多重度)に減少すると思って問題ない でしょうか?他のコストは無視できるとします。

  • ストアドプロシジャからデータベースリンクを使っての参照について

    OracleツールのJDeveloperを使って、PL/SQLでストアドプロシジャを作成しています。 (Oracleは9i) DBが2つありまして(DB-AとDB-Bとする)、 DB-Bから、データベースリンクを介してDB-Aのテーブルを参照しています。 (SELECT * FROM XXXXX.テーブル名@データベースリンク名) DB-Bに接続してSQL*PLUS上で上記SELECT文を実行すると正しく処理されるのですが 上記SELECT文が組み込まれているDB-B上のプロシジャをコンパイルすると、 「ORA-04052」が返ってきてしまいます。 エラーコードを調べると、 DB-A側のテーブルを参照できていないようで、 「KGLR.SQLが実行されていることを確認してください」とのことなのですが、 この「KGLR.SQL」とやらが何者かわかりません。 タチの悪いことに、上記の現象が出る端末と出ない端末があります。 みんな同じIDでログインしているので権限の問題ではないと思ってるのですが・・・ 「KGLR.SQL」は置いといて、このような事象に出くわしたことのある方、 推測でもなんらかの情報をお持ちの方がいらっしゃいましたらご教授ください。 よろしくお願い致します。

  • mysql_select_db()関数に関して・・・。MySQLでテーブルの作成ができません。

    こんにちは、さくらインターネットのレンタルサーバでMySQLとphpを連動させたサイトを作っているのですが、初歩的なことでつまずいてしまい困っています。 まず、フォームで入力させたデータをPOSTで受け取り、その受け取ったデータをテーブル名として、データベース上にテーブルをつくりたいのですが、エラー文が表示されるだけでできません。 データベース自体への接続はできているようなのですが、phpMyAdminで見ても全くできていません。SQL文をphpMyAdminで実行するときちんと正常にテーブルができますので、そもそもデータベースが使用できないとか、もしくはSQL文の間違いでもなさそうです。 $t1 = $_POST['test1']; $t2 = $_POST['test2']; echo"{$t1}を受け取りました<br>"; $link = mysql_connect('mysql**.db.sakura.ne.jp', 'ユーザー名', 'パスワード'); if (!$link) { die('接続失敗です。'.mysql_error()); } print('接続に成功しました。<br>'); //1.さくらインターネット内にあるデータベースの選択 $db_name = "自分のデータベース名"; $selectDB = mysql_select_db($db_name,$link) or die("接続できません。"); //2.データベース内にテーブルを作成。 echo"{$t1}がテーブル名になります。<br>"; //3.テーブル作成用SQL文 $str_sql = "CREATE TABLE {$t1}" . "(" . "{$t2} INT(7) NOT NULL," . ");"; //4.上のSQL文を実行してテーブルを作る。 mysql_query($str_sql,$selectDB); echo"データベース内にテーブル「{$t1}」を作成しました。<br>"; //データベースへの接続を切断 $close_flag = mysql_close($link); if ($close_flag){ print('切断しました。<br>'); } 実行結果:Warning: mysql_query(): supplied argument is not a valid MySQL-Link resourceとなってテーブルは作成されず。 自分でも調べて見たところ、mysql_connect()での接続はちゃんとできているようなのですが、その次のmysql_select_db()関数がうまく働いていないようです。 つまりデータベースの選択ができていないので当然エラーとなるようです。 もう何日も悩んでいます。わかる方がいましたらどうぞよろしくお願いします。

    • ベストアンサー
    • PHP
  • Recordsetの ID PWは?

    GWで暇なので WebからSQL Server2008 Expressをダウンロードしてインストールして試している所です。 インストールは無事終了して、SQL Sever Managementを使って 新しいデータベースやテーブルも作成できました。 元々あったAccessのテーブルをインポートもできました。 しかし、エクセルのVBAで Recodsetを試みようとしているところですが Sub ボタン1_Click() Set cnnSql = New ADODB.Connection With cnnSql .Provider = "SQLOLEDB" .Properties("Data Source").Value = "PC\SQLEXPRESS" 'サーバー名 .Properties("User ID").Value = "sa" 'ユーザー名 .Properties("Password").Value = "" 'パスワード '.Properties("Initial Catalog").Value = "master" 'サーバー上のデータベース名 .Open End With cnnSql.Close Set cnnSql = Nothing End Sub という簡単なコードで ユーザー "sa"にログインできませんでした のメッセージで 先に進めません。 SQL Server management のログイン sa のプロパティをみると SQLServer認証 ですが 15ケタのパスワードが ●●・・・●と出ています。 ●をすべて削除してOKでいても次に開くと元の通りなのですが これが原因かどうかわかりませんが VBA Recodesetを使って SQLServerのテーブルに接続して操作したいのです。 どこの設定を見ればよいのかご存知の方、教えてください。 PCは Windows7 Office2010です。