INTERLEAVE IN PARENT

Warning:

INTERLEAVE IN PARENT was deprecated in v20.2, disabled by default in v21.1, and permanently removed in v21.2. We do not recommend interleaving tables or indexes in new clusters.

For details, see Deprecation.

Deprecation

Interleaving tables and indexes was deprecated in CockroachDB v20.2 for the following reasons:

  • Scans over tables or indexes with interleaved, child objects (i.e., interleaved tables or indexes) are much slower than scans over tables and indexes with no child objects, as the scans must traverse the parent object and all of its child objects.
  • Database schema changes are slower for interleaved objects and their parents than they are for non-interleaved objects and objects with no interleaved children. For example, if you add or remove a column to a parent or child table, CockroachDB must rewrite the entire interleaved hierarchy for that table and its parents/children.
  • Internal benchmarks have shown the performance benefits of interleaving tables and indexes are limited to a small number of use cases.

In CockroachDB v21.1, interleaving is disabled with the sql.defaults.interleaved_tables.enabled cluster setting set to false by default.

For more details, see the GitHub tracking issue.

After upgrading to v21.1, we recommend that you do the following:

Tip:

Test your schema changes in a non-production environment before implementing them in production.

Convert interleaved tables

To convert an interleaved table to a non-interleaved table, issue an ALTER PRIMARY KEY statement on the table, specifying the existing primary key column(s) for the table, and no INTERLEAVE IN PARENT clause.

When converting interleaved tables with ALTER PRIMARY KEY, note the following:

  • CockroachDB executes ALTER PRIMARY KEY statements as online schema changes. This means that you can convert your interleaved tables to non-interleaved tables without experiencing any downtime.
  • ALTER PRIMARY KEY statements can only convert a child table if that table is not a parent. If your cluster has child tables that are also parents, you must start from the bottom of the interleaving hierarchy and work your way up (i.e., start with child tables that are not parents).

For example, suppose you created an interleaved hierarchy between the customers, orders, and packages tables, using the following CREATE TABLE statements:

icon/buttons/copy
> CREATE TABLE customers (
   id INT PRIMARY KEY,
   name STRING(50)
 );
icon/buttons/copy
> CREATE TABLE orders (
   customer INT,
   id INT,
   total DECIMAL(20, 5),
   PRIMARY KEY (customer, id),
   CONSTRAINT fk_customer FOREIGN KEY (customer) REFERENCES customers
 ) INTERLEAVE IN PARENT customers (customer);
icon/buttons/copy
> CREATE TABLE packages (
   customer INT,
   "order" INT,
   id INT,
   address STRING(50),
   delivered BOOL,
   delivery_date DATE,
   PRIMARY KEY (customer, "order", id),
   CONSTRAINT fk_order FOREIGN KEY (customer, "order") REFERENCES orders
 ) INTERLEAVE IN PARENT orders (customer, "order");

The INTERLEAVE IN PARENT clauses will appear in SHOW CREATE statements for the packages and orders tables:

icon/buttons/copy
> SHOW CREATE TABLE orders;
 table_name |                                  create_statement
-------------+-------------------------------------------------------------------------------------
 orders     | CREATE TABLE public.orders (
            |     customer INT8 NOT NULL,
            |     id INT8 NOT NULL,
            |     total DECIMAL(20,5) NULL,
            |     CONSTRAINT "primary" PRIMARY KEY (customer ASC, id ASC),
            |     CONSTRAINT fk_customer FOREIGN KEY (customer) REFERENCES public.customers(id),
            |     FAMILY "primary" (customer, id, total)
            | ) INTERLEAVE IN PARENT public.customers (customer)
(1 row)
icon/buttons/copy
> SHOW CREATE TABLE packages;
 table_name |                                        create_statement
-------------+--------------------------------------------------------------------------------------------------
 packages   | CREATE TABLE public.packages (
            |     customer INT8 NOT NULL,
            |     "order" INT8 NOT NULL,
            |     id INT8 NOT NULL,
            |     address STRING(50) NULL,
            |     delivered BOOL NULL,
            |     delivery_date DATE NULL,
            |     CONSTRAINT "primary" PRIMARY KEY (customer ASC, "order" ASC, id ASC),
            |     CONSTRAINT fk_order FOREIGN KEY (customer, "order") REFERENCES public.orders(customer, id),
            |     FAMILY "primary" (customer, "order", id, address, delivered, delivery_date)
            | ) INTERLEAVE IN PARENT public.orders (customer, "order")
(1 row)

To convert these tables to non-interleaved tables, use ALTER PRIMARY KEY statements, starting at the bottom of the hierarchy (i.e., with packages):

icon/buttons/copy
> ALTER TABLE packages ALTER PRIMARY KEY USING COLUMNS (customer, "order", id);
icon/buttons/copy
> ALTER TABLE orders ALTER PRIMARY KEY USING COLUMNS (customer, id);
icon/buttons/copy
> SHOW CREATE TABLE orders;
 table_name |                                  create_statement
-------------+-------------------------------------------------------------------------------------
 orders     | CREATE TABLE public.orders (
            |     customer INT8 NOT NULL,
            |     id INT8 NOT NULL,
            |     total DECIMAL(20,5) NULL,
            |     CONSTRAINT "primary" PRIMARY KEY (customer ASC, id ASC),
            |     CONSTRAINT fk_customer FOREIGN KEY (customer) REFERENCES public.customers(id),
            |     UNIQUE INDEX orders_customer_id_key (customer ASC, id ASC),
            |     FAMILY "primary" (customer, id, total)
            | )
(1 row)
icon/buttons/copy
> SHOW CREATE TABLE packages;
 table_name |                                        create_statement
-------------+--------------------------------------------------------------------------------------------------
 packages   | CREATE TABLE public.packages (
            |     customer INT8 NOT NULL,
            |     "order" INT8 NOT NULL,
            |     id INT8 NOT NULL,
            |     address STRING(50) NULL,
            |     delivered BOOL NULL,
            |     delivery_date DATE NULL,
            |     CONSTRAINT "primary" PRIMARY KEY (customer ASC, "order" ASC, id ASC),
            |     CONSTRAINT fk_order FOREIGN KEY (customer, "order") REFERENCES public.orders(customer, id),
            |     UNIQUE INDEX packages_customer_order_id_key (customer ASC, "order" ASC, id ASC),
            |     FAMILY "primary" (customer, "order", id, address, delivered, delivery_date)
            | )
(1 row)

Replace interleaved indexes

Interleaved secondary indexes cannot be converted to non-interleaved indexes. You must drop the existing index, and then create a new index without an INTERLEAVE IN PARENT clause.

YesYes NoNo