When To Use JSON-Type Columns for a Duality View

Whether to store some of the data underlying a duality view as JSON data type and, if so, whether to enforce its structure and typing, are design choices to consider when defining a JSON-relational duality view.

By storing some JSON data that contributes to the JSON documents supported by (generated by) a duality view, you can choose the granularity and complexity of the building blocks that define the view. Put differently, you can choose the degree of normalization you want for the underlying data. Different choices involve different tradeoffs.

When the table data underlying a duality view is completely normalized, in which case the table columns contain only values of scalar SQL data types, the structure of the documents supported by the view, and the types of its fields, are fixed and strictly defined using relational constructs.

Although normalization reduces schema flexibility, complete normalization gives you the most flexibility in terms of combining data from multiple tables to support different kinds of duality view (more generally, in terms of combining some table data with other table data, outside of any use for duality views).

And in an important particular use case, complete normalization lets you access the data in existing relational tables from a document-centric application, as JSON documents.

On the other hand, the greater the degree of normalization, the more tables you have, which means more decomposition when inserting or updating JSON data and more joining (recomposition) when querying it. If an application typically accesses complex objects as a whole, then greater normalization can thus negatively impact performance.

Like any other column in a table underlying a duality view, a JSON-type column can be shared among different duality views, and thus its values can be shared in their different resulting (generated) JSON documents.

By default, a JSON value is free-form: its structure and typing are not defined by, or forced to conform to, any given pattern/schema. In this case, applications can easily change the shape and types of the values as needed — schema flexibility.

You can, however, impose typing and structure on the data in a JSON-type column, using JSON Schema. JSON Schema gives you a full spectrum of control:

  1. From fields whose values are completely undefined to fields whose values are strictly defined.

  2. From scalar JSON values to large, complex JSON objects and arrays.

  3. From simple type definitions to combinations of JSON-language types. For example:

    • A value that satisfies anyOf, allOf, or oneOf a set of JSON schemas

    • A value that does not satisfy a given JSON schema

Note:

Using, in a duality-view definition, a JSON-type column that's constrained by a JSON schema to hold only data of a particular JSON scalar type (date, string, etc.) that corresponds to a SQL scalar type (DATE, VARCHAR2, etc.) has the same effect on the JSON documents supported by the view as using a column of the corresponding SQL scalar type.

However, code that acts directly on such stored JSON-type data won't necessarily recognize and take into account this correspondence. The SQL type of the data is, after all, JSON, not DATE, VARCHAR2, etc. To extract a JSON scalar value as a value of a SQL scalar data type, code needs to use SQL/JSON function json_value. See SQL/JSON Function JSON_VALUE in Oracle AI Database JSON Developer’s Guide.

Let's summarize some of the tradeoffs between using SQL scalar columns and JSON-type columns in a table underlying a duality view:

  1. Flexibility of combination. For the finest-grain combination, use completely normalized tables, whose columns are all SQL scalars.

  2. Flexibility of document type and structure. For maximum flexibility of JSON field values at any given time, and thus also for changes over time (evolution), use JSON-type columns with no JSON-schema constraints.

  3. Granularity of field definition. The finest granularity requires a column for each JSON field, regardless of where the field is located in documents supported by the duality view. (The field value could nevertheless be a JSON object or array, if the column is JSON-type.)

If it makes sense for your application to share some complex JSON data among different kinds of documents, and if you expect to have no need for combining only parts of that complex data with other documents or, as SQL scalars, with relational data, then consider using JSON data type for the columns underlying that complex data.

In other words, in such a use case consider sharing JSON documents, instead of sharing the scalar values that constitute them. In still other words, consider using more complex ingredients in your duality-view recipe.

Note that the granularity of column data — how complex the data in it can be — also determines the granularity of updating operations and ETAG-checking (for optimistic concurrency control). The smallest unit for such operations is an individual column underlying a duality view; it's impossible to annotate individual fields inside a JSON-type column.

Update operations can selectively apply to particular fields contained in the data of a given JSON-type column, but control of which update operations can be used with a given view is defined at the level of an underlying column or whole table — nothing smaller. So if you need finer grain updating or ETAG-checking then you need to break out the relevant parts of the JSON data into their own JSON-type columns.

See Also: