phoenix 5.0 CURSOR 游标(二) 不得不说的坑

这个坑很深沉,官方文档太简短了。

这个坑是由:select语句引起的。

也就是声明游标时的查询语句,如下:

 

phoenix 5.0 CURSOR 游标(二) 不得不说的坑_第1张图片

 

拉开序幕:

这是一张很简单的表test,id是row key,一共15条数据。

phoenix 5.0 CURSOR 游标(二) 不得不说的坑_第2张图片

 

接着,我们使用游标遍历这个表数据。

public static void main(String[] args) throws SQLException {
        long start = System.currentTimeMillis();
        // 获得连接资源
        Connection con = PhoenixUtils.getConnection();
        ResultSet rset = null;
        // 游标语句
        PreparedStatement statement = con.prepareStatement("DECLARE empCursor CURSOR FOR select * from test");
        statement.execute();
        // 开启游标
        statement = con.prepareStatement("OPEN empCursor");
        statement.execute();

        int countTotal=0;

        // 一次拿2条
        statement = con.prepareStatement("FETCH NEXT 2 ROWS FROM empCursor");
        rset = statement.executeQuery();
        while (rset.next()){
            countTotal++;
            System.out.println(rset.getString("id"));
        }

        System.out.println("countTotal="+countTotal);
        // 关闭游标
        statement = con.prepareStatement("CLOSE empCursor");
        statement.execute();
        // 释放资源
        PhoenixUtils.colseResource(con,statement,rset);
        long end = System.currentTimeMillis();
        System.out.println("耗时:" + (end - start) +" ms");
    }

执行结果:

phoenix 5.0 CURSOR 游标(二) 不得不说的坑_第3张图片

拿2条数据,没错只拿到了两条数据!这个逻辑很正常。

 

重点来了,我改了一下声明游标的sql。

DECLARE empCursor CURSOR FOR select * from test

改为:

DECLARE empCursor CURSOR FOR select id from test

只是把查询内容由*号,改为了id,我们继续执行一次,来看看结果。

执行结果:

phoenix 5.0 CURSOR 游标(二) 不得不说的坑_第4张图片

What???

说好了只拿2条,怎么拿到了16条?

什么什么test表一共就15条数据,怎么会有16条??这是假的吧。冷静、冷静。

 

查下test表的索引有哪些

!indexes test

果然有个二级索引表,接着查下二级索引表内容。

phoenix 5.0 CURSOR 游标(二) 不得不说的坑_第5张图片

果然有16条数据,执行以下计划看看。

phoenix 5.0 CURSOR 游标(二) 不得不说的坑_第6张图片

select id from test; 直接走的二级索引表。

这下大概明白问题所在了,原来test是不可变表。出现索引表与原始表,数据不一致,也就正常了。

为了证实我的想法,再修改sql测试下改为:

select age from test; -- age字段不会走二级索引表

执行结果:

phoenix 5.0 CURSOR 游标(二) 不得不说的坑_第7张图片

 

结论:

申明游标的语句

1、数据如果来自索引表那么会一次性都给到结果集。即使你指定了取的行数。

2、SQL不走索引表,数据来自原表。则会按照你指定的行数,返回结果集。如果你需要遍历全部数据,去统计结果。那么需要在外部增加循环。类似递归。

https://mp.csdn.net/postedit/84875099 不走二级索引表可以参考这个循环。

注意:声明游标的SQL走,二级索引 和 不走二级索引的差别!!!!

(如果是不可变表,那么遍历数据一定不能取索引表,否则统计结果是不正确的。)

 

当然,走表自身的row key是没有问题的。我们还可以使用hint /*+NO_INDEX*/ 来处理,数据遍历二级索引表的情况。

注意:一定要用explain查看sql

 

END,闭幕--

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Phoenix)