使用 gob 序列化到磁盘后检索

我一直在学习数据库,并希望出于学习目的而非生产目的实施一个数据库。我有一个定义的模式:


type Row struct {

    ID       int32

    Username string

    Email    string

}

现在,目前,我能够以仅附加的方式将这种类型的结构编码到文件中。


//Just to show i use a file for the encoding, it has missing details.


func NewEncoder(db *DB) *gob.Encoder{

    return gob.NewEncoder(db.File)

}


func SerializeRow(r Row, encoder *gob.Encoder, db *DB) {

    err := encoder.Encode(r)

    if err != nil {

        log.Println("encode error:", err)

    }

}

现在,通过简单地解码整个文件来模仿“选择”语句相对容易gob.decode


func DeserializeRow(decoder *gob.Decoder, db *DB){

    var rows Row

    db.File.Seek(0, 0)

    err := decoder.Decode(&rows)

    for err == nil {

        if err != nil {

            log.Println("decode error:", err)

        }

        fmt.Printf("%d %s %s\n", rows.ID, rows.Username, rows.Email)

        err = decoder.Decode(&rows)

    }

}

我当前的问题是,我希望能够根据 ID 检索特定行。我知道sqlite使用 4kb 分页,在某种意义上,序列化的行占据一个“页面”,即。4KB 直到一个页面不能再容纳它们,然后创建另一个。我如何gob以最简单和惯用的方式模仿这种行为?


POPMUISE
浏览 89回答 1
1回答

阿晨1998

一个 Gob 流可能包含类型定义和解码指令,所以你不能寻找一个 Gob 流。您只能从头开始阅读,直到找到所需内容为止。Gob 流完全不适合需要跳过元素的数据库存储格式。您可以创建一个新的编码器并分别序列化每个记录,在这种情况下您可以跳过元素(通过维护一个文件索引来存储哪个记录从哪个位置开始),但这将是非常低效和冗余的(如链接答案中所述,当您写入更多相同类型的值时,速度和存储成本会摊销,并且总是创建新的编码器会失去这种收益)。更好的方法是不encoding/gob为此使用,而是定义自己的格式。为了有效地支持搜索(select),您必须在可搜索的列/字段上构建某种索引,否则您仍然需要执行全表扫描。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go