0

私が取り組んでいるデータ アプリの基本的な ORM を設計しようとしています。私が思いついたモデルについての質問は 2 つあります。

  • これは、データベース追跡の「最適」で最も「効率的な」モデルですか?
  • これは慣用的な囲碁ですか?

アイデアは、アプリの開始時にデータベースの完全なモデルをメモリにロードすることです。このモデルを使用して、各オブジェクト (データベース内の行に対応) の crc32 ハッシュでマップを生成します。これは、モデルと比較して、.save() が呼び出されたときに変更が加えられた場所を特定するために使用するものです。

次の最初の部分はcrc32マップを生成し、2番目の部分はランダムな変更を導入し、最後の部分はdbの変更をディスクに書き込む.save()の一部になります

コード:

func main() {
    // Read data off of disk into memory
    memDB := ddb

    // Create hash map of memDB
    peopleMap := make(map[int]uint32)
    for _, v := range memDB.people {
        // make row into byte array, looks kludgy
        hash := []byte(fmt.Sprintf("%#v", v))
        peopleMap[v.pID] = crc32.ChecksumIEEE(hash)
        fmt.Printf("%v: %v %v \t(%v %v) - crc sum: %v\n",
            v.pID, v.fName, v.lName, v.job, v.location,
            peopleMap[v.pID])
    }
    fmt.Println("\n# of people in memory:", len(memDB.people))

    // Sometime later, we need to delete Danielle, so
    // Delete in memory:
    var tmpSlice []ddPerson
    for _, v := range memDB.people {
        if v.fName == "Danielle" {
            continue
        }
        tmpSlice = append(tmpSlice, v)
    }
    memDB.people = tmpSlice
    fmt.Println("# of people in memory:", len(memDB.people))

    // Okay, we save in-memory representation mem.DB back
    // to disk with some kind of .save() assertion
    // a len(peopleMap) comparison to len(memDB.people) will
    // tell us there has been a change for INSERTS and
    // DELETES, but it won't tell us about updates or which
    // record was inserted or deleted

    // First, check for additions
    if len(peopleMap) < len(memDB.people) {
        // Code to find and add person to disk db ddb here
        fmt.Println("Adding someone to disk database...")
    } else if len(peopleMap) > len(memDB.people) {
        // Check for deletions
        fmt.Println("Purging someone from disk database...")
    }

    // in any case, recheck hashes
    tMap := make(map[int]uint32)
    for _, v := range memDB.people {
        hash := []byte(fmt.Sprintf("%#v", v))
        t := crc32.ChecksumIEEE(hash)
        // Add to temporary map
        tMap[v.pID] = t
        // And check for changes
        if t != peopleMap[v.pID] {
            fmt.Println("Change detected in in-memory model...")
            fmt.Println("Writing changes to disk db now")
            // Writing any changes to DB here
            ddb.people = memDB.people
        }
    }

    // 'Fix' our hashmap checker deal
    peopleMap = tMap

    // Carry on
}

動作中のバージョンがあります: http://play.golang.org/p/XMTmynNy7t

4

2 に答える 2

1

ORMと実際には同じではない、データベースのメモリ内キャッシュを実装しました。

あなたが持っているものにはいくつかの問題があります:

  • 他のプロセス/アプリケーションがデータベースを変更した場合、メモリ内モデルは古くなります。これにより、キャッシュが古くなっていることを知らなかったため、書き込みによってデータベースへの書き込みが上書きされる可能性があります。
  • データベースが大きくなると、アプリケーションもそれに応じて大きくなります。

ほとんどの ORM は、型 (構造体など) を db の読み取りと書き込みにマップする方法を提供します。これにより、データベースから単一のオブジェクトを読み取り、それを変更してから、そのオブジェクトをデータベースに書き戻すことができます。これはおそらくこれに対するより良いアプローチです。

あなたのgoがどれほど慣用的であるかについては、明らかに非慣用的なgoは見られませんでしたが、あまり進んでいません。一番上memDb := ddbに関数呼び出しがありますが、その後に括弧がありません。これは構文エラーです。

于 2012-08-04T01:14:02.343 に答える
0

データをロードするときにチェックサムを生成し、保存するときに再度生成することは、私にはかなり非効率的です。

データベース バックエンドを使用するほとんどの Web アプリケーションは、データベースに直接変更を加えます。しかし、ユーザーが自分の変更を元に戻すことができるように、別の「保存」操作が必要なようです…?

トランザクションの使用を検討しましたか? ユーザーがデータの編集を開始したときに、BEGIN TRANSACTION コマンドを発行できます。次に、彼が「保存」を押すと、COMMIT コマンドを発行して、変更をデータベースに永続的に保存します。ユーザーが変更を取り消したり、保存せずに終了した場合は、代わりに ROLLBACK コマンドを発行します。

ここでの問題は、Go の慣用的な使用ではなく、SQL の慣用的な使用に関するものです。

于 2012-08-05T02:08:01.167 に答える