Oracle NoSQL Database Cloud Service Reference

Learn about supported data types, DDL statements, Oracle NoSQL Database Cloud Service Service parameters and metrics.

This article has the following topics:

Supported Data Types

Oracle NoSQL Database Cloud Service supports many common data types.

Data Type Description

BINARY

A sequence of zero or more bytes. The storage size is the number of bytes plus an encoding of the size of the byte array, which is a variable, depending on the size of the array.

FIXED_BINARY A fixed-size byte array. There is no extra encoding overhead for this data type.

BOOLEAN

A data type with one of two possible values: TRUE or FALSE. The storage size of the boolean is 1 byte.

DOUBLE

A long floating-point number, encoded using 8 bytes of storage for index keys. If it is a primary key then it uses 10 bytes of storage.

FLOAT

A long floating point number, encoded using 4 bytes of storage for index keys. If it is a primary key then it uses 5 bytes of storage.

LONG

A long integer number has a variable-length encoding that uses 1-8 bytes of storage depending on the value. If it is a primary key then it uses 10 bytes of storage.

INTEGER

A long integer number has a variable-length encoding that uses 1-4 bytes of storage depending on the value. If it is a primary key then it uses 5 bytes of storage.

STRING

A sequence of zero or more Unicode characters. The String type is encoded as UTF-8 and stored in that encoding. The storage size is the number of UTF-8 bytes plus the length, which may be 1-4 bytes depending on the number of bytes in the encoding. When stored in an index key the storage size is the number of UTF-8 bytes plus a single null termination byte.

NUMBER

An arbitrary-precision signed decimal number.

It is serialized in a byte array format that can be used for ordered comparisons. The format has 2 parts:
  1. The sign and exponent plus a single digit. This takes 1-6 bytes but normally is 2 unless the exponent is quite large
  2. The mantissa of the value which is approximately one byte for every 2 digits

Examples:

12.345678 serializes in 6 bytes

1.234E+102 serializes in 5 bytes

Note

When you need to use numeric values in your schema, it is recommended to decide on the data types in the order given below: INTEGER, LONG, FLOAT, DOUBLE, NUMBER Avoid NUMBER unless you really need it for your use case as NUMBER is expensive both in terms of storage and processing power used.
TIMESTAMP

A point in time with a precision. The precision affects the storage size and usage. Timestamp is stored and managed in UTC (Coordinated Universal Time). The Timestamp datatype requires anywhere from 3 to 9 bytes depending on the precision used.

The following breakdown illustrates the storage used by this datatype:
  • bit[0~13] year - 14 bits
  • bit[14~17] month - 4 bits
  • bit[18~22] day - 5 bits
  • bit[23~27] hour - 5 bits [optional]
  • bit[28~33] minute - 6 bits [optional]
  • bit[34~39] second - 6 bits [optional]
  • bit[40~71] fractional second [optional with variable length]

UUID

Note: The UUID data type is considered a subtype of the STRING data type. The storage size is 16 bytes as an index key. If used as a primary key the storage size is 19 bytes.

ENUM

An enumeration is represented as an array of strings. ENUM values are symbolic identifiers (tokens) and are stored as a small integer value representing an ordered position in the enumeration.

ARRAY

An ordered collection of zero of more typed items. Arrays that are not defined as JSON cannot contain NULL values.

Arrays declared as JSON can contain any valid JSON, including the special value, null, which is relevant to JSON.

MAP

An unordered collection of zero or more key-item pairs, where all keys are strings and all items are the same type. All keys must be unique. The key-item pairs are called fields, the keys are field names, and the associated items are field values. Field values can have different types, but maps cannot contain NULL field values.

RECORD

A fixed collection of one or more key-item pairs, where all keys are strings. All keys in a record must be unique.

JSON

Any valid JSON data.

Table States and Life Cycles

Learn about the different table states and their significance (table life cycle process).

Each table passes through a series of different states from table creation to deletion (drop). For example, a table in the DROPPING state cannot proceed to the ACTIVE state, while a table in the ACTIVE state can change to the UPDATING state. You can track the different table states by monitoring the table life cycle. This section describes the various table states.

Description of table-state.png follows

Table State Description

CREATING

The table is in the process of being created. It is not ready to use.

UPDATING

Updating the table is in process. Further table modifications are not possible while the table is in this state.

A table is in the UPDATING state when:

  • The table limits are being changed
  • The table schema is evolving
  • Adding or dropping a table index

ACTIVE

The table can be used in the current state. The table may have been recently created, or modified, but the table state is now stable.

DROPPING

The table is being dropped and cannot be accessed for any purpose.

DROPPED

The table has been dropped and no longer exists for read, write, or query activities.
Note

Once dropped, a table with the same name can be created again.

Debugging SQL statement errors in the OCI console

When you are using the OCI console to create a table using a DDL statement or using a DML statement to insert or update data or using a SELECT query to fetch data, you may get an error that your statement is Incomplete or faulty in one of the following common scenarios:
  • If you have a semi-colon at the end of your SQL statement.
  • If there is a syntax error in your SQL statement like the wrong usage of commas, usage of any unnecessary character in the statement, etc.
  • If there is a spelling error in your SQL statement in any of the SQL keywords or in your datatype definition.
  • If you have defined the column as NOT NULL but not assigned a DEFAULT value to it.
  • If you have defined the column as NOT NULL but not assigned a DEFAULT value to it.
How to handle some Incomplete or faulty errors while using the OCI console to create or manage data:
  • Remove the semi-colon ( if present) at the end of the SQL statement.
  • Check if there is any undesired character or wrong punctuation in your SQL statement.
  • Check for spelling errors in your SQL statement.
  • Check if all your column definitions are complete and correct.
  • Check if you have defined a primary key for your table.

If you still get an error after eliminating some of the possible situations as discussed above, you can use Cloud Shell to run your query and capture the exact error as shown in the example below.

Example : Getting the error message for a SELECT statement from the cloud shell

The summarize command checks the syntax and returns a brief summary of a SQL statement.
  1. In your OCI console, Open the Cloud Shell from the top right menu.
  2. Copy your SQL SELECT statement( for example, query1.sql) into a variable (SQL_SELECTSTMT).
    Example:
    SQL_SELECTSTMT=$(cat ~/query1.sql | tr '\n' ' ')
  3. Invoke the oci command below to check the syntax of your SQL SELECT statement.
    Note

    You need to give the compartment_id for this SELECT statement.
    oci raw-request --http-method GET --target-uri 
    https://nosql.${OCI_REGION}.oci.oraclecloud.com/20190828/query/summarize?compartmentId=$NOSQL_COMPID\
    &statement="$SQL_SELECTSTMT" | jq '.data'

This will give you the exact error in your SQL statement.

Data Definition Language Reference

Learn how to use DDL in Oracle NoSQL Database Cloud Service.

Use Oracle NoSQL Database Cloud Service DDL to create, alter, and drop tables and indexes.

For information on the syntax of the DDL language, see Table Data Definition Language Guide. This guide documents the DDL language as supported by the on-premises Oracle NoSQL Database product. The Oracle NoSQL Database Cloud Service supports a subset of this functionality and the differences are documented in the DDL Differences in the Cloud section.

Also, each NoSQL <language> driver provides an API to execute a DDL statement. To write your application, see Using APIs to Create Tables and Indexes in Oracle NoSQL Database Cloud Service .

Typical DDL Statements

Few samples of common DDL statements are as follows:

Create Table
CREATE TABLE [IF NOT EXISTS] (
    field-definition, field-definition-2 ...,
    PRIMARY KEY (field-name, field-name-2...),
) [USING TTL ttl]
For example:
CREATE TABLE IF NOT EXISTS audience_info (
    cookie_id LONG,
    ipaddr STRING,
    audience_segment JSON,
    PRIMARY KEY(cookie_id))
Alter Table
ALTER TABLE table-name (ADD field-definition)
ALTER TABLE table-name (DROP field-name)
ALTER TABLE table-name USING TTL ttl 
For example:
ALTER TABLE audience_info USING TTL 7 days
Create Index
CREATE INDEX [IF NOT EXISTS] index-name ON table-name (path_list)
For example:
CREATE INDEX segmentIdx ON audience_info
       (audience_segment.sports_lover AS STRING)
Drop Table
DROP TABLE [IF EXISTS] table-name
For example:
DROP TABLE audience_info

See the reference guides for a complete list:

DDL Differences in the Cloud

The cloud service DDL language differs from what is described in the reference guide in the following way:

Table Names

  • Limited to 256 characters, and are restricted to alphanumeric characters and underscore
  • Must start with a letter
  • Cannot include special characters
  • Child tables are not supported

Unsupported Concepts

  • DESCRIBE and SHOW TABLE statements.
  • Full text indexes
  • User and role management
  • On-premise regions

Query Language Reference

Learn how to use SQL statements to update and query data in Oracle NoSQL Database Cloud Service.

The Oracle NoSQL Database uses the SQL query language to update and query data in NoSQL tables. See SQL Reference for Oracle NoSQL Database to learn the query language syntax.

Typical Queries

SELECT <expression>
FROM <table name>
[WHERE <expression>]
[GROUP BY <expression>]
[ORDER BY <expression> [<sort order>]]
[LIMIT <number>]
[OFFSET <number>]; 

For example:
SELECT * FROM Users;
SELECT id, firstname, lastname FROM Users WHERE firstname = "Taylor";
UPDATE <table_name> [AS <table_alias>]
    <update_clause>[, <update_clause>]*
WHERE <expr>[<returning_clause>];

For example:
UPDATE JSONPersons $j
  SET TTL 1 DAYS
  WHERE id = 6
  RETURNING remaining_days($j) AS Expires;

Query Language Differences in the Cloud

The cloud service query support differs from what is described in the query language reference guide in the following way:

Restrictions on Expressions Used in the SELECT Clause

Oracle NoSQL Database Cloud Service supports grouping expressions or arithmetic expressions among aggregate functions. No other kinds of expressions are allowed in the SELECT clause. For example, CASE expressions are not allowed in the SELECT clause.

Each NoSQL Database driver provides an API to execute a query statement.

Query Plan Reference

A query execution plan is the sequence of operations Oracle NoSQL Database performs to run a query.

A query execution plan is a tree of plan iterators. Each kind of iterator evaluates a different kind of expression that may appear in a query. In general, the choice of index and the kind of associated index predicates can have a drastic effect on query performance. As a result, you as a user often want to see what index is used by a query and what predicates have been pushed down to it. Based on this information, you may want to force the use of a different index via index hints. This information is contained in the query execution plan. . All Oracle NoSQL drivers provide APIs to display the execution plan of a query.

Some of the most common and important iterators used in queries are :

TABLE iterator: A table iterator is responsible for:
  • Scanning the index used by the query (which may be the primary index).
  • Applying any filtering predicates pushed to the index
  • Retrieve the rows pointed to by the qualifying index entries if necessary. If the index is covering, the result set of the TABLE iterator is a set of index entries, otherwise, it is a set of table rows.
Note

An index is called a covering index with respect to a query if the query can be evaluated using only the entries of that index, that is, without the need to retrieve the associated rows.

SELECT iterator: It is responsible for executing the SELECT expression.

Every query has a SELECT clause in it. So every query plan will have a SELECT iterator. A SELECT iterator has the following structure:

"iterator kind" : "SELECT",
"FROM" :
  {
  },
"FROM variable" : "...",
"SELECT expressions" : 
[
  {
  }
]

The SELECT iterator has fields like: “FROM”, "WHERE", “FROM variable”, and “SELECT expressions”. “FROM” and “FROM variable” represent the FROM clause of the SELECT expression, WHERE represents the filter clause, and “SELECT expression” represents the SELECT clause.

RECEIVE iterator: It is a special internal iterator that separates the query plan into 2 parts:
  1. The RECEIVE iterator itself and all iterators that are above it in the iterator tree are executed at the driver.
  2. All iterators below the RECEIVE iterator are executed at the replication nodes (RNs); these iterators form a subtree rooted at the unique child of the RECEIVE iterator.

In general, the RECEIVE iterator acts as a query coordinator. It sends its subplan to appropriate RNs for execution and collects the results. It may perform additional operations such as sorting and duplicate elimination and propagates the results to its ancestor iterators (if any) for further processing.

Distribution kinds :

A distribution kind specifies how the query will be distributed for execution across the RNs participating in an Oracle NoSQL database (a store). The distribution kind is a property of the RECEIVE iterator.

Different choices of Distribution kinds are:
  • SINGLE_PARTITION: A SINGLE_PARTITION query specifies a complete shard key in its WHERE clause. As a result, its full result set is contained in a single partition, and the RECEIVE iterator will send its subplan to a single RN that stores that partition. A SINGLE_PARTITION query may use either the primary-key index or a secondary index.
  • ALL_PARTITIONS: Queries use the primary-key index here and they don’t specify a complete shard key. As a result, if the store has M partitions, the RECEIVE iterator will send M copies of its subplan to be executed over one of the M partitions each.
  • ALL_SHARDS: Queries use a secondary index here and they don’t specify a complete shard key. As a result, if the store has N shards, the RECEIVE iterator will send N copies of its subplan to be executed over one of the N shards each.

Anatomy of a query execution plan:

Query execution takes place in batches. When a query subplan is sent to a partition or shard for execution, it will execute there until a batch limit is reached. The batch limit is a number of read units consumed locally by the query. The default is 2000 read units (about 2MB of data), and it can only be decreased via a query-level option.

When the batch limit is reached, any local results that were produced are sent back to the RECEIVE iterator for further processing along with a boolean flag that says whether more local results may be available. If the flag is true, the reply includes resume information. If the RECEIVE iterator decides to resend the query to the same partition/shard, it will include this resume information in its request, so that the query execution will restart at the point where it stopped during the previous batch. This is because no query state is maintained at the RN after a batch finishes. The next batch for the same partition/shard may take place at the same RN as the previous batch or at a different RN that also stores the same partition/shard.