从ES数据库中随机抽样10%的数据

本文介绍如何在Elasticsearch中实现数据的随机抽样,包括适用于小数据量的简单方法及处理大数据量时采用的Scroll API技术。

如果数据量比较小,从 Elasticsearch 数据库中随机抽取 10% 的数据,可以使用以下步骤来实现:

  1. 使用 Elasticsearch 的 Search API 搜索数据库中的数据。
  2. 使用 QueryBuilder 构建查询语句,并指定要查询的索引和类型。
  3. 在查询中添加一个随机排序的子句,例如:
queryBuilder.addSort(new FieldSortBuilder("_doc").order(SortOrder.ASC).sortMode(SortMode.RANDOM));

  1. 使用 SearchResponse 执行查询,并使用 SearchHits 获取查询结果。
  2. 使用 SearchHits 的 getTotalHits 方法计算总共有多少文档符合查询条件。
  3. 计算出 10% 的数量,并使用 SearchHits 的 getHits 方法获取查询结果,只取前 10% 个文档即可。
    以下是一个示例方法,该方法可以实现上述步骤:
public List<Map<String, Object>> sampleData(String index, String type, int sampleSize) {
    // 1. 使用 Elasticsearch 的 Search API 搜索数据库中的数据
    SearchRequest searchRequest = new SearchRequest(index);
    searchRequest.types(type);

    // 2. 使用 QueryBuilder 构建查询语句,并指定要查询的索引和类型
    QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();

    // 3. 在查询中添加一个随机排序的子句
    queryBuilder.addSort(new FieldSortBuilder("_doc").order(SortOrder.ASC).sortMode(SortMode.RANDOM));

    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(queryBuilder);
    searchRequest.source(searchSourceBuilder);

    // 4. 使用 SearchResponse获取前10%的数据
    //todo

如何处理大量数据的情况

如果要处理的数据量很大,可能会对 Elasticsearch 的性能造成压力。 为了解决这个问题,可以使用 Elasticsearch 的 Scroll API。

Scroll API 可以用来执行批量查询,它会在内部使用滚动查询,允许在一个查询中搜索大量的数据,并将结果分批返回。这样,您就可以在单个查询中处理大量的数据,而不会对 Elasticsearch 造成太大的压力。

下面是一个示例方法,该方法使用 Scroll API 来实现随机抽样:

public List<Map<String, Object>> sampleDataWithScroll(String index, String type, int sampleSize) {
    List<Map<String, Object>> result = new ArrayList<>();

    // 1. 使用 Elasticsearch 的 Search API 搜索数据库中的数据
    SearchRequest searchRequest = new SearchRequest(index);
    searchRequest.types(type);

    // 2. 使用 QueryBuilder 构建查询语句,并指定要查询的索引和类型
    QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();

    // 3. 在查询中添加一个随机排序的子句
    queryBuilder.addSort(new FieldSortBuilder("_doc").order(SortOrder.ASC).sortMode(SortMode.RANDOM));

    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(queryBuilder);
    searchRequest.source(searchSourceBuilder);

    // 4. 使用 SearchResponse 执行查询
    SearchResponse searchResponse = client.search(searchRequest);

    // 5. 使用 SearchHits 获取查询结果
    SearchHits hits = searchResponse.getHits();

    // 6. 使用 SearchHits 的 getTotalHits 方法计算总共有多少文档符合查询条件
    long totalHits = hits.getTotalHits();

    // 7. 计算出 10% 的数量
    int sampleCount = (int) (totalHits * sampleSize);

    // 8. 设置滚动参数
    String scrollId = searchResponse.getScrollId();
    searchRequest.scroll(TimeValue.timeValueMinutes(1));

    while (result.size() < sampleCount) {
	    searchResponse = client.searchScroll(new SearchScrollRequest(scrollId).scroll(TimeValue.timeValueMinutes(1)));
	    hits = searchResponse.getHits();
	
	    // 9. 使用 SearchHits 的 getHits 方法获取查询结果,只取前 10% 个文档
	    for (int i = 0; i < hits.getHits().length && result.size() < sampleCount; i++) {
	        result.add(hits.getAt(i).getSourceAsMap());
	    }
	
	    // 10. 更新滚动 ID
	    scrollId = searchResponse.getScrollId();
	}

}
<think>我们当前的目标是:在通过`./ksql -p 54321 -U kkingbase -d test`进入的test数据库中查找已插入的三百多个数据,确认插入表名以及操作权限。 根据用户上一次的问题,他已经在数据库中插入了三百多个数据,但不知道数据在哪里,需要查找。 步骤: 1. 确认当前数据库连接和用户权限。 2. 查找当前用户有权限访问的表。 3. 在这些表中查找包含三百多条数据的表(因为用户插入了三百多条,所以这个表应该至少有三百多条记录)。 4. 进一步确认数据是否在找到的表中。 具体操作: 第一步:确认当前用户和权限 我们可以使用以下SQL查询当前用户: ```sql SELECT current_user; ``` 以及查看当前用户的权限,可以查询information_schema.table_privileges视图,但更直接的方式是查看pg_tables(KingbaseES兼容PostgreSQL的系统视图)来查看当前用户有权限看到的表。 第二步:列出当前数据库中的所有表(排除系统表)以及记录数 我们可以编写一个查询来列出所有非系统模式下的表及其行数(注意:如果表很大,count(*)可能较慢,但三百多条数据是小表,很快)。 但是,需要注意的是,直接count(*)所有表可能比较慢,而且如果表非常多,可能不合适。我们可以先列出表,然后根据用户记忆(比如表名)或者通过查看最近修改的表来缩小范围。 另一种思路:用户刚刚插入,那么可以通过查询系统视图pg_stat_user_tables来查看最近修改的表(n_tup_ins表示插入的行数)或通过xmin等系统列来查看,但KingbaseES中,用户表默认没有记录插入时间,除非用户自己创建了时间戳字段。 因此,我们分两步: 1. 列出当前用户有权限访问的所有表(在public模式或其他自定义模式中)。 2. 统计每个表的数据量,然后找到包含三百多条数据的表。 但是,由于用户可能插入了多个表,我们还需要结合表名是否有印象。我们可以先查询表名,然后让用户回忆。 我们可以这样查询: ```sql -- 查看当前用户有权限的所有表(非系统表) SELECT schemaname, tablename FROM pg_catalog.pg_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema'); -- 或者更详细的权限查询(使用information_schema) SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema') AND table_type = 'BASE TABLE'; ``` 然后,对于每个表,我们可以快速查询行数(注意:使用count(*)可能慢,我们可以使用估算值,但三百多条数据估算可能不准确,所以直接count(*)也可以接受,因为表不会太大)。 但是,为了避免对每个表都执行count(*),我们可以先根据表名猜测,或者使用以下方法获取每个表的精确行数(如果表不多,可以接受): ```sql SELECT schemaname, relname, n_live_tup FROM pg_stat_user_tables; ``` 这个视图中的n_live_tup是估算值,但比较快。不过,如果是刚插入的,可能统计信息还没更新,所以可能不准确。 另一种方法是使用以下查询(精确但较慢): ```sql SELECT table_schema, table_name, (xpath('/row/c/text()', query_to_xml(format('select count(*) as c from %I.%I', table_schema, table_name), false, true, '')))[1]::text::int AS rows FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema') AND table_type = 'BASE TABLE'; ``` 但这种方法复杂且慢。 我们可以折中:先通过pg_stat_user_tables视图查看行数,然后对行数在300左右的表进行精确count。 第三步:确认权限 我们可以检查当前用户对某个表的权限,例如: ```sql SELECT table_catalog, table_schema, table_name, privilege_type FROM information_schema.table_privileges WHERE grantee = CURRENT_USER; ``` 但是,用户可能只需要知道能否访问该表即可,如果能查询到数据,说明有权限。 综合以上,我们建议如下步骤: 1. 查询当前用户有权限的所有表,并查看每个表的行数(通过pg_stat_user_tables的估算值),然后找出行数在300以上的表(因为插入三百多条,可能不止300)。 2. 如果估算值不准确,再对候选表进行精确count。 3. 如果找到了多个候选表,可能需要用户回忆表名,或者查看表结构(\d 表名)来确认。 由于用户是在ksql命令行下,我们可以直接使用ksql的元命令: 例如: - \d 列出所有表(显示表、视图、序列等) - \dt 只列出表 在ksql中,我们可以使用: ``` test=# \dt ``` 这会列出所有表(在search_path中且用户有权限的)。 然后,我们可以查看某个表的行数: ```sql SELECT count(*) FROM 表名; ``` 但是,用户插入的三百多条数据,可能在一个表中,也可能分散在多个表。所以需要用户回忆表名。 如果用户不记得表名,那么我们可以通过以下步骤: 1. 查找最近被修改的表(插入操作会修改表),可以通过pg_stat_user_tables中的last_autovacuum, last_autoanalyze, last_insert等时间?但是KingbaseES的pg_stat_user_tables视图没有last_insert时间,但有n_tup_ins(插入行数)和seq_scan等。 2. 按照n_tup_ins倒序排序,找到最近插入最多的表。 因此,我们可以这样查询: ```sql SELECT relname, n_tup_ins FROM pg_stat_user_tables ORDER BY n_tup_ins DESC LIMIT 10; ``` 然后查看这些表,特别是n_tup_ins在300以上的表。 注意:n_tup_ins是累计插入的行数,所以可能是之前就有数据。 所以,我们需要结合当前总行数(n_live_tup)来看。 查询: ```sql SELECT relname, n_live_tup, n_tup_ins FROM pg_stat_user_tables ORDER BY n_tup_ins DESC LIMIT 10; ``` 然后,用n_live_tup在300以上的表,再精确count。 如果这样还找不到,我们可以考虑全库搜索(比较慢),比如查找包含某个特征字段的表(如果用户记得某个字段名或数据类型)。 根据用户的问题,我们重点在于找到表,然后确认权限。 关于权限,如果用户能执行select * from 表名 limit 10; 那么说明有查询权限。 所以,我们总结操作步骤: 1. 查询当前用户有权限的表,并查看这些表的统计信息(行数和插入行数),找出可能的目标表。 2. 逐一检查这些表的数据。 3. 如果找不到,考虑用户是否插入到了错误的数据库或者模式(schema)中。 具体命令: 步骤1:连接数据库 ``` ./ksql -p 54321 -U kkingbase -d test ``` 步骤2:在ksql中执行: ```sql -- 查看当前用户 SELECT current_user; -- 查看当前用户有权限的表及其统计信息 SELECT relname AS table_name, n_live_tup AS estimated_rows, n_tup_ins AS inserted_rows_since_stat_reset FROM pg_stat_user_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema') ORDER BY n_tup_ins DESC; ``` 步骤3:查看每个候选表的前10数据,例如: ```sql SELECT * FROM 表名 LIMIT 10; ``` 步骤4:如果找到了数据,然后用count(*)确认行数。 步骤5:如果没找到,可能是统计信息未更新,我们可以尝试更新统计信息: ```sql ANALYZE; ``` 然后重新执行步骤2。 或者,用户可能没有插入到这个数据库?确认连接的是正确的数据库。 另外,用户可能插入了数据但回滚了?或者没有commit?用户是否执行了commit? 在ksql中,默认是自动提交吗?KingbaseES的ksql默认是自动提交(autocommit on)吗?需要确认。 如果是显式开启事务(BEGIN)而没有提交,那么数据不会被其他会话看到(包括当前会话在事务中未提交时也只能在当前事务中看到,但如果当前事务结束了就看不到了)。所以用户需要确认是否提交了事务。 但我们假设用户已经提交。 关于权限:如果用户是表的创建者,那么肯定有所有权限。 我们可以查询表的所有者: ```sql SELECT schemaname, tablename, tableowner FROM pg_catalog.pg_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema'); ``` 如果当前用户是表的所有者,那么肯定有权限。 如果在执行SELECT时收到权限错误,则需要向表的所有者或管理员申请权限。 因此,完整步骤: 1. 查询当前用户:`SELECT current_user;` 2. 查询非系统表及其所有者和统计信息: ```sql SELECT t.relname AS table_name, t.n_live_tup AS estimated_rows, t.n_tup_ins AS inserted_rows, p.tableowner FROM pg_stat_user_tables t JOIN pg_catalog.pg_tables p ON t.schemaname=p.schemaname AND t.relname=p.tablename WHERE t.schemaname NOT IN ('pg_catalog', 'information_schema'); ``` 3. 对于估计行数在300附近(比如大于300)的表,执行精确查询: ```sql SELECT count(*) FROM 表名; ``` 4. 如果找到目标表,查询数据: ```sql SELECT * FROM 表名 LIMIT 300; -- 或者更多,但注意不要输出太多 ``` 5. 如果遇到权限问题,检查当前用户是否是表的所有者(tableowner)或者已经被授权: ```sql -- 查看当前用户对某个表的权限 SELECT * FROM information_schema.table_privileges WHERE table_name = '表名' AND grantee = CURRENT_USER; ``` 注意:以上操作都是在同一个ksql会话中执行。 如果用户无法执行上述某些查询(比如权限不足),那么可能需要联系管理员。 考虑到用户可能不是管理员,我们尽量使用用户有权限访问的视图。 另外,KingbaseES可能有自己的系统视图,但一般情况下与PostgreSQL兼容。 由于用户之前已经连接到了test数据库,并且以kkingbase用户登录,所以我们可以按上述步骤操作。 现在,我们按照用户要求给出在ksql中的操作步骤。 注意:在ksql中,我们可以使用元命令,也可以使用SQL。 我们给出两种方式,但这里以SQL为主。 操作步骤: 1. 连接数据库: ```bash ./ksql -p 54321 -U kkingbase -d test ``` 2. 在ksql提示符(test=#)下,执行以下SQL: ```sql -- 确认当前用户 SELECT current_user; -- 列出所有非系统表,包括表的所有者和估计行数 SELECT pg_stat_user_tables.relname AS table_name, pg_stat_user_tables.n_live_tup AS estimated_row_count, pg_tables.tableowner FROM pg_stat_user_tables JOIN pg_tables ON pg_stat_user_tables.schemaname = pg_tables.schemaname AND pg_stat_user_tables.relname = pg_tables.tablename WHERE pg_stat_user_tables.schemaname NOT IN ('pg_catalog', 'information_schema') ORDER BY estimated_row_count DESC; ``` 3. 观察输出结果,寻找估计行数在300条以上的表。假设我们发现一个表名为"my_data",估计行数为350,所有者为kkingbase。 4. 检查该表的数据: ```sql -- 精确统计行数(如果表很大,可能需要等待) SELECT count(*) FROM my_data; -- 查看前10数据 SELECT * FROM my_data LIMIT 10; ``` 5. 如果确认是目标表,查看全部数据(注意:如果数据量太大,不要使用SELECT *): ```sql -- 分页查看 SELECT * FROM my_data LIMIT 300 OFFSET 0; ``` 6. 如果遇到权限问题,比如执行SELECT时提示权限被拒绝,则检查权限: ```sql -- 检查当前用户对表my_data的权限 SELECT privilege_type FROM information_schema.table_privileges WHERE table_name = 'my_data' AND grantee = CURRENT_USER; ``` 如果返回结果中没有SELECT,则需要授权: ```sql -- 以表所有者的身份或者管理员执行授权 GRANT SELECT ON my_data TO kkingbase; ``` 但注意,当前用户如果是表的所有者(在tableowner列中显示为当前用户),则默认拥有所有权限。 7. 如果找不到合适的表,考虑是否插入到了其他模式(schema)中?可以切换模式: ```sql SET search_path TO 模式名; ``` 然后重新执行步骤2。 8. 另外,用户可能插入到了其他数据库?请确认连接的是正确的数据库(test)。 如果以上步骤仍然找不到,可能是数据插入失败(比如事务回滚)或者插入到了其他数据库。 最后,我们生成几个相关问题: §§相关问题§§ 1. 如何查看KingbaseES中当前用户的权限? 2. 如何更新KingbaseES的统计信息以提高查询效率? 3. 在KingbaseES中,如何查看表的创建时间和最后修改时间? 4. 如何授权用户对表的SELECT权限? 注意:在回答中,我们引用了KingbaseES的系统视图,如pg_stat_user_tables、pg_tables等,这些在KingbaseES中与PostgreSQL类似。 </think>### 在KingbaseES中查找插入数据和确认权限的完整指南 #### 一、确认当前用户权限 首先验证当前用户的数据库操作权限: ```sql -- 查看当前用户权限 SELECT * FROM information_schema.role_table_grants WHERE grantee = CURRENT_USER; ``` 这将列出`kkingbase`用户对所有表的`SELECT`、`INSERT`、`UPDATE`等权限[^3]。 #### 二、查找可能的数据表 通过系统表定位包含300+记录的用户表: ```sql -- 查找非系统表且包含300+记录的表 SELECT schemaname, relname AS tablename, n_live_tup AS row_count FROM pg_stat_user_tables WHERE schemaname NOT IN ('pg_catalog', 'sys', 'information_schema') AND n_live_tup BETWEEN 300 AND 400 -- 300+数据范围 ORDER BY n_live_tup DESC; ``` 关键字段说明: - `n_live_tup`:统计信息中表的活元组数量 - `schemaname`:表所在的模式名(默认public) #### 三、精确验证数据内容 发现候选表后进一步验证: ```sql -- 1. 查看表结构确认是否为插入目标 \d 表名 -- 2. 抽样检查数据(避免全表扫描) SELECT * FROM 表名 TABLESAMPLE BERNOULLI(1) -- 1%随机抽样 WHERE ctid IN ( SELECT ctid FROM 表名 ORDER BY random() LIMIT 20 ); -- 3. 精确统计行数 SELECT count(*) FROM 表名; ``` #### 四、特殊场景排查 若未找到目标表: 1. **事务未提交检查** ```sql SELECT * FROM pg_prepared_xacts; -- 查看未提交事务 ``` 2. **跨模式搜索** ```sql -- 搜索所有模式中300+记录的表 SELECT schemaname, relname, n_live_tup FROM pg_stat_all_tables WHERE n_live_tup > 300; ``` 3. **对象权限验证** ```sql -- 检查表的访问权限 SELECT has_table_privilege('表名', 'SELECT'); ``` #### 五、连接与权限问题处理 ```mermaid graph TD A[连接问题] --> B[检查服务状态] A --> C[验证连接参数] B --> D[netstat -an | grep 54321] C --> E[ksql -p 54321 -U kkingbase -d test] F[权限不足] --> G[申请授权] G --> H[GRANT SELECT ON 表名 TO kkingbase] ``` #### 六、操作示例流程 ```bash # 连接数据库 ./ksql -p 54321 -U kkingbase -d test # 在ksql中执行: test=# SELECT schemaname, relname, n_live_tup FROM pg_stat_user_tables WHERE n_live_tup > 300; schemaname | relname | n_live_tup ------------+----------+------------ public | sales | 325 (1 row) test=# SELECT * FROM sales LIMIT 5; -- 展示前5行数据... ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值