7

FTP で暗号化された 250mb~ の ZIP ファイルのパスワードをダウンロードする必要があります。ダウンロードした後、共通のパスワードで解凍する必要があります.Zipファイルには1.5GBのMS Access DBが含まれており、これを読み取ってDB Oracleのいくつかのテーブルと結合し、そのデータを変換してそのOracle DBにロードする必要があります.

このプロセスを行うための最良の方法を探しています。私は ac# 開発者なので、最初に考えたのは、c# を使用し、FtpClientまたはFtpWebRequestを介してファイルをダウンロードし、次にDotNetZipなどの zip ライブラリを使用し、ODBC を介して MS Access データベースを開き、ODP.NEt を使用してレコードを Oracle にロードすることでした。それが私の「簡単な方法」だと思います。私はそれを行う方法を知っているからです。

しかし、これは大きなファイルであり、これには長い時間がかかる可能性があることがわかっているため、時間と効率、およびこのプロセスの時間を短縮する方法について懸念しています。

だから私はすべてのリクエストをオラクルに直接処理すると考えています(そこからFTPをダウンロードし、そこで解凍し、そこに直接情報を処理すると、C#からオラクルにレコードごとに渡すような時間が短縮されます)、この時間を短縮する必要がありますプロセスですが、これが正しい方法かどうかはわかりません。

そこで、私がアーカイブしようとしていることができるオラクルのライブラリを調べ始めたところ、PLSQL -utilsが見つかりました。MS Access データベースを読むことを除いて、私が必要とするすべてのことを実行できるようです。異機種間サービスですが、私はそれらを使用したことがないので、それについて少し迷っています。

また、Java を Oracle から直接使用できると聞いたことがあります。また、Java が JDBC 経由で MS Access に接続できることも知っています。それで私はそれについて検索し、Oracle DatabaseでのJavaメソッドの呼び出しに関する何かを見つけました

それが私がこれまでに持っているものですが、どの方法を使用すればよいかわかりません。つまり、私が知る限り、RDBMSはデータの処理を目的としていますが、ファイルのダウンロードなどのプログラミングを目的としていません。 OOPの言語を持っています。

追加情報として、このプロセスは月に 1 回か 2 回実行されるため、スケジュールを設定する必要があります。オラクルの場合は、スケジュール ジョブを使用して簡単に実行できます。C# では、スケジュールされたタスクまたは Windows サービス (これらの私が知っているツールです)

私が持っているいくつかの制限

  • クライアントは MS SQL Server を持っておらず、ライセンスを購入することもできません (したがって、このプロセスに DTSX を使用することはできません)
  • Oracle本番サーバーでは、すべてのことを行うのに十分な権限がない可能性がありますが、プロセスに最適であれば、それらに準拠できます
  • バックエンド サーバー (Java、IIS、WebLogic、JBoss などでホストされている c#) が必要な場合、このサーバーと Oracle サーバーは異なるものになります。
  • Unix サーバーでホストされている Oracle データベース

以上のことから、このすべてのプロセスを効率的に行うにはどうすればよいですか? .net を使用して、Oracle データベースにレコードごとにロードする必要がありますか? オラクルですべてを行う必要がありますか?または、これのどれもありませんか? これを行うより良い方法はありますか?

4

7 に答える 7

2

C# コンソール アプリケーションを使用して反復可能なプロセスにすることは、正しい方向に進んでいると思います。これは、私が多くのプロジェクトで zip に使用した素晴らしい無料ライブラリです。

using (var client = new WebClient())
using (var stream = client.OpenRead(@"ftp://mysite.com/mydb.zip"))
using (var file = File.Create(@"c:\temp\mydb.zip"))
{
    stream.CopyTo(@"c:\temp\mydb.zip", 32000);
}

using (ZipFile zip = ZipFile.Read(@"c:\temp\mydb.zip"))
{
    ZipEntry e = zip["bigdb.mdb"];
    e.Password = "yourpassword";
    e.Extract("c:\temp\bigdb.mdb");
}

解凍したら、アクセス DB と datareader オブジェクトへのデータ接続を作成できます。次に、dreader を使用して行を読み取り、フラット ファイルに書き込みます (大きなデータ セットでのメモリ不足例外を回避します)。

private constr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=yourdbfile.mdb;Jet OLEDB:Database Password=yourpassword;";
OleDbConnection conn = new OleDbConnection(constr);
string query = "SELECT * FROM [YourTable]";

OleDbCommand cmd = new OleDbCommand(query, conn);
OleDbDataReader reader = cmd.ExecuteReader();
int rowNum = 0;
StringBuilder sb = new StringBuilder(); 
while (reader.Read())
{
   // write rows to flat file in chunks of 10K rows.
   sb.Append(reader["FieldA"].ToString() + "|");
   sb.Append(reader["FieldB"].ToString() + "|");
   sb.Append(reader["FieldC"].ToString() + System.Environment.NewLine);

   if (rowNum % 10000 == 0)
   {
        File.AppendText(@"c:\temp\data.psv", sb.ToString());
        sb = new StringBuilder(); 
   }
   rowNum++;
}
File.AppendText(@"c:\temp\data.psv", sb.ToString());
reader.Close();

データ テーブルを入力したら、それをフラット ファイルにエクスポートできます。行ごとにデータを挿入することはお勧めしません。これは非常に遅くなり、Oracle db トランザクション ログが肥大化します。Oracle 10g にはバルク ロードをサポートする .Net ドライバがあるとは思えないため、おそらくフラット ファイルを介してバルク ロードする必要があります。

次に、コマンド ライン経由で Oracle にインポートします。これを C# コンソール アプリから呼び出すことができますこれを行う前に、制御ファイル ctl.ldrを作成しておく必要があります。これは、最初に Oracle で一括読み込み操作に使用されます。

options (skip=1)
load data
 INFILE 'c:\temp\data.psv'
 INTO table tblTest
 APPEND
 FIELDS TERMINATED BY "|" optionally enclosed by '"'      
 ( fielda,fieldb,etc...)

and then 
run it in as follows via command line

sqlldr username/pswd@oracle_sid control=ctl.ldr

うまくいけば、これが役に立ちます、頑張ってください!

[編集]

.Net Oracle Bulk copy クラスも参照してください。これは、Oracle 11gクライアントドライバーに同梱されています。おそらく、10g サーバーに対しては引き続き機能します。潜在的な問題は、同じアプリケーション サーバー上の他のすべてのアプリも、これらの新しい 11g クライアント ドライバーで動作する必要があることです。もう 1 つのオプションは、一括読み込みをサポートするJena フレームワークを使用する Java アプリケーションを構築することです。

于 2013-10-18T16:04:29.297 に答える
2

ペンタホをチェックしてください。これは基本的に Java オープン ソース SSIS ライクな製品です。Access db をダウンロードして抽出した後、このツールで残りの作業を行い、データを Oracle にロードします。以前にMySQLで使用したことがありますが、非常にうまく機能し、現在はバルクOracle db load componentを備えています。Pentaho は db サーバーでも実行する必要がないため、これが探している特効薬になる可能性があります。トレードオフは、立ち上げに時間がかかることです。

Oracle サーバーが Windows Server を実行していて、Access ファイルをそのサーバーのローカルのどこかに、またはサーバーが読み取れる場所に置くことができると仮定した場合の別の潜在的なオプションは、次のように実行できます。

  1. C# アプリを作成して、Access データベースをダウンロードし、抽出して、Oracle がアクセス可能な場所にコピーします。
  2. Access データベースへのローカル システム DSN (ODBC エントリ) を db サーバー上に作成します。
  3. Oracle Listener、HS、および接続設定を構成して開始します。
  4. データベース リンクを追加します。
  5. リンクされたデータベースとクエリで結合します。

この記事では、アクセスする Oracle db リンクを構成するプロセス全体の概要を説明します。

于 2013-10-18T18:53:40.020 に答える
1

ファイルをダウンロードして解凍し、行ごとにレコードを Oracle に直接挿入するために呼び出すことができるアプリケーション、Web ページ、または WCF サービスを作成します。すべてのデータをできるだけ Oracle に保存しようとします。取得して保存します。ダウンロードしたら、zipファイルをいじることはあまりありません。

基本的:

データ -> プロセッサ アプリケーション -> Oracle

このようにして、物事を自動化することができます。C# でプロセッサを実行します。

于 2013-10-15T22:30:18.100 に答える
1

私は 2 つのPowershell スクリプトを持っています。最初のスクリプトは、中国からftpファイルをダウンロードするのに役立ちます。

FTPスクリプトをダウンロード

# Parametros
param([string]$url, [string]$user, [string]$pass, [string]$folder, [string]$fecpro)


if (!$fecpro)
{
    $date = Get-Date
    $date = $date.AddDays(-1)
    $fecpro = '{0:yyyyMMdd}' -f $date
}

$FtpServer     = "ftp://$url/$fecpro"
$Username      = $user
$Password      = $pass
$RemoteFolder  = $FtpServer
if (!$folder)
{
    $LocalFolder   = $pwd.path + "\"
} 
else 
{
    $LocalFolder   = $folder + "\"
    if (-not(Test-Path -Path $LocalFolder))
    {
        New-Item -ItemType Directory -Force -Path $LocalFolder
    }
}
Write-Host "Searching *.zip files from $RemoteFolder..."

$existfiles = gci $LocalFolder | Where-Object { $_.name -like "*.zip" }

$cntFile = 0
$totFiles = 1
$listFiles = @(0)*$totfiles
$listFiles[1] = "cs2-" + $fecpro + "-6004-0000-1.zip"

$existfiles = gci $LocalFolder | Where-Object { $_.name -like "*.zip" }

do
{
    try
    {
        $f_exist = $false
        $cntFile = $cntFile + 1
        if ($existfiles) {
            foreach($file in $existfiles) {
                $tmpname = $file.name.ToString()
                $bool = $listFiles[$cntFile].CompareTo($file.name)                              
                if ($bool -eq 0) {
                    $f_exist = ($f_exist -or $true)
                } else {
                    $f_exist = ($f_exist -or $false)
                }
            }
        }

        if (!$f_exist -and $rescnt['CNT'] -eq 0) {
            $ftpfile = $RemoteFolder + "/" + $listFiles[$cntFile]
            $FTPRequest1 = [System.Net.FtpWebRequest]::Create($ftpfile)
            $FTPRequest1.Credentials = New-Object System.Net.NetworkCredential($Username,$Password)
            $FTPRequest1.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
            $FTPRequest1.UsePassive = $true
            $FTPRequest1.UseBinary = $true
            $FTPRequest1.KeepAlive = $false
            $destfile = $LocalFolder + $listFiles[$cntFile]
            $file = New-Object IO.FileStream ($destfile, [IO.FileMode]::Create)
            $FTPResponse = $FTPRequest1.GetResponse()
            $ResponseStream = $FTPResponse.GetResponseStream()
            [byte[]] $buffer = New-Object byte[] 64
            $FTPReader = $ResponseStream.Read($buffer, 0, 64)
            while($FTPReader -ne 0){
                $FTPReader = $ResponseStream.Read($buffer,0, 64)
                $file.Write($buffer,0,$FTPReader)
            }
            Write-Host "File $ftpfile is downloaded in local folder."       
            $file.Close()               
            $FTPReader.Close()
            $FTPResponse.Close()
            $ResponseStream.Close()

        } 
        else {
                Write-Host "The file $name already exists in local folder."
        }
    }
    catch
    {
        if ($file) {
            $file.Close()
        }

    }
}
while ($cntFile -lt $totFiles+1) 

2 番目のスクリプトは、 Oracle クライアントに付属の unzip.exe を使用してファイルを解凍します。(%ORACLE_HOME%\product\10.2.0\client_1\BIN)

ファイルの解凍スクリプト

param([string]$folder_origen, [string]$folder_destino, [string]$fecpro)

$P_FOLDER = $folder_origen + "\"
$P_DESTINO = $folder_destino + "\"

if (!$fecpro)
{
    $date = Get-Date
    $date = $date.AddDays(-1)
    $fecpro = '{0:yyyyMMdd}' -f $date
}

Write-Host "Searching *.zip files in $P_FOLDER"

# Inicio del programa
$LocalFolder = $P_FOLDER + "*$fecpro*.zip"
$filelocation = gci $LocalFolder
foreach ($file in $filelocation){
    if (($file) -and ($file.length -gt 0kb))
    {
        $shell = new-object -com shell.application
        $filename = $file.name.ToString()
        $split = $filename.Split(".")
        $dest = $P_DESTINO + $split[0]
        If (!(Test-Path $dest))
        { 
            New-Item $dest -Type Directory
        }
        $orifile = $P_FOLDER + $filename
        $time = "{0:hh_mm_ss.ffff}" -f (get-date)
        $prefile = "d." + (get-date).ToShortDateString() + ".t." + $time
        $prefile = $prefile -replace "/", "_"
        $filename = $prefile + ".f." + $filename
        $P_DESTZIP = $P_FOLDER + "proc" + "\"
        If (!(Test-Path $P_DESTZIP))
        { 
            New-Item $P_DESTZIP -Type Directory
        }
        #Copy-Item $orifile "$P_DESTZIP$prefile_$filename"
        $zipname = $orifile
        #"$P_DESTZIP$prefile_$filename"
        $zip = $shell.NameSpace($zipname)
        $destn = $shell.Namespace($dest)

        unzip -o -qq $zipname "*$fecpro*afsbjdtl.*" "*$fecpro*afgnled.bin" -d $dest

        Write-Host "$orifile was renamed and unzipped."
    } else
    {
        Write-Host "Zip files not found in the folder."
    }
}

ファイルのサイズ名前拡張子などのフィルターを使用できる場合、パターンで抽出するファイルを検索しますが、非常に高速です。

最後に、ロードについては、 LOAD DATAコマンドも使用することをお勧めします。最高のパフォーマンスを発揮します。

于 2013-10-24T20:22:55.883 に答える
1

コメントで尋ねたように、Oracle から別のデータベースへの DBLink を作成することは可能です。そのため、ファイルを特定の領域 (Oracle サーバーが読み取れる領域) にダウンロードして解凍するアプリケーションを作成します。次に、 https ://forums.oracle.com/thread/407779 の指示に従って、または asktom http://asktom.oracle.com/pls/asktom/f?p=100のように、このファイルへの DBLink を設定します 。 11:::::P11_QUESTION_ID:4406709207206

次に、msAccess db を読み取ってオラクルからデータを直接インポートします。

于 2013-10-18T16:26:42.077 に答える
1

明白なことを述べている場合は申し訳ありませんが、パフォーマンスの主な懸念が msaccess.db の ftp/sftp 転送の速度である場合は、実際にアクセスしたテーブル/レコードのサブセットをアクセス データベースに定期的にエクスポートさせることが理にかなっています。 Oracle に必要な更新を行うには、にアクセスする必要があります。

数年前、「ArrayDML」を使用して Oracle にレコードを追加すると、一度に 1 つのレコードを追加する場合の約 10 倍の速さであることがわかりました。(それがodp.netでサポートされているかどうかはわかりません...)

于 2013-10-25T00:03:54.840 に答える
1

自分が一番よく知っているツールを使ったほうがいいと思います。Java で同じことを行い、それをデータベースにロードするか、別のアプリケーションとして実行することは可能ですが、なぜわざわざするのでしょうか? C# で Access データベースをダウンロード/解凍/開く効率的な方法を知っていると思います。

アクセスデータベースからOracleデータベースにデータを効率的にアップロードする方法が1つだけ欠けています。

簡単な答えは -bulk insertsです。一時テーブルと組み合わせて、さらに一括処理するためのストアド プロシージャを使用することもできます。データベース/テーブルのカスタム チューニングを使用して、データをより適切に調整することで、さらに高速化を実現できます。

Javaでも同じことができますが、高速になるとは思えません。データのバッファリングと一括読み込みを適切に処理することは、他の要因よりもはるかに重要です。その後、DBA とバグを取得して、データベースのチューニングに役立ててください。詳細はこの質問の範囲外です。

于 2013-10-24T23:38:06.043 に答える