Realtime Tables¶
This page contains information on how to create and update realtime tables using AMI SQL.
Overview¶
The Center has 2 types of tables:
- Realtime tables (which can be in-memory or on-disk)
- Historical tables
Realtime tables are SQL compliant tables that can be stored in-memory or on-disk. They are optimized for fast read and write speed.
Commands¶
There are 5 commands for creating and modifying realtime table schemas in the Center:
Each command's section provides information on its syntax, usage, and other case-specific behaviors.
Note
- Parameters in square brackets (
[]) are optional - Pipe-delimited (
|) values indicate valid options for a given key
CREATE PUBLIC TABLE¶
A new public table must have:
- A unique name across existing public tables (however a temporary and public table can share the same name)
- At least one specified column
- Uniquely named columns
Warning
Attempting to create a public table with an existing name will cause the command to fail, as will updating/inserting column values with null if they have the NONULL attribute
Syntax¶
To create a new, empty (no rows) public table, use the following command:
tblname: Name of the tablecolN: Name of Nth columncolumn_type: Accepted data type for that column
Example¶
USE Options¶
The following USE options can also be supplied:
The Persist Engine is responsible for persisting Center data onto disk so it can be re-accessed. For more information on using the Persist Engine, see this section.
The persist engine can take one of the following options:
The table will be persisted to disk using a fast, binary protocol.
Additional Options:
-
persist_dir = "/path/to/directory/for/storing/file"- The directory where the
.fastbinary file will be saved/loaded from
- The directory where the
-
persist_compact_percent = ".95"- A number between 0 and 1 which says how much of the file should contain updates & deletes before it's compacted
- E.g: a value of .95 indicates that if the file becomes 95% updates and deletes, then the file should be rebuilt
- The FAST table uses a journaling strategy, updates and deletes will get appended and can create large files
-
persist_encrypter="default"- For encrypting persisted data
Note
We currently only support 3forge's default encrypter which is an AES encrypter. If you require a custom encrypter, please reach out to us at support@3forge.com.
The table will be persisted to disk as a slower but human-readable text file. 3forge backs up the entire text file after every change (except insertion) making write speed slower compared to FAST.
Additional Options:
-
persist_dir="/path/to/directory/for/storing/file"- The directory where the
.txttext file will be saved/loaded from
- The directory where the
-
persist_encrypter="default"- For encrypting persisted data
Note
We currently only support 3forge's default encrypter which is an AES encrypter. If you require a custom encrypter, please reach out to us at support@3forge.com.
The table will be persisted as a historical table using a disk-based historical engine. Optimized for storing large volumes of data and querying on demand.
Additional Options:
- None
Whether to notify front end visualizations and external listeners when data in the table is updated.
The period that the table will conflate and broadcast changes to the front end in milliseconds.
If a cell's value changes more frequently than the refresh period, those changes will be conflated.
Behavior when a realtime Object record contains an undefined column. Valid options are:
The number of rows to allocate memory for when the table is created. The default initial capacity is 1,000 rows and there must be at least 1.
Persist Engine¶
Creating tables in the Center saves the schema (its definition) but not the table's data by default. To keep data after a session is closed, the data needs to be "persisted" into the Center.
The Persist Engine is responsible for writing table data to disk. The data can then be accessed again on restart.
Persisted data can either be:
- System tables (
__CENTER.dat,__DATASOURCE.dat,__REPLICATION.dat) - User-created public tables (file type is dependent on which Persist Engine type is used)
Note
System tables are updated during Center Replication. See this page for more information.
There are 4 protocols:
- FAST
- Stored as binary
.fastfiles - Efficient storage for rapidly changing/updating data
- Stored as binary
- TEXT
- Stored as plaintext
.datfiles - Ideal for small or static tables as any new changes will trigger a new back up resulting in slower write speeds (compared to FAST)
- System tables for replication are stored as
.datfiles
- Stored as plaintext
- HISTORICAL
- Designed for storing large volumes of data, optimized for fast retrieval
- Useful for archiving data
- See this page for more information
- Custom
- A custom user-written protocol for persisting data
- Please see this page for implementation details
Persist File Location¶
By default, persisted tables are saved to amione/persist. You can change this directory with the following properties in your local.properties file:
Note
Historical tables are stored in a separate Historical Database (amione/hdb) directory. More information can be found on the Historical Tables page.
CREATE PUBLIC TABLE AS¶
Use this command to create a new, uniquely named public table whose schema definition is the result set of an AmiScript query clause or USE...EXECUTE clause.
All rows from the query's result set will be inserted into the table.
Syntax¶
To create new public tables from a query:
tblname: Name of the table to create.
Example¶
ALTER PUBLIC TABLE¶
This command alters the schema (column names and types) of an existing table.
There are 4 types of ALTER commands:
ADD- Add new columns
RENAME ... TO- Rename columns
DROP- Delete columns
MODIFY- Change column data type
Syntax¶
To alter the schema of a table, use the following command:
-
tblname: Name of the table to alter -
alter_public_col_expr: The alter command's expressionnew_name: Name of new columncolumn_type: Data type of new columnbefore_col: Name of an existing column where the new column will go before
Note
If no
BEFOREexpression is specified, new columns will be added to the end of the table. New cells will default to null.col_name: Name of existing column to changenew_name: New name of column
col_name: Name of the column to delete
col_name: Name of the existing column to modifynew_name: New name of the column (can be the same)column_type: New data type of the column (a best effort cast will be applied)
If multiple ALTER expressions are supplied, they are evaluated from left-to-right
Example¶
RENAME PUBLIC TABLE¶
This command renames an existing table.
Warning
If another table already exists with the new name, the existing table will be implicitly dropped and replaced with the renamed table.
Syntax¶
-
tblname: Name of the table to rename. -
new_name: New name for the table.
Example¶
DROP PUBLIC TABLE¶
This command drops an existing table, along with its schema and all rows. Multiple tables can be specified in a comma-delimited list.
Syntax¶
tblname: Name of table to delete
Example¶
Supported Data Types¶
Public tables support a large variety of data types for column values:
-
- Numeric Types
BYTE,SHORT,INT,LONG,DOUBLE,FLOAT,UTC,UTCN,DATE
-
- Other Reference Types
BOOLEAN,CHAR,STRING,ENUM,BINARY,BIGDECIMAL,BIGINTEGER,COMPLEX,UUID
Note
Types are case insensitive. Both STRING and String are valid syntax.
A full description of data types including storage size is listed in the tables below.
Optional arguments are denoted by square brackets ([]). The global attributes are:
-
NONULL- If included, the column will not accept null values
- Inserts/updates of
nullwill fail
-
NOBROADCAST- If included, columns with broadcast disabled will not be included in updates sent to front end visualizations & external listeners
- This is a more granular version of the Broadcast option at the table level
Numeric Types¶
| Type | Description | Example |
|---|---|---|
BYTE [NONULL] [NOBROADCAST] |
|
age Byte NONULL |
SHORT [NONULL] [NOBROADCAST] |
|
temperature SHORT NOBROADCAST |
INT [NONULL] [NOBROADCAST] |
|
population int |
LONG [NONULL] [NOBROADCAST] |
|
id Long NONULL NOBROADCAST |
DOUBLE [NONULL] [NOBROADCAST] |
|
tot_price double |
FLOAT [NONULL] [NOBROADCAST] |
|
price float nonull |
UTC [NONULL] [NOBROADCAST] |
|
ts_millis UTC nobroadcast |
UTCN [NONULL] [NOBROADCAST] |
|
transaction_time UTCN |
DATE [NONULL] [NOBROADCAST] |
|
report_date DATE |
Other Reference Types¶
| Type | Description | Example |
|---|---|---|
BOOLEAN [NONULL] [NOBROADCAST] |
|
isactive boolean NONULL |
CHAR [NONULL] [NOBROADCAST] |
|
dept_id Char |
STRING [NONULL] [NOBROADCAST] [COMPACT] [COMPACT ASCII] [BITMAP] [ONDISK [CACHE="nnnMB"]] |
|
ticker STRING |
ENUM [NONULL] [NOBROADCAST] |
|
buy_or_sell ENUM NONULL |
BINARY [NONULL] [NOBROADCAST] [ONDISK [CACHE="nnnMB"]] |
|
filedata BINARY NOBROADCAST To cache \~100 MB: cached_file BINARY ONDISK CACHE="100000000" |
BIGDECIMAL [NONULL] [NOBROADCAST] |
|
tax_rate BIGDECIMAL |
BIGINTEGER [NONULL] [NOBROADCAST] |
|
mod_key BigInteger |
COMPLEX [NONULL] [NOBROADCAST] |
|
complement COMPLEX NONULL NOBROADCAST |
UUID [NONULL] [NOBROADCAST] |
|
uid UUID nobroadcast |
String Directives¶
Strings have additional optional directives for performance optimization.
| Directive | Storage | Example |
|---|---|---|
ONDISK [CACHE="nnnMB"] |
|
To cache 2 gigabytes: cached_string_data STRING ONDISK CACHE="2GB" |
COMPACT |
|
name STRING COMPACT |
COMPACT ASCII |
|
firstname STRING COMPACT ASCII |
BITMAP |
|
permissions string bitmap |
Determining which type of String is best will be case-dependent and ultimately up to developer discretion. We generally recommend the following set of guidelines to help:
- For data that never repeats and is queried often,
STRINGis the most flexible and preferred choice - For columns with data that does not repeat but is not queried often,
STRING COMPACT(orSTRING COMPACT ASCIIfor non-extended ascii data) offers a lower memory footprint - For repeating data, generally
STRING BITMAPis best
Below is a table outlining the advantages/disadvantages of each.
String Type Comparison¶
| Type | Size | Advantage | Disadvantage | Usage Scenario |
|---|---|---|---|---|
STRING |
Variable | |||
STRING COMPACT |
32 bits |
|
||
STRING COMPACT ASCII |
32 bits | STRING COMPACT |
STRING COMPACT, except limited to shorter strings that are basic ascii (not extended) |
|
STRING BITMAP |
8, 16, or 32 bits depending on number of unique values | STRING COMPACT type columns |
STRING columns |
|
ENUM |
32-bit address |
STRING BITMAP is preferred |
||
STRING ONDISK |
64-bit address |
Temporary Tables and Collection Types¶
Data types like List, Set, and Map are not valid column types for public tables but can be used in temporary tables. This is because the data cannot be persisted to disk.
We generally discourage the use of temporary tables, however if you are using them please be aware of the following:
- Temporary tables are not persisted into the Center schema
- Temporary tables are session specific to both the user's Web and Center session
- Temporary tables are dropped when the session is closed
Reserved Columns¶
3forge has a number of reserved columns listed in the table below. If any of these columns are declared, they will be automatically populated by the 3forge engine.
Columns A, D, T, and W will be populated even if they are not declared.
Warning
When declaring reserved columns, the column's data type must match the data type specified below, otherwise table creation will fail.
All times are since Unix epoch in milliseconds.
| Name | Type | Label | Mutable | Description |
|---|---|---|---|---|
A |
String |
AMI-Center | Stores the name of the AMI Center | |
C |
Long |
Created Time | Time that the record was inserted into the table | |
D |
Long |
AMI-ID | A unique auto-generated incrementing id for the row. Unique across all tables. | |
E |
Long |
Expires Time | INSERT, UPDATE | Time when the row should automatically be deleted (expires).
|
I |
Object |
UniqueID | INSERT | The Id (I) value supplied from the real-time streaming on the Object (O) message. See this page for more information. |
M |
Long |
Modified Time | Most recent time that the record was updated (initially the time the row was inserted). | |
P |
String |
Application | INSERT | The Login Id (I) value supplied from the realtime messaging API on login (L) message. |
V |
Int |
Revision | The number of times the record has been updated (initially zero). | |
T |
String |
Table Name | The name of the table. All cells will contain the same value (this is for backwards compatibility). | |
W |
Long |
Current Time | Stores the current Unix timestamp. |
AMI-ID (I) Column¶
The I column (and P by extension) behavior can be used to support upserting. When defined, 3forge treats the I column as a pseudo-primary key.
Note
If both I and P are defined, 3forge uses the combination as a pseudo-primary key instead.
Attempting to insert an Object into a table with an existing non-null I value will update the existing row instead of inserting a new one.
Note
This is different from standard primary keys as two rows can exist in a table with the same key if the key is null
To use standard primary keys, please see this page.
Capacity Planning¶
Overview¶
Below is the formula to use for calculating the amount of memory to expect public tables to consume, based on the types of data being stored. For total capacity planning of 3forge in memory database, one should run this on each table and aggregate the results.
Where each variable is:
| Variable | Definition |
|---|---|
table_size_mb |
The total number meg you can expect the table to require |
table_suggested_capacity_mb |
3forge Recommendation for hardware capacity planning |
row_cnt |
Number of rows |
idx_cnt |
Number of indexes on the table, composite indexes are larger |
null_col_cnt |
Number of non-string columns that allow null |
data_size |
Sum(column_type_sizes), see column types below |
Where data size is defined below:
| Column Type | Data Size (bytes) |
|---|---|
UTC,UTCN,Double,Long |
8 |
Int,Float |
4 |
Char,Short |
2 |
Byte |
1 |
Boolean |
1/8 |
Enum (legacy) |
4 |
String BITMAP1 |
1 |
String BITMAP2 |
2 |
String BITMAP3 |
3 |
String COMPACT |
String Size * 2 + 6 bytes |
String COMPACT ASCII |
String Size * 1 + 5 bytes |
String |
String Size * 2 + 64 bytes |
Binary |
Length in Bytes + 56 bytes |
String ONDISK |
8 |
Binary ONDISK |
8 |
BIGDECIMAL |
68+size of number in bytes |
BIGINTEGER |
64+size of number in bytes |
COMPLEX |
128 |
UUID |
128 |
Examples¶
Example 1: Small Table¶
Below, we walk through the math given the below table, assuming 10 million executions and 1 index on symbol:
Below is the actual experienced capacity for 100,000,000 executions being sent into an AMI instance:
Example 2: Large Table¶
Test of 20,000,000,000 (20 billion) cells using 33 columns x 607,000,000 rows = ~171 GB RAM Used = Suggested ~ 342 GB RAM be reserved.
List of System Tables¶
__COLUMN¶
Column information for tables in the Center.
| Variables | Description |
|---|---|
TableName |
Name of all the tables |
ColumnName |
Name of columns within each table |
ColumnFormula |
Formula associated with column |
DataType |
Data type of column (String, Enum, Integer, etc.) |
NoNull |
If column is Nullable |
Position |
Position of column within the associated table |
DefinedBy |
Which user defined (USER, AMI, SYSTEM) |
__COMMAND¶
Command definition and information for user-defined commands for realtime messaging.
| Variables | Description |
|---|---|
CI |
Connection ID of the connection that this command was registered using |
RI |
Relay ID that this command was registered using |
ID |
Command ID of the command, typically the purpose of the command (e.g: "cancel_order"), not guaranteed unique |
AR |
Input arguments for form fields. ({"form":{"inputs":[{"label":"Symbol","required":true, "var":"symbol","type":"text"}]}}) |
PR |
Priority for display in the menu. Commands with a higher priority are listed in the context menu above those with lower priority (0 = highest priority, 1 = 2nd highest, etc.) |
NA |
Name of the command that appears on the GUI after the user right-clicks on a row in AMI (e.g: "order.cancel") |
FL |
Command filter. An expression that will determine which rows the command will be available at on a panel level (e.g: panel.types=="Orders" or panel.types=="Executions") |
WH |
Conditional "where" clause. It determines which rows the command will be available at a row/node level (e.g: qty>0 && user.canbust=="true") |
HP |
Explanation/outcome of the command. (E.g: "This command is used to cancel order(s)") |
SM |
Constrains the number of rows that can be selected when running the command (1-10) |
AmiScript |
AmiScript will reflect here, if any |
N |
Enabled where (expression). (E="Quantity==300"; the command E will only be enabled where the Quantity = 300) |
L |
Command level. Permissions Level of 0 means remove command, and any other number is used for entitlements as part of the AMI entitlement engine |
F |
Fields; returns the values of specified fields (e.g: price, status, level) |
I |
Relay name with command name (e.g: 29002751:CancelCmd) |
P |
Login name used to access the realtime database (e.g: "demo") |
V |
Number of times a row is being updated |
M |
Command modified time in milliseconds |
C |
Command created time in milliseconds |
__CONNECTION¶
Information on connections to the Center.
| Variables | Description |
|---|---|
AI |
Login ID associated with this connection, not guaranteed unique |
EC |
Connection/login attempt error count |
CI |
Connection ID of logged in user |
MA |
ID remote machine of logged in user |
MC |
Message count from current connection |
O |
Used to supply options about the current session’s connection. The following options are available:
|
PL |
A fully qualified Java class name to a 3forge Relay plugin. The class must implement the com.vortex.agent.AmiPlugin interface |
RI |
The Relay which was used to run on (e.g: relay_0) |
RP |
Remote host port used |
RH |
Remote host name, localhost, IP address |
CT |
Time of connection made |
__DATASOURCE¶
Information on datasources available to this Center.
| Variables | Description |
|---|---|
NM |
Datasource name, self-specified |
AD |
Adapter type (RestAPI, MySQL) |
UR |
Datasource URL (protocol://[host]/[database][?properties], e.g: https://example.com/api/data) |
US |
Username, credentials to access datasource URL |
PW |
Unencrypted password, credentials to access datasource URL (Deprecated) |
Password |
Encrypted password, credentials to access datasource URL |
OP |
Additional options
|
RelayId |
Relay to run on option in dropdown (e.g: relay_0) |
PermittedOverrides |
Combination of URL, USERNAME, PASSWORD, OPTIONS, RELAY |
__DATASOURCE_TYPE¶
Information on the list of supplied datasource adapters for this Center.
| Variables | Description |
|---|---|
Description |
Description of associated datasource (Shell Command, AMIDB, MySQL JDBC) |
I |
Identifier of datasource type (SHELL, AMIDB, MYSQL) |
ClassType |
Class of plugin associated with datasource (e.g: com.f1.ami.center.ds.AmiShellDatasourcePlugin, com.f1.ami.center.ds.AmiAmiDbDatasourcePlugin, com.f1.ami.plugins.mysql.AmiMysqlDatasourcePlugin, etc) |
Icon |
Icon (svg file) associated with the datasource |
Properties |
Map of properties associated with the datasource |
__INDEX¶
Information on column indexes across tables in the Center.
| Variables | Description |
|---|---|
IndexName |
Name of index (e.g: pk, relayId, etc) |
TableName |
Table associated with the index |
ColumnName |
Column of table associated with the index |
IndexType |
Type of indexing (SORT, HASH) |
IndexPosition |
Position of column in table associated with the index |
Constraint |
Constraints of index (PRIMARY, NONE) |
DefinedBy |
Which user defined (USER, AMI, SYSTEM) |
__PLUGIN¶
Information on all the plugins including datasource adapters available to the Center.
| Variables | Description |
|---|---|
PluginName |
Name of plugin (MYSQL, ORACLE, SSH, MSEXCEL) |
PluginType |
Plugin Type (DATASOURCE, PROCEDURE, TIMER, TRIGGER) |
ClassType |
Class of plugin (com.f1.ami.center.ds.AmiShellDatasourcePlugin, com.f1.ami.center.ds.AmiAmiDbDatasourcePlugin, com.f1.ami.plugins.mysql.AmiMysqlDatasourcePlugin, etc) |
Arguments |
Arguments/Parameters used in conjunction with plugin |
__PROCEDURE¶
Information on procedures stored in the Center.
| Variables | Description |
|---|---|
ProcedureName |
Name of procedure (e.g: __ADD_DATASOURCE, __REMOVE_DATASOURCE, __RESET_TIMER_STATS, etc) |
ProcedureType |
Type of procedure (e.g: AMISCRIPT, __SYSTEM) |
ReturnType |
Return type after running procedure (e.g: Object, String, Integer, etc) |
Arguments |
Arguments/Parameters used in conjunction with procedure |
Options |
Additional procedure-specific options (scripts, arguments, etc) |
DefinedBy |
Which user defined the procedure (USER, AMI, SYSTEM) |
__PROPERTY¶
Information on configured properties found in local.properties that use the prefix ami.property..
E.g: ami.property.someprop=123 corresponds to the record PropertyName="someprop", PropertyValue="123"`.
| Variables | Description |
|---|---|
PropertyName |
Name of property |
PropertyValue |
Value of property |
__RELAY¶
Information on relays that this Center is connected to.
| Variables | Description |
|---|---|
MachineUid |
Unique Machine ID of the host (e.g: UID_DESKTOP-RVO4948) |
ProcessUid |
System Generated Process Id (e.g: F1-Inw6XE0p8YaqdbREAp5MxN) |
StartTime |
Starting time in UTC (e.g: 2022-01-20 03:03:06.101 EST) |
ServerPort |
Connection port (e.g: 3289) |
RelayId |
Relay ID (e.g relay_0) |
Hostname |
Host name (e.g: DESKTOP-RVO4948) |
ConnectTime |
Connection time in UTC (e.g: 2022-01-20 03:03:28.299 EST) |
__RESOURCE¶
Information on resources available to the Center (by default amione/resources).
| Variables | Description |
|---|---|
I |
Name of file |
ModifiedOn |
Modified time in milliseconds since Unix epoch |
Checksum |
Unique checksum value used for validation |
FileSize |
File size in bytes |
ImageWidth |
If image, width in pixels (-1 if not) |
ImageHeight |
If image, height in pixels (-1 if not) |
__TABLE¶
Information on all tables in the Center.
| Variables | Description |
|---|---|
TableName |
Name of table |
Broadcast |
Whether front end visualizations & external listeners will be notified as data is updated in the table (true or false) |
RefreshPeriodMs |
The period in milliseconds that the table will conflate and broadcast changes to front end at. If a cell's value changes more frequently than the refresh period, those changes will be conflated |
PersistEngine |
If the table is persisted, which Persist Engine protocol was used |
OnUndefColumn |
Behavior when a realtime Object record contains an undefined column. Valid options are:
|
DefinedBy |
The ID of the owner |
InitialCapacity |
The number of rows to allocate memory for when the table is created. The default initial capacity is 1,000 rows and there must be at least 1 |
__TIMER¶
Information on any timers in the Center.
| Variables | Description |
|---|---|
TimerName |
Name of the Timer created. |
TimerType |
Either AMISCRIPT or a user-defined custom timer type created using timer plugin. |
Priority |
A number that is set when two or more timers have the same exact scheduled time. The lowest value is executed first. |
Schedule |
A positive number defining the period in milliseconds between timer executions
|
Options |
AmiScript to run when timer is executed |
DefinedBy |
The ID of the owner |
LastRunTime |
Timestamp when the timer is last ran |
NextRunTime |
Timestamp that the next timer would run |
Enabled |
Is the timer currently active |
__TRIGGER¶
| Variables | Description |
|---|---|
TriggerName |
Name of the trigger to create, must be unique within the database |
TableName |
Name of the table(s) that will cause the trigger to execute |
TriggerType |
Either AMISCRIPT or a user-defined custom trigger type created using trigger plugin. |
Priority |
A number that is set when two or more triggers are triggered at the same time. The lowest value is executed first |
Options |
AmiScript to run when trigger is executed |
DefinedBy |
The ID of the owner |
Enabled |
Is the trigger currently active |



