C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

データテーブル内の検索

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■93981 / inTopicNo.1)  データテーブル内の検索
  
□投稿者/ ぽむ (1回)-(2020/02/28(Fri) 15:28:44)

分類:[.NET 全般] 



vb2017/windows7
windowsフォームアプリケーションで開発しています。

データテーブルから条件を指定して該当行(複数)を抽出したいのですが、
データビューで取り出すか、データテーブルのSelectメソッドを考えています。

結果的には同じように使えるのですが、どちらのほうが早い、推奨などが分からず、
どちらを使うべきか判断できません。

どなたか、それぞれのメリットデメリットがあれば教えていただきたいです。

引用返信 編集キー/
■93991 / inTopicNo.2)  Re[1]: データテーブル内の検索
□投稿者/ daive (2回)-(2020/02/28(Fri) 17:54:03)
せめて、
データベースは使っているのかどうか、
使っているとしたら、製品名、エディション、バージョン の記載
MS−SQL Server であれば、
SQL Server Management Studio (SSMS) のダウンロード
https://docs.microsoft.com/ja-jp/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver15
あたりから、SSMS のダウンロード、インストール終わって、
当該SQLインスタンスの、初期設定終了、最低でもメモリ設定位は、終わらせたかどうかなども。

対象テーブルに、適切かつ有効なインデックスが付いて居るか?
⇒設計等含めて適切なテーブルかどうか、データは適切かなど?
データ検索用のクエリは、適切か?
→インデックス等を適切に使用できる物になっているかどうか?

等も、書くべきかとおもいますが?

貴方のPCの隣で、貴方のPCを見ているわけではありません。
御自分は、解っていても、他の人には、貴方の、環境や状況が何かは解りません。
⇒何を使っているかなんて、解りませんので。
引用返信 編集キー/
■93992 / inTopicNo.3)  Re[2]: データテーブル内の検索
□投稿者/ Hongliang (967回)-(2020/02/28(Fri) 18:04:33)
> 等も、書くべきかとおもいますが?

DataTableの話なので、RDBMSは特に関係ない話ですが…。
まあ、クライアントプログラム内でやるよりSQLでRDBMSにやらせた方がいいかもしれない、という視点はありますが。

// 私はメリットデメリットを提示できるほど詳しくないので、
// 抽出結果を画面に出すとかじゃないのならSelectでいいんじゃないかな、ぐらいしか言えません。
引用返信 編集キー/
■93997 / inTopicNo.4)  Re[1]: データテーブル内の検索
□投稿者/ 魔界の仮面弁士 (2577回)-(2020/02/28(Fri) 20:34:05)
2020/02/28(Fri) 20:37:15 編集(投稿者)

No93981 (ぽむ さん) に返信
> データテーブルから条件を指定して該当行(複数)を抽出したいのですが、

DataTable の PrimaryKey プロパティで示された列群を対象にする場合に限り、
.Rows.Find を使うという手もありますね。まぁ、複数行の列挙には使えませんけれど…。
(主キーが競合していた場合は、先に見つかった方の行が返される仕様です)


> データビューで取り出すか、データテーブルのSelectメソッドを考えています。

複数行の場合、昨今だと LINQ to DataSet を使って抽出するという選択肢もありますが、それはさておき。

ひとまず、「DataView のフィルター」を使う方法と、
「DataTable の Select でフィルター」を比べてみた場合、基本的は
同等レベルの抽出パフォーマンスが得られるものと認識しています。


また、「DataTable の DefaultView を操作した場合」や
「DataTable の Select を呼んだ場合」、再検索に備えて
インデックスが構築されるらしく、次回以降の検索効率が上がるようです。

その半面、インデックスが生成された後は、その後の .Row.Add 時のパフォーマンスが
劣化することになります。(データ件数が多くなるほど悪化)

そのため、抽出後に行数の変動がありえる場合は、Select や DefaultView を用いず、
新しい DataView インスタンスを New してフィルターをかけた方が望ましいです。


下記の事例にも、抽出処理後はデータ追加に 1〜2分もの時間が
かかるようになってしまった…という報告があります。
https://blog.doizaki.com/entry/2014/01/11/004238



当方の事例ですと、データ表示用にバインド用の型付 DataSet を使いまわして、
Select で抽出したり、最新データの再表示のために
.Rows.Clear() & Rows.Add() しなおすなんて使い方をしていたことが
あるのですが、上記の「遅くなる」という記事を見て、
DataSet や DataTable の使いまわしを避けて、
毎回インスタンスを作り直すようにしたところ、
2 項目 31 レコードを Row.Add するだけの単純な処理が
 修正前: 27.9 秒
 修正後: 0.17 秒
という劇的な改善を見せたことがあります。

その当時 Row.Add にかかっていた時間も載せておきます。
 修正前:1 件目 0.46 秒、31件目 1.30 秒
 修正後:1 件目 0.0000114 秒、31件目 0000105 秒


ただし、DataSet のインスタンスを都度都度作り直していたとしても、
下記のような問題が起きる可能性はあります。
今回の質問内容からは脱線しますが、一応参考までに。
http://bbs.wankuma.com/index.cgi?mode=al2&namber=81781&KLOG=140
引用返信 編集キー/
■94001 / inTopicNo.5)  Re[1]: データテーブル内の検索
□投稿者/ WebSurfer (2030回)-(2020/03/01(Sun) 16:40:37)
No93981 (ぽむ さん) に返信

> 結果的には同じように使えるのですが、どちらのほうが早い、推奨などが分からず、
> どちらを使うべきか判断できません。

ユーザーが抽出条件を指定して結果を DataGridView にユーザーに表示というような
ユーザー操作が絡む場合は、早い/遅いはあまり気にする必要はなく、どちらがより
簡単かつ問題なく実装できるかで考える方がよさそうな気がします。

例えば、DataTable ⇔ BindingSource ⇔ DataGridView という定番の構成で、ユー
ザー入力で絞り込む場合、DataTable の Select メソッドでは問題があるので、
DataView を取得してその RowFilter プロパティを使うのが正解という例もありま
した。

その時のサンプルコードをアップしておきます。質問者さんのケースでは関係ない話
かもしれませんが、ご参考まで。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();
        }

        private void productsBindingNavigatorSaveItem_Click(object sender, EventArgs e)
        {
            this.Validate();
            this.productsBindingSource.EndEdit();
            this.tableAdapterManager.UpdateAll(this.northwindDataSet);
        }

        private void Form3_Load(object sender, EventArgs e)
        {
            // TODO: このコード行はデータを 'northwindDataSet.Products' テーブルに読み込みます。
            // 必要に応じて移動、または削除をしてください。
            this.productsTableAdapter.Fill(this.northwindDataSet.Products);
        }

        // 上のコードまではデザイナで自動生成される

        // 検索用の TextBox と Button を追加し、Button の Click イベントのハンドラを以下のようにする。

        private void button1_Click(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(this.textBox1.Text))
            {
                NorthwindDataSet.ProductsDataTable table = this.northwindDataSet.Products;

                //NorthwindDataSet.ProductsRow[] rows = 
                //    (NorthwindDataSet.ProductsRow[])table.Select("ProductName LIKE '%" + this.textBox1.Text + "%'");
                //this.productsBindingSource.DataSource = rows;

                // 上記のように NorthwindDataSet.ProductsRow[] を DataSource に設定した場合は
                // ProductsRow クラスに定義されているプロパティの get アクセサを使って
                // ProductsDataTable からデータを取得するので、そのデータが DBNull の場合キャスト
                // に失敗して StrongTypingException がスローされるので注意。

                // 以下のように DataView を取得して、その RowFilter プロパティに設定するのが正解。

                table.DefaultView.RowFilter = "ProductName LIKE '%" + this.textBox1.Text + "%'";
                this.productsBindingSource.DataSource = this.northwindDataSet.Products;
            }
            else
            {
                // 元に戻す場合
                NorthwindDataSet.ProductsDataTable table = this.northwindDataSet.Products;
                table.DefaultView.RowFilter = "";

                // このコードは無くても OK
                //this.productsBindingSource.DataSource = this.northwindDataSet.Products;
            }
        }
    }
}

引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ