Smile CDR v2022.08.PRE
On this page:

6.0FHIR Storage (Relational) Module

 

The FHIR Storage (Relational) module is responsible for resource storage and retrieval. It stores data in two places:

  • A relational database is used as the primary storage mechanism. All resources are stored in the database and indexes are created to help in finding them.
  • A Lucene filesystem is used to provide fulltext searching capability, as well as to support some terminology service functions.

6.0.1Preparing for a New Installation

 

To create a new FHIR Storage (Relational) module, you should first ensure that your host server (or virtual machine, docker container, etc.) has access to a dedicated directory with a sufficiently large amount of storage to keep its data.

This directory can be a mounted filesystem or a directory on a local disk but it should be dedicated to the given node. In other words, if this directory is network mounted, it should not be shared across multiple nodes of the cluster.

You will also require a relational database with a user and schema created. See the Platform Requirements page for information on supported database platforms.

6.0.2Creating the Module

 

When creating a FHIR Storage (Relational) module, you must first choose which version of FHIR it will support. There are multiple types of FHIR Storage (Relational) modules, and each one supports a specific version of FHIR.

6.0.3Database Schema

 

Details on the database schema for the FHIR Storage (Relational) module can be found in the HAPI FHIR Documentation. Initialization scripts can be found in the Database Administration section.

6.0.4Multi-Node Architectures

 
Note: Do not confuse the concept of a Smile CDR Node and a Smile CDR Process. In Smile CDR terms, a Node is a configuration set consisting of a group of modules with individual configuration and dependencies between modules. A Node can be scaled horizontally by creating multiple Processes, either running on separate VMs or as separate docker containers. Each process for a given node ID will have the same modules and configuration. A full Smile CDR cluster could have one node or multiple nodes, and can have one process or multiple processes for each node. See Designing a Cluster for more information.

In a basic deployment, a single Node with a FHIR Storage (RDBMS) module can be created. This module will service all FHIR requests. This architecture can easily be scaled hirozontally by creating multiple processes for this node.

In more complex architectures, it is possible to create multiple modules (generally on separate nodes) that share the same RDBMS connection details (i.e. the same connection URL). This is typically done when there is a separation of duties needed. This type of architecture is possible in Smile CDR as long as the considerations here are noted.

Scheduled Tasks

The FHIR Storage (RDBMS) module has a number of scheduled tasks that can selectively be enabled or disabled.

In most deployments there is no benefit to disabling these tasks, as they do not add any meaningful load to the system unless they detect work that needs doing. The exception to this rule is in deployments where you have multiple Smile CDR Nodes sharing a single relational database schema instance for FHIR Resource storage; in which case, one should enable the Suppress Scheduled Maintenance Jobs property on all but one of such FHIR Storage modules.

Descriptions of the available settings to enable and disable these tasks can be found at Storage Module Scheduled Tasks.

Read Only Nodes

If you wish to take advantage of native RDBMS database replication which creates read-only replicas, you will need to configure the read-only FHIR Storage module with Read-Only Mode Enabled. In this mode, the job scheduler is disabled entirely.

The following diagram shows a Smile CDR cluster with a writeable node and a read-only node using database replication. In this diagram, each of the nodes can be scaled independently, using as many node processes as needed. The Read-Only Mode Enabled setting should be enabled on the read-only node.

When using a node in read-only mode, it is still required to have a non-read-only node as well with at least one process active, even if this node is not actually serving FHIR client requests. This node is required in order to ensure that scheduled background jobs are executed.

Read Only Replicas

Read-Only Mode Limitations

Note that this setting will not prevent the server from attempting write transactions in response to FHIR operations such as create and update. This setting is intended to indicate to Smile CDR that connections to the RDBMS will always be read-only, it is not intended to enforce read-only behavior on a writeable database. If you need to ensure that write requests (e.g. FHIR create, update, etc.) are directed to the appropriate node processes, the FHIR Gateway module can be a useful component in your architecture.

6.0.5Resource Body Storage

 

By default, the FHIR Storage (Relational) module uses a database LOB column to store resource body text in a separate storage area. See the RES_TEXT column on the HFJ_RES_VER table in the HAPI FHIR Database Schema for more information.

This storage mode allows for resources of unlimited size, limited only by available memory. Data is compressed using the GZip compression algorithm in order to reduce storage requirements as well.

Optimizing for Performance

Although this form of storage is good for reducing overall storage size, it is not the most efficient in terms of read/write performance. If faster performance is desired, the Inline Resource Storage Below Size (chars) setting can be used to specify that resources under a given size should be stored as regular uncompressed text in a VARCHAR2 column called RES_TEXT_VC on the HFJ_RES_VER table.

This column is sized by default to a maximum length 4000 characters, so a value of 4000 is a sensible setting. This length is chosen because it is the maximum VARCHAR2 column length on Oracle RDBMS by default. It is possible and acceptable to manually increase the length of this column in your database, in which case you can choose a larger length for this column. Doing so may further improve performance.

For example, if you wish to inline any resources with a length below a length of 10000 characters (this has been found to be an optimal setting in many tests):

6.0.6Practical Limitations

 

Response: Generally speaking, the only real limitation is for fields that you want to index for searching. So for example, the length of Observation.note is effectively unbounded. The full resource body is temporarily stored in memory, so there are practical scalability limits if you had massive strings (ie multiple megabytes) and lots of concurrency, but other than that there is no limit.

However, in the case of fields that are indexed for searching the indexer may impose a maximum length on the field. For example, Patient.name.family will be indexed because it has a search parameter by default. The maximum length for string indexes is 200 characters.

6.0.7Configuration

 

Database Configuration

Once you have selected your module type, the first set of configuration options will be the relational database configuration itself. A complete reference of options is found on the Database configuration page.

Most importantly, you will need to configure the following properties:

Lucene FullText Configuration

The Lucene FullText configuration sets up the local filesystem to use for indexing. A complete reference of options is found on the Lucene FullText Indexing configuration page.

Most importantly, you should configure the following property:

Reference

The configuration options available for this module type are as follows: