Json 类型与多值索引 — OceanBase 4.3.2 AP 功能体验

本文来自 2024年OceanBase技术征文大赛——“让技术被看见 | OceanBase 布道师计划”的用户征文。也欢迎更多的技术爱好者参与征文,赢取万元大奖。和我们一起,用文字让代码跳动起来!   参与2024年OceanBase技术征文大赛>>

MySQL在5.7.8版本中引入了JSON数据类型及相应的JSON函数,而在8.0.17版本中,又推出了针对值数组的多值索引。这些功能非常实用,一度成为  ​​​MySQL迁移到OceanBase 上的一个阻点。之前,OceanBase 在 3.2.2版本推出了JSON数据类型及JSON函数,4.3.2版本则实现了多值索引。本文将分享OceanBase 4.3.2版本中JSON数据类型及其索引的使用示例和实践。


OB 的 ORACLE 租户和 MySQL 租户都支持 JSON 类型,本文主要演示 MySQL 租户下的 JSON 使用。

首先创建一个含有 JSON 类型的表,示例参考 MySQL 官方文档中 JSON 示例表。

CREATE TABLE customers (id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,modified DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,custinfo JSON);INSERT INTO customers VALUES(NULL, NOW(), '{"user":"Jack","user_id":37,"zipcode":[94582,94536]}'),(NULL, NOW(), '{"user":"Jill","user_id":22,"zipcode":[94568,94507,94582]}'),(NULL, NOW(), '{"user":"Bob","user_id":31,"zipcode":[94477,94507]}'),(NULL, NOW(), '{"user":"Mary","user_id":72,"zipcode":[94536]}'),(NULL, NOW(), '{"user":"Ted","user_id":56,"zipcode":[94507,94582]}')
;select * from customers;

1730180347

JSON 列不支持直接索引,如果想对 JSON 列部分字段做索引,可以新增一个虚拟列,然后针对这个虚拟列创建索引。

ALTER TABLE customers ADD v_user varchar(20) GENERATED ALWAYS AS (json_unquote(json_extract (`custinfo`, _utf8mb4'$.user'))) virtual ;
ALTER TABLE customers ADD KEY idx_user(v_user);

1730180359

再看看查询虚拟列的执行计划。

mysql> explain SELECT * FROM customers WHERE v_user='Bob';
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan                                                                                                                                                                         |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ===============================================================                                                                                                                    |
| |ID|OPERATOR        |NAME               |EST.ROWS|EST.TIME(us)|                                                                                                                    |
| ---------------------------------------------------------------                                                                                                                    |
| |0 |TABLE RANGE SCAN|customers(idx_user)|1       |7           |                                                                                                                    |
| ===============================================================                                                                                                                    |
| Outputs & filters:                                                                                                                                                                 |
| -------------------------------------                                                                                                                                              |
|   0 - output([customers.id], [customers.modified], [customers.custinfo], [column_conv(VARCHAR,utf8mb4_general_ci,length:20,NULL,cast(json_unquote(json_extract(customers.custinfo, |
|        '$.user')), VARCHAR(1048576)))]), filter(nil)                                                                                                                               |
|       access([customers.id], [customers.custinfo], [customers.v_user], [customers.modified]), partitions(p0)                                                                       |
|       is_index_back=true, is_global_index=false,                                                                                                                                   |
|       range_key([customers.v_user], [customers.id]), range(Bob,MIN ; Bob,MAX),                                                                                                     |
|       range_cond([customers.v_user = 'Bob'])                                                                                                                                       |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
13 rows in set, 1 warning (0.02 sec)

上面方法如果要对 JSON 字段 zipcode 做索引就有点困难,这个列的值是个数组。这就用到新推出的多值索引功能。

先看查询场景 SQL 。

EXPLAIN SELECT * FROM customers WHERE 94507 MEMBER OF(custinfo->'$.zipcode');
EXPLAIN SELECT * FROM customers WHERE JSON_CONTAINS(custinfo->'$.zipcode', CAST('[94507,94582]' AS JSON));
EXPLAIN SELECT * FROM customers WHERE JSON_OVERLAPS(custinfo->'$.zipcode', CAST('[94507,94582]' AS JSON));

这三个 SQL 使用了常见的 JSON 函数,执行计划全部是全表扫描就不发了。应对方法就是新增多值索引。

mysql> ALTER TABLE customers ADD INDEX zips( (CAST(custinfo->'$.zipcode' AS UNSIGNED ARRAY)) );
ERROR 1235 (0A000): dynamic add multivalue index not supported yet not supported
mysql> 

遗憾的是由于 OB 4.3.2 是刚支持多值索引,目前还只实现在建表的时候创建多值索引,暂不支持后期动态添加多值索引。

所以我们再创建一个带多值索引的新表看看。

create table customers2(id bigint not null auto_increment  ,modified datetime default current_timestamp on update current_timestamp,custinfo json,index zips((cast(custinfo->'$.zipcode' as unsigned array))),INDEX comp(id, modified,(cast(custinfo->'$.zipcode' as unsigned array)))
);INSERT INTO customers2 SELECT * FROM customers;

为了减少篇幅,我这里一次性创建两类多值索引。一个是针对单列的多值索引,一个是多列组合索引。

mysql> EXPLAIN SELECT * FROM customers2 WHERE 94507 MEMBER OF(custinfo->'$.zipcode');                                                                                                                                                                                       
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+                                                                                                            
| Query Plan                                                                                                                                                   |                                                                                                            
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+                                                                                                            
| ===========================================================                                                                                                  |                                                                                                            
| |ID|OPERATOR       |NAME            |EST.ROWS|EST.TIME(us)|                                                                                                  |                                                                                                            
| -----------------------------------------------------------                                                                                                  |                                                                                                            
| |0 |TABLE FULL SCAN|customers2(zips)|2       |13          |                                                                                                  |                                                                                                            
| ===========================================================                                                                                                  |                                                                                                            
| Outputs & filters:                                                                                                                                           |                                                                                                            
| -------------------------------------                                                                                                                        |                                                                                                            
|   0 - output([customers2.id], [customers2.modified], [customers2.custinfo]), filter([JSON_MEMBER_OF(94507, JSON_EXTRACT(customers2.custinfo, '$.zipcode'))]) |                                                                                                            
|       access([customers2.__pk_increment], [customers2.custinfo], [customers2.id], [customers2.modified]), partitions(p0)                                     |                                                                                                            
|       is_index_back=true, is_global_index=false, filter_before_indexback[false],                                                                             |                                                                                                            
|       range_key([customers2.SYS_NC_mvi_19], [customers2.__pk_increment], [customers2.__doc_id_1727685398954214]), range(94507,MIN,MIN ; 94507,MAX,MAX)       |                                                                                                            
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+                                                                                                            
11 rows in set (0.00 sec)                                                                                                                                                                                                                                                   mysql> EXPLAIN SELECT * FROM customers2 WHERE JSON_CONTAINS(custinfo->'$.zipcode', CAST('[94507,94582]' AS JSON));                                                                                                                                                          
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+                                                                                                        
| Query Plan                                                                                                                                                       |                                                                                                        
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+                                                                                                        
| ===========================================================                                                                                                      |                                                                                                        
| |ID|OPERATOR       |NAME            |EST.ROWS|EST.TIME(us)|                                                                                                      |                                                                                                        
| -----------------------------------------------------------                                                                                                      |                                                                                                        
| |0 |TABLE FULL SCAN|customers2(zips)|3       |23          |                                                                                                      |                                                                                                        
| ===========================================================                                                                                                      |                                                                                                        
| Outputs & filters:                                                                                                                                               |                                                                                                        
| -------------------------------------                                                                                                                            |
|   0 - output([customers2.id], [customers2.modified], [customers2.custinfo]), filter([JSON_CONTAINS(JSON_EXTRACT(customers2.custinfo, '$.zipcode'), cast('[94507, |
|       94582]', JSON(536870911)))])                                                                                                                               |
|       access([customers2.__pk_increment], [customers2.custinfo], [customers2.id], [customers2.modified]), partitions(p0)                                         |
|       is_index_back=true, is_global_index=false, filter_before_indexback[false],                                                                                 |
|       range_key([customers2.SYS_NC_mvi_19], [customers2.__pk_increment], [customers2.__doc_id_1727685398954214]), range(94507,MIN,MIN ; 94507,MAX,MAX),          |
|       (94582,MIN,MIN ; 94582,MAX,MAX)                                                                                                                            |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
13 rows in set (0.00 sec)
mysql> EXPLAIN SELECT * FROM customers2 WHERE JSON_OVERLAPS(custinfo->'$.zipcode', CAST('[94507,94582]' AS JSON));
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan                                                                                                                                                       |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ===========================================================                                                                                                      |
| |ID|OPERATOR       |NAME            |EST.ROWS|EST.TIME(us)|                                                                                                      |
| -----------------------------------------------------------                                                                                                      |
| |0 |TABLE FULL SCAN|customers2(zips)|3       |23          |                                                                                                      |
| ===========================================================                                                                                                      |
| Outputs & filters:                                                                                                                                               |
| -------------------------------------                                                                                                                            |
|   0 - output([customers2.id], [customers2.modified], [customers2.custinfo]), filter([JSON_OVERLAPS(JSON_EXTRACT(customers2.custinfo, '$.zipcode'), cast('[94507, |
|       94582]', JSON(536870911)))])                                                                                                                               |
|       access([customers2.__pk_increment], [customers2.custinfo], [customers2.id], [customers2.modified]), partitions(p0)                                         |
|       is_index_back=true, is_global_index=false, filter_before_indexback[false],                                                                                 |
|       range_key([customers2.SYS_NC_mvi_19], [customers2.__pk_increment], [customers2.__doc_id_1727685398954214]), range(94507,MIN,MIN ; 94507,MAX,MAX),          |
|       (94582,MIN,MIN ; 94582,MAX,MAX)                                                                                                                            |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
13 rows in set (0.00 sec)mysql> EXPLAIN SELECT * FROM customers2 WHERE id = 23 and modified = 103 and 94507 MEMBER OF(custinfo->'$.zipcode');
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan                                                                                                                                                   |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ============================================================                                                                                                 |
| |ID|OPERATOR        |NAME            |EST.ROWS|EST.TIME(us)|                                                                                                 |
| ------------------------------------------------------------                                                                                                 |
| |0 |TABLE RANGE SCAN|customers2(comp)|1       |7           |                                                                                                 |
| ============================================================                                                                                                 |
| Outputs & filters:                                                                                                                                           |
| -------------------------------------                                                                                                                        |
|   0 - output([customers2.id], [customers2.modified], [customers2.custinfo]), filter([JSON_MEMBER_OF(94507, JSON_EXTRACT(customers2.custinfo, '$.zipcode'))]) |
|       access([customers2.__pk_increment], [customers2.custinfo], [customers2.id], [customers2.modified]), partitions(p0)                                     |
|       is_index_back=true, is_global_index=false, filter_before_indexback[false],                                                                             |
|       range_key([customers2.id], [customers2.modified], [customers2.SYS_NC_mvi_21], [customers2.__pk_increment], [customers2.__doc_id_1727685398954214]),    |
|        range(23,2000-01-03 00:00:00.000000,MIN,MIN,MIN ; 23,2000-01-03 00:00:00.000000,MAX,MAX,MAX),                                                         |
|       range_cond([customers2.id = 23], [customers2.modified = INTERNAL_FUNCTION(103, 110, 17)])                                                              |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
13 rows in set (0.00 sec)

这里直接将 4 种使用多值索引的查询场景 SQL 以及执行计划放出,这执行计划中的细节大家可以一一详细查看。

多值索引的结构如下。

mysql> show indexes from customers2;
+------------+------------+----------+--------------+---------------------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+--------------------------------------------------------------------------------------------------------------------------------+
| Table      | Non_unique | Key_name | Seq_in_index | Column_name               | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment   | Index_comment | Visible | Expression                                                                                                                     |
+------------+------------+----------+--------------+---------------------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+--------------------------------------------------------------------------------------------------------------------------------+
| customers2 |          1 | zips     |            1 | SYS_NC_mvi_19             | A         |        NULL | NULL     | NULL   | YES  | BTREE      | available |               | YES     | json_query(`custinfo`,'$.zipcode' RETURNING unsigned WITHOUT ARRAY WRAPPER asis error on error null on empty null on mismatch) |
| customers2 |          1 | zips     |            2 | __pk_increment            | A         |        NULL | NULL     | NULL   |      | BTREE      | available |               | YES     | NULL                                                                                                                           |
| customers2 |          1 | zips     |            3 | __doc_id_1727685398954214 | A         |        NULL | NULL     | NULL   |      | BTREE      | available |               | YES     | NULL                                                                                                                           |
| customers2 |          1 | comp     |            1 | id                        | A         |        NULL | NULL     | NULL   |      | BTREE      | available |               | YES     | NULL                                                                                                                           |
| customers2 |          1 | comp     |            2 | modified                  | A         |        NULL | NULL     | NULL   | YES  | BTREE      | available |               | YES     | NULL                                                                                                                           |
| customers2 |          1 | comp     |            3 | SYS_NC_mvi_21             | A         |        NULL | NULL     | NULL   | YES  | BTREE      | available |               | YES     | json_query(`custinfo`,'$.zipcode' RETURNING unsigned WITHOUT ARRAY WRAPPER asis error on error null on empty null on mismatch) |
| customers2 |          1 | comp     |            4 | __pk_increment            | A         |        NULL | NULL     | NULL   |      | BTREE      | available |               | YES     | NULL                                                                                                                           |
| customers2 |          1 | comp     |            5 | __doc_id_1727685398954214 | A         |        NULL | NULL     | NULL   |      | BTREE      | available |               | YES     | NULL                                                                                                                           |
+------------+------------+----------+--------------+---------------------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+--------------------------------------------------------------------------------------------------------------------------------+
8 rows in set (0.00 sec)

还有一类特殊的场景是多值索引的唯一性索引。

CREATE TABLE customers3 (id BIGINT not null primary key,modified BIGINT not null,custinfo JSON,UNIQUE INDEX zips1( (CAST(custinfo->'$.zipcode' AS UNSIGNED ARRAY)) )
);INSERT INTO customers3 VALUES(10, 21, '{"user":"Jack","user_id":37,"zipcode":[94582,94536]}');mysql> select * from customers3;
+----+----------+------------------------------------------------------------+
| id | modified | custinfo                                                   |
+----+----------+------------------------------------------------------------+
| 10 |       21 | {"user": "Jack", "user_id": 37, "zipcode": [94582, 94536]} |
+----+----------+------------------------------------------------------------+
1 row in set (0.00 sec)mysql> INSERT INTO customers3 VALUES  (11, 22, '{"user":"Jill","user_id":22,"zipcode":[94568,94507,94582]}');
ERROR 1062 (23000): Duplicate entry '94582' for key 'zips1'
mysql> mysql> show indexes from customers3;
+------------+------------+----------+--------------+---------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+--------------------------------------------------------------------------------------------------------------------------------+
| Table      | Non_unique | Key_name | Seq_in_index | Column_name   | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment   | Index_comment | Visible | Expression                                                                                                                     |
+------------+------------+----------+--------------+---------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+--------------------------------------------------------------------------------------------------------------------------------+
| customers3 |          0 | PRIMARY  |            1 | id            | A         |        NULL | NULL     | NULL   |      | BTREE      | available |               | YES     | NULL                                                                                                                           |
| customers3 |          0 | zips1    |            1 | SYS_NC_mvi_19 | A         |        NULL | NULL     | NULL   | YES  | BTREE      | available |               | YES     | json_query(`custinfo`,'$.zipcode' RETURNING unsigned WITHOUT ARRAY WRAPPER asis error on error null on empty null on mismatch) |
+------------+------------+----------+--------------+---------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+--------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

由此可见唯一性的多值索引能拦截导致多值数组中出现重复的值。

多值索引也有一些功能限制。

  • 多值索引不能定义列的顺序 ASC 或 DESC,也不能用于消除排序,多值列不能用于主键。
EXPLAIN SELECT v_user FROM customers order by v_user;
EXPLAIN SELECT custinfo FROM customers2 order by custinfo;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/58469.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ORACLE建表(11G)

BEGIN EXECUTE IMMEDIATE DROP TABLE business CASCADE CONSTRAINTS; EXCEPTION WHEN OTHERS THEN IF SQLCODE ! -942 THEN -- 942 是表不存在的错误码 RAISE; END IF; END; CREATE TABLE business ( uuid VARCHAR2(255) NOT NULL, product VARCHAR2(255) NULL, promotion VARC…

Spark on YARN:Spark集群模式之Yarn模式的原理、搭建与实践

Spark 的介绍与搭建:从理论到实践-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交:本地与集群模式全解析-CSDN博客 目录 一、Spark on YARN 的优势 (一&#…

java后端工程师转行AI大模型岗,工作、自我提升两不误!

随着技术的不断进步,人工智能(AI)已经成为当今科技领域最热门的话题之一。许多开发者开始考虑从传统的软件开发领域,如Java,转向人工智能领域,今天小编和大家一起来探讨Java开发者是否可以转型到人工智能&a…

【系统设计】提升Kafka系统性能:Spring Boot实现Lag感知的生产者与消费者

在分布式系统中,消息队列扮演着至关重要的角色,而Kafka凭借其高吞吐量和低延迟的特性,成为了流数据处理的首选。然而,随着应用规模的扩大,如何有效管理Kafka的offset与lag,确保系统的高可用性和性能稳定&am…

通宵修bug

前两个月的某天凌晨,我司全新的一个营销工具,在全国如期上线。然而整个发布过程并非一帆风顺,在线上环境全量发布后,有同事观测到他所负责模块的监控曲线有异常!监控曲线在发布的时刻近乎于直线下跌。 经过初步排查&am…

Rust-宏编程

巴山楚水凄凉地,二十三年弃置身。 怀旧空吟闻笛赋,到乡翻似烂柯人。 沉舟侧畔千帆过,病树前头万木春。 今日听君歌一曲,暂凭杯酒长精神。 ——《酬乐天扬州初逢席上见赠》唐刘禹锡 【哲理】翻覆的船只旁仍有千千万万的帆船经过&a…

leetcode912.排序数组的题解

题目描述: 题目要求在不使用任何内置函数的情况下解决问题,时间复杂度为 O(nlog(n))。 笔者使用了快速排序,但是直接使用最原始的快速排序,有些特殊的测试用例会超时。 1)如果数组本身基本有序,则使用原始…

TikTok品牌出海:从“流量为王”到“价值为王”

随着市场竞争的加剧,品牌逐渐意识到,仅仅依靠流量已不足以在海外市场立足,必须实现从“流量为王”到“价值为王”的转变。本文Nox聚星将和大家探讨品牌如何与TikTok达人合作,在海外市场中建立长期稳定的品牌形象。 一、品牌出海的…

纯血鸿蒙系统 HarmonyOS NEXT自动化测试实践

1、测试框架选择 hdc:类似 android 系统的 adb 命令,提供设备信息查询,包管理,调试相关的命令ohos.UiTest:鸿蒙 sdk 的一部分,类似 android sdk 里的uiautomator,基于 Accessibility 服务&…

Kafka 可观测性最佳实践

Kafka 概述 Kafka 是由 LinkedIn 开发一个分布式的基于发布订阅模式的消息队列,是一个实时数据处理系统,可以横向扩展。与 RabbitMQ、RockerMQ 等中间件一样拥有几大特点: 异步处理服务解耦流量削峰 监控 Kafka 是非常重要的,因…

《XGBoost算法的原理推导》12-13树的叶子节点权重w和映射关系q 公式解析

本文是将文章《XGBoost算法的原理推导》中的公式单独拿出来做一个详细的解析,便于初学者更好的理解。 我们重新定义一颗树,包括两个部分: 叶子结点的权重向量 w w w;实例 -> 叶子结点的映射关系 q q q(本质是树的…

电商API:开启电商新时代的关键钥匙

一、电商API:定义与发展 电商API,即应用程序编程接口,是连接不同软件系统的桥梁,在电商领域中发挥着至关重要的作用。电商API的发展历程可以追溯到20世纪90年代,当时电子商务刚刚兴起,企业开始意识到通过A…

多client向同一个pushgateway推送指标被覆盖问题

问题: 多个client向同一个pushgateway推送指标,每个client推送的指标名称相同但是lable不同。如下: # TYPE ObjectCount gauge ObjectCount{server_id"server1"} 4 ObjectCount{server_id"server2"} 4 ObjectCount{server_id"…

C++__XCode工程中Debug版本库向Release版本库的切换

Debug和Release版本分别设置编译后,就分别得到了对应的lib库,如下图: 再生成Release后如下图:

梧桐数据库中处理连续日期序列的解决方案

在数据库管理中,处理时间序列数据是一项常见的任务,尤其是在需要识别连续日期序列的场景中。例如,在一个生产环境中,我们可能需要跟踪产品的输出类型,并记录这些输出是否连续。本文将介绍如何在梧桐数据库中实现这一功…

增删改增删改

savePostMapping("/save") public ResponseResult save(RequestBody ChannelDto channelDto){ // 参数判断 if(channelDto null || StringUtils.isBlank(channelDto.getName())){ return ResponseResult.error(AppHttpCodeEnum.PARA…

消费疲软下,家居品牌如何利用营销实现新的突围与增长?

在消费疲软的大环境下,家居品牌面临着前所未有的挑战与机遇。尤其以耐消品为主的家居行业,也受到一定程度影响——有效需求不足导致产能过剩,营销乏力,市场竞争开始变得激烈,不少家居品牌正在面临业绩压力。家居品牌如…

Apache Shiro -配置先后的影响

在Apache Shiro框架中,shiroFilterChainDefinition(或filterChainDefinitions)的配置顺序确实有影响。以下是具体的影响和原因: URL匹配规则:Shiro在验证URL时,会按照filterChainDefinitions中配置的顺序进…

How to use ffmpeg to convert video format from .webm to .mp4

The .mp4 container format doesn’t support the VP8 codec, which is commonly used in .webm files. MP4 containers typically use the H.264 codec for video and AAC for audio. You’ll need to re-encode the video using the H.264 codec and re-encode the audio us…

ORACLE _11G_R2_ASM 常用命令

--------查看磁盘组,(空间情况) select name,state,free_mb,total_mb,usable_file_mb from v$asm_diskgroup; --------查看磁盘情况 select GROUP_NUMBER,free_mb,total_mb,disk_number,MOUNT_STATUS,mode_status, HEADER_STATUS,name,PATH from v$asm_disk order …