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

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

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

Re[4]: Access2013による大量データ計算について


(過去ログ 166 を表示中)

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

■95685 / inTopicNo.1)  Access2013による大量データ計算について
  
□投稿者/ くまくま (42回)-(2020/09/02(Wed) 15:11:59)

分類:[Microsoft Office 全般] 

2020/09/02(Wed) 15:16:07 編集(投稿者)

Access2013による大量データ計算について
※質問が2種類の為分割しています

質問2. 現在 1,563,992,064データの計算を行い結果をファイル出力していますが
終わるまで約1日かかってしまいます。
計算の時間短縮する良い方法はありますでしょうか?

できればVBA内で完結したいのですが、VB.netへの変更も考えています。
(Double型計算誤差の関係上、Decmal型で計算を行い結果をDouble型に変換しています。)

処理時間内訳
・レコード読込合計時間
約2分30秒(169分割で合計6,109,344レコード)

・計算合計時間
約27時間(MeshesToDegreeを1,563,992,064回)

・ファイル出力合計時間
約1時間15分(169ファイルに分割出力 合計84,455,571,118バイト)

計算内容
 9次メッシュコードから緯度経度を算出する。

標準モジュール
以下の通り
引用返信 編集キー/
■95686 / inTopicNo.2)  Re[1]: Access2013による大量データ計算について
□投稿者/ くまくま (43回)-(2020/09/02(Wed) 15:12:53)
Option Explicit

Private con1 As Variant
Private con2 As Variant
'----- 1次メッシュコード変換(一辺約80km)
Private conMes1stLat As Variant
Private conMes1stLon As Variant
Private conDeg1stLat As Variant
Private conDeg1stLon As Variant
'----- 2次メッシュコード変換(一辺約10km 1次メッシュを縦横8分割)
Private conMes2ndLat As Variant
Private conMes2ndLon As Variant
Private conDeg2ndLat As Variant
Private conDeg2ndLon As Variant
'----- 3次メッシュコード変換(一辺約1km 2次メッシュを縦横10分割)
Private conMes3rdLat As Variant
Private conMes3rdLon As Variant
Private conDeg3rdLat As Variant
Private conDeg3rdLon As Variant
'----- 4次メッシュコード変換(一辺約500m 3次メッシュを縦横2分割)
Private conMes4thLat As Variant
Private conMes4thLon As Variant
Private conDeg4thLat As Variant
Private conDeg4thLon As Variant
'----- 5次メッシュコード変換(一辺約250m 4次メッシュを縦横2分割)
Private conMes5thLat As Variant
Private conMes5thLon As Variant
Private conDeg5thLat As Variant
Private conDeg5thLon As Variant
'----- 6次メッシュコード変換(一辺約125m 5次メッシュを縦横2分割)
Private conMes6thLat As Variant
Private conMes6thLon As Variant
Private conDeg6thLat As Variant
Private conDeg6thLon As Variant
'----- 7次メッシュコード変換(一辺約75m 6次メッシュを縦横2分割)
Private conMes7thLat As Variant
Private conMes7thLon As Variant
Private conDeg7thLat As Variant
Private conDeg7thLon As Variant
'----- 8次メッシュコード変換(一辺約37.5m 7次メッシュを縦横2分割)
Private conMes8thLat As Variant
Private conMes8thLon As Variant
Private conDeg8thLat As Variant
Private conDeg8thLon As Variant
'----- 9次メッシュコード変換(一辺約18.75m 8次メッシュを縦横2分割)
Private conMes9thLat As Variant
Private conMes9thLon As Variant
Private conDeg9thLat As Variant
Private conDeg9thLon As Variant

Private Sub MeshesInit()
'-------------------------------------------------------------------------------
'   MeshesInit
'   説明
'       変換用値設定
'       MeshesToDegree
'       DegreeToMeshes
'   パラメータ
'       なし
'-------------------------------------------------------------------------------
    
    If con1 = 1 Then Exit Sub
    
    con1 = CDec(1)
    con2 = CDec(2)
    '----- 1次メッシュコード変換(一辺約80km)
    conMes1stLat = CDec(3) / CDec(2)
    conMes1stLon = CDec(100)
    conDeg1stLat = CDec(2) / CDec(3)
    conDeg1stLon = CDec(100)
    '----- 2次メッシュコード変換(一辺約10km 1次メッシュを縦横8分割)
    conMes2ndLat = CDec(3 * 8) / CDec(2)
    conMes2ndLon = CDec(8)
    conDeg2ndLat = CDec(2) / CDec(3 * 8)
    conDeg2ndLon = CDec(8)
    '----- 3次メッシュコード変換(一辺約1km 2次メッシュを縦横10分割)
    conMes3rdLat = CDec(3 * 8 * 10) / CDec(2)
    conMes3rdLon = CDec(8 * 10)
    conDeg3rdLat = CDec(2) / CDec(3 * 8 * 10)
    conDeg3rdLon = CDec(8 * 10)
    '----- 4次メッシュコード変換(一辺約500m 3次メッシュを縦横2分割)
    conMes4thLat = CDec(3 * 8 * 10 * 2) / CDec(2)
    conMes4thLon = CDec(8 * 10 * 2)
    conDeg4thLat = CDec(2) / CDec(3 * 8 * 10 * 2)
    conDeg4thLon = CDec(8 * 10 * 2)
    '----- 5次メッシュコード変換(一辺約250m 4次メッシュを縦横2分割)
    conMes5thLat = CDec(3 * 8 * 10 * 2 * 2) / CDec(2)
    conMes5thLon = CDec(8 * 10 * 2 * 2)
    conDeg5thLat = CDec(2) / CDec(3 * 8 * 10 * 2 * 2)
    conDeg5thLon = CDec(8 * 10 * 2 * 2)
    '----- 6次メッシュコード変換(一辺約125m 5次メッシュを縦横2分割)
    conMes6thLat = CDec(3 * 8 * 10 * 2 * 2 * 2) / CDec(2)
    conMes6thLon = CDec(8 * 10 * 2 * 2 * 2)
    conDeg6thLat = CDec(2) / CDec(3 * 8 * 10 * 2 * 2 * 2)
    conDeg6thLon = CDec(8 * 10 * 2 * 2 * 2)
    '----- 7次メッシュコード変換(一辺約75m 6次メッシュを縦横2分割)
    conMes7thLat = CDec(3 * 8 * 10 * 2 * 2 * 2 * 2) / CDec(2)
    conMes7thLon = CDec(8 * 10 * 2 * 2 * 2 * 2)
    conDeg7thLat = CDec(2) / CDec(3 * 8 * 10 * 2 * 2 * 2 * 2)
    conDeg7thLon = CDec(8 * 10 * 2 * 2 * 2 * 2)
    '----- 8次メッシュコード変換(一辺約37.5m 7次メッシュを縦横2分割)
    conMes8thLat = CDec(3 * 8 * 10 * 2 * 2 * 2 * 2 * 2) / CDec(2)
    conMes8thLon = CDec(8 * 10 * 2 * 2 * 2 * 2 * 2)
    conDeg8thLat = CDec(2) / CDec(3 * 8 * 10 * 2 * 2 * 2 * 2 * 2)
    conDeg8thLon = CDec(8 * 10 * 2 * 2 * 2 * 2 * 2)
    '----- 9次メッシュコード変換(一辺約18.75m 8次メッシュを縦横2分割)
    conMes9thLat = CDec(3 * 8 * 10 * 2 * 2 * 2 * 2 * 2 * 2) / CDec(2)
    conMes9thLon = CDec(8 * 10 * 2 * 2 * 2 * 2 * 2 * 2)
    conDeg9thLat = CDec(2) / CDec(3 * 8 * 10 * 2 * 2 * 2 * 2 * 2 * 2)
    conDeg9thLon = CDec(8 * 10 * 2 * 2 * 2 * 2 * 2 * 2)

End Sub


引用返信 編集キー/
■95687 / inTopicNo.3)  Re[2]: Access2013による大量データ計算について
□投稿者/ くまくま (44回)-(2020/09/02(Wed) 15:13:20)
Public Function MeshesToDegree(ByVal Meshes As String, ByRef Latitude As Double, ByRef Longitude As Double, Optional LatitudePoint As Double = 0, Optional LongitudePoint As Double = 0)
'-------------------------------------------------------------------------------
'   MeshesToDegree
'   説明
'       「メッシュコード」から「緯度経度」への変換
'   パラメータ
'       Meshes              : 1〜9次メッシュ情報
'       LatitudePoint       : 0/南 0.5/中心 1/北
'       LongitudePoint      : 0/西 0.5/中心 1/東
'   戻り値
'       Latitude            : 緯度「度」情報
'       Longitude           : 経度「度」情報
'-------------------------------------------------------------------------------
    
    Dim decLatitude         As Variant  '緯度
    Dim decLongitude        As Variant  '経度
    Dim decMeshesLatitude   As Variant  'メッシュ緯度
    Dim decMeshesLongitude  As Variant  'メッシュ経度
    Dim decMeshesTemp       As Variant  'メッシュ
    
    decLatitude = CDec(0)    '緯度
    decLongitude = CDec(0)   '経度
    
    '----- 変換用値設定
    Call MeshesInit

    '----- 1次メッシュコード変換(一辺約80km)
    If Len(Meshes) >= 4 Then
        decMeshesLatitude = CDec(Mid(Meshes, 1, 2))     'メッシュ緯度
        decMeshesLongitude = CDec(Mid(Meshes, 3, 2))    'メッシュ経度
        If Len(Meshes) = 4 Then
            decMeshesLatitude = decMeshesLatitude + CDec(LatitudePoint)       'メッシュ緯度
            decMeshesLongitude = decMeshesLongitude + CDec(LongitudePoint)    'メッシュ経度
        End If
        decLatitude = decLatitude + (decMeshesLatitude * conDeg1stLat)
        decLongitude = decLongitude + (decMeshesLongitude + conDeg1stLon)
    End If

    '----- 2次メッシュコード変換(一辺約10km 1次メッシュを縦横8分割)
    If Len(Meshes) >= 6 Then
        decMeshesLatitude = CDec(Mid(Meshes, 5, 1))     'メッシュ緯度
        decMeshesLongitude = CDec(Mid(Meshes, 6, 1))    'メッシュ経度
        If Len(Meshes) = 6 Then
            decMeshesLatitude = decMeshesLatitude + CDec(LatitudePoint)       'メッシュ緯度
            decMeshesLongitude = decMeshesLongitude + CDec(LongitudePoint)    'メッシュ経度
        End If
        decLatitude = decLatitude + (decMeshesLatitude * conDeg2ndLat)
        decLongitude = decLongitude + (decMeshesLongitude / conDeg2ndLon)
    End If

    '----- 3次メッシュコード変換(一辺約1km 2次メッシュを縦横10分割)
    If Len(Meshes) >= 8 Then
        decMeshesLatitude = CDec(Mid(Meshes, 7, 1))     'メッシュ緯度
        decMeshesLongitude = CDec(Mid(Meshes, 8, 1))    'メッシュ経度
        If Len(Meshes) = 8 Then
            decMeshesLatitude = decMeshesLatitude + CDec(LatitudePoint)       'メッシュ緯度
            decMeshesLongitude = decMeshesLongitude + CDec(LongitudePoint)    'メッシュ経度
        End If
        decLatitude = decLatitude + (decMeshesLatitude * conDeg3rdLat)
        decLongitude = decLongitude + (decMeshesLongitude / conDeg3rdLon)
    End If

    '----- 4次メッシュコード変換(一辺約500m 3次メッシュを縦横2分割)
    If Len(Meshes) >= 9 Then
        decMeshesTemp = CDec(Mid(Meshes, 9, 1)) - con1
        decMeshesLatitude = CDec(Fix(decMeshesTemp / con2))             'メッシュ緯度
        decMeshesLongitude = decMeshesTemp - (decMeshesLatitude * con2) 'メッシュ経度
        If Len(Meshes) = 9 Then
            decMeshesLatitude = decMeshesLatitude + CDec(LatitudePoint)       'メッシュ緯度
            decMeshesLongitude = decMeshesLongitude + CDec(LongitudePoint)    'メッシュ経度
        End If
        decLatitude = decLatitude + (decMeshesLatitude * conDeg4thLat)
        decLongitude = decLongitude + (decMeshesLongitude / conDeg4thLon)
    End If

    '----- 5次メッシュコード変換(一辺約250m 4次メッシュを縦横2分割)
    If Len(Meshes) >= 10 Then
        decMeshesTemp = CDec(Mid(Meshes, 10, 1)) - con1
        decMeshesLatitude = CDec(Fix(decMeshesTemp / con2))             'メッシュ緯度
        decMeshesLongitude = decMeshesTemp - (decMeshesLatitude * con2) 'メッシュ経度
        If Len(Meshes) = 10 Then
            decMeshesLatitude = decMeshesLatitude + CDec(LatitudePoint)       'メッシュ緯度
            decMeshesLongitude = decMeshesLongitude + CDec(LongitudePoint)    'メッシュ経度
        End If
        decLatitude = decLatitude + (decMeshesLatitude * conDeg5thLat)
        decLongitude = decLongitude + (decMeshesLongitude / conDeg5thLon)
    End If

    '----- 6次メッシュコード変換(一辺約125m 5次メッシュを縦横2分割)
    If Len(Meshes) >= 11 Then
        decMeshesTemp = CDec(Mid(Meshes, 11, 1)) - con1
        decMeshesLatitude = CDec(Fix(decMeshesTemp / con2))             'メッシュ緯度
        decMeshesLongitude = decMeshesTemp - (decMeshesLatitude * con2) 'メッシュ経度
        If Len(Meshes) = 11 Then
            decMeshesLatitude = decMeshesLatitude + CDec(LatitudePoint)       'メッシュ緯度
            decMeshesLongitude = decMeshesLongitude + CDec(LongitudePoint)    'メッシュ経度
        End If
        decLatitude = decLatitude + (decMeshesLatitude * conDeg6thLat)
        decLongitude = decLongitude + (decMeshesLongitude / conDeg6thLon)
    End If

    '----- 7次メッシュコード変換(一辺約75m 6次メッシュを縦横2分割)
    If Len(Meshes) >= 12 Then
        decMeshesTemp = CDec(Mid(Meshes, 12, 1)) - con1
        decMeshesLatitude = CDec(Fix(decMeshesTemp / con2))             'メッシュ緯度
        decMeshesLongitude = decMeshesTemp - (decMeshesLatitude * con2) 'メッシュ経度
        If Len(Meshes) = 12 Then
            decMeshesLatitude = decMeshesLatitude + CDec(LatitudePoint)       'メッシュ緯度
            decMeshesLongitude = decMeshesLongitude + CDec(LongitudePoint)    'メッシュ経度
        End If
        decLatitude = decLatitude + (decMeshesLatitude * conDeg7thLat)
        decLongitude = decLongitude + (decMeshesLongitude / conDeg7thLon)
    End If

    '----- 8次メッシュコード変換(一辺約37.5m 7次メッシュを縦横2分割)
    If Len(Meshes) >= 13 Then
        decMeshesTemp = CDec(Mid(Meshes, 13, 1)) - con1
        decMeshesLatitude = CDec(Fix(decMeshesTemp / con2))             'メッシュ緯度
        decMeshesLongitude = decMeshesTemp - (decMeshesLatitude * con2) 'メッシュ経度
        If Len(Meshes) = 13 Then
            decMeshesLatitude = decMeshesLatitude + CDec(LatitudePoint)       'メッシュ緯度
            decMeshesLongitude = decMeshesLongitude + CDec(LongitudePoint)    'メッシュ経度
        End If
        decLatitude = decLatitude + (decMeshesLatitude * conDeg8thLat)
        decLongitude = decLongitude + (decMeshesLongitude / conDeg8thLon)
    End If

    '----- 9次メッシュコード変換(一辺約18.75m 8次メッシュを縦横2分割)
    If Len(Meshes) >= 14 Then
        decMeshesTemp = CDec(Mid(Meshes, 14, 1)) - con1
        decMeshesLatitude = CDec(Fix(decMeshesTemp / con2))             'メッシュ緯度
        decMeshesLongitude = decMeshesTemp - (decMeshesLatitude * con2) 'メッシュ経度
        If Len(Meshes) = 14 Then
            decMeshesLatitude = decMeshesLatitude + CDec(LatitudePoint)       'メッシュ緯度
            decMeshesLongitude = decMeshesLongitude + CDec(LongitudePoint)    'メッシュ経度
        End If
        decLatitude = decLatitude + (decMeshesLatitude * conDeg9thLat)
        decLongitude = decLongitude + (decMeshesLongitude / conDeg9thLon)
    End If

    Latitude = decLatitude      '緯度
    Longitude = decLongitude    '経度

End Function

引用返信 編集キー/
■95691 / inTopicNo.4)  Re[1]: Access2013による大量データ計算について
□投稿者/ 大谷刑部 (100回)-(2020/09/03(Thu) 13:19:36)
No95685 (くまくま さん) に返信
> 2020/09/02(Wed) 15:16:07 編集(投稿者)
>
> Access2013による大量データ計算について
> ※質問が2種類の為分割しています
>
> 質問2. 現在 1,563,992,064データの計算を行い結果をファイル出力していますが
> 終わるまで約1日かかってしまいます。
> 計算の時間短縮する良い方法はありますでしょうか?
画期的に減らす方法はないでしょうね。
ここまでデータ量多いと。
そもそもAccessのキャパを超えてると思います。

> できればVBA内で完結したいのですが、VB.netへの変更も考えています。
> (Double型計算誤差の関係上、Decmal型で計算を行い結果をDouble型に変換しています。)
inの情報はDoubleでしか来ないのですか?
とするなら端数処理に切り上げ、切捨て処理がないなら、Decimal型に代入した時点で2進→10進の有効桁数に絡む誤差は発生してしまう可能性大なので、
精度上もDecimalに変換するのは逆効果な気がします。
inをDecimalにできるならDecimalの方が精度は高いですけど。
処理速度が再重要視ならそもそも計算もDoubleかと。
お金の計算なら基本Doubleは禁止でしょうけど、お使いになるのが緯度経度情報なら、誤差はそんなにクリティカルじゃないのでは?
引用返信 編集キー/
■95692 / inTopicNo.5)  Re[1]: Access2013による大量データ計算について
□投稿者/ shu (1232回)-(2020/09/03(Thu) 14:32:34)
No95685 (くまくま さん) に返信


> ・計算合計時間
> 約27時間(MeshesToDegreeを1,563,992,064回)
>
メモリ内の計算で時間がかかっているようですね。
27時間 = 27 * 60 * 60 * 1000 * 1000 = 97200000000マイクロ秒
を1,563,992,064回
で割るとおよそ62マイクロ秒となります。
VBAで行うには打倒な時間かと思います。
これを早くするには回数をなんとか減らす方法とか
処理をもっと少なくする方法がなければVBAでは無理かと思います。
VB.NETでコンパイルしたものであれば1回辺りの速度を速めることは可能かと思います。


引用返信 編集キー/
■95697 / inTopicNo.6)  Re[2]: Access2013による大量データ計算について
□投稿者/ くまくま (45回)-(2020/09/03(Thu) 18:30:27)
大谷刑部さん
shuさん
ご返事ありがとうございます。

ます緯度経度情報の計算がDecimalで行っているのは
ここには書いていませんが「緯度経度」から「メッシュコード」への逆変換で結果が異なってしまう事が確認された為です
「緯度経度」データ自体の精度としてはDoubleで問題なさそうなのですが
本当に問題ないかは全データで試さなくてはならず、そうすると検証に2日以上かかってしまいます。

そこからチューニング等を行って再度確認の繰り返しを考えると、いつ終わるかわからない為相談させていただいた次第です。
(このような処理がまだ10種類以上待っています。)

処理に関して「ミリ秒」単位で計測していたのですが判りませんでしたが
shuさんの計算で「62マイクロ秒」という事が判ったので塵も積もればですね

やはりVB.netに変更するほうがよさそうですね...

一応もう少しご意見を伺いたいので「解決済み」は保留としておきます。
引用返信 編集キー/
■95703 / inTopicNo.7)  Re[3]: Access2013による大量データ計算について
□投稿者/ 大谷刑部 (102回)-(2020/09/04(Fri) 10:39:58)
No95697 (くまくま さん) に返信
> 大谷刑部さん
> shuさん
> ご返事ありがとうございます。
> 処理に関して「ミリ秒」単位で計測していたのですが判りませんでしたが
> shuさんの計算で「62マイクロ秒」という事が判ったので塵も積もればですね
>
> やはりVB.netに変更するほうがよさそうですね...

コンパイルの観点からはその通りなのかもしれませんが、
Accessを使う+.Net系言語=.NetからComへの参照が発生する(Excelではそれが問題になり、office.interopを使わない方法を推奨する人が出てきたりします)
ので、性能の問題で.Netに飛びつくのは慎重になさった方がよろしいかと。
Accessの場合、ADO.netを使用してもOLEDB(ACE.OLEDB)を経由するので、OracleやSQL Serverのように直接つなぎに行くプロバイダーがあるDBとはコード上は似ていても技術的には若干異なります。
ADO.NetのOLEDB経由は結構曲者で、SQL Sever ではODBC経由の方がOLEDBプロバイダー経由より速いという、
ADOの時代とは逆転する現象も起きているようです。これはここの掲示板でとある方から教わりました。
引用返信 編集キー/
■95705 / inTopicNo.8)  Re[4]: Access2013による大量データ計算について
□投稿者/ くまくま (48回)-(2020/09/04(Fri) 13:55:46)
No95703 (大谷刑部 さん) に返信

現在質問を別にした「Access2013による大量データ管理について」の関係での解説ありがとうございます。
私もそのことがある為AccessのVBAですませたかった経緯があります。

今現在計算部分をVB.netでVBA向けに.NETのクラス・ライブラリを作成して検証していますが
感触として「VBAの80〜90%の速度」といった感じです。
(結局実行が終わるまで約1日はかかりそうです)

ちなみに私は「ADO派」です。
・DAOだとページロックになってしまう
・DAOが将来の64ビットオペレーティングシステムで利用可能になることはない
・DAO3.6で開発が終了している→データベースのバージョンアップによる不都合を吸収できない恐れがある
と思っています。

「Access2013による大量データ管理について」のほうで書きましたが
Accessから変更予定の為、ストアドでの実行という手段も生まれますので
これで解決済としたいと思います


解決済み
引用返信 編集キー/


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

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -