Compute Resources#
The RelationalAI (RAI) Native App requires compute resources to evaluate queries from RAI Python models. This section provides an overview of these compute resources and how they are managed. For information on costs associated with these resources, see Cost Management.
Table Of Contents#
App Warehouse#
The RAI Native App utilizes an X-SMALL
Snowflake warehouse for Snowflake interoperability.
This warehouse is named RELATIONAL_AI_ERP_WAREHOUSE
and is fully managed by the native app.
It is automatically provisioned when you activate the app and suspended when you deactivate the app.
See the Snowflake documentation for information on managing warehouses.
Compute Pools#
To run on Snowpark Container Services, the RAI Native App requires three compute pools:
Name | Instance Family | Description |
---|---|---|
RELATIONAL_AI_ERP_COMPUTE_POOL | CPU_X64_XS | Used for internal app operations. |
RELATIONAL_AI_HIGHMEM_X64_S | HIGHMEM_X64_S | Runs engines that execute queries from RAI Python models. |
RELATIONAL_AI_HIGHMEM_X64_M | HIGHMEM_X64_M | Runs engines that execute queries from RAI Python models. |
These compute pools are fully managed by the RAI Native App. They are automatically provisioned when you activate the app and suspended when you deactivate the app.
Additionally, the RAI Native App provisions three compute pools with CPU_X64_S
, CPU_X64_M
, and HIGHMEM_X64_L
instance families.
These pools are reserved for future use and are not currently utilized by the app.
Engines#
Engines process queries and other transactions from RAI Python models. They are hosted on the compute pools managed by the RAI Native App. Like Snowflake virtual warehouses, engines can be independently created for workload isolation or scaling purposes.
An engine’s size is determined by its host compute pool’s instance family.
Refer to the Snowflake documentation for CPU, memory, and storage details for each instance family.
Currently, RAI supports the HIGHMEM_X64_S
and HIGHMEM_X64_M
instance families.
CDC Engine#
If you have enabled the CDC Service, an engine named CDC_MANAGED_ENGINE
is automatically provisioned whenever changes to a data stream are detected.
This engine processes changes to Snowflake tables and views shared with the RAI Native App for use in RAI models.
It is suspended automatically after 30 minutes of inactivity or when you disable the CDC Service.
By default, the CDC_MANAGED_ENGINE
is provisioned in the app’s HIGHMEM_X64_S
compute pool.
However, you may alter the CDC engine size if needed.
Auto-Created User Engines#
Engines are automatically created for Python users when they create a model.
The names and host compute pools for these engines are configured by the engine
and engine_size
configuration keys in a user’s raiconfig.toml
file or a Python Config
object:
Configuration Key | Default Value |
---|---|
engine | The user’s Snowflake username, with any dot characters replaced with an underscore. For example, if a user’s username is jane.doe@relational.ai , then the default engine name is jane_doe . |
engine_size | HIGHMEM_X64_S |
Auto-created engines are automatically suspended after 60 minutes of inactivity. See Change Engine Auto-Suspend Time for details on altering the auto-suspend time for an engine.
User-Managed Engines#
If you need fine-grained control over resource allocation, you can create and manage engines manually using SQL, Python, or the RAI CLI.
RAI models can then be configured to use specific engines for query evaluation by setting the engine
configuration key to the name of the desired engine.
See Engine Management for more details.
Engine Suspension#
By default, new engines automatically suspend after one hour of inactivity. While suspended, an engine does not consume compute resources. Transactions sent to a suspended engine will fail until the engine is resumed.
To change the inactivity window for an engine:
-
Set the
auto_suspend_mins
option when creating a new engine. -
Use the
api.alter_engine_auto_suspend_mins()
procedure to update the auto-suspend time for an existing engine. See Change Engine Auto-Suspend Time for details. -
Set the
auto_suspend_mins
configuration key in a user’sraiconfig.toml
file or aConfig
object. If unset, the default value of60
minutes applies. Changes to this key take effect the next time the user creates a model.
Suspended engines automatically resume via the RAI Python API when users execute a query. You can also manually resume a suspended engine.
Auto-suspension saves costs by avoiding unnecessary resource use.
However, it may cause latency when queries require resuming the engine.
To avoid latency, set auto_suspend_mins
to 0
to disable auto-suspension.
Concurrent Transactions#
Each engine supports up to 8 concurrent transactions and has a queue capacity of 128 transactions with first-in/first-out priority. However, engines may process resource-intensive transactions, like large-scale graph algorithms, sequentially.
By default, each user has a dedicated engine created for them automatically the first time they create a model. This ensures transactions are isolated per user by default, though a user can run multiple concurrent transactions on their engine.
Concurrent transactions on the same engine may impact each other’s performance. To avoid coordination issues, especially when resource-intensive transactions are involved, consider creating a dedicated engine for each workload.
You can determine if an engine is overloaded by monitoring it for a large number of transactions in the QUEUED
or CREATED
state.
See Monitor Engine Transactions for details.
Engine Management#
You can manage engines using SQL, Python, or the RAI CLI.
Create an Engine#
Requires the eng_admin
application role.
To create an engine, pass strings with the desired engine name and size to the api.create_engine()
procedure:
#CALL relationalai.api.create_engine(
'my_engine',
'HIGHMEM_X64_S', -- Change to HIGHMEM_X64_M for a larger engine.
{'auto_suspend_mins': 60}, -- Auto-suspend after 60 minutes of inactivity.
NULL
);
/*+----------+
| Success. |
+----------+ */
To create an engine using Python, create a Provider
instance and use its .sql()
method to execute the api.create_engine()
procedure.
#import relationalai as rai
# Get a provider instance.
app = rai.Provider()
# Create a HIGHMEM_X64_S engine configured to auto-suspend after 60 minutes of inactivity.
app.sql("""
CALL relationalai.api.create_engine(
'my_engine',
'HIGHMEM_X64_S' -- Change to HIGHMEM_X64_M for a larger engine.
{'auto_suspend_mins': 60}, -- Auto-suspend after 60 minutes of inactivity.
NULL
);
""")
To create an engine using the RAI CLI, run the engines:create
command with the desired engine name and size provided as arguments to the --name
and --size
options:
## Create a HIGHMEM_X64_S engine.
rai engines:create --name my_engine --size HIGHMEM_X64_S --auto_suspend_mins 60
# Create a HIGHMEM_X64_M engine.
rai engines:create --name my_engine --size HIGHMEM_X64_M --auto_suspend_mins 60
Engine names must be between 3 and 50 characters long and can contain only a-z
, A-Z
, 0-9
, and _
characters.
Note that it may take several minutes for the engine to be provisioned and ready for use.
An engine’s size is the same as its host compute pool’s instance family. See Compute Pools for details on the available instance families.
Delete an Engine#
Requires the eng_admin
application role.
To delete an engine, pass the engine name to the api.delete_engine()
procedure:
#-- Delete the engine named 'my_engine'.
CALL relationalai.api.delete_engine('my_engine');
/*+-----------+----------------------+
| NAME | MESSAGE |
|-----------+----------------------|
| my_engine | deleted successfully |
+-----------+----------------------+ */
To delete an engine using Python, create a Provider
instance and use its .sql()
method to execute the api.delete_engine()
procedure:
#import relationalai as rai
# Get a provider instance.
app = rai.Provider()
# Delete the engine named 'my_engine'.
app.sql("CALL relationalai.api.delete_engine('my_engine')")
To delete an engine using the RAI CLI, run the engines:delete
command with the engine name provided as an argument to the --name
option:
#rai engines:delete --name my_engine
When an engine is deleted, all current and queued transactions are cancelled. Any new transactions submitted to the engine will fail.
List Engines#
Requires the eng_user
application role.
To list all engines, query the api.engines
view:
#SELECT * FROM relationalai.api.engines;
/*+------------------------+--------------+------+-------+-----------------------+--------------------------------+-------------------------------+-----------------------------+-------------------------+
| NAME | ID | SIZE | STATUS | CREATED_BY | CREATED_ON | UPDATED_ON | COMPUTE_POOL | VERSION |
|------------------------+--------------+------+--------+----------------------+--------------------------------+-------------------------------+-----------------------------+-------------------------|
| CDC_MANAGED_ENGINE | b7c1d8f9a2b3 | S | READY | SYSTEM | 2024-10-27 15:22:15.500 -0700 | 2024-10-27 15:22:16.731 -0700 | RELATIONAL_AI_HIGHMEM_X64_S | 2024.10.27-e829e39d |
| john_doe | e4f5a6d7c8e9 | M | READY | john.doe@company.com | 2024-10-27 17:29:53.110 -0700 | 2024-10-27 17:29:54.319 -0700 | RELATIONAL_AI_CPU_X64_M | 2024.10.27-e829e39d |
+------------------------+--------------+------+--------+----------------------+--------------------------------+-------------------------------+-----------------------------+-------------------------+ */
Refer to the reference docs for details about each column in the api.engines
view.
To list all engines using Python, create a Provider
instance and use its .sql()
method to query the api.engines
view:
#import relationalai as rai
# Get a provider instance.
app = rai.Provider()
# List all engines.
engines = app.sql("SELECT * FROM relationalai.api.engines")
print(engines)
To list all engines using the RAI CLI, run the engines:list
command:
#rai engines:list
Get Engine Details#
Requires the eng_user
application role.
To get details about a specific engine, pass the engine name to the api.get_engine()
procedure:
#-- Get details about the CDC engine. Note that if CDC is disabled, this engine may not exist.
CALL relationalai.api.get_engine('CDC_MANAGED_ENGINE');
/*+---------------------+--------------+-------------------------+------+--------+------------+-------------------------------+------------------------------ +-----------------------------+
| NAME | ID | VERSION | SIZE | STATUS | CREATED_BY | CREATED_ON | UPDATED_ON | COMPUTE_POOL |
|---------------------+--------------+-------------------------+------+--------+------------+-------------------------------+-------------------------------+-----------------------------|
| CDC_MANAGED_ENGINE | a9d7f3b2c8e4 | 2024.10.27-e829e39d | S | READY | SYSTEM | 2024-10-27 15:22:15.500 -0700 | 2024-10-27 15:22:16.731 -0700 | RELATIONAL_AI_HIGHMEM_X64_S |
+---------------------+--------------+-------------------------+------+--------+------------+-------------------------------+-------------------------------+-----------------------------+ */
To get details about a specific engine using Python, create a Provider
instance and use its .sql()
method to execute the api.get_engine()
procedure:
#import relationalai as rai
# Get a provider instance.
app = rai.Provider()
# Get details about the engine named 'my_engine'.
engine = app.sql("CALL relationalai.api.get_engine('my_engine')")
print(engine)
To get details about a specific engine using the RAI CLI, run the engines:get
command with the engine name provided as an argument to the --name
option:
#rai engines:get --name my_engine
View Idle Engines#
Requires the eng_user
application role.
Engines that have been automatically scheduled for suspension due to inactivity are considered idle.
You can view idle engines by filtering the api.engines
view on the for rows where the STATUS
column is READY
and the SUSPENDS_AT
column is not null:
#SELECT * FROM relationalai.api.engines
WHERE STATUS = 'READY' AND SUSPENDS_AT IS NOT NULL;
Engines that have been automatically scheduled for suspension due to inactivity are considered idle.
To view idle engines using Python, create a Provider
instance and use its .sql()
method to query the api.engines
view:
#import relationalai as rai
# Get a provider instance.
app = rai.Provider()
# List all idle engines.
idle_engines = app.sql("""
SELECT * FROM relationalai.api.engines
WHERE STATUS = 'READY' AND SUSPENDS_AT IS NOT NULL;
""")
print(idle_engines)
Resume a Suspended Engine#
Requires the eng_admin
application role.
To resume a suspended engine, pass the engine name to the api.resume_engine()
procedure:
#-- Resume the engine 'my_engine' if it is suspended.
CALL relationalai.api.resume_engine('my_engine');
/*+-----------+----------------------+
| NAME | MESSAGE |
|-----------+----------------------|
| my_engine | resumed successfully |
+-----------+----------------------+ */
To resume a suspended engine using Python, create a Provider
instance and use its .sql()
method to execute the api.resume_engine()
procedure:
#import relationalai as rai
# Get a provider instance.
app = rai.Provider()
# Resume the engine named 'my_engine'.
app.sql("CALL relationalai.api.resume_engine('my_engine')")
Change Engine Auto-Suspend Time#
Requires the eng_admin
application role.
To change the auto-suspend time for an engine, pass the engine name and the desired auto-suspend time in minutes to the api.alter_engine_auto_suspend_mins()
procedure:
#-- Set the auto-suspend time for the engine 'my_engine' to 30 minutes.
CALL relationalai.api.alter_engine_auto_suspend_mins('my_engine', 30);
/*+---------+
| Success |
+---------+ */
To change the auto-suspend time for an engine, create a Provider
instance and use its .sql()
method to execute the api.alter_engine_auto_suspend_mins()
procedure:
#import relationalai as rai
# Get a provider instance.
app = rai.Provider()
# Set the auto-suspend time for the engine 'my_engine' to 30 minutes.
app.sql("CALL relationalai.api.alter_engine_auto_suspend_mins('my_engine', 30)")
Setting the auto-suspend time to 0
will prevent the engine from suspending due to inactivity.
Resize an Engine#
Requires the eng_admin
application role.
Engines cannot be resized on-the-fly. To resize an engine, first delete the engine and then create a new engine with the same name and a different size:
#-- Delete the engine named 'my_engine'.
CALL relationalai.api.delete_engine('my_engine');
/*+-----------+----------------------+
| NAME | MESSAGE |
|-----------+----------------------|
| my_engine | deleted successfully |
+-----------+----------------------+ */
-- Create a HIGHMEM_X64_M engine with the same name.
CALL relationalai.api.create_engine('my_engine', 'HIGHMEM_X64_M');
/*+----------+
| Success. |
+----------+ */
Engines cannot be resized on-the-fly. To resize an engine, first delete the engine and then create a new engine with the same name and a different size:
#import relationalai as rai
# Get a provider instance.
app = rai.Provider()
# Delete the engine named 'my_engine'.
app.sql("CALL relationalai.api.delete_engine('my_engine')")
# Create a HIGHMEM_X64_M engine with the same name.
app.sql("CALL relationalai.api.create_engine('my_engine', 'HIGHMEM_X64_M')")
Engines cannot be resized on-the-fly. To resize an engine, first delete the engine and then create a new engine with the same name and a different size:
## Delete the engine named 'my_engine'.
rai engines:delete --name my_engine
# Create a HIGHMEM_X64_M engine with the same name.
rai engines:create --name my_engine --size HIGHMEM_X64_M
Monitor Engine Transactions#
Requires the eng_user
application role.
You can view an engine’s transactions by querying the api.transactions
view a filtering by the ENGINE_NAME
column:
#-- List transactions for the engine named 'my_engine'.
SELECT * FROM relationalai.api.transactions WHERE ENGINE_NAME = 'my_engine';
/*+--------------------------------------+---------------+-----------+-----------+-----------------------+----------+-------------------------------+-------------------------------+-------------+
| ID | DATABASE_NAME | STATE | READ_ONLY | CREATED_BY | DURATION | CREATED_ON | FINISHED_AT | ENGINE_NAME |
|--------------------------------------+---------------+-----------+-----------+-----------------------+----------+-------------------------------+-------------------------------+-------------|
| 02c8fa31-1234-5678-90ab-abcdef123456 | MyModel | ABORTED | TRUE | john.doe@company.com | 7643 | 2024-10-28 08:00:12.123 -0700 | 2024-10-28 08:00:19.766 -0700 | my_engine |
| 03d9ab41-2345-6789-01bc-bcdef2345678 | MyModel | COMPLETED | TRUE | john.doe@company.com | 500 | 2024-10-28 08:02:15.456 -0700 | 2024-10-28 08:02:15.956 -0700 | my_engine |
| 04e8bc52-3456-7890-12cd-cdef34567890 | MyModel | RUNNING | FALSE | john.doe@company.com | 3200 | 2024-10-28 08:05:00.789 -0700 | 2024-10-28 08:05:03.989 -0700 | my_engine |
+--------------------------------------+---------------+-----------+-----------+-----------------------+----------+-------------------------------+-------------------------------+-------------+ */
To list all transactions using Python, create a Provider
instance and use its .sql()
method to query the api.transactions
view:
#import relationalai as rai
# Get a provider instance.
app = rai.Provider()
# List all transactions for the engine named 'my_engine'.
engine = 'my_engine'
transactions = app.sql(f"SELECT * FROM relationalai.api.transactions WHERE engine_name = {engine}")
print(transactions)
You can monitor an engine’s transactions by passing the engine name to the transactions:list
command’s --engine
option:
## List transactions for the engine named 'my_engine'. The `--all-users` flag
# ensures that transactions from all users are included in the list.
rai transactions:list --all-users --engine my_engine
Note that multiple transactions for the same engine may be RUNNING
simultaneously.
See Concurrent Transactions for information on how concurrent transactions are handled.
Take note of the following states. While occasional occurrences are normal, a high volume may indicate potential issues:
Status | Description |
---|---|
CREATED | The transaction has been accepted but is not yet in the engine queue. If it remains in this state, the engine’s resources are at capacity. Consider increasing the engine size or cancelling the transaction and running it on a different engine. |
QUEUED | The transaction is in the engine’s queue. If it remains in this state, the engine’s concurrency limit has been reached. Wait for the transaction to leave the queue or cancel it and rerun on a different engine. |
ABORTED | The transaction was cancelled or failed due to an error. Check the ABORT_REASON column for more details. |
Get Transaction Details#
Requires the eng_user
application role.
To get details about a specific transaction, pass the transaction ID to the api.get_transaction()
procedure:
#-- Get details for the transaction with ID '02c8fa31-1234-5678-90ab-abcdef123456'.
CALL relationalai.api.get_transaction('02c8fa31-1234-5678-90ab-abcdef123456');
/*+--------------------------------------+---------------+-----------+--------------+-----------+-----------------------+----------+-------------------------------+-------------------------------+-------------+
| ID | DATABASE_NAME | STATE | ABORT_REASON | READ_ONLY | CREATED_BY | DURATION | CREATED_ON | FINISHED_AT | ENGINE_NAME |
|--------------------------------------+---------------+-----------+--------------+-----------+-----------------------+----------+-------------------------------+-------------------------------+-------------|
| 02c8fa31-1234-5678-90ab-abcdef123456 | MyModel | COMPLETED | NULL | TRUE | john.doe@company.com | 7643 | 2024-10-28 08:00:12.123 -0700 | 2024-10-28 08:00:19.766 -0700 | my_engine |
+--------------------------------------+---------------+-----------+--------------+-----------+-----------------------+----------+-------------------------------+-------------------------------+-------------+ */
To get details about a specific transaction, create a Provider
instance and use its .sql()
method to execute the api.get_transaction()
procedure:
#import relationalai as rai
# Get a provider instance.
app = rai.Provider()
# Get details for the transaction with ID '02c8fa31-1234-5678-90ab-abcdef123456'.
transaction = app.sql("CALL relationalai.api.get_transaction('02c8fa31-1234-5678-90ab-abcdef123456')")
print(transaction)
To get details about a specific transaction, pass the transaction’s ID to the --id
option of the transactions:get
command:
## Get details for the transaction with ID '02c8fa31-1234-5678-90ab-abcdef123456'.
rai transactions:get --id 02c8fa31-1234-5678-90ab-abcdef123456
Cancel a Transaction#
Requires the eng_user
application role.
To cancel a transaction, pass the transaction ID to the api.cancel_transaction()
procedure:
#-- Cancel the transaction with ID '02c8fa31-1234-5678-90ab-abcdef123456'.
CALL relationalai.api.cancel_transaction('02c8fa31-1234-5678-90ab-abcdef123456');
/*+------------------------+
| Cancelling transaction |
+------------------------+ */
To cancel a transaction, create a Provider
instance and use its .sql()
method to execute the api.cancel_transaction()
procedure:
#import relationalai as rai
# Get a provider instance.
app = rai.Provider()
# Cancel the transaction with ID '02c8fa31-1234-5678-90ab-abcdef123456'.
app.sql("CALL relationalai.api.cancel_transaction('02c8fa31-1234-5678-90ab-abcdef123456')")
To cancel a transaction using, pass the transaction’s ID to the --id
option of the transactions:cancel
command:
## Cancel the transaction with ID '02c8fa31-1234-5678-90ab-abcdef123456'.
rai transactions:cancel --id 02c8fa31-1234-5678-90ab-abcdef123456
It may take a few moments for the transaction to be cancelled.
You may monitor the transaction and confirm that it has been cancelled once the STATE
is reported as CANCELED
.