如何在 Tarantool 中执行客户端全面扫描?

How to perform a client-side full scan in Tarantool?

我需要在我的应用程序中持续遍历整个 space。 目前我正在使用批处理(例如经典的限制偏移方法),但是 它不能在一个事务中完成并且会不一致(例如,从已读取元组的子集中删除将导致丢失元组,因为偏移量已更改)。

此外,手动批处理不是那么人性化,我想要这样的东西:

    rows, err := conn.Query(ctx, "SELECT id, title, tags FROM video")
    if err != nil {
        panic(err)
    }
    var videos []Video
    for rows.Next() {
        var v Video
        if err := rows.Scan(&v.ID, &v.Title, &v.Tags); err != nil {
            panic(err)
        }
        videos = append(videos, v)
    }

这就是我如何在 go 和 postgresql 中执行 SELECT 整个 table,这将在内部缓冲并且仍然一致。

有没有办法在 Tarantool 中实现这一点?

可能回答可能与您的主题不完全相关,但我尝试描述没有SQL应该怎么做。

首先,Tarantool 不支持交互式事务 (https://github.com/tarantool/tarantool/issues/2016) 和服务器端游标。 您不能执行多个选择并确保它们之间的所有数据都没有被修改。

所以,如果您对这些限制感到满意,我们就继续吧。这是一个小例子。这里我使用官方的 Tarantool go connector (https://github.com/tarantool/go-tarantool)


    spaceName := "tester"
    indexName := "scanner"
    idFn := conn.Schema.Spaces[spaceName].Fields["id"].Id // field number of Id
    bandNameFn := conn.Schema.Spaces[spaceName].Fields["band_name"].Id

    var tuplesPerRequest uint32
    cursor := []interface{}{}
    tuplesPerRequest = 10


    for {
        resp, err := conn.Select(spaceName, indexName, 0, tuplesPerRequest, tarantool.IterGt, cursor)
        if err != nil {
            panic(err)
        }

        if resp.Code != tarantool.OkCode {
            panic(err)
        }
     
        if len(resp.Data) == 0 {
            break // No more data
        }

        tuples := resp.Tuples()
        for _, tuple := range tuples {
            fmt.Printf("\t%v\n", tuple)
        }
        
        lastTuple := tuples[len(tuples) - 1]
        cursor = []interface{}{lastTuple[idFn], lastTuple[bandNameFn]}
    }

我应该注意一些事情。我不使用偏移量。切勿在 Tarantool 中使用偏移量!我使用“游标”。它是一组您已编制索引的字段加上一个迭代器(在我的示例中为 Gt)。简而言之,“偏移量”导致对 B-Tree 索引进行全面扫描,而建议的方法指定了一个扫描点 started/continued.

您可以为 lua 存储过程使用“调用”,而不是使用 Select 函数。例如。您想直接在 database/application 服务器级别过滤元组。