2014年8月10日日曜日

MarkdownNote0.0.0.2

今日も更新

検索/置換/表の挿入機能の追加

今後の予定

プレビューがあやしい&使えなくしてる機能の修正
ファイルのエンコードを変更できるように
シンタックスハイライトの追加
見出しの一覧/移動ができるように

怪しい英語から日本語へ切り替えれるようにLanguageファイルの追加



2014年8月8日金曜日

MarkdownNote0.0.0.1


最近Markdown記法にハマっているのでタブ切り替え型のエディターを作成中
とりあえず形になってきたのでうpしてみました




動作には.netFramework4.0以上が必要です
ここからダウンロード

2014年4月23日水曜日

引き継いだAccessのシステムが激遅な件

15年近く前に外注に出したAccessのシステムの保守を引き継いだ
データのサイズは400MBを超えていて、数万件のデータから1レコードを検索をしようと思ったら1分近くかかるシステムだった。
外注の書いたコードか前任者の追加コードが原因かは今となってはわからない(仕様書もない)が
VBAソースコードを見直してみたらナポリタンの匂いがした

TCP Monitor Plusをダウンロードして、ファイルサーバーとクライアントPCのパケットをモニタリングしてみたところ1レコードの検索で80MBのデータを受信していることが判明(/・ω・)/

見直しをしてみたらテーブルのフィールドに適切なインデックスが設定されておらずRecordsetでFilter使いまくりだった

Indexの有無とFilter使った場合でどんだけ違うのかをテストしてみた

新しいAccessファイルを作りテーブル1にフィールド1~6を追加
フィールド1はインデックスをはい (重複あり)に指定

下のコードで500000件のテストデータを入れ込んだ

Option Compare Database
Option Explicit

Sub TestData()

    Dim db As DAO.Database
    Set db = CurrentDb
  
    Dim l As Long
    For l = 0 To 500000
      
        db.Execute ("INSERT INTO テーブル1 (フィールド1,フィールド2,フィールド3,フィールド4,フィールド5,フィールド6) " & _
                    "VALUES ('" & GetGUID() & "','" & GetGUID() & "','" & GetGUID() & "','" & GetGUID() & "','" & GetGUID() & "','" & GetGUID() & "')")
  
    Next

End Sub

'下のサイトを参考にさせてもらいました
'http://maeda0414.blog.fc2.com/blog-entry-26.html
Public Function GetGUID() As String
    GetGUID = Mid$(CreateObject("Scriptlet.TypeLib").Guid, 2, 36)
End Function
このファイルをファイルサーバに置き
クライアント側にも新しいAccessファイルを作りモジュールに下のテストコードを書く

Option Compare Database
Option Explicit

Public Sub Test1()

    Dim db As DAO.Database
    Dim rs As DAO.Recordset
  
    Set db = CurrentDb
  
    'インデックスを設定したフィールドを条件にして直にクエリ文を書いた
    Set rs = db.OpenRecordset("SELECT * FROM テーブル1 WHERE フィールド1 = '884EBDD8-0516-480D-9C13-6F2EF60B2202'")
    
    Do Until rs.EOF
        Debug.Print ("Test1 " & rs!ID)
        rs.MoveNext
    Loop
  
End Sub

Public Sub Test2()

    Dim db As DAO.Database
    Dim rs As DAO.Recordset
  
    Set db = CurrentDb
  
    'インデックスの設定をしていないフィールドを条件にして直にクエリ文を書いた
    Set rs = db.OpenRecordset("SELECT * FROM テーブル1 WHERE フィールド2 = '7BFD061C-711E-404F-89D3-0973CADFF5F6'")
    
    Do Until rs.EOF
        Debug.Print ("Test2 " & rs!ID)
        rs.MoveNext
    Loop
      
End Sub

Public Sub Test3()

    Dim db As DAO.Database
    Dim rs As DAO.Recordset
  
    Set db = CurrentDb
  
    'Filterプロパティにインデックスを設定したフィールドの条件を書いた
    Set rs = db.OpenRecordset("テーブル1")
    rs.Filter = "フィールド1 = '884EBDD8-0516-480D-9C13-6F2EF60B2202'"
    Set rs = rs.OpenRecordset
    
    Do Until rs.EOF
        Debug.Print ("Test3 " & rs!ID)
        rs.MoveNext
    Loop
  
End Sub

Public Sub Test4()
  
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
  
    Set db = CurrentDb
  
    'Filterプロパティにインデックスの設定していないフィールドの条件を書いた
    Set rs = db.OpenRecordset("SELECT * FROM テーブル1 WHERE フィールド2 = '7BFD061C-711E-404F-89D3-0973CADFF5F6'")
    
    Set rs = db.OpenRecordset("テーブル1")
    rs.Filter = "フィールド2 = '7BFD061C-711E-404F-89D3-0973CADFF5F6'"
    Set rs = rs.OpenRecordset
    Do Until rs.EOF
        Debug.Print ("Test4 " & rs!ID)
        rs.MoveNext
    Loop
      
End Sub

リンクテーブルを張ってテスト

結果
Test1 送受信量 226KB
Test2 送受信量 153MB
Test3 送受信量 157MB
Test4 送受信量 157MB

まとめ
適切なインデックス設定を行う事とRecordsetのFilterは使わないと心に誓った

2014年3月12日水曜日

忘れていた

ブログが三日坊主になっていたので更新
モジュラス103もそのうち更新するよてえい

電子タバコおいしいれす(^q^)

C#で9DSRの計算

/// 
/// 9DSR 計算
/// NW-7
/// 
/// /// 
public static string Get9DSR(string Value)
{
    bool result = Regex.IsMatch(Value, @"^[0-9]+$");
    if (!result)
    {
        return null;
    }
    return (ulong.Parse(Value) % 9 == 0 ? 0 : 9 - (int.Parse(Value) % 9)).ToString();
}

C#でルーンズ(モジュラス10/ウェイト2)の計算

/// 
/// ルーンズ(モジュラス10/ウェイト2 計算
/// NW-7
/// 
/// /// 
public static string GetModulus10Weight2Runes(string Value)
{
    bool result = Regex.IsMatch(Value, @"^[0-9]+$");
    if (!result)
    {
        return null;
    }

    long checkDigit = 0;

    for (int i = 0; i < Value.Length; i++)
    {
        if (i % 2 == 0)
        {
            int x = int.Parse(Value.Substring(Value.Length - 1 - i, 1)) * 2;
            //10以上の場合、桁ごとに加算
            if (10 <= x) x = 1 + (x % 10);

            checkDigit += x;
        }
        else
        {
            checkDigit += int.Parse(Value.Substring(Value.Length - 1 - i, 1));
        }
    }

    checkDigit = 10 - (checkDigit % 10);

    checkDigit = checkDigit == 10 ? 0 : checkDigit;

    return checkDigit.ToString();
}

C#で加重モジュラス11の計算

/// 
/// 加重モジュラス11 計算
/// NW-7
/// 
/// /// 
public static string GetWeightedModulus11(string Value)
{
    bool result = Regex.IsMatch(Value, @"^[0-9]+$");
    if (!result || Value.Length > 12)
    {
        return null;
    }

    int[] weight1 = { 2, 6, 3, 5, 4, 8, 7, 10, 9, 5, 3, 6, };
    int[] weight2 = { 9, 5, 8, 6, 7, 3, 4, 10, 2, 6, 8, 5, };

    try
    {
        int checkDigit = 0;
        for (int i = 0; i < 2; i++)
        {
            checkDigit = 0;
            for (int j = 0; j < Value.Length; j++)
            {
                checkDigit += int.Parse(Value.Substring(Value.Length - 1 - j, 1)) * (i == 0 ? weight1[j] : weight2[j]);
            }
            checkDigit = checkDigit % 11;

            if (checkDigit == 0) return "0";
            if (checkDigit != 1) break;
        }

        return (11 - checkDigit).ToString();
    }
    catch
    { }
    return null;
}

C#でモジュラス10/ウェイト2の計算

/// 
/// モジュラス10/ウェイト2 計算
/// NW-7
/// 
/// /// 
public static string GetModulus10Weight2(string Value)
{
    bool result = Regex.IsMatch(Value, @"^[0-9]+$");
    if (!result)
    {
        return null;
    }

    int checkDigit = 0;

    for (int i = 0; i < Value.Length; i++)
    {
        checkDigit += int.Parse(Value.Substring(Value.Length - 1 - i, 1)) * (i % 2 == 0 ? 2 : 1);
    }

    checkDigit = 10 - (checkDigit % 10);

    checkDigit = checkDigit == 10 ? 0 : checkDigit;

    return checkDigit.ToString();
}

C#でモジュラス11の計算

/// 
/// モジュラス11 計算
/// NW-7
/// 
/// /// 
public static string GetModulus11(string Value)
{
    bool result = Regex.IsMatch(Value, @"^[0-9]+$");
    if (!result || 6 > Value.Length)
    {
        return null;
    }

    string val = Value.Substring(0, 6);

    int checkDigit = 0;
    for (int i = 0; i < val.Length; i++)
    {
        checkDigit += int.Parse(val.Substring(i, 1)) * (7 - i);
    }
    checkDigit = checkDigit % 11;

    if (checkDigit == 0)
    {
        return "1";
    }
    else if (checkDigit == 1)
    {
        return "0";
    }
    else
    {
        return (11 - checkDigit).ToString();
    }
}

C#で9DRの計算

/// 
/// 9DR 計算
/// NW-7
/// 
/// /// 
public static string Get9DR(string Value)
{
    bool result = Regex.IsMatch(Value, @"^[0-9]+$");
    if (!result)
    {
        return null;
    }

    return (ulong.Parse(Value) % 9).ToString();
}

C#で7DSRの計算

/// 
/// 7DSR 計算
/// NW-7
/// 
/// /// 
public static string Get7DSR(string Value)
{
    bool result = Regex.IsMatch(Value, @"^[0-9]+$");
    if (!result)
    {
        return null;
    }

    string value =(ulong.Parse(Value) % 7 == 0 ? 0 : 7 - (ulong.Parse(Value) % 7)).ToString();

    return value;
}

C#でモジュラス16の計算

/// 
/// モジュラス16 計算
/// NW-7
/// 
/// /// 
public static string GetModulus16(string Value)
{
    bool result = Regex.IsMatch(Value, @"^[0-9|\-|$|:|/|・|+|A-D]+$");
    if (!result)
    {
        return null;
    }

    long digit = 0;
    for (int i = 0; i < Value.Length; i++)
    {
        digit += Array.IndexOf(modulus16CharList, Value[i]);
    }

    string value = modulus16CharList[(digit % 16) == 0 ? 0 : 16 - (digit % 16)].ToString();

    return value;
}

C#で7DRの計算

/// 
/// 7DR 計算
/// NW-7
/// 
/// /// 
public static string Get7DR(string Value)
{
    bool result = Regex.IsMatch(Value, @"^[0-9]+$");
    if (!result)
    {
        return null;
    }

    string value = (ulong.Parse(Value) % 7).ToString();

    return value;
}