From fb484af72ed9042989d59322fb65f10d1fc98833 Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Fri, 27 Mar 2020 16:09:59 +0100 Subject: [PATCH 001/300] Update version to 2020.1 final --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index c111b0426..0b0806f9f 100644 --- a/conf.py +++ b/conf.py @@ -25,7 +25,7 @@ author = 'Arnon Shimoni, Jake Wheat' # The full version, including alpha/beta/rc tags -release = '2020.1-b1' +release = '2020.1' # -- General configuration --------------------------------------------------- From 8ccea418913a32f1efbf46dde5bd85acec471082 Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Mon, 6 Apr 2020 12:38:11 +0200 Subject: [PATCH 002/300] Improve default permissions documentation --- guides/features/access_control.rst | 19 +++++++++++---- .../alter_default_permissions.rst | 23 +++++++++++++------ .../access_control_commands/grant.rst | 5 +++- .../access_control_commands/revoke.rst | 4 ++-- 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/guides/features/access_control.rst b/guides/features/access_control.rst index 4e3621c7f..c4cf11f8f 100644 --- a/guides/features/access_control.rst +++ b/guides/features/access_control.rst @@ -185,7 +185,7 @@ Permissions GRANT ----- -Grant gives permissions to a role. +:ref:`grant` gives permissions to a role. .. code-block:: postgres @@ -257,7 +257,7 @@ Examples: REVOKE ------ -Revoke removes permissions from a role. +:ref:`revoke` removes permissions from a role. .. code-block:: postgres @@ -308,15 +308,16 @@ Examples: Default permissions ------------------- -The default permissions system can be used to automatically grant -permissions to newly created objects. See the departmental example -below for one way it can be used. +The default permissions system (See :ref:`alter_default_permissions`) +can be used to automatically grant permissions to newly +created objects (See the departmental example below for one way it can be used). A default permissions rule looks for a schema being created, or a table (possibly by schema), and is table to grant any permission to that object to any role. This happens when the create table or create schema statement is run. + .. code-block:: postgres @@ -429,6 +430,8 @@ As a superuser, you connect to the system and run the following: ALTER DEFAULT PERMISSIONS FOR my_schema_database_designers IN my_schema FOR TABLES GRANT SELECT,INSERT,DELETE TO my_schema_updaters; + -- For every table created by my_schema_database_designers, give access to my_schema_readers: + ALTER DEFAULT PERMISSIONS FOR my_schema_database_designers IN my_schema FOR TABLES GRANT SELECT TO my_schema_readers; @@ -436,6 +439,12 @@ As a superuser, you connect to the system and run the following: This process needs to be repeated by a superuser each time a new schema is brought into this permissions management approach. +.. note:: + By default, any new object created will not be accessible by our new ``my_schema_readers`` group. + Running a ``GRANT SELECT ...`` only affects objects that already exist in the schema or database. + If you're getting a ``Missing the following permissions: SELECT on table 'database.public.tablename'`` error, make sure that + you've altered the default permissions with the ``ALTER DEFAULT PERMISSIONS`` statement. + .. todo: create some example users show that they have the right permission diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index 5897c4275..bef17f22f 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -6,6 +6,10 @@ ALTER DEFAULT PERMISSIONS ``ALTER DEFAULT PERMISSIONS`` allows granting automatic permissions to future objects. +By default, if one user creates a table, another user will not have ``SELECT`` permissions on it. +By modifying the target role's default permissions, a database administrator can ensure that +all objects created by that role will be accessible to others. + Learn more about the permission system in the :ref:`access control guide`. Permissions @@ -42,12 +46,14 @@ Syntax target_role_name ::= identifier + role_name ::= identifier + schema_name ::= identifier .. include:: grant.rst - :start-line: 123 - :end-line: 174 + :start-line: 127 + :end-line: 180 Examples @@ -55,20 +61,23 @@ Examples Automatic permissions for newly created schemas ------------------------------------------------- + +When role ``demo`` creates a new schema, roles u1,u2 will get USAGE and CREATE permissions in the new schema: + .. code-block:: postgres - -- When role ``demo`` creates a new schema, roles u1,u2 will get USAGE and CREATE permissions in the new schema: - ALTER DEFAULT PERMISSIONS FOR demo FOR SCHEMAS GRANT USAGE, CREATE TO u1,u2; + Automatic permissions for newly created tables in a schema ---------------------------------------------------------------- -.. code-block:: postgres - -- When role ``demo`` create a new table in schema ``s1``, roles u1,u2 wil be granted with SELECT on it: +When role ``demo`` creates a new table in schema ``s1``, roles u1,u2 wil be granted with SELECT on it: + +.. code-block:: postgres ALTER DEFAULT PERMISSIONS FOR demo IN s1 FOR TABLES GRANT SELECT TO u1,u2; - + Revoke (``DROP GRANT``) permissions for newly created tables --------------------------------------------------------------- diff --git a/reference/sql/sql_statements/access_control_commands/grant.rst b/reference/sql/sql_statements/access_control_commands/grant.rst index 2c67e32ea..3efa755b3 100644 --- a/reference/sql/sql_statements/access_control_commands/grant.rst +++ b/reference/sql/sql_statements/access_control_commands/grant.rst @@ -8,6 +8,9 @@ The ``GRANT`` statement adds permissions for a role. It allows for setting permi It also allows adding a role as a memeber to another role. +When granting permissions to a role, the permission is added for existing objects only. +To automatically add permissions to newly created objects, see :ref:`alter_default_permissions`. + Learn more about the permission system in the :ref:`access control guide`. See also :ref:`revoke`, :ref:`create_role`. @@ -209,7 +212,7 @@ Creating a new role for a group of users .. code-block:: postgres - -- Create new users (we will grant htem password/login later) + -- Create new users (we will grant them passwords and logins later) CREATE ROLE dba_user1; CREATE ROLE dba_user2; CREATE ROLE dba_user3; diff --git a/reference/sql/sql_statements/access_control_commands/revoke.rst b/reference/sql/sql_statements/access_control_commands/revoke.rst index 52e53f452..fbeee701d 100644 --- a/reference/sql/sql_statements/access_control_commands/revoke.rst +++ b/reference/sql/sql_statements/access_control_commands/revoke.rst @@ -120,8 +120,8 @@ Parameters .. include:: grant.rst - :start-line: 123 - :end-line: 174 + :start-line: 127 + :end-line: 180 Examples From b0899c73234671718ef7f9a8ac0110a8a0285cb1 Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Mon, 6 Apr 2020 14:14:12 +0200 Subject: [PATCH 003/300] Add client link --- guides/client_drivers/index.rst | 10 ++++++++++ .../get_statement_permissions.rst | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/guides/client_drivers/index.rst b/guides/client_drivers/index.rst index 315aee8c2..e81e938d9 100644 --- a/guides/client_drivers/index.rst +++ b/guides/client_drivers/index.rst @@ -49,6 +49,16 @@ Windows Linux -------------- +* + **SQream SQL** (x86) - `sqream-sql-v2020.1.1_stable.x86_64.tar.gz `_ + + :ref:`sqream sql` - Interactive command-line SQL client for Intel-based machines + +* + **SQream SQL** (IBM POWER9) - `sqream-sql-v2020.1.1_stable.ppc64le.tar.gz `_ + + :ref:`sqream sql` - Interactive command-line SQL client for IBM POWER9-based machines + * **ODBC installer** - ``sqream_odbc_4.0.0_x86_64_linux.tar.gz`` diff --git a/reference/sql/sql_statements/access_control_commands/get_statement_permissions.rst b/reference/sql/sql_statements/access_control_commands/get_statement_permissions.rst index 03c2f7467..0846c5cc4 100644 --- a/reference/sql/sql_statements/access_control_commands/get_statement_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/get_statement_permissions.rst @@ -59,8 +59,8 @@ If the statement requires no special permissions, the utility returns an empty r - The object name .. include:: grant.rst - :start-line: 123 - :end-line: 174 + :start-line: 127 + :end-line: 180 Examples =========== From ffeafe8a65a57d04fedd0ae05052d5454e26228f Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Mon, 6 Apr 2020 14:41:12 +0200 Subject: [PATCH 004/300] Note about installing sqream sql on any linux host --- reference/cli/sqream_sql.rst | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/reference/cli/sqream_sql.rst b/reference/cli/sqream_sql.rst index 3d29e5654..439e42f0d 100644 --- a/reference/cli/sqream_sql.rst +++ b/reference/cli/sqream_sql.rst @@ -11,13 +11,31 @@ This page serves as a reference for the options and parameters. Learn more about .. contents:: In this topic: :local: -Running sqream sql -====================== +Installing sqream sql +========================= -``sqream sql`` can be found in the ``bin`` directory of your SQream DB installation, under the name ``sqream``. +If you have a SQream DB installation on your server, ``sqream sql`` can be found in the ``bin`` directory of your SQream DB installation, under the name ``sqream``. .. versionchanged:: 2020.1 - Starting from version 2020.1, ``ClientCmd`` has been renamed to ``sqream sql``. + As of version 2020.1, ``ClientCmd`` has been renamed to ``sqream sql``. + +To run ``sqream sql`` on any other Linux host: + +#. Download the ``sqream sql`` tarball package from the :ref:`client_drivers` page. +#. Untar the package: ``tar xf sqream-sql-v2020.1.1_stable.x86_64.tar.gz`` +#. Start the client: + + .. code-block:: psql + + $ cd sqream-sql-v2020.1.1_stable.x86_64 + $ ./sqream sql --port=5000 --username=jdoe --databasename=master + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=> _ + Using sqream sql ================= From 775b1a43311a45ba263819c66e98c68d779b183a Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Mon, 6 Apr 2020 22:08:38 +0200 Subject: [PATCH 005/300] Final release notes for v2020.1 --- guides/inserting_data.rst | 14 ++++- .../sql_statements/dml_commands/copy_from.rst | 23 ++++++-- releases/2020.1.rst | 58 ++++++++++++++++--- 3 files changed, 79 insertions(+), 16 deletions(-) diff --git a/guides/inserting_data.rst b/guides/inserting_data.rst index aea6e7f7f..11db76f7c 100644 --- a/guides/inserting_data.rst +++ b/guides/inserting_data.rst @@ -13,9 +13,17 @@ SQream DB supports importing data from the following sources: * Using :ref:`insert` with :ref:`a client driver` * Using :ref:`copy_from`: -* * Local filesystem and locally mounted network filesystems -* * S3 -* * HDFS + + - Local filesystem and locally mounted network filesystems + - S3 + - HDFS + +* Using :ref:`external_tables`: + + - Local filesystem and locally mounted network filesystems + - S3 + - HDFS + SQream DB supports loading files in the following formats: diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 59f6c06e7..7bdd2b9af 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -107,9 +107,7 @@ Elements Supported date formats ========================= -Supported date parsers - -.. list-table:: +.. list-table:: Supported date parsers :widths: auto :header-rows: 1 @@ -131,8 +129,21 @@ Supported date parsers * - ``MDY`` - ``MM/DD/YYYY [hh:mm:ss[.SSS]]`` - ``12/31/2017 11:12:13.456`` - -Date pattern description + * - ``YYYYMMDD`` + - ``YYYYMMDD[hh[mm[ss[SSS]]]]`` + - ``20171231111213456`` + * - ``YYYY-M-D`` + - ``YYYY-M-D[ h:m[:s[.S]]]`` + - ``2017-9-10 10:7:21.1`` (optional leading zeroes) + * - ``YYYY/M/D`` + - ``YYYY/M/D[ h:m[:s[.S]]]`` + - ``2017/9/10 10:7:21.1`` (optional leading zeroes) + * - ``DD-mon-YYYY`` + - ``DD-mon-YYYY[ hh:mm[:ss[.SSS]]]`` + - ``31-Dec-2017 11:12:13.456`` + * - ``YYYY-mon-DD` + - ``YYYY-mon-DD[ hh:mm[:ss[.SSS]]]`` + - ``2017-Dec-31 11:12:13.456`` .. list-table:: :widths: auto @@ -341,6 +352,8 @@ Loading non-standard dates If files contain dates not formatted as ``ISO8601``, tell ``COPY`` how to parse the column. After parsing, the date will appear as ``ISO8601`` inside SQream DB. +These are called date parsers. You can find the supported dates in the :ref:`'Supported date parsers' table` above + In this example, ``date_col1`` and ``date_col2`` in the table are non-standard. ``date_col3`` is mentioned explicitly, but can be left out. Any column that is not specified is assumed to be ``ISO8601``. .. code-block:: postgres diff --git a/releases/2020.1.rst b/releases/2020.1.rst index 4abe40738..c7e6f98d5 100644 --- a/releases/2020.1.rst +++ b/releases/2020.1.rst @@ -12,14 +12,16 @@ New features Integrations ----------------- -* Load files directly from S3 buckets +* Load files directly from :ref:`S3 buckets` -* Load files directly from HDFS +* Load files directly from :ref:`HDFS` -* Import :ref:`ORC files` directly or through :ref:`external_tables` +* Import :ref:`ORC files`, through :ref:`external_tables` * :ref:`Python driver (pysqream)` is now DB-API v2.0 compliant +* Certified :ref:`Tableau JDBC connector (taco)`, now also :ref:`supported on MacOS` + SQL support --------------- @@ -37,6 +39,7 @@ Improvements and fixes * 207 bug fixes, including: + - Improved performance of both inner and outer joins - Fixed wrong results on STDDEV (0 instead of ``NULL``) - Fixed wrong results on nested Parquet files - Fixed failing cast from ``VARCHAR`` to ``FLOAT`` @@ -52,6 +55,8 @@ Improvements and fixes - Fixed situation in which a malformed time (``24:00:00``) would get incorrectly inserted from a CSV - Fixed race condition in which loading thousands of small files from HDFScaused a memory leak +* The :ref:`saved query` feature can now be used with :ref:`insert` statements + * Faster "Deferred gather" algorithm for joins with text keys * Faster filtering when using :ref:`datepart` @@ -64,7 +69,9 @@ Improvements and fixes * ``highCardinalityColumns`` can be configured to tell the system about :ref:`high selectivity` columns -* :ref:`sqream sql` starts up faster and can be deployed standalone +* :ref:`sqream sql` starts up faster, can run on any Linux machine + +* Additional CSV date formats (date parsers) added for compatibility Behaviour changes ======================== @@ -79,6 +86,26 @@ Behaviour changes * All logs are now unified into one log. See :ref:`logging` for more information +* Compression changes: + + - The latest version of SQream DB could select a different compression scheme if data is reloaded, compared to previous versions of SQream DB. This internal change improves performance. + + - With ``LZ4`` compression, the maximum chunk size is limited to 2.1GB. If the chunk size is bigger, another compression may be selected - primarily ``SNAPPY``. + +* The following configuration flags have been deprecated: + + - ``addStatementRechunkerAfterGpuToHost`` + - ``increasedChunkSizeFactor`` + - ``gpuReduceMergeOutputFactor`` + - ``fullSortInputMemFactor`` + - ``reduceInputMemFactor`` + - ``distinctInputMemFactor`` + - ``useAutoMemFactors`` + - ``autoMemFactorsVramFactor`` + - ``catchNotEnoughVram`` + - ``useNetworkRechunker`` + - useMemFactorInJoinOutput + Operations ======================== @@ -87,17 +114,28 @@ Operations * When upgrading from a previous version of SQream DB or lower, the storage version must be upgraded using the :ref:`upgrade_storage_cli_reference` utility: ``./bin/upgrade_storage /path/to/storage/sqreamdb/`` * - Because of a change in memory allocation behaviour in this version, a new flag ``limitQueryMemoryGB`` has been added to the ``runtimeGlobalFlag`` section. The recommended value for this is ``total host memory`` / ``sqreamd workers on host``. - For example, for a machine with 512GB of RAM and 4 workers, the recommended setting is ``512/4 → 128``. + Because of a change in memory allocation behaviour in this version, a new setting ``limitQueryMemoryGB`` has been added to the ``runtimeGlobalFlag`` section. The recommended value for this is ``total host memory`` * 90% / ``sqreamd workers on host``. + For example, for a machine with 512GB of RAM and 4 workers, the recommended setting is ``⌊(512 * 0.95 / 4)⌋ → ~ 486 / 4 → 121``. + The 95% is to allow for some overhead for other system processes. This number can be modified to allow SQream DB to take more or memory, as required. + +* + The ``spoolMemoryGB`` setting dictates how much memory is set aside for spooling. This flag should be set at 90% of the ``limitQueryMemoryGB``. + As per the example above, ``⌊( 0.9 * limitQueryMemoryGB )⌋ → ⌊( 0.9 * 121 )⌋ → 108`` + .. code-block:: none "runtimeGlobalFlags": { - "limitQueryMemoryGB" : 128 + "limitQueryMemoryGB" : 121, + "spoolMemoryGB" : 108 + + Known Issues & Limitations ================================ +* An invalid formatted CSV can cause an ``insufficient memory`` error on a :ref:`copy_from` statement if a quote isn't closed and the file is much larger than system memory. + * ``TEXT`` columns cannot be used in a window functions' partition * Parsing errors are sometimes hard to read - the location points to the wrong part of the statement @@ -106,10 +144,14 @@ Known Issues & Limitations * Using ``SUM`` on very large numbers in window functions can error (``overflow``) when not used with an ``ORDER BY`` clause -* Slight performance decrease with :ref:`dateadd` in this version +* Slight performance decrease with :ref:`dateadd` in this version (<4%) + +* Operations on Snappy-compressed ORC files are slower than their Parquet equivalents. Upgrading to v2020.1 ======================== +Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. + Contact your account manager to get the latest release of SQream DB. \ No newline at end of file From 67c10ebd9359c663707f300a869af3426b3ef791 Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Tue, 7 Apr 2020 09:53:08 +0200 Subject: [PATCH 006/300] Update release notes for 2020.1 --- releases/2020.1.rst | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/releases/2020.1.rst b/releases/2020.1.rst index c7e6f98d5..1c2ddbbe6 100644 --- a/releases/2020.1.rst +++ b/releases/2020.1.rst @@ -111,24 +111,32 @@ Operations * The client-server protocol has been updated to support faster data flow, and more reliable memory allocations on the client side. End users are required to use only the latest :ref:`sqream sql`, :ref:`java_jdbc`, and :ref:`odbc` drivers delivered with this version. See the :ref:`client driver download page` for the latest drivers and connectors. -* When upgrading from a previous version of SQream DB or lower, the storage version must be upgraded using the :ref:`upgrade_storage_cli_reference` utility: ``./bin/upgrade_storage /path/to/storage/sqreamdb/`` +* When upgrading from a previous version of SQream DB (for example, v2019.2), the storage version must be upgraded using the :ref:`upgrade_storage_cli_reference` utility: ``./bin/upgrade_storage /path/to/storage/sqreamdb/`` * - Because of a change in memory allocation behaviour in this version, a new setting ``limitQueryMemoryGB`` has been added to the ``runtimeGlobalFlag`` section. The recommended value for this is ``total host memory`` * 90% / ``sqreamd workers on host``. - For example, for a machine with 512GB of RAM and 4 workers, the recommended setting is ``⌊(512 * 0.95 / 4)⌋ → ~ 486 / 4 → 121``. + A change in memory allocation behaviour in this version sees the introduction of a new setting, ``limitQueryMemoryGB``. This is an addition to the previous ``spoolMemoryGB`` setting. + + A good rule-of-thumb is to allow 5% system memory for other processes. The spool memory allocation should be around 90% of the total memory allocated. - The 95% is to allow for some overhead for other system processes. This number can be modified to allow SQream DB to take more or memory, as required. + - ``limitQueryMemoryGB`` defines how much total system memory is used by the worker. The recommended setting is (``total host memory`` - 5%) / ``sqreamd workers on host``. -* - The ``spoolMemoryGB`` setting dictates how much memory is set aside for spooling. This flag should be set at 90% of the ``limitQueryMemoryGB``. - As per the example above, ``⌊( 0.9 * limitQueryMemoryGB )⌋ → ⌊( 0.9 * 121 )⌋ → 108`` + - ``spoolMemoryGB`` defines how much memory is set aside for spooling, out of the total system memory allocated in ``limitQueryMemoryGB``. The recommended setting is 90% of the ``limitQueryMemoryGB``. + + For example, for a machine with 512GB of RAM and 4 workers, the recommended settings are: + + - ``limitQueryMemoryGB`` - ``⌊(512 * 0.95 / 4)⌋ → ~ 486 / 4 → 121``. + + - ``spoolMemoryGB`` - ``⌊( 0.9 * limitQueryMemoryGB )⌋ → ⌊( 0.9 * 121 )⌋ → 108`` + Example settings per-worker, for 512GB of RAM and 4 workers: + .. code-block:: none "runtimeGlobalFlags": { "limitQueryMemoryGB" : 121, "spoolMemoryGB" : 108 + Known Issues & Limitations From 29d525f253b9dd4dac6c194e1f8d89b93484dbe9 Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Mon, 6 Apr 2020 22:10:41 +0200 Subject: [PATCH 007/300] Typo --- releases/2020.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2020.1.rst b/releases/2020.1.rst index 1c2ddbbe6..5b54d1b36 100644 --- a/releases/2020.1.rst +++ b/releases/2020.1.rst @@ -104,7 +104,7 @@ Behaviour changes - ``autoMemFactorsVramFactor`` - ``catchNotEnoughVram`` - ``useNetworkRechunker`` - - useMemFactorInJoinOutput + - ``useMemFactorInJoinOutput`` Operations ======================== From c0a869ac330fa641e0aca5a75200ae479e647c4e Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Fri, 10 Apr 2020 10:25:04 +0200 Subject: [PATCH 008/300] Refresh release notes, fix typo in client drivers --- guides/client_drivers/index.rst | 6 +++--- releases/2020.1.rst | 35 ++++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/guides/client_drivers/index.rst b/guides/client_drivers/index.rst index e81e938d9..929e55733 100644 --- a/guides/client_drivers/index.rst +++ b/guides/client_drivers/index.rst @@ -13,13 +13,13 @@ All operating systems --------------------------- * - **JDBC** - `sqream-jdbc v3.0.0 (.zip) `_ + **JDBC** - `sqream-jdbc v4.0.0 (.zip) `_ - :ref:`java_jdbc` Driver for all systems + :ref:`java_jdbc` Driver * - **Python** - `pysqream v3.0.1 (.tar.gz) `_ + **Python** - `pysqream v3.0.2 (.tar.gz) `_ :ref:`pysqream` - Python driver diff --git a/releases/2020.1.rst b/releases/2020.1.rst index 5b54d1b36..72c857e55 100644 --- a/releases/2020.1.rst +++ b/releases/2020.1.rst @@ -6,28 +6,47 @@ What's new in 2020.1 SQream DB v2020.1 contains lots of new features, improved performance, and bug fixes. +This is the first release of 2020, with a strong focus on integration into existing environments. The release includes connectivity to Hadoop and other legacy data warehouse ecosystems. We’re also bringing lots of new capabilities to our analytics engine, to empower data users to analyze more data with less friction. + +The latest release vastly improves reliability and performance, and makes getting more data into SQream DB easier than ever. + +The core of SQream DB v2020.1 contains new integration features, more analytics capabilities, and better drivers and connectors. + + New features ================ Integrations ----------------- -* Load files directly from :ref:`S3 buckets` +* Load files directly from :ref:`S3 buckets`. Customers with columnar data in S3 data lakes can now access the data directly. All that is needed is to simply point an external table to an S3 bucket with Parquet, ORC, or CSV objects. This feature is available on all deployments of SQream DB – in the cloud and on-prem. -* Load files directly from :ref:`HDFS` +* Load files directly from :ref:`HDFS`. SQream DB now comes with built-in, native HDFS support for directly loading data from Hadoop-based data lakes. Our focus on helping Hadoop customers do more with their data led us to develop this feature, which works out of the box. As a result, SQream DB can now not only read but also write data, and intermediate results back to HDFS for HIVE and other data consumers. SQream DB now fits seamlessly into a Hadoop data pipeline. -* Import :ref:`ORC files`, through :ref:`external_tables` -* :ref:`Python driver (pysqream)` is now DB-API v2.0 compliant +* Import :ref:`ORC files`, through :ref:`external_tables`. ORC files join Parquet as files that can be natively accessed and inserted into SQream DB tables. + +* :ref:`Python driver (pysqream)` is now DB-API v2.0 compliant. Customers can write high-performance Python applications that make full use of SQream DB - connect, query, delete, and insert data. Data scientists can use pysqream with Pandas, Numpy, and AI/ML frameworks like TensorFlow for direct queries of huge datasets. + +* Certified :ref:`Tableau JDBC connector (taco)`, now also :ref:`supported on MacOS`. Users are encouraged to install the new JDBC connector. + +* + All logs are now unified into one log, which can be analyzed with SQream DB directly. + See :ref:`logging` for more information. -* Certified :ref:`Tableau JDBC connector (taco)`, now also :ref:`supported on MacOS` SQL support --------------- -* Added frames and frame exclusions to :ref:`window_functions`. This is available for preview, with more features coming in the next version +* + Added frames and frame exclusions to :ref:`window_functions`. This is available for preview, with more features coming in the next version. + + The new frames and frame exclusionsfeature adds complex analytics capabilities to the already powerful window functions. -* New datatype - ``TEXT``, which replaces ``NVARCHAR`` directly with UTF-8 support and improved performance +* + New datatype - ``TEXT``, which replaces ``NVARCHAR`` directly with UTF-8 support and improved performance. + + Unlike ``VARCHAR``, the new ``TEXT`` data type has no restrictions on size, and carries no performance overhead as the text sizes grow. * ``TEXT`` join keys are now supported @@ -37,6 +56,8 @@ SQL support Improvements and fixes ======================== +SQream DB v2020.1 includes hundreds of small new features and tunable parameters that improve performance, reliability, and stability. Existing SQream DB users can expect to see a general speedup of around 10% on most statements and queries! + * 207 bug fixes, including: - Improved performance of both inner and outer joins From 00c21754faed220ac55a5a5e42075d33044d38e9 Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Mon, 20 Apr 2020 10:53:28 +0200 Subject: [PATCH 009/300] Update to CSV guidelines --- guides/migration/csv.rst | 13 ++++++- guides/operations/hardware_guide.rst | 4 +-- index.rst | 2 +- .../sql_statements/dml_commands/copy_from.rst | 35 +++++++++++++++++++ 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/guides/migration/csv.rst b/guides/migration/csv.rst index 4e8092317..d95411d73 100644 --- a/guides/migration/csv.rst +++ b/guides/migration/csv.rst @@ -28,7 +28,18 @@ Prepare the source CSVs, with the following requirements: * A newline -* If a field is quoted, any double quote that appears must be double-quoted (similar to the :ref:`string literals quoting rules`. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. +* + If a field is quoted, any double quote that appears must be double-quoted (similar to the :ref:`string literals quoting rules`. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. + + Other modes of escaping are not supported (e.g. ``1,"What are \"birds\"?"`` is not a valid way of escaping CSV values). + +* ``NULL`` values can be marked in two ways in the CSV: + + - An explicit null marker. For example, ``col1,\N,col3`` + - An empty field delimited by the field delimiter. For example, ``col1,,col3`` + + .. note:: If a text field is quoted but contains no content (``""``) it is considered an empty text field. It is not considered ``NULL``. + 2. Place CSVs where SQream DB workers can access ======================================================= diff --git a/guides/operations/hardware_guide.rst b/guides/operations/hardware_guide.rst index 30f35f1c8..bccb6da53 100644 --- a/guides/operations/hardware_guide.rst +++ b/guides/operations/hardware_guide.rst @@ -48,7 +48,7 @@ An average single-node cluster can be a rackmount server or workstation, contain * - Onboard storage - * 2x 960GB SSD 2.5in Hot-plug for OS, RAID1 - * 14x 3.84TB SSD 2.5in Hot-plug for storage, RAID5 + * 14x 3.84TB SSD 2.5in Hot-plug for storage, RAID10 * - Networking - Intel X710 DP 10Gb DA/SFP+ * - GPU @@ -174,7 +174,7 @@ Storage For clustered scale-out installations, SQream DB relies on NAS/SAN storage. These devices have extremely high reliability and durability, with five 9s of up-time. -For stand-alone installations, SQream DB relies on redundant disk configurations, like RAID 5/6/10/50. These RAID configurations ensure that blocks of data are replicated between disks, so that failure of a number of disks will not result in data loss or availability of the system. +For stand-alone installations, SQream DB relies on redundant disk configurations, like RAID 10/50. These RAID configurations ensure that blocks of data are replicated between disks, so that failure of a number of disks will not result in data loss or availability of the system. Because storage reliability is important, SQream recommends enterprise-grade SAS SSD drives. However, as with other components – there is a tradeoff for cost/performance. When performance and reliability are important, SQream recommends SAS SSD or NVMe drives. diff --git a/index.rst b/index.rst index ad1b9603b..36aec7fd2 100644 --- a/index.rst +++ b/index.rst @@ -38,7 +38,7 @@ SQream DB comes with standard SQL client drivers, including :ref:`JDBC` + :ref:`Bulk load CSVs` - :ref:`SQL reference` diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 7bdd2b9af..0fb72f83a 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -225,6 +225,41 @@ Whenever the data can’t be parsed because it is improperly formatted or doesn #. When ``ERROR_LOG`` is set and ``ERROR_VERBOSITY`` is set to ``0``, rejected rows are saved to the file path specified, but errors are not logged. This is useful for replaying the file later. +CSV support +================ + +By default, SQream DB's CSV parser can handle `RFC 4180 standard CSVs `_ , but can also be modified to support non-standard CSVs (with multi-character delimiters, unquoted fields, etc). + +All CSV files shoudl be prepared according to these recommendations: + +* Files are UTF-8 or ASCII encoded + +* Field delimiter is an ASCII character or characters + +* Record delimiter, also known as a new line separator, is a Unix-style newline (``\n``), DOS-style newline (``\r\n``), or Mac style newline (``\r``). + +* Fields are optionally enclosed by double-quotes, or mandatory quoted if they contain one of the following characters: + + * The record delimiter or field delimiter + + * A double quote character + + * A newline + +* + If a field is quoted, any double quote that appears must be double-quoted (similar to the :ref:`string literals quoting rules`. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. + + Other modes of escaping are not supported (e.g. ``1,"What are \"birds\"?"`` is not a valid way of escaping CSV values). + +Null markers +--------------- + +``NULL`` values can be marked in two ways in the CSV: + +* An explicit null marker. For example, ``col1,\N,col3`` +* An empty field delimited by the field delimiter. For example, ``col1,,col3`` + +.. note:: If a text field is quoted but contains no content (``""``) it is considered an empty text field. It is not considered ``NULL``. Examples =========== From 24e9f1558dde928129823f09140550fd9106d695 Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Mon, 20 Apr 2020 11:14:39 +0200 Subject: [PATCH 010/300] Add links from config guide to first steps, add links from first steps to setup and sqream sql --- first_steps.rst | 72 +++++++++++++------ .../setup/recommended_configuration.rst | 6 ++ 2 files changed, 58 insertions(+), 20 deletions(-) diff --git a/first_steps.rst b/first_steps.rst index 0dad5a597..38c3d2142 100644 --- a/first_steps.rst +++ b/first_steps.rst @@ -22,7 +22,14 @@ Preparing for this tutorial This tutorial assumes you already have a SQream DB cluster running and the SQream command line client installed on the machine you are on. -Run the client like this. It will interactively ask for the password. +.. rubric:: If you haven't already: + +* :ref:`Set up a SQream DB cluster` + +* :ref:`Install SQream SQL CLI` + + +Run the SQream SQL client like this. It will interactively ask for the password. .. code-block:: psql @@ -40,12 +47,37 @@ You should use a username and password that you have set up or your DBA has give * To exit the shell, type ``\q`` or :kbd:`Ctrl-d`. * A new SQream DB cluster contains a database named `master`. We will start with this database. -.. TODO: the tutorial should absolutely not start creating tables in the master database ... +Create a new database for playing around in +======================================================= + +To create a database, we will use the :ref:`create_database` syntax. + +.. code-block:: psql + + master=> CREATE DATABASE test; + executed + +Now, reconnect to the newly created database. + +First, exit the client by typing :kdb:`\q` and hitting enter. + +From the Linux shell, restart the client with the new database name: + +.. code-block:: psql + + $ sqream sql --port=5000 --username=rhendricks -d test + Password: + + Interactive client mode + To quit, use ^D or \q. + + test=> _ + +The new database name appears in the prompt. This lets you know which database you're connected to. Creating your first table ============================ - To create a table, we will use the :ref:`create_table` syntax, with a table name and some column specifications. For example, @@ -75,7 +107,7 @@ You can ask SQream DB to list the full, verbose ``CREATE TABLE`` statement for a .. code-block:: psql - master=> SELECT GET_DDL('cool_animals'); + test=> SELECT GET_DDL('cool_animals'); create table "public"."cool_animals" ( "id" int not null, "name" varchar(20), @@ -90,7 +122,7 @@ If you are done with this table, you can use :ref:`drop_table` to remove the tab .. code-block:: psql - master=> DROP TABLE cool_animals; + test=> DROP TABLE cool_animals; executed @@ -101,7 +133,7 @@ To see the tables in the current database, we will query the catalog .. code-block:: psql - master=> SELECT table_name FROM sqream_catalog.tables; + test=> SELECT table_name FROM sqream_catalog.tables; cool_animals 1 rows @@ -115,7 +147,7 @@ The statement includes the table name, an optional list of column names, and col .. code-block:: psql - master=> INSERT INTO cool_animals VALUES (1, 'Dog', 7); + test=> INSERT INTO cool_animals VALUES (1, 'Dog', 7); executed @@ -123,7 +155,7 @@ To change the order of values, specify the column order: .. code-block:: psql - master=> INSERT INTO cool_animals(weight, id, name) VALUES (3, 2, 'Possum'); + test=> INSERT INTO cool_animals(weight, id, name) VALUES (3, 2, 'Possum'); executed @@ -131,7 +163,7 @@ You can use ``INSERT`` to insert multiple rows too. Here, you use sets of parent .. code-block:: psql - master=> INSERT INTO cool_animals VALUES + test=> INSERT INTO cool_animals VALUES (3, 'Cat', 5) , (4, 'Elephant', 6500) , (5, 'Rhinoceros', 2100); @@ -144,16 +176,16 @@ When you leave out columns that have a :ref:`default value` (inc .. code-block:: psql - master=> INSERT INTO cool_animals (id) VALUES (6); + test=> INSERT INTO cool_animals (id) VALUES (6); executed .. code-block:: psql - master=> INSERT INTO cool_animals (id) VALUES (6); + test=> INSERT INTO cool_animals (id) VALUES (6); executed - master=> SELECT * FROM cool_animals; + test=> SELECT * FROM cool_animals; 1,Dog ,7 2,Possum ,3 3,Cat ,5 @@ -172,7 +204,7 @@ For querying, use the :ref:`select` keyword, followed by a list of columns and v .. code-block:: psql - master=> SELECT id, name, weight FROM cool_animals; + test=> SELECT id, name, weight FROM cool_animals; 1,Dog ,7 2,Possum ,3 3,Cat ,5 @@ -186,7 +218,7 @@ To get all columns without specifying them, use the star operator ``*``: .. code-block:: psql - master=> SELECT * FROM cool_animals; + test=> SELECT * FROM cool_animals; 1,Dog ,7 2,Possum ,3 3,Cat ,5 @@ -200,7 +232,7 @@ To get the number of values in a table without getting the full result set, use .. code-block:: psql - master=> SELECT COUNT(*) FROM cool_animals; + test=> SELECT COUNT(*) FROM cool_animals; 6 1 row @@ -210,7 +242,7 @@ Filter results by adding a :ref:`WHERE` clause and specifying the filter .. code-block:: psql - master=> SELECT id, name, weight FROM cool_animals WHERE weight > 1000; + test=> SELECT id, name, weight FROM cool_animals WHERE weight > 1000; 4,Elephant ,6500 5,Rhinoceros ,2100 @@ -220,7 +252,7 @@ Sort the results by adding an :ref:`ORDER BY` clause, and specifying a .. code-block:: psql - master=> SELECT * FROM cool_animals ORDER BY weight DESC; + test=> SELECT * FROM cool_animals ORDER BY weight DESC; 4,Elephant ,6500 5,Rhinoceros ,2100 1,Dog ,7 @@ -234,7 +266,7 @@ Filter null rows by adding a filter :ref:`IS NOT NULL`: .. code-block:: psql - master=> SELECT * FROM cool_animals WHERE weight IS NOT NULL ORDER BY weight DESC; + test=> SELECT * FROM cool_animals WHERE weight IS NOT NULL ORDER BY weight DESC; 4,Elephant ,6500 5,Rhinoceros ,2100 1,Dog ,7 @@ -250,7 +282,7 @@ To delete rows in a table selectively, use the :ref:`DELETE` command, wi .. code-block:: psql - master=> DELETE FROM cool_animals WHERE weight is null; + test=> DELETE FROM cool_animals WHERE weight is null; executed master=> SELECT * FROM cool_animals; @@ -266,7 +298,7 @@ To delete all rows in a table, use the :ref:`TRUNCATE` command followe .. code-block:: psql - master=> TRUNCATE TABLE cool_animals; + test=> TRUNCATE TABLE cool_animals; executed diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst index 4baf69d5c..d56048a57 100644 --- a/guides/operations/setup/recommended_configuration.rst +++ b/guides/operations/setup/recommended_configuration.rst @@ -263,3 +263,9 @@ If not required, you can disable the server's firewall. This will reduce connect $ sudo systemctl stop firewalld +.. rubric:: What's next? + +* :ref:`Test your SQream DB installation by creating your first table` + +* :ref:`Connect an external tool to SQream DB ` + From 2f3165ef996db8df0218b97c474fd311f7e5883b Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Mon, 20 Apr 2020 11:16:37 +0200 Subject: [PATCH 011/300] Link to hardware guide --- guides/operations/setup/before_you_begin.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/guides/operations/setup/before_you_begin.rst b/guides/operations/setup/before_you_begin.rst index 424bf5860..ff86f37b4 100644 --- a/guides/operations/setup/before_you_begin.rst +++ b/guides/operations/setup/before_you_begin.rst @@ -6,12 +6,14 @@ Before you begin Before you install or deploy SQream DB, please verify you have the following: -* An NVIDIA-capable server, either on-premise or on supported cloud platforms +* An NVIDIA-capable server, either on-premise or on supported cloud platforms. * Supported operating systems: Red Hat Enterprise Linux v7.x / CentOS v7.x / Ubuntu 18.04 / Amazon Linux * NVIDIA GPU. A Tesla GPU is highly recommended * A privileged SSH connection to the server (sudo) +.. tip:: Refer to our :ref:`hardware_guide` for more information about supported and recommended configurations. + * A SQream DB license (contact support@sqream.com or your SQream account manager for your license key) * A 3rd party tool that can connect to SQream DB via JDBC, ODBC, or Python From f5184f6c9b9ced3bf5ca4e96da47bca3d75c5564 Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Mon, 20 Apr 2020 11:19:22 +0200 Subject: [PATCH 012/300] Formatting issue with meta-command in first steps --- first_steps.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/first_steps.rst b/first_steps.rst index 38c3d2142..160d6f11a 100644 --- a/first_steps.rst +++ b/first_steps.rst @@ -59,7 +59,7 @@ To create a database, we will use the :ref:`create_database` syntax. Now, reconnect to the newly created database. -First, exit the client by typing :kdb:`\q` and hitting enter. +First, exit the client by typing ``\q`` and hitting enter. From the Linux shell, restart the client with the new database name: From 4fdc930bc9e111f2b8f4e12b7e65e4336902fe74 Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Mon, 20 Apr 2020 11:22:12 +0200 Subject: [PATCH 013/300] Reshuffle order of information in the before you begin install guide --- guides/operations/setup/before_you_begin.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/guides/operations/setup/before_you_begin.rst b/guides/operations/setup/before_you_begin.rst index ff86f37b4..9c307ce8b 100644 --- a/guides/operations/setup/before_you_begin.rst +++ b/guides/operations/setup/before_you_begin.rst @@ -9,17 +9,17 @@ Before you install or deploy SQream DB, please verify you have the following: * An NVIDIA-capable server, either on-premise or on supported cloud platforms. * Supported operating systems: Red Hat Enterprise Linux v7.x / CentOS v7.x / Ubuntu 18.04 / Amazon Linux - * NVIDIA GPU. A Tesla GPU is highly recommended + * NVIDIA GPU. A Tesla GPU is highly recommended. See more information in our :ref:`hardware_guide`. * A privileged SSH connection to the server (sudo) -.. tip:: Refer to our :ref:`hardware_guide` for more information about supported and recommended configurations. - * A SQream DB license (contact support@sqream.com or your SQream account manager for your license key) * A 3rd party tool that can connect to SQream DB via JDBC, ODBC, or Python If you do not have a SQream DB license, visit our website and `sign up for SQream DB`_ today! +Refer to our :ref:`hardware_guide` for more information about supported and recommended configurations. + What does the installation process look like? ---------------------------------------------- From 046202a86f5bcdd08cb658c22f122c34d2f28c2f Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Tue, 21 Apr 2020 23:37:45 +0200 Subject: [PATCH 014/300] Update config and release notes to better explain the new setting --- guides/operations/configuration.rst | 13 +++++++------ releases/2020.1.rst | 2 ++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/guides/operations/configuration.rst b/guides/operations/configuration.rst index 684b0a347..142973fee 100644 --- a/guides/operations/configuration.rst +++ b/guides/operations/configuration.rst @@ -110,9 +110,9 @@ Frequently set parameters - Example * - ``spoolMemoryGb`` - ``runtimeGlobalFlags`` - - Modifies RAM allocated for the worker for intermediate results. Statements that use more memory will spool to disk. We recommend not to exceed the amount of RAM in the machine. + - Modifies RAM allocated for the worker for intermediate results. Statements that use more memory than this setting will spool to disk, which could degrade performance. We recommend not to exceed the amount of RAM in the machine. This setting must be set lower than the ``limitQueryMemoryGB`` setting. - ``128`` - - 1 to maximum available RAM in gigabytes + - 1 to maximum available RAM in gigabytes. - ``"spoolMemoryGb": 250`` * - ``limitQueryMemoryGB`` - ``runtimeGlobalFlags`` @@ -186,12 +186,12 @@ Frequently set parameters - ``false`` - automatically derived by the TCP socket - ``false`` or ``true`` - ``"useConfigIP" : true`` - * - ``machineIp`` + * - ``machineIP`` - ``runtimeGlobalFlags`` - Specifies the worker's external IP or hostname, when used from a remote network. - No default - A valid IP or hostname - - ``"machineIp": "10.0.1.4"`` + - ``"machineIP": "10.0.1.4"`` .. list-table:: Runtime flags :widths: auto @@ -242,13 +242,14 @@ Recommended configuration file "insertCompressors": 8 }, "runtimeGlobalFlags":{ - "spoolMemoryGB": 250, + "limitQueryMemoryGB" : 121, + "spoolMemoryGB" : 108, "cudaMemQuota": 90, "initialSubscribedServices" : "sqream", "useMetadataServer": true, "metadataServerIp": "127.0.0.1", "useConfigIP": true, - "machineIp": "127.0.0.1" + "machineIP": "127.0.0.1" }, "server":{ diff --git a/releases/2020.1.rst b/releases/2020.1.rst index 72c857e55..ff261925e 100644 --- a/releases/2020.1.rst +++ b/releases/2020.1.rst @@ -143,6 +143,8 @@ Operations - ``spoolMemoryGB`` defines how much memory is set aside for spooling, out of the total system memory allocated in ``limitQueryMemoryGB``. The recommended setting is 90% of the ``limitQueryMemoryGB``. + This setting must be set lower than the ``limitQueryMemoryGB`` setting. + For example, for a machine with 512GB of RAM and 4 workers, the recommended settings are: - ``limitQueryMemoryGB`` - ``⌊(512 * 0.95 / 4)⌋ → ~ 486 / 4 → 121``. From fef76aba29cf5f15445e67d03c8f48014a66df58 Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Wed, 29 Apr 2020 11:37:49 +0200 Subject: [PATCH 015/300] Improvements for troubleshooting and best practices. --- .../filesystem_and_filesystem_usage.rst | 5 +- guides/operations/configuration.rst | 17 +++-- guides/operations/information_for_support.rst | 2 +- guides/operations/logging.rst | 32 ++++---- .../optimization_best_practices.rst | 5 ++ guides/operations/troubleshooting.rst | 76 +++++++++++++++++++ index.rst | 15 ++-- .../sql_statements/dml_commands/copy_from.rst | 2 +- 8 files changed, 123 insertions(+), 31 deletions(-) diff --git a/guides/architecture/filesystem_and_filesystem_usage.rst b/guides/architecture/filesystem_and_filesystem_usage.rst index d9890431b..d1838d4e8 100644 --- a/guides/architecture/filesystem_and_filesystem_usage.rst +++ b/guides/architecture/filesystem_and_filesystem_usage.rst @@ -77,12 +77,15 @@ The ``temp`` directory is where SQream DB writes temporary data. The directory to which SQream DB writes temporary data can be changed to any other directory on the filesystem. SQream recommends remapping this directory to a fast local storage to get better performance when executing intensive larger-than-RAM operations like sorting. SQream recommends an SSD or NVMe drive, in mirrored RAID 1 configuration. +If desired, the ``temp`` folder can be redirected to a local disk for improved performance, by setting the ``tempPath`` setting in the :ref:`configuration` file. + + ``logs`` ---------------- The logs directory contains logs produced by SQream DB. -See more about the logs in the :ref:`operations` guide. +See more about the logs in the :ref:`logging` guide. .. what kind of access patterns for different files to optimise for diff --git a/guides/operations/configuration.rst b/guides/operations/configuration.rst index 142973fee..feceb5e56 100644 --- a/guides/operations/configuration.rst +++ b/guides/operations/configuration.rst @@ -11,7 +11,7 @@ Configuration files By default, configuration files are stored in ``/etc/sqream``. -A very basic configuration file looks like this: +A very minimal configuration file looks like this: .. code-block:: json @@ -30,9 +30,9 @@ A very basic configuration file looks like this: } } -Each SQream DB worker has a dedicated configuration file. +* Each SQream DB worker (``sqreamd``) has a dedicated configuration file. -The configuration file contains four distinct sections, ``compileFlags``, ``runtimeFlags``, ``runtimeGlobalFlags``, and ``server``. +* The configuration file contains four distinct sections, ``compileFlags``, ``runtimeFlags``, ``runtimeGlobalFlags``, and ``server``. In the example above, the worker will start on port 5000, and will use GPU #0. @@ -192,6 +192,14 @@ Frequently set parameters - No default - A valid IP or hostname - ``"machineIP": "10.0.1.4"`` + * - ``tempPath`` + - ``runtimeGlobalFlags`` + - Specifies an override for the temporary file path on the local machine. Set this to a local path to improve performance for spooling. + - Defaults to the central storage's built-in temporary folder + - A valid path to a folder on the local machine + - ``"tempPath": "/mnt/nvme0/temp"`` + + .. list-table:: Runtime flags :widths: auto @@ -250,7 +258,6 @@ Recommended configuration file "metadataServerIp": "127.0.0.1", "useConfigIP": true, "machineIP": "127.0.0.1" - }, "server":{ "gpu":0, @@ -266,7 +273,7 @@ Changing settings temporarily The ``SET`` statement can modify one of the configuration settings for the session or connection. -For example: +For example, to set the query plan's logging interval to "every 3 seconds" for subsequent statements: .. code-block:: psql diff --git a/guides/operations/information_for_support.rst b/guides/operations/information_for_support.rst index addc882d4..167d4dddf 100644 --- a/guides/operations/information_for_support.rst +++ b/guides/operations/information_for_support.rst @@ -112,7 +112,7 @@ Collecting logs and metadata database SQream DB comes bundled with a data collection utility and an SQL utility intended for collecting logs and additional information that can help SQream support drill down into possible issues. -See more information in the :ref:`Collect logs from your cluster` section of the logging guide. +See more information in the :ref:`Collect logs from your cluster` section of the :ref:`logging` guide. Examples ----------------- diff --git a/guides/operations/logging.rst b/guides/operations/logging.rst index b5f0c9671..31b236570 100644 --- a/guides/operations/logging.rst +++ b/guides/operations/logging.rst @@ -15,13 +15,13 @@ The :ref:`storage cluster` contains a ``logs`` directory. Each The worker logs contain information messages, warnings, and errors pertaining to SQream DB's operation, including: -* server start-up and shutdown -* configuration changes -* exceptions and errors -* user login events -* session events -* statement execution success / failure -* statement execution statistics +* Server start-up and shutdown +* Configuration changes +* Exceptions and errors +* User login events +* Session events +* Statement execution success / failure +* Statement execution statistics Log structure and contents --------------------------------- @@ -35,7 +35,7 @@ The log is a CSV, with several fields. * - Field - Description * - ``#SQ#`` - - Start delimiter. When used with the end of line delimiter can be used to combine multi-line statements into one row + - Start delimiter. When used with the end of line delimiter can be used to parse multi-line statements correctly * - Row Id - Unique identifier for the row * - Timestamp @@ -357,22 +357,22 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas start_marker VARCHAR(4), row_id BIGINT, timestamp DATETIME, - message_level NVARCHAR(6), - thread_id NVARCHAR(40), - worker_hostname NVARCHAR(30), + message_level TEXT, + thread_id TEXT, + worker_hostname TEXT, worker_port INT, connection_id INT, - database_name NVARCHAR(128), - user_name NVARCHAR(128), + database_name TEXT, + user_name TEXT, statement_id INT, - service_name NVARCHAR(128), + service_name TEXT, message_type_id INT, - message NVARCHAR(10000), + message TEXT, end_message VARCHAR(5) ) USING FORMAT CSV WITH - PATH '//home/rhendricks/sqream_storage/logs/**/sqream*.log' + PATH '/home/rhendricks/sqream_storage/logs/**/sqream*.log' FIELD DELIMITER '|' ; diff --git a/guides/operations/optimization_best_practices.rst b/guides/operations/optimization_best_practices.rst index 4d63ca421..c9543c9bb 100644 --- a/guides/operations/optimization_best_practices.rst +++ b/guides/operations/optimization_best_practices.rst @@ -6,6 +6,8 @@ Optimization and best practices This topic explains some best practices of working with SQream DB. +.. _table_design_best_practices: + Table design ============== This section describes best practices and guidelines for designing tables. @@ -83,6 +85,8 @@ Data sorting is an important factor in minimizing storage size and improving que * For longer-running queries that run on a regular basis, performance can be improved by sorting data based on the ``WHERE`` and ``GROUP BY`` parameters. Data can be sorted during insert by using :ref:`external tables` or by using :ref:`create_table_as`. +.. _query_best_practices: + Query best practices ===================== @@ -118,6 +122,7 @@ Can be rewritten as .. _high_selectivity: + Use the high selectivity hint -------------------------------- diff --git a/guides/operations/troubleshooting.rst b/guides/operations/troubleshooting.rst index f1fd1db0f..18ff74a06 100644 --- a/guides/operations/troubleshooting.rst +++ b/guides/operations/troubleshooting.rst @@ -4,9 +4,85 @@ Troubleshooting *********************** +Follow this checklist if you find that the performance is slower than you expect. + +.. list-table:: Troubleshooting checklist + :widths: auto + :header-rows: 1 + + * - Step + - Description + - Results + * - 1 + - A single query is slow + - + If a query isn't performing as you expect, follow the :ref:`Query best practices` part of the :ref:`sql_best_practices` guide. + + If all queries are slow, continue to step 2. + * - 2 + - All queries on a specific table are slow + - + #. If all queries on a specific table aren't performing as you expect, follow the :ref:`Table design best practices` part of the :ref:`sql_best_practices` guide. + #. Check for active delete predicates in the table. Consult the :ref:`delete_guide` guide for more information. + + If the problem spans all tables, continue to step 3. + * - 3 + - Check that all workers are up + - + Use ``SELECT show_cluster_nodes();`` to list the active cluster workers. + + If the worker list is incomplete, follow the :ref:`cluster troubleshooting` section below. + + If all workers are up, continue to step 4. + * - 4 + - Check that all workers are performing well + - + #. Identify if a specific worker is slower than others by running the same query on different workers. (e.g. by connecting directly to the worker or through a service queue) + #. If a specific worker is slower than others, investigate performance issues on the host using standard monitoring tools (e.g. ``top``). + #. Restart SQream DB workers on the problematic host. + + If all workers are performing well, continue to step 5. + * - 5 + - Check if the workload is balanced across all workers + - + #. Run the same query several times and check that it appears across multiple workers (use ``SELECT show_server_status()`` to monitor) + #. If some workers have a heavier workload, check the service queue usage. Refer to the :ref:`workload_manager` guide. + + If the workload is balanced, continue to step 6. + * - 6 + - Check if there are long running statements + - + #. Identify any currently running statements (use ``SELECT show_server_status()`` to monitor) + #. If there are more statements than available resources, some statements may be in an ``In queue`` mode. + #. If there is a statement that has been running for too long and is blocking the queue, consider stopping it (use ``SELECT stop_statement()``). + + If the statement does not stop correctly, contact SQream support. + + If there are no long running statements or this does not help, continue to step 7. + * - 7 + - Check if there are active locks + - + #. Use ``SELECT show_locks()`` to list any outstanding locks. + #. If a statement is locking some objects, consider waiting for that statement to end or stop it. + #. If after a statement is completed the locks don't free up, refer to the :ref:`concurrency_and_locks` guide. + + If performance does not improve after the locks are released, continue to step 8. + * - 8 + - Check free memory across hosts + - + #. Check free memory across the hosts by running ``$ free -th`` from the terminal. + #. If the machine has less than 5% free memory, consider **lowering** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. Refer to the :ref:`configuration` guide. + #. If the machine has a lot of free memory, consider **increasing** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. + + If performance does not improve, contact SQream support for more help. + + + Troubleshooting common issues ====================================== +.. _cluster_troubleshooting: + Troubleshoot cluster setup and configuration ----------------------------------------------------- diff --git a/index.rst b/index.rst index 36aec7fd2..71e6a4c0a 100644 --- a/index.rst +++ b/index.rst @@ -18,10 +18,9 @@ SQream DB is a columnar analytic SQL database management system. SQream DB supports regular SQL including :ref:`a substantial amount of ANSI SQL`, uses :ref:`serializable transactions`, and :ref:`scales horizontally` for concurrent statements. -.. TODO: something about a single node of sqream being able to support 10 or even 100TB of data as long as it has enough storage. - -SQream DB comes with standard SQL client drivers, including :ref:`JDBC`, :ref:`ODBC`, and :ref:`Python DB-API`. +Even a :ref:basic SQream DB machine` can support tens to hundreds of terabytes of data. +SQream DB easily plugs in to third-party tools like :ref:`Tableau` comes with standard SQL client drivers, including :ref:`JDBC`, :ref:`ODBC`, and :ref:`Python DB-API`. .. .. ref`features_tour` @@ -69,16 +68,18 @@ SQream DB comes with standard SQL client drivers, including :ref:`JDBC`_ for additional support. +If you couldn't find what you're looking for, we're always happy to help. Visit `SQream's support portal `_ for additional support. -.. rubric:: Looking for the old documentation? +.. rubric:: Looking for older versions? If you're looking for an older version of the documentation, versions 1.10 through 2019.2.1 are available at http://previous.sqream.com . diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 0fb72f83a..d8e23b7a4 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -141,7 +141,7 @@ Supported date formats * - ``DD-mon-YYYY`` - ``DD-mon-YYYY[ hh:mm[:ss[.SSS]]]`` - ``31-Dec-2017 11:12:13.456`` - * - ``YYYY-mon-DD` + * - ``YYYY-mon-DD`` - ``YYYY-mon-DD[ hh:mm[:ss[.SSS]]]`` - ``2017-Dec-31 11:12:13.456`` From 2d35e62afb4f5b2167ad69690d3f50313072cfb2 Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Wed, 29 Apr 2020 12:20:43 +0200 Subject: [PATCH 016/300] Fix some outdated information in the support guides, replace links to support desk --- guides/operations/information_for_support.rst | 4 ++-- guides/operations/optimization_best_practices.rst | 2 +- guides/operations/troubleshooting.rst | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/guides/operations/information_for_support.rst b/guides/operations/information_for_support.rst index 167d4dddf..62f79b227 100644 --- a/guides/operations/information_for_support.rst +++ b/guides/operations/information_for_support.rst @@ -10,12 +10,12 @@ Gathering information for SQream support .. what about bug reports -`SQream Support `_ is ready to answer any questions, and help solve any issues with SQream DB. +`SQream Support `_ is ready to answer any questions, and help solve any issues with SQream DB. Getting support and reporting bugs ======================================= -When contacting `SQream Support `_, we recommend reporting the following information: +When contacting `SQream Support `_, we recommend reporting the following information: * What is the problem encountered? * What was the expected outcome? diff --git a/guides/operations/optimization_best_practices.rst b/guides/operations/optimization_best_practices.rst index c9543c9bb..1f06f43d9 100644 --- a/guides/operations/optimization_best_practices.rst +++ b/guides/operations/optimization_best_practices.rst @@ -81,7 +81,7 @@ Data sorting is an important factor in minimizing storage size and improving que * Minimizing storage saves on physical resources and increases performance by reducing overall disk I/O. Prioritize the sorting of low-cardinality columns. This reduces the number of chunks and extents that SQream DB reads during query execution. -* Where possible, sort columns with the lowest cardinality first. Avoid sorting ``VARCHAR`` and ``NVARCHAR`` columns with lengths exceeding 50 characters. +* Where possible, sort columns with the lowest cardinality first. Avoid sorting ``VARCHAR`` and ``TEXT/NVARCHAR`` columns with lengths exceeding 50 characters. * For longer-running queries that run on a regular basis, performance can be improved by sorting data based on the ``WHERE`` and ``GROUP BY`` parameters. Data can be sorted during insert by using :ref:`external tables` or by using :ref:`create_table_as`. diff --git a/guides/operations/troubleshooting.rst b/guides/operations/troubleshooting.rst index 18ff74a06..6951e2840 100644 --- a/guides/operations/troubleshooting.rst +++ b/guides/operations/troubleshooting.rst @@ -88,8 +88,6 @@ Troubleshoot cluster setup and configuration #. Note any errors - Make a note of any error you see, or check the :ref:`logs` for errors you might have missed. -.. note:: Logs are generated per-worker, so you will need to identify the worker on which the error occured, or collect logs from all nodes. - #. If SQream DB can't start, start SQream DB on a new storage cluster, with default settings. If it still can't start, there could be a driver or hardware issue. :ref:`Contact SQream support`. #. Reproduce the issue with a standalone SQream DB - starting up a temporary, standalone SQream DB can isolate the issue to a configuration issue, network issue, or similar. From e30834d60f3829c07570ae91871d52f7a0daee80 Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Wed, 29 Apr 2020 16:46:51 +0200 Subject: [PATCH 017/300] Add HDFS and S3 guides --- guides/features/external_data/hdfs.rst | 266 ++++++++++++++++++++++++ guides/features/external_data/index.rst | 16 ++ guides/features/external_data/s3.rst | 118 +++++++++++ guides/features/external_tables.rst | 16 +- guides/features/index.rst | 2 + 5 files changed, 414 insertions(+), 4 deletions(-) create mode 100644 guides/features/external_data/hdfs.rst create mode 100644 guides/features/external_data/index.rst create mode 100644 guides/features/external_data/s3.rst diff --git a/guides/features/external_data/hdfs.rst b/guides/features/external_data/hdfs.rst new file mode 100644 index 000000000..548c3e677 --- /dev/null +++ b/guides/features/external_data/hdfs.rst @@ -0,0 +1,266 @@ +.. _hdfs: + +*********************** +HDFS +*********************** + +SQream DB has a native HDFS connector for inserting data. The ``hdfs://`` URI specifies an external file path on a Hadoop Distributed File System. + +File names may contain wildcard characters and the files can be a CSV or columnar format like Parquet and ORC. + + +Verifying HDFS configuration +============================== + +SQream DB's built-in HDFS relies on the host's Hadoop HDFS configuration. + +Before you can use HDFS, you should verify that all SQream DB hosts are configured correctly. + +Use built-in Hadoop libraries +------------------------------- + +SQream DB comes with Hadoop libraries built-in. In a typical SQream DB installation, you'll find Hadoop and JDK libraries in the ``hdfs`` subdirectory of the package. + +If you are using the built-in libraries, it's important to note where they are. + +For example, if SQream DB was installed to ``/opt/sqream``, here's how to set-up the environment variables: + +.. _set_hadoop_classpath: + +.. code-block:: console + + $ export JAVA_HOME=/opt/sqream/hdfs/jdk + $ export CLASSPATH=`/opt/sqream/hdfs/hadoop/hadoop classpath --glob` + $ export HADOOP_HOME=/opt/sqream/hdfs/hadoop/ + $ export HADOOP_OPTS="$HADOOP_OPTS -Djava.library.path=$HADOOP_HOME/lib/native" + $ export ARROW_LIBHDFS_DIR=/opt/sqream/hdfs/hadoop/lib/native/ + +You'll find ``core-site.xml`` and other configuration files in ``/opt/sqream/hdfs/hadoop/etc/hadoop`` + +If they don't already exist, place these variable settings in a 'run commands' file like ``.bashrc``. Test this by examining the output of ``$ echo $ARROW_LIBHDFS_DIR``. + +.. note:: This process needs to be repeated for every host in the SQream DB cluster. + +(Optional) Overriding the Hadoop environment +------------------------------------------------------ + +If you have an existing Hadoop environment set-up on the host, you can override SQream DB's built-in Hadoop by setting the environment variables accordingly. + +For example, + +.. code-block:: console + + $ export JAVA_HOME=/usr/local/java-1.8.0/ + $ export CLASSPATH=`/usr/local/hadoop-3.2.1/hadoop classpath --glob`:$CLASSPATH + $ export HADOOP_HOME=/usr/local/hadoop-3.2.1/ + $ export HADOOP_OPTS="$HADOOP_OPTS -Djava.library.path=$HADOOP_HOME/lib/native" + $ export ARROW_LIBHDFS_DIR=/usr/local/hadoop-3.2.1/lib/native/ + +Place these variable settings in a 'run commands' file like ``.bashrc``. Test this by examining the output of ``$ echo $ARROW_LIBHDFS_DIR``. + +.. note:: This process needs to be repeated for every host in the SQream DB cluster. + +Configuring the node +====================== + +A Hadoop administrator will want to edit the configuration XMLs to allow access to your Hadoop cluster. + +If using the SQream DB Hadoop libraries, modify the following files to match your cluster settings: + +* ``/opt/sqream/hdfs/hadoop/etc/hadoop/core-site.xml`` +* ``/opt/sqream/hdfs/hadoop/etc/hadoop/yarn-site.xml`` +* ``/opt/sqream/hdfs/hadoop/etc/hadoop/hdfs-site.xml`` + +If using the system Hadoop libraries, be sure to override ``JAVA_HOME``, ``CLASSPATH``, ``HADOOP_HOME``, and ``ARROW_LIBHDFS_DIR`` as described above. + +Verifying Hadoop configuration +================================== + +To test HDFS access, try accessing files using the HDFS shell: + +.. code-block:: console + + $ hdfs dfs -ls + Found 2 items + -rw-r--r-- 3 hdfs supergroup 63446 2020-02-29 16:37 MD1.csv + -rw-r--r-- 3 hdfs supergroup 63906 2020-02-29 16:37 MD2.csv + $ hdfs dfs -tail MD1.csv + 985,Obediah,Reith,oreithrc@time.com,Male,Colombia,859.28 + 986,Lennard,Hairesnape,lhairesnaperd@merriam-webster.com,Male,North Korea,687.60 + 987,Valaree,Pieper,vpieperre@tinyurl.com,Female,Kazakhstan,1116.23 + 988,Rosemaria,Legan,rleganrf@slideshare.net,Female,Indonesia,62.19 + 989,Rafaellle,Hartill,rhartillrg@marketwatch.com,Male,Albania,1308.17 + 990,Symon,Edmett,sedmettrh@tinyurl.com,Male,China,1216.97 + 991,Hiram,Slayton,hslaytonri@amazon.de,Male,China,510.55 + 992,Sylvan,Dalgliesh,sdalglieshrj@booking.com,Male,China,1503.60 + 993,Alys,Sedgebeer,asedgebeerrk@va.gov,Female,Moldova,1947.58 + 994,Ninette,Hearl,nhearlrl@sakura.ne.jp,Female,Palau,917.66 + 995,Tommy,Atterley,tatterleyrm@homestead.com,Female,Philippines,1660.22 + 996,Sean,Mully,smullyrn@rakuten.co.jp,Female,Brunei,938.04 + 997,Gabe,Lytell,glytellro@cnn.com,Male,China,491.12 + 998,Clementius,Battison,cbattisonrp@dedecms.com,Male,Norway,1781.92 + 999,Kyle,Vala,kvalarq@paginegialle.it,Male,France,11.26 + 1000,Korrie,Odd,koddrr@bigcartel.com,Female,China,471.96 + +If the command succeeded and the file was read correctly, you HDFS has been configured correctly and can now be used in SQream DB. + +If an access error occured, check your Hadoop configuration or contact SQream support. + + +Configuring HDFS for Kerberos access +======================================== + +This section describes how to configure SQream DB to access HDFS secured with Kerberos. + +When a Hadoop cluster is Kerberized, SQream DB's user must be configured to to authenticate through Kerberos. + +Prerequisites +---------------- + +This section assumes you already have Java and Hadoop installed on your SQream DB hosts. + +* SQream DB hosts and Kerberos servers should have the same JCE (Java Cryptography Extension). You can copy the JCE files from the Kerberos server to the SQream DB hosts if needed, to the ``$JAVA_HOME/jre/lib/security`` path. + +* Install the Kerberos clients + + CentOS / RHEL: ``$ sudo yum install krb5-libs krb5-workstation`` + Ubuntu: ``$ sudo apt-get install krb5-user`` + +* Configure Hadoop as per your distribution. + +Creating keytabs +---------------------- + +#. Sign into your Kerberos Key Distribution Center (KDC) as a root user + +#. + Create a new principal for the SQream DB OS users (e.g. ``sqream`` by default): + + ``# kadmin.local -q "addprinc -randkey sqream@KRLM.PIEDPIPER.COM"`` + + Make sure to replace the realm (``KRLM.PIEDPIPER.COM``) with your actual Kerberos realm. + +#. + Create a Kerberos service principal for each SQream DB host in the cluster. + + In this example, three cluster hosts: + + .. code-block:: console + + # kadmin.local -q "addprinc -randkey sqream/sqreamdb-01.piedpiper.com@KRLM.PIEDPIPER.COM" + # kadmin.local -q "addprinc -randkey sqream/sqreamdb-02.piedpiper.com@KRLM.PIEDPIPER.COM" + # kadmin.local -q "addprinc -randkey sqream/sqreamdb-03.piedpiper.com@KRLM.PIEDPIPER.COM" + + The format for each principal is ``user/host@realm``, where: + * ``user`` is the OS username + * ``host`` is the hostname (typically the output of ``hostname -f``) + * ``realm`` is the Kerberos realm + +#. Generate a keytab for each principal. + + .. code-block:: console + + # kadmin.local -q "xst -k /etc/security/keytabs/sqreamdb-01.service.keytab sqream/sqreamdb-01 sqream/sqreamdb-01.piedpiper.com@KRLM.PIEDPIPER.COM" + # kadmin.local -q "xst -k /etc/security/keytabs/sqreamdb-02.service.keytab sqream/sqreamdb-02 sqream/sqreamdb-02.piedpiper.com@KRLM.PIEDPIPER.COM" + # kadmin.local -q "xst -k /etc/security/keytabs/sqreamdb-03.service.keytab sqream/sqreamdb-03 sqream/sqreamdb-03.piedpiper.com@KRLM.PIEDPIPER.COM" + + You can now exit ``kadmin``. + +#. Change permissions and ownership on each keytab: + + .. code-block:: console + + # chown sqream:sqream /etc/security/keytabs/sqreamdb* + # chmod 440 /etc/security/keytabs/sqreamdb* + +#. Copy the keytab files for each service principal to its respective SQream DB host: + + .. code-block:: console + + # scp /etc/security/keytabs/sqreamdb-01.service.keytab sqreamdb-01.piedpiper.com:/home/sqream/sqreamdb-01.service.keytab + # scp /etc/security/keytabs/sqreamdb-02.service.keytab sqreamdb-02.piedpiper.com:/home/sqream/sqreamdb-02.service.keytab + # scp /etc/security/keytabs/sqreamdb-03.service.keytab sqreamdb-03.piedpiper.com:/home/sqream/sqreamdb-03.service.keytab + +Configuring HDFS for Kerberos +--------------------------------- + +#. + Edit the ``core-site.xml`` configuration file on each SQream DB host to enable authorization. + + For example, editing ``/opt/sqream/hdfs/hadoop/etc/hadoop/core-site.xml``: + + .. code-block:: xml + + + hadoop.security.authorization + true + + +#. Edit the ``yarn-site.xml`` configuration file on each SQream DB host to set the Yarn Kerberos principal + + For example, editing ``/opt/sqream/hdfs/hadoop/etc/hadoop/yarn-site.xml``: + + .. code-block:: xml + + + yarn.resourcemanager.address + hadoop-nn.piedpiper.com:8032 + + + yarn.resourcemanager.principal + yarn/_hostname@KRLM.PIEDPIPER.COM + + +#. + + Edit the ``hdfs-site.xml`` configuration file on each SQream DB host to set the NameNode Kerberos principals, the location of the Kerberos keytab file, and the principal: + + For example, editing ``/opt/sqream/hdfs/hadoop/etc/hadoop/hdfs-site.xml`` on the first host (``sqreamdb-01``): + + .. code-block:: xml + + + dfs.namenode.kerberos.principal + sqream/sqreamdb-01.piedpiper.com@KRLM.PIEDPIPER.COM + + + dfs.namenode.https.principal + sqream/sqreamdb-01.piedpiper.com@KRLM.PIEDPIPER.COM + + + com.emc.greenplum.gpdb.hdfsconnector.security.user.keytab.file + /home/sqream/sqreamdb-01.service.keytab + + + com.emc.greenplum.gpdb.hdfsconnector.security.user.name + sqream/sqreamdb-01.piedpiper.com@KRLM.PIEDPIPER.CO + + +Test the access +-------------------- + +To confirm that Kerberized HDFS is accessible on all SQream DB hosts, run the following command to list a directory: + +.. code-block:: console + + $ hdfs dfs -ls hdfs://hadoop-nn.piedpiper.com:8020 + +Repeat the command on all hosts. +If the command succeeds and you see a directory listing, Kerberized HDFS has been configured correctly and can now be used in SQream DB. + +If an error occured, check your configuration or contact SQream support. + +Troubelshooting HDFS access +================================== + +``class not found`` error +--------------------------------- + +If you get a ``class not found`` error that looks like this: + + java.lang.ClassNotFoundException: Class org.apache.hadoop.hdfs.DistributedFileSystem not found + +#. Verify that the CLASSPATH and ARROW_LIBHDFS_DIR are set correctly. Read more about :ref:`setting the environment variables` above. + +#. Try restarting SQream DB after setting the environment variables. + diff --git a/guides/features/external_data/index.rst b/guides/features/external_data/index.rst new file mode 100644 index 000000000..c5bbd2597 --- /dev/null +++ b/guides/features/external_data/index.rst @@ -0,0 +1,16 @@ +.. _external_data: + +********************************** +Working with external data +********************************** + +SQream DB supports external data sources for use with :ref:`external_tables`, :ref:`copy_from`, and :ref:`copy_to`. + +.. toctree:: + :maxdepth: 2 + :caption: In this section: + :glob: + + s3 + hdfs + diff --git a/guides/features/external_data/s3.rst b/guides/features/external_data/s3.rst new file mode 100644 index 000000000..4e7992087 --- /dev/null +++ b/guides/features/external_data/s3.rst @@ -0,0 +1,118 @@ +.. _s3: + +*********************** +S3 +*********************** + +SQream DB has a native S3 connector for inserting data. The ``s3://`` URI specifies an external file path on an S3 bucket. + +File names may contain wildcard characters and the files can be a CSV or columnar format like Parquet and ORC. + +S3 configuration +============================== + +Any SQream DB host that has access to S3 endpoints can access S3 without any configuration. + +To read files from an S3 bucket, it must have listable files. + +S3 URI format +=============== + +With S3, specify a location for a file (or files) when using :ref:`copy_from` or :ref:`external_tables`. + +The general S3 syntax is: +``s3://bucket_name/path`` + +Authentication +================= + +SQream DB supports ``AWS ID`` and ``AWS SECRET`` authentication. +These should be specified when executing a statement. + +Examples +========== + +Use an external table to stage data from S3 before loading from CSV, Parquet or ORC files. + +Planning for data staging +-------------------------------- + +For the following examples, we will want to interact with a CSV file. Here's a peek at the table contents: + +.. csv-table:: nba.csv + :file: ../nba-t10.csv + :widths: auto + :header-rows: 1 + +The file is stored on :ref:`s3`, at ``s3://sqream-demo-data/nba_players.csv``. +This bucket is public and listable. + +We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_TABLE`` statement. + +Creating the external table +----------------------------- + +Based on the source file structure, we we :ref:`create an external table` with the appropriate structure, and point it to the file. + +.. code-block:: postgres + + CREATE EXTERNAL TABLE nba + ( + Name varchar(40), + Team varchar(40), + Number tinyint, + Position varchar(2), + Age tinyint, + Height varchar(4), + Weight real, + College varchar(40), + Salary float + ) + USING FORMAT CSV -- Text file + WITH PATH 's3://sqream-demo-data/nba_players.csv' + RECORD DELIMITER '\r\n'; -- DOS delimited file + +The file format in this case is CSV, and it is stored as an S3 object (if the path is on :ref:`hdfs`, change the URI accordingly). + +We also took note that the record delimiter was a DOS newline (``\r\n``). + +Querying external tables +------------------------------ + +Let's peek at the data from the external table: + +.. code-block:: psql + + t=> SELECT * FROM nba LIMIT 10; + name | team | number | position | age | height | weight | college | salary + --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- + Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 + Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 + John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | + R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 + Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 + Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 + Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 + Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 + Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 + Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 + +Bulk loading a file from a public S3 bucket +---------------------------------------------- + +The :ref:`copy_from` command can also be used to load data without staging it first. + +.. note:: The bucket must be publicly available and objects can be listed + +.. code-block:: postgres + + COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n'; + +Loading files from an authenticated S3 bucket +--------------------------------------------------- + +.. code-block:: postgres + + COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n' + AWS_ID '12345678' + AWS_SECRET 'super_secretive_secret'; \ No newline at end of file diff --git a/guides/features/external_tables.rst b/guides/features/external_tables.rst index 6a29d4867..1cc4e2c53 100644 --- a/guides/features/external_tables.rst +++ b/guides/features/external_tables.rst @@ -15,12 +15,20 @@ Although external tables can be used without inserting data into SQream DB, one What kind of data is supported? ===================================== -SQream DB supports external tables over text files (e.g. CSV, PSV, TSV) as well as columnar formats like ORC and Parquet. +SQream DB supports external tables over: + +* text files (e.g. CSV, PSV, TSV) +* ORC +* Parquet What kind of data staging is supported? ============================================ -SQream DB can stage data from a local filesystem, S3, and HDFS. +SQream DB can stage data from: + +* a local filesystem (e.g. ``/mnt/storage/....``) +* :ref:`s3` buckets (e.g. ``s3://pp-secret-bucket/users/*.parquet``) +* :ref:`hdfs` (e.g. ``hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv``) Using external tables - a practical example ============================================== @@ -37,7 +45,7 @@ For the following examples, we will want to interact with a CSV file. Here's a p :widths: auto :header-rows: 1 -The file is stored on S3, at ``s3://sqream-demo-data/nba_players.csv``. +The file is stored on :ref:`s3`, at ``s3://sqream-demo-data/nba_players.csv``. We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_TABLE`` statement. @@ -64,7 +72,7 @@ Based on the source file structure, we we :ref:`create an external table Date: Wed, 29 Apr 2020 16:51:33 +0200 Subject: [PATCH 018/300] Add some TOCs --- guides/features/external_data/hdfs.rst | 3 +++ guides/features/external_data/s3.rst | 4 ++++ guides/features/external_tables.rst | 4 ++++ guides/migration/csv.rst | 3 +++ guides/migration/parquet.rst | 2 ++ guides/operations/troubleshooting.rst | 3 +++ 6 files changed, 19 insertions(+) diff --git a/guides/features/external_data/hdfs.rst b/guides/features/external_data/hdfs.rst index 548c3e677..a9b097a7c 100644 --- a/guides/features/external_data/hdfs.rst +++ b/guides/features/external_data/hdfs.rst @@ -9,6 +9,9 @@ SQream DB has a native HDFS connector for inserting data. The ``hdfs://`` URI sp File names may contain wildcard characters and the files can be a CSV or columnar format like Parquet and ORC. +.. contents:: In this topic: + :local: + Verifying HDFS configuration ============================== diff --git a/guides/features/external_data/s3.rst b/guides/features/external_data/s3.rst index 4e7992087..3f2fc3dc8 100644 --- a/guides/features/external_data/s3.rst +++ b/guides/features/external_data/s3.rst @@ -8,6 +8,10 @@ SQream DB has a native S3 connector for inserting data. The ``s3://`` URI specif File names may contain wildcard characters and the files can be a CSV or columnar format like Parquet and ORC. + +.. contents:: In this topic: + :local: + S3 configuration ============================== diff --git a/guides/features/external_tables.rst b/guides/features/external_tables.rst index 1cc4e2c53..8d971a4f9 100644 --- a/guides/features/external_tables.rst +++ b/guides/features/external_tables.rst @@ -12,6 +12,10 @@ Running queries directly on external data is most effectively used for things li Although external tables can be used without inserting data into SQream DB, one of their main use cases is to help with the insertion process. An insert select statement on an external table can be used to insert data into SQream using the full power of the query engine to perform ETL. + +.. contents:: In this topic: + :local: + What kind of data is supported? ===================================== diff --git a/guides/migration/csv.rst b/guides/migration/csv.rst index d95411d73..de18d716e 100644 --- a/guides/migration/csv.rst +++ b/guides/migration/csv.rst @@ -7,6 +7,9 @@ Insert from CSV This guide covers inserting data from CSV files into SQream DB using the :ref:`copy_from` method. +.. contents:: In this topic: + :local: + 1. Prepare CSVs ===================== diff --git a/guides/migration/parquet.rst b/guides/migration/parquet.rst index 955f39ee0..a13d59d2d 100644 --- a/guides/migration/parquet.rst +++ b/guides/migration/parquet.rst @@ -6,6 +6,8 @@ Insert from Parquet This guide covers inserting data from Parquet files into SQream DB using :ref:`EXTERNAL TABLE`. +.. contents:: In this topic: + :local: 1. Prepare the files ===================== diff --git a/guides/operations/troubleshooting.rst b/guides/operations/troubleshooting.rst index 6951e2840..7eed4c757 100644 --- a/guides/operations/troubleshooting.rst +++ b/guides/operations/troubleshooting.rst @@ -4,6 +4,9 @@ Troubleshooting *********************** +.. contents:: In this topic: + :local: + Follow this checklist if you find that the performance is slower than you expect. .. list-table:: Troubleshooting checklist From 4f3f30a60d7c8fbe6a307ad4f81f5ce856790f53 Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Wed, 29 Apr 2020 16:54:31 +0200 Subject: [PATCH 019/300] Fix styling --- guides/features/external_data/hdfs.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/guides/features/external_data/hdfs.rst b/guides/features/external_data/hdfs.rst index a9b097a7c..44242b619 100644 --- a/guides/features/external_data/hdfs.rst +++ b/guides/features/external_data/hdfs.rst @@ -127,6 +127,7 @@ This section assumes you already have Java and Hadoop installed on your SQream D * Install the Kerberos clients CentOS / RHEL: ``$ sudo yum install krb5-libs krb5-workstation`` + Ubuntu: ``$ sudo apt-get install krb5-user`` * Configure Hadoop as per your distribution. @@ -139,7 +140,9 @@ Creating keytabs #. Create a new principal for the SQream DB OS users (e.g. ``sqream`` by default): - ``# kadmin.local -q "addprinc -randkey sqream@KRLM.PIEDPIPER.COM"`` + .. code-block:: console + + # kadmin.local -q "addprinc -randkey sqream@KRLM.PIEDPIPER.COM" Make sure to replace the realm (``KRLM.PIEDPIPER.COM``) with your actual Kerberos realm. From fe6bf3cccea86be09d42ddd828fa421a39e5bbc6 Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Fri, 1 May 2020 12:46:05 +0200 Subject: [PATCH 020/300] Security and access control refinements --- guides/features/access_control.rst | 99 +++++++++++++++++++++++------- guides/operations/index.rst | 1 + guides/operations/security.rst | 95 ++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+), 22 deletions(-) create mode 100644 guides/operations/security.rst diff --git a/guides/features/access_control.rst b/guides/features/access_control.rst index c4cf11f8f..45038dee8 100644 --- a/guides/features/access_control.rst +++ b/guides/features/access_control.rst @@ -8,30 +8,60 @@ Access control :local: Overview -======== +========== Access control provides authentication and authorization in SQream DB. -:term:`Authentication` : verifying the identity of the user. Users have usernames (:term:`role names`) and passwords. +SQream DB manages authentication and authorization using a role-based access control system (RBAC), like ANSI SQL and other SQL products. -:term:`Authorization` : checking the user has permissions to do a particular thing. The :ref:`grant` command is used for this. +SQream DB has a default permissions system which is inspired by Postgres, but with more power. In most cases, this allows an administrator to set things up so that every object gets permissions set automatically. -* SQream DB uses roles as users and groups, like ANSI SQL and other SQL products +In SQream DB, users log in from any worker which verifies their roles and permissions from the metadata server. Each statement issues commands as the currently logged in role. + +Roles are defined at the cluster level, meaning they are valid for all databases in the cluster. + +To bootstrap SQream DB, a new install will always have one ``SUPERUSER`` role, typically named ``sqream``. To create more roles, you should first connect as this role. + + +Terminology +================ + +Roles +---------- + +:term:`Role` : a role can be a user, a group, or both. + +Roles can own database objects (e.g. tables), and can assign permissions on those objects to other roles. + +Roles can be members of other roles, meaning a user role can inherit permissions from its parent role. + +Authentication +-------------------- + +:term:`Authentication` : verifying the identity of the role. User roles have usernames (:term:`role names`) and passwords. + + +Authorization +---------------- + +:term:`Authorization` : checking the role has permissions to do a particular thing. The :ref:`grant` command is used for this. -* SQream DB has a default permissions system based on the system in Postgres, but with more power. - In most cases, this allows an administrator to set things up so that every object gets permissions set automatically. Roles ===== -Roles are used for users and for groups. +Roles are used for both users and groups. -Roles are global across all databases in the instance / storage cluster. +Roles are global across all databases in the SQream DB cluster. -To use a ``ROLE`` as USER, it should have a password, the login permission, and connect permissions to the relevant databases. +To use a ``ROLE`` as a user, it should have a password, the login permission, and connect permissions to the relevant databases. -Creating a user ---------------- +Creating new roles (users) +------------------------------ + +A user role can log in to the database, so it should have ``LOGIN`` permissions, as well as a password. + +For example: .. code-block:: postgres @@ -49,6 +79,8 @@ Examples: GRANT PASSWORD 'my_password' TO new_role_name; GRANT CONNECT ON DATABASE master TO new_role_name; +A database role may have a number of permissions that define what tasks it can perform. These are assigned using the :ref:`grant` command. + Dropping a user --------------- @@ -60,7 +92,7 @@ Examples: .. code-block:: postgres - DROP ROLE admin_role ; + DROP ROLE admin_role ; Altering a user --------------- @@ -73,7 +105,7 @@ Examples: .. code-block:: postgres - ALTER ROLE admin_role RENAME TO copy_role ; + ALTER ROLE admin_role RENAME TO copy_role ; Public Role ----------- @@ -82,22 +114,45 @@ There is a public role which always exists. Each role is granted to the ``PUBLIC The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, new users can create, :ref:`insert`, :ref:`delete`, and :ref:`select` from objects in the ``PUBLIC`` schema. -Groups ------- -A group can be created, altered, and dropped the same way as a user. +Role membership (groups) +------------------------- + +Many database administrators find it useful to group user roles together. By grouping users, permissions can be granted to, or revoked from a group with one command. In SQream DB, this is done by creating a group role, granting permissions to it, and then assigning users to that group role. -To use a role purely as a group, omit granting it ``LOGIN`` and ``PASSWORD`` permissions. The ``CONNECT`` permission can be given directly to users, and/or to the groups they are part of. +To use a role purely as a group, omit granting it ``LOGIN`` and ``PASSWORD`` permissions. + +The ``CONNECT`` permission can be given directly to user roles, and/or to the groups they are part of. .. code-block:: postgres CREATE ROLE my_group; - GRANT CONNECT ON DATABASE a_database TO my_group; - -- add my_user to this group + +Once the group role exists, you can add user roles (members) using the ``GRANT`` command. For example: + +.. code-block:: postgres + + -- Add my_user to this group GRANT my_group TO my_user; - -- remove my_other_user from this group +To manage object permissions like databases and tables, you would then grant permissions to the group-level role (see :ref:`the permissions table below`. + +All member roles then inherit the permissions from the group. For example: + +.. code-block:: postgres + + -- Grant all group users connect permissions + GRANT CONNECT ON DATABASE a_database TO my_group; + + -- Grant all permissions on tables in public schema + GRANT ALL ON all tables IN schema public TO my_group; + +Removing users and permissions can be done with the ``REVOKE`` command: + +.. code-block:: postgres + + -- remove my_other_user from this group REVOKE my_group FROM my_other_user; .. _permissions_table: @@ -341,10 +396,10 @@ schema statement is run. | EXECUTE | ALL } - + Departmental Example -==================== +======================= You work in a company with several departments. diff --git a/guides/operations/index.rst b/guides/operations/index.rst index 556028584..96f6a6338 100644 --- a/guides/operations/index.rst +++ b/guides/operations/index.rst @@ -21,5 +21,6 @@ The guides in this section include information about best practices, monitoring, xxstarting_and_stopping_the_system statement_editor hardware_guide + security setup/index diff --git a/guides/operations/security.rst b/guides/operations/security.rst new file mode 100644 index 000000000..3577c8f00 --- /dev/null +++ b/guides/operations/security.rst @@ -0,0 +1,95 @@ +.. _security: + +************************* +Security +************************* + +.. contents:: In this topic: + :local: + +SQream DB has some security features that you should be aware of to increase the security of your data. + + +Overview +============ + +An **initial, unsecured** installation of SQream DB can carry some risks: + +* Your data open to any client that can access an open node through an IP and port combination. +* The initial administrator username and password, when unchanged, can let anyone log in. +* Network connections to SQream DB aren't encrypted. + +To avoid these security risks, SQream DB provides authentication, authorizaiton, logging, and network encryption. + +Read through the best practices guide to understand more. + +Security best practices for SQream DB +============================================== + +Secure OS access +------------------------- + +SQream DB often runs as a dedicated user on the host OS. This user is the file system owner of SQream DB data files. + +Any user who logs in to the OS with this user can read or delete data from outside of SQream DB. + +This user can also read any logs which may contain user login attempts. + +Therefore, it is very important to secure the host OS and prevent unauthorized access. + +System administrators should only log in to the host OS to perform maintenance tasks like upgrades. A database user should not log in using the same username in production environments. + +Change the default ``SUPERUSER`` +----------------------------------- + +To bootstrap SQream DB, a new install will always have one ``SUPERUSER`` role, typically named ``sqream``. +After creating a second ``SUPERUSER`` role, remove or change the default credentials to the default ``sqream`` user. + +No database user should ever use the default ``SUPERUSER`` role in a production environment. + +Create distinct user roles +-------------------------------- + +Each user that signs in to a SQream DB cluster should have a distinct user role for several reasons: + +* For logging and auditing purposes. Each user that logs in to SQream DB can be identified. + +* For limiting permissions. Use groups and permissions to manage access. See our :ref:`access_control` guide for more information. + +Limit ``SUPERUSER`` access +------------------------------- + +Limit users who have the ``SUPERUSER`` role. + +A superuser role bypasses all permissions checks. Only system administrators should have ``SUPERUSER`` roles. See our :ref:`access_control` guide for more information. + +Password strength guidelines +-------------------------------- + +System administrators should verify the passwords used are strong ones. + +SQream DB stores passwords as salted SHA1 hashes in the system catalog so they are obscured and can't be recovered. However, passwords may appear in server logs. Prevent access to server logs by securing OS access as described above. + +Follow these recommendations to strengthen passwords: + +* Pick a password that's easy to remember +* At least 8 characters +* Mix upper and lower case letters +* Mix letters and numbers +* Include non-alphanumeric characters (except ``"`` and ``'``) + +Use TLS/SSL when possible +---------------------------- + +SQream DB's protocol implements client/server TLS security (even though it is called SSL). + +All SQream DB connectors and drivers support transport encryption. Ensure that each connection uses SSL and the correct access port for the SQream DB cluster: + +* The load balancer (``server_picker``) is often started with the secure port at an offset of 1 from the original port (e.g. port 3108 for the unsecured connection and port 3109 for the secured connection). + +* A SQream DB worker is often started with the secure port enabled at an offset of 100 from the original port (e.g. port 5000 for the unsecured connection and port 5100 for the secured connection). + +Refer to each :ref:`client driver` for instructions on enabling TLS/SSL. + + + From 733dda8fefd07bb48153cc5db6b22821b0b8ba6e Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Fri, 1 May 2020 12:46:25 +0200 Subject: [PATCH 021/300] HDFS typos, crosslinking to insertion guide --- guides/features/external_data/hdfs.rst | 3 +++ guides/inserting_data.rst | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/guides/features/external_data/hdfs.rst b/guides/features/external_data/hdfs.rst index 44242b619..a4c628e50 100644 --- a/guides/features/external_data/hdfs.rst +++ b/guides/features/external_data/hdfs.rst @@ -158,8 +158,11 @@ Creating keytabs # kadmin.local -q "addprinc -randkey sqream/sqreamdb-03.piedpiper.com@KRLM.PIEDPIPER.COM" The format for each principal is ``user/host@realm``, where: + * ``user`` is the OS username + * ``host`` is the hostname (typically the output of ``hostname -f``) + * ``realm`` is the Kerberos realm #. Generate a keytab for each principal. diff --git a/guides/inserting_data.rst b/guides/inserting_data.rst index 11db76f7c..c554b7625 100644 --- a/guides/inserting_data.rst +++ b/guides/inserting_data.rst @@ -15,14 +15,14 @@ SQream DB supports importing data from the following sources: * Using :ref:`copy_from`: - Local filesystem and locally mounted network filesystems - - S3 - - HDFS + - :ref:`s3` + - :ref:`hdfs` * Using :ref:`external_tables`: - Local filesystem and locally mounted network filesystems - - S3 - - HDFS + - :ref:`s3` + - :ref:`hdfs` SQream DB supports loading files in the following formats: From ebd50ba639ac26d7c1292c122abba5e7e67a299c Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Fri, 1 May 2020 14:51:54 +0200 Subject: [PATCH 022/300] Write a bit about time based data management --- guides/features/index.rst | 2 +- .../features/time_based_data_management.rst | 71 +++++++++++++++---- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/guides/features/index.rst b/guides/features/index.rst index 9ae5e93ff..8c7fbb018 100644 --- a/guides/features/index.rst +++ b/guides/features/index.rst @@ -16,7 +16,7 @@ Features guides external_data/index delete - xxtime_based_data_management + time_based_data_management xxmetadata_system xxchunks_and_extents diff --git a/guides/features/time_based_data_management.rst b/guides/features/time_based_data_management.rst index 7da9d2793..b152b5597 100644 --- a/guides/features/time_based_data_management.rst +++ b/guides/features/time_based_data_management.rst @@ -1,24 +1,67 @@ .. _time_based_data_management: -************************** +*************************** Time based data management -************************** +*************************** -you have data with a timestamp column +SQream DB's columnar-storage system is well adapted to timestamped data. -the time stamp matches more or less with when the data is inserted -into sqream/ and when the event that generated that data happened -(e.g. you are inserting new event data every hour or every day) +When loading data with natural ordering (sorted by a timestamp), SQream DB organizes and collects metadata in chunks of time. +Natural ordering allows for fast retrieval when performing range queries. -you want to keep x months or years of data in sqream to query. so -e.g. you delete the oldest month of data every month, by this -timestamp column +Timestamped data +=========================== -you often query over a range on this timestamp, e.g. a specific hour, -day or month. +Timestamped data usually has some interesting attributes: -the sqream chunk/extent system, the insert implementation, and the -free cheap metadata system will all support this kind of process -extremely effectively +* Data is loaded in a natural order, as it is created +* Updates are infrequent or non-existent. Any updates are done by inserting a new row relating to a new timestamp +* Queries on timestamped data is typically on continuous time ranges + +* Inserting and reading data are performed in independently, not in the operation or transaction + +* Timestamped data has a high data volume and accumulates faster than typical OLTP workloads + +Chunking +================= + +Core to handling timestamped data is SQream DB's chunking and metadata system. + +When data is inserted, data is automatically partitioned vertically by column, and horizontally by chunk. + +A chunk can be thought of as an automatic partition that spans several millions of records of one column. +Unlike node-partitioning (or sharding), chunking carries several benefits: + +* Chunks are small enough to allow multiple workers to read them concurrently + +* Chunks are optimized for fast insertion of data + +* Chunks carry metadata, which narrows down their contents for the optimizer + +* CHunks are ideal for data retension as they can be deleted en-masse + +* Chunks are optimized for reading into RAM and the GPU + +* Chunks are compressed individually, which improves compression and data locality + + +Use cases +============ + +Consider a set of data with a timestamp column. + +The timestamp order matches the order of data insertion (i.e. newer data is loaded after older data). +This is common when you insert data in small bulks - every 15 minutes, every hour, every day, etc. + +SQream DB's storage works by appending new data, partitioned into chunks containing millions of values. +As new data is loaded, it is chunked and appended to a table. + +This is particularly useful in many scenarios: + +* You run analytical queries spanning specific date ranges (e.g. the sum of transactions during the summer in 2020 vs. the summer in 2019) + +* You :ref:`delete data` when it is older than X months old + +* Regulations instruct you to keep several years' worth of data, but you're not interested in querying this data all the time \ No newline at end of file From db57b6b006773a7372579e90e0c03f46ad2eb9dc Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Fri, 1 May 2020 15:00:48 +0200 Subject: [PATCH 023/300] More time based stuff --- .../features/time_based_data_management.rst | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/guides/features/time_based_data_management.rst b/guides/features/time_based_data_management.rst index b152b5597..0ec279842 100644 --- a/guides/features/time_based_data_management.rst +++ b/guides/features/time_based_data_management.rst @@ -9,6 +9,10 @@ SQream DB's columnar-storage system is well adapted to timestamped data. When loading data with natural ordering (sorted by a timestamp), SQream DB organizes and collects metadata in chunks of time. Natural ordering allows for fast retrieval when performing range queries. +.. contents:: In this topic: + :local: + + Timestamped data =========================== @@ -46,7 +50,6 @@ Unlike node-partitioning (or sharding), chunking carries several benefits: * Chunks are compressed individually, which improves compression and data locality - Use cases ============ @@ -64,4 +67,36 @@ This is particularly useful in many scenarios: * You :ref:`delete data` when it is older than X months old -* Regulations instruct you to keep several years' worth of data, but you're not interested in querying this data all the time \ No newline at end of file +* Regulations instruct you to keep several years' worth of data, but you're not interested in querying this data all the time + +Best practices for time-based data +========================================= + +Use date and datetime types for columns +----------------------------------------- + +When creating tables with dates or timestamps, using the purpose-built ``DATE`` and ``DATETIME`` types over integer types or ``VARCHAR`` will bring performance and storage footprint improvements, and in many cases huge performance improvements (as well as data integrity benefits). SQream DB stores dates and datetimes very efficiently and can strongly optimize queries using these specific types. + +Ordering +----------- + +Data ordering is an important factor in minimizing storage size and improving query performance. + +Prioritize inserting data based on timestamps. This will likely reduces the number of chunks that SQream DB reads during query execution. + +Limit workload by timestamp +------------------------------ + +Grouping by and filtering data based on timestamps will improve performance. + +For example, + +.. code-block:: postgres + + SELECT DATEPART(HOUR, timestamp), + MIN(transaction_amount), + MAX(transaction_amount), + avg(transaction_amount) + FROM transactions + WHERE timestamp BETWEEN (CURRENT_TIMESTAMP AND DATEADD(MONTH,-3,CURRENT_TIMESTAMP)) + GROUP BY 1; From fc6c7a3edf2095e72035db3e199f7cb244321c0f Mon Sep 17 00:00:00 2001 From: Arnon Shimoni Date: Fri, 1 May 2020 15:00:57 +0200 Subject: [PATCH 024/300] Local TOCs --- guides/inserting_data.rst | 8 ++++++++ guides/operations/optimization_best_practices.rst | 3 +++ guides/operations/security.rst | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/guides/inserting_data.rst b/guides/inserting_data.rst index c554b7625..a2256eef8 100644 --- a/guides/inserting_data.rst +++ b/guides/inserting_data.rst @@ -6,6 +6,10 @@ Inserting data This guide covers inserting data into SQream DB, with subguides on inserting data from a variety of sources and locations. +.. contents:: In this topic: + :local: + + Data loading overview ================================ @@ -42,9 +46,13 @@ Like other RDBMSs, SQream DB has its own set of best practcies for table design SQream therefore recommends: * Verify that the data is as you expect it (e.g. row counts, data types, formatting, content) + * The performance of your queries is adequate + * :ref:`Best practices` were followed for table design + * Applications such as :ref:`Tableau` and others have been tested, and work + * Data types were not over-provisioned (e.g. don't use VARCHAR(2000) to store a short string) File source location for loading diff --git a/guides/operations/optimization_best_practices.rst b/guides/operations/optimization_best_practices.rst index 1f06f43d9..7290f49ac 100644 --- a/guides/operations/optimization_best_practices.rst +++ b/guides/operations/optimization_best_practices.rst @@ -6,6 +6,9 @@ Optimization and best practices This topic explains some best practices of working with SQream DB. +.. contents:: In this topic: + :local: + .. _table_design_best_practices: Table design diff --git a/guides/operations/security.rst b/guides/operations/security.rst index 3577c8f00..598c40196 100644 --- a/guides/operations/security.rst +++ b/guides/operations/security.rst @@ -4,11 +4,11 @@ Security ************************* +SQream DB has some security features that you should be aware of to increase the security of your data. + .. contents:: In this topic: :local: -SQream DB has some security features that you should be aware of to increase the security of your data. - Overview ============ From 2244bf2f7e4d85a636c8125e21b662b261eaa1d7 Mon Sep 17 00:00:00 2001 From: Sean-Tomarian <72871619+Sean-Tomarian@users.noreply.github.com> Date: Mon, 26 Oct 2020 10:29:08 +0200 Subject: [PATCH 025/300] Update show_server_status.rst --- .../sql_statements/monitoring_commands/show_server_status.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/monitoring_commands/show_server_status.rst b/reference/sql/sql_statements/monitoring_commands/show_server_status.rst index 19fb4a582..7b2dd43f5 100644 --- a/reference/sql/sql_statements/monitoring_commands/show_server_status.rst +++ b/reference/sql/sql_statements/monitoring_commands/show_server_status.rst @@ -78,6 +78,8 @@ This function returns a list of active sessions. If no sessions are active acros - Statement has entered execution checks * - ``Executing`` - Statement is executing + * - ``Stopping`` + - Statement is in the process of stopping Notes =========== @@ -98,4 +100,4 @@ Using ``SHOW_SERVER_STATUS`` to get statement IDs --------+------------+---------------+--------------+------------+---------------+------------+-------------+-------------+-----------------------------+---------------------+-----------------+--------------------- sqream | | 102 | 192.168.1.91 | 5000 | t | rhendricks | 192.168.0.1 | 128 | SELECT SHOW_SERVER_STATUS() | 24-12-2019 00:14:53 | Executing | 24-12-2019 00:14:53 -The statement ID is ``128``, running on worker ``192.168.1.91``. \ No newline at end of file +The statement ID is ``128``, running on worker ``192.168.1.91``. From d7559a67e22e2d0cd991eb92ed638e37861ce088 Mon Sep 17 00:00:00 2001 From: Sean-Tomarian <72871619+Sean-Tomarian@users.noreply.github.com> Date: Sun, 31 Jan 2021 18:22:34 +0200 Subject: [PATCH 026/300] added 3rd argument to CHARINDEX function --- .../sql/sql_functions/scalar_functions/string/charindex.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/charindex.rst b/reference/sql/sql_functions/scalar_functions/string/charindex.rst index 30b7a583a..fa9c89027 100644 --- a/reference/sql/sql_functions/scalar_functions/string/charindex.rst +++ b/reference/sql/sql_functions/scalar_functions/string/charindex.rst @@ -13,7 +13,7 @@ Syntax .. code-block:: postgres - CHARINDEX ( needle_string_expr , haystack_string_expr ) --> INT + CHARINDEX ( needle_string_expr , haystack_string_expr [ , start_location ] ) Arguments ============ @@ -28,6 +28,8 @@ Arguments - String to find * - ``haystack_string_expr`` - String to search within + * - ``start_location`` + - An integer at which the search starts. This value is optinoal and when not supplied, the search starts at the beggining of ``needle_string_expr`` Returns ============ @@ -37,8 +39,6 @@ Integer start position of a match, or 0 if no match was found. Notes ======= - * This function is supported on ``VARCHAR`` strings only. - * If the value is NULL, the result is NULL. From a1b655363ade7e4fe6489d356f6e63d34ff02c67 Mon Sep 17 00:00:00 2001 From: Sean-Tomarian <72871619+Sean-Tomarian@users.noreply.github.com> Date: Sun, 14 Feb 2021 19:19:36 +0200 Subject: [PATCH 027/300] 2020.3.2 --- conf.py | 2 +- index.rst | 2 ++ releases/2020.3.2.rst | 28 ++++++++++++++++++++++++++++ releases/index.rst | 3 +++ 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 releases/2020.3.2.rst diff --git a/conf.py b/conf.py index 8c9b81b5a..f96c0c33b 100644 --- a/conf.py +++ b/conf.py @@ -25,7 +25,7 @@ author = 'Sean Tomarian' # The full version, including alpha/beta/rc tags -release = '2020.3.1' +release = '2020.3.2' # -- General configuration --------------------------------------------------- diff --git a/index.rst b/index.rst index c4499a443..dc409cc2e 100644 --- a/index.rst +++ b/index.rst @@ -57,6 +57,8 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` + :ref:`2020.3.1<2020.3.1>` :ref:`2020.3<2020.3>` diff --git a/releases/2020.3.2.rst b/releases/2020.3.2.rst new file mode 100644 index 000000000..c97e2bd47 --- /dev/null +++ b/releases/2020.3.2.rst @@ -0,0 +1,28 @@ +.. _2020.3.2: + +************************** +What's new in 2020.3.2 +************************** + +SQream DB v2020.3.2 contains major performance improvements and some bug fixes. + +Performance Enhancements +========================= +* Metadata on Demand optimization resulting in reduced latency and improved overall performance + + +Known Issues & Limitations +================================ +* Bug with STDDEV_SAMP,STDDEV_POP and STDEV functions +* Window function query returns wrong results +* rank() in window function sometimes returns garbage +* Window function on null value could have bad result +* Window function lead() on varchar can have garbage results +* Performance degradation when using "groupby" or outer_join + +Upgrading to v2020.3.2 +======================== + +Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. + +Contact your account manager to get the latest release of SQream DB. diff --git a/releases/index.rst b/releases/index.rst index 65468dd27..e3a5aa1dc 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -10,6 +10,8 @@ Releases * - Version - Release Date + * - :ref:`2020.3.2` + - January 28, 2021 * - :ref:`2020.3.1` - January 11, 2021 * - :ref:`2020.3` @@ -27,6 +29,7 @@ Releases :glob: :hidden: + 2020.3.2 2020.3.1 2020.3 2020.2 From 89e8d60de871ba1f67adbc2cee1eea1396053083 Mon Sep 17 00:00:00 2001 From: Sean-Tomarian <72871619+Sean-Tomarian@users.noreply.github.com> Date: Mon, 1 Mar 2021 10:54:03 +0200 Subject: [PATCH 028/300] updated client drivers --- guides/client_drivers/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/guides/client_drivers/index.rst b/guides/client_drivers/index.rst index e3ece94e4..3ebf87b1f 100644 --- a/guides/client_drivers/index.rst +++ b/guides/client_drivers/index.rst @@ -20,14 +20,14 @@ All operating systems (SQream recommends installing via ``mvn``) * - **Python** - `pysqream v3.1.0 (.tar.gz) `_ + **Python** - `pysqream v3.1.3 (.tar.gz) `_ :ref:`pysqream` - Python driver (SQream recommends installing via ``pip``) * - **Node.JS** - `sqream-v4.2.0 (.tar.gz) `_ + **Node.JS** - `sqream-v4.2.4 (.tar.gz) `_ :ref:`nodejs` - Node.JS driver From 0c2eb6900c7f533bca1009124200a6b08ac358d9 Mon Sep 17 00:00:00 2001 From: Sean-Tomarian <72871619+Sean-Tomarian@users.noreply.github.com> Date: Mon, 1 Mar 2021 14:09:39 +0200 Subject: [PATCH 029/300] 2020.3.2.1 --- index.rst | 2 ++ releases/2020.3.2.1.rst | 23 +++++++++++++++++++++++ releases/index.rst | 3 +++ 3 files changed, 28 insertions(+) create mode 100644 releases/2020.3.2.1.rst diff --git a/index.rst b/index.rst index dc409cc2e..2ef59d284 100644 --- a/index.rst +++ b/index.rst @@ -57,6 +57,8 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` + :ref:`2020.3.2<2020.3.2>` :ref:`2020.3.1<2020.3.1>` diff --git a/releases/2020.3.2.1.rst b/releases/2020.3.2.1.rst new file mode 100644 index 000000000..93fb3d802 --- /dev/null +++ b/releases/2020.3.2.1.rst @@ -0,0 +1,23 @@ +.. _2020.3.2.1: + +************************** +What's new in 2020.3.2.1 +************************** + +SQream DB v2020.3.2.1 contains major performance improvements and some bug fixes. + +Performance Enhancements +========================= +* Metadata on Demand optimization resulting in reduced latency and improved overall performance + + +Known Issues & Limitations +================================ +* Multiple count distinct operations - is blocked for Text data type + +Upgrading to v2020.3.2.1 +======================== + +Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. + +Contact your account manager to get the latest release of SQream DB. diff --git a/releases/index.rst b/releases/index.rst index e3a5aa1dc..bc82d4fbc 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -10,6 +10,8 @@ Releases * - Version - Release Date + * - :ref:`2020.3.2.1` + - February 24, 2021 * - :ref:`2020.3.2` - January 28, 2021 * - :ref:`2020.3.1` @@ -29,6 +31,7 @@ Releases :glob: :hidden: + 2020.3.2.1 2020.3.2 2020.3.1 2020.3 From 7c832a8524190bb4345c46cfd60f69e942621970 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 8 Apr 2021 12:26:19 +0300 Subject: [PATCH 030/300] Updated index.rst Added space. --- guides/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/index.rst b/guides/index.rst index 515f4e5c4..38338e26b 100644 --- a/guides/index.rst +++ b/guides/index.rst @@ -14,7 +14,7 @@ This section has concept and features guides, and task focused guides. * :ref:`Client drivers for SQream DB` -Full list of guides +Full list of guides ========================= .. toctree:: From da9a78cb37420237ca093de9915a02f4933187d2 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 25 Apr 2021 14:35:29 +0300 Subject: [PATCH 031/300] Updated file Sample change. --- guides/operations/setup/recommended_configuration.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst index d56048a57..b37769d82 100644 --- a/guides/operations/setup/recommended_configuration.rst +++ b/guides/operations/setup/recommended_configuration.rst @@ -4,6 +4,8 @@ Recommended post-installation configuration ********************************************* +Edit. + Once you've :ref:`installed SQream DB`, you can and should tune your system for better performance and stability. This page provides recommendations for production deployments of SQream DB. From 71aceb774dbe762a71c0acdf5ea54ac9309bdf6c Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 25 Apr 2021 17:37:03 +0300 Subject: [PATCH 032/300] Edited two lines of recommended_configuration.rst Insertion and deletion example. --- guides/operations/setup/recommended_configuration.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst index b37769d82..b68b5dfdd 100644 --- a/guides/operations/setup/recommended_configuration.rst +++ b/guides/operations/setup/recommended_configuration.rst @@ -4,7 +4,8 @@ Recommended post-installation configuration ********************************************* -Edit. +An insertion looks like this. +A deletion looks like this. Once you've :ref:`installed SQream DB`, you can and should tune your system for better performance and stability. From 3bf8e4eafd19333797721733b93b2244a0321f03 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 25 Apr 2021 17:37:38 +0300 Subject: [PATCH 033/300] Update recommended_configuration.rst --- guides/operations/setup/recommended_configuration.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst index b68b5dfdd..38cd44c5c 100644 --- a/guides/operations/setup/recommended_configuration.rst +++ b/guides/operations/setup/recommended_configuration.rst @@ -5,7 +5,6 @@ Recommended post-installation configuration ********************************************* An insertion looks like this. -A deletion looks like this. Once you've :ref:`installed SQream DB`, you can and should tune your system for better performance and stability. From c68cefa91e97839eab3cf1ede2cfa23211aef2ed Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 25 Apr 2021 17:38:15 +0300 Subject: [PATCH 034/300] Update recommended_configuration.rst --- guides/operations/setup/recommended_configuration.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst index 38cd44c5c..670be3cc9 100644 --- a/guides/operations/setup/recommended_configuration.rst +++ b/guides/operations/setup/recommended_configuration.rst @@ -4,6 +4,7 @@ Recommended post-installation configuration ********************************************* +An insertion looks like this. An insertion looks like this. Once you've :ref:`installed SQream DB`, you can and should tune your system for better performance and stability. From 6d6f1513721d1ea283c1b0ddc6f0edbc9c713e27 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 25 Apr 2021 17:40:01 +0300 Subject: [PATCH 035/300] Update recommended_configuration.rst --- guides/operations/setup/recommended_configuration.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst index 670be3cc9..b966740ff 100644 --- a/guides/operations/setup/recommended_configuration.rst +++ b/guides/operations/setup/recommended_configuration.rst @@ -4,8 +4,6 @@ Recommended post-installation configuration ********************************************* -An insertion looks like this. -An insertion looks like this. Once you've :ref:`installed SQream DB`, you can and should tune your system for better performance and stability. From e07ca7e7f1d68c62984033069a296d355f88db57 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 25 Apr 2021 17:45:51 +0300 Subject: [PATCH 036/300] Update recommended_configuration.rst --- guides/operations/setup/recommended_configuration.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst index b966740ff..30f8886ec 100644 --- a/guides/operations/setup/recommended_configuration.rst +++ b/guides/operations/setup/recommended_configuration.rst @@ -4,6 +4,7 @@ Recommended post-installation configuration ********************************************* +# Irina's comments. Once you've :ref:`installed SQream DB`, you can and should tune your system for better performance and stability. From 201737cc78c03507ff6da2fd839b40108a72c18d Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 25 Apr 2021 17:50:32 +0300 Subject: [PATCH 037/300] Update recommended_configuration.rst --- guides/operations/setup/recommended_configuration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst index 30f8886ec..c04cea25c 100644 --- a/guides/operations/setup/recommended_configuration.rst +++ b/guides/operations/setup/recommended_configuration.rst @@ -4,7 +4,7 @@ Recommended post-installation configuration ********************************************* -# Irina's comments. +### Irina's comments. Once you've :ref:`installed SQream DB`, you can and should tune your system for better performance and stability. From 394fba1b48cf722b6c3281934f04aee741fc3d31 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 25 Apr 2021 17:51:20 +0300 Subject: [PATCH 038/300] Update recommended_configuration.rst --- guides/operations/setup/recommended_configuration.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst index c04cea25c..b966740ff 100644 --- a/guides/operations/setup/recommended_configuration.rst +++ b/guides/operations/setup/recommended_configuration.rst @@ -4,7 +4,6 @@ Recommended post-installation configuration ********************************************* -### Irina's comments. Once you've :ref:`installed SQream DB`, you can and should tune your system for better performance and stability. From d09e8493808870f78d49ef423dfea8c84fa2cd1c Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 25 Apr 2021 17:51:33 +0300 Subject: [PATCH 039/300] Update recommended_configuration.rst --- guides/operations/setup/recommended_configuration.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst index b966740ff..c04cea25c 100644 --- a/guides/operations/setup/recommended_configuration.rst +++ b/guides/operations/setup/recommended_configuration.rst @@ -4,6 +4,7 @@ Recommended post-installation configuration ********************************************* +### Irina's comments. Once you've :ref:`installed SQream DB`, you can and should tune your system for better performance and stability. From ce18643fdda2fcbd5015e50cc34a7f017289c46a Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 25 Apr 2021 17:53:20 +0300 Subject: [PATCH 040/300] Update recommended_configuration.rst --- guides/operations/setup/recommended_configuration.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst index c04cea25c..d56048a57 100644 --- a/guides/operations/setup/recommended_configuration.rst +++ b/guides/operations/setup/recommended_configuration.rst @@ -4,8 +4,6 @@ Recommended post-installation configuration ********************************************* -### Irina's comments. - Once you've :ref:`installed SQream DB`, you can and should tune your system for better performance and stability. This page provides recommendations for production deployments of SQream DB. From 0725fcb5159a36d4e58e59df2b4b1dd4f897139e Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 29 Apr 2021 16:57:00 +0300 Subject: [PATCH 041/300] Update index.rst Added launching_sqream_with_monit into index. --- guides/operations/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/guides/operations/index.rst b/guides/operations/index.rst index 55afe6f92..16aeca767 100644 --- a/guides/operations/index.rst +++ b/guides/operations/index.rst @@ -14,6 +14,7 @@ The guides in this section include information about best practices, monitoring, optimization_best_practices xxmonitoring monitoring_query_performance + launching_sqream_with_monit logging configuration troubleshooting From 805d0d795b94bf89cb8aaa2dd747092095c543ba Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 15 Jun 2021 22:41:27 +0300 Subject: [PATCH 042/300] Update 2020.3.rst Capitalization --- releases/2020.3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2020.3.rst b/releases/2020.3.rst index f4264a19e..691ba5adf 100644 --- a/releases/2020.3.rst +++ b/releases/2020.3.rst @@ -1,7 +1,7 @@ .. _2020.3: ************************** -What's new in 2020.3 +What's New in 2020.3 ************************** SQream DB v2020.3 contains new features, improved performance, and bug fixes. From 8c591408965e02f83a8f577428eaa90d003808d4 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 15 Jun 2021 22:48:50 +0300 Subject: [PATCH 043/300] Update 2019.2.1.rst Capitalized "new." --- releases/2019.2.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2019.2.1.rst b/releases/2019.2.1.rst index 7de2d2e8d..238e18353 100644 --- a/releases/2019.2.1.rst +++ b/releases/2019.2.1.rst @@ -1,7 +1,7 @@ .. _2019.2.1: ****************************** -What's new in 2019.2.1 +What's New in 2019.2.1 ****************************** * 250 bugs fixed. Thanks to all of our customers and an unprecedented number of deployments for helping us find and fix these! From 5b01b38384e5eb6ee576fd0f50770420c308e7bd Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 15 Jun 2021 22:49:38 +0300 Subject: [PATCH 044/300] Update 2020.1.rst Capitalized "new." --- releases/2020.1.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/2020.1.rst b/releases/2020.1.rst index ff261925e..7915ac261 100644 --- a/releases/2020.1.rst +++ b/releases/2020.1.rst @@ -1,7 +1,7 @@ .. _2020.1: ************************** -What's new in 2020.1 +What's New in 2020.1 ************************** SQream DB v2020.1 contains lots of new features, improved performance, and bug fixes. @@ -185,4 +185,4 @@ Upgrading to v2020.1 Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. -Contact your account manager to get the latest release of SQream DB. \ No newline at end of file +Contact your account manager to get the latest release of SQream DB. From a89d273386f8862ef5c912ba80b9d12b7d9d392a Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 15 Jun 2021 22:49:52 +0300 Subject: [PATCH 045/300] Update 2020.2.rst Capitalized "new." --- releases/2020.2.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/2020.2.rst b/releases/2020.2.rst index 9fa249b78..006708b9c 100644 --- a/releases/2020.2.rst +++ b/releases/2020.2.rst @@ -1,7 +1,7 @@ .. _2020.2: ************************** -What's new in 2020.2 +What's New in 2020.2 ************************** SQream DB v2020.2 contains some new features, improved performance, and bug fixes. @@ -112,4 +112,4 @@ Upgrading to v2020.2 Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. -Contact your account manager to get the latest release of SQream DB. \ No newline at end of file +Contact your account manager to get the latest release of SQream DB. From 2847a58786c94e98d9696d2cd1462919652b34c2 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 15 Jun 2021 22:50:10 +0300 Subject: [PATCH 046/300] Update 2020.3.1.rst Capitalized "new." --- releases/2020.3.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2020.3.1.rst b/releases/2020.3.1.rst index 8bf24dd55..755d75684 100644 --- a/releases/2020.3.1.rst +++ b/releases/2020.3.1.rst @@ -1,7 +1,7 @@ .. _2020.3.1: ************************** -What's new in 2020.3.1 +What's New in 2020.3.1 ************************** SQream DB v2020.3.1 contains minor features, many performance improvements and bug fixes. From ca334bdd1bd61b7c1d9395185d34e171180a5417 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 15 Jun 2021 22:50:23 +0300 Subject: [PATCH 047/300] Update 2020.3.2.1.rst Capitalized "new." --- releases/2020.3.2.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2020.3.2.1.rst b/releases/2020.3.2.1.rst index 93fb3d802..caf07b6f2 100644 --- a/releases/2020.3.2.1.rst +++ b/releases/2020.3.2.1.rst @@ -1,7 +1,7 @@ .. _2020.3.2.1: ************************** -What's new in 2020.3.2.1 +What's New in 2020.3.2.1 ************************** SQream DB v2020.3.2.1 contains major performance improvements and some bug fixes. From 9e0754a0c62de9811ab5a3c2f564c999f05367b7 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 15 Jun 2021 22:50:36 +0300 Subject: [PATCH 048/300] Update 2020.3.2.rst Capitalized "new." --- releases/2020.3.2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2020.3.2.rst b/releases/2020.3.2.rst index c97e2bd47..66bd0db68 100644 --- a/releases/2020.3.2.rst +++ b/releases/2020.3.2.rst @@ -1,7 +1,7 @@ .. _2020.3.2: ************************** -What's new in 2020.3.2 +What's New in 2020.3.2 ************************** SQream DB v2020.3.2 contains major performance improvements and some bug fixes. From 2770eeb8162f7942bcfd4add7ae0e6d8ad1169f0 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 15 Jun 2021 22:51:06 +0300 Subject: [PATCH 049/300] Update 2019.2.1.rst Capitalized "new." --- releases/2019.2.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2019.2.1.rst b/releases/2019.2.1.rst index 7de2d2e8d..238e18353 100644 --- a/releases/2019.2.1.rst +++ b/releases/2019.2.1.rst @@ -1,7 +1,7 @@ .. _2019.2.1: ****************************** -What's new in 2019.2.1 +What's New in 2019.2.1 ****************************** * 250 bugs fixed. Thanks to all of our customers and an unprecedented number of deployments for helping us find and fix these! From 45aea58a042b0a8cf30ad0768f198a3ef0b4c9bd Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 15 Jun 2021 22:51:19 +0300 Subject: [PATCH 050/300] Update 2020.1.rst Capitalized "new." --- releases/2020.1.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/2020.1.rst b/releases/2020.1.rst index ff261925e..7915ac261 100644 --- a/releases/2020.1.rst +++ b/releases/2020.1.rst @@ -1,7 +1,7 @@ .. _2020.1: ************************** -What's new in 2020.1 +What's New in 2020.1 ************************** SQream DB v2020.1 contains lots of new features, improved performance, and bug fixes. @@ -185,4 +185,4 @@ Upgrading to v2020.1 Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. -Contact your account manager to get the latest release of SQream DB. \ No newline at end of file +Contact your account manager to get the latest release of SQream DB. From c3d1892be0acbbcd1f6e604da9521b9ce9db1e4e Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 19 Jul 2021 10:36:23 +0300 Subject: [PATCH 051/300] Update values.rst Per Ticket SQ-7549, removed the following line: .. note:: The maximum number of values in the ``VALUE`` clause is limited to 500. --- reference/sql/sql_statements/dml_commands/values.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/values.rst b/reference/sql/sql_statements/dml_commands/values.rst index d087e79ff..4e8e1f28b 100644 --- a/reference/sql/sql_statements/dml_commands/values.rst +++ b/reference/sql/sql_statements/dml_commands/values.rst @@ -9,7 +9,6 @@ VALUES .. tip:: * Use VALUES in conjunction with :ref:`INSERT` statements to insert a set of one or more rows. -.. note:: The maximum number of values in the ``VALUE`` clause is limited to 500. Permissions ============= @@ -81,4 +80,4 @@ Use ``AS`` to assign names to columns (3, 'horse'), (4, 'hippopotamus') ) AS t(id, name) - ); \ No newline at end of file + ); From 1ebba4ff218dcfdcc0bd39720056a13925812cff Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 19 Jul 2021 10:37:42 +0300 Subject: [PATCH 052/300] Update values.rst Per Ticket SQ-7549, removed the following line: .. note:: The maximum number of values in the ``VALUE`` clause is limited to 500. --- reference/sql/sql_statements/dml_commands/values.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/values.rst b/reference/sql/sql_statements/dml_commands/values.rst index d087e79ff..4e8e1f28b 100644 --- a/reference/sql/sql_statements/dml_commands/values.rst +++ b/reference/sql/sql_statements/dml_commands/values.rst @@ -9,7 +9,6 @@ VALUES .. tip:: * Use VALUES in conjunction with :ref:`INSERT` statements to insert a set of one or more rows. -.. note:: The maximum number of values in the ``VALUE`` clause is limited to 500. Permissions ============= @@ -81,4 +80,4 @@ Use ``AS`` to assign names to columns (3, 'horse'), (4, 'hippopotamus') ) AS t(id, name) - ); \ No newline at end of file + ); From 382b510da124d4c6dc79a876c7d034f30d04b30b Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 4 Aug 2021 17:07:18 +0300 Subject: [PATCH 053/300] Update access_control.rst Removed line from example because it was causing errors: GRANT SELECT ON all views IN schema admin TO userA; --- guides/features/access_control.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/guides/features/access_control.rst b/guides/features/access_control.rst index 9850fafda..9aced4b02 100644 --- a/guides/features/access_control.rst +++ b/guides/features/access_control.rst @@ -315,8 +315,6 @@ GRANT GRANT ALL ON all tables IN schema public TO userB; - GRANT SELECT ON all views IN schema admin TO userA; - GRANT admin TO userC; GRANT superuser ON schema demo TO userA From 8bf48206b4396fb8adcec33c907e98d38abde59f Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 4 Aug 2021 17:12:07 +0300 Subject: [PATCH 054/300] Update access_control.rst Removed line from example because it was causing errors: GRANT SELECT ON all views IN schema admin TO userA; --- guides/features/access_control.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/guides/features/access_control.rst b/guides/features/access_control.rst index 45038dee8..920280180 100644 --- a/guides/features/access_control.rst +++ b/guides/features/access_control.rst @@ -301,8 +301,6 @@ Examples: GRANT ALL ON all tables IN schema public TO userB; - GRANT SELECT ON all views IN schema admin TO userA; - GRANT admin TO userC; GRANT superuser ON schema demo TO userA From b9c9565c17b8fc8046e84bf62f5ab1ceeee13ac8 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 20 Oct 2021 10:24:28 +0300 Subject: [PATCH 055/300] Update sql_feature_support.rst Corrected typo. --- reference/sql_feature_support.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql_feature_support.rst b/reference/sql_feature_support.rst index 25ed8a896..9c75adde7 100644 --- a/reference/sql_feature_support.rst +++ b/reference/sql_feature_support.rst @@ -272,7 +272,7 @@ Scalar expressions * - ``IN``, ``NOT IN`` - Partial - Literal values only - * - Bitwise arithemtic + * - Bitwise arithmetic - ✓ - ``&``, ``|``, ``XOR``, ``~``, ``>>``, ``<<`` From ee382d33799783992d3066cf278323f66cbbd1e6 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 24 Oct 2021 14:53:01 +0300 Subject: [PATCH 056/300] Update logging.rst Added missing comma to following line: DELIMITER = '|', --- guides/operations/logging.rst | 61 +++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/guides/operations/logging.rst b/guides/operations/logging.rst index 31b236570..29a743668 100644 --- a/guides/operations/logging.rst +++ b/guides/operations/logging.rst @@ -4,7 +4,7 @@ Logging *********************** -Locating the log files +Locating the Log Files ========================== The :ref:`storage cluster` contains a ``logs`` directory. Each worker produces a log file in its own directory, which can be identified by the worker's hostname and port. @@ -23,7 +23,7 @@ The worker logs contain information messages, warnings, and errors pertaining to * Statement execution success / failure * Statement execution statistics -Log structure and contents +Log Structure and Contents --------------------------------- The log is a CSV, with several fields. @@ -68,7 +68,7 @@ The log is a CSV, with several fields. .. _information_level: -.. list-table:: Information level +.. list-table:: Information Level :widths: auto :header-rows: 1 @@ -87,7 +87,7 @@ The log is a CSV, with several fields. .. _message_type: -.. list-table:: Message type +.. list-table:: Message Type :widths: auto :header-rows: 1 @@ -191,7 +191,7 @@ The log is a CSV, with several fields. - Worker shutdown - ``"Server shutdown"`` -Log naming +Log-Naming --------------------------- Log file name syntax @@ -210,13 +210,13 @@ For example, ``/home/rhendricks/sqream_storage/192.168.1.91_5000``. See the :ref:`log_rotation` below for information about controlling this setting. -Logging control and maintenance +Log Control and Maintenance ====================================== -Change log verbosity +Changing Log Verbosity -------------------------- -A few configuration settings alter the verbosity of the logs +A few configuration settings alter the verbosity of the logs: .. list-table:: Log verbosity configuration :widths: auto @@ -239,10 +239,10 @@ A few configuration settings alter the verbosity of the logs .. _log_rotation: -Change log rotation +Changing Log Rotation ----------------------- -A few configuration settings alter the log rotation policy +A few configuration settings alter the log rotation policy: .. list-table:: Log rotation configuration :widths: auto @@ -267,10 +267,10 @@ A few configuration settings alter the log rotation policy .. _collecting_logs2: -Collect logs from your cluster +Collecting Logs from Your Cluster ==================================== -Collecting logs from your cluster can be as simple as creating an archive from the ``logs`` subdirectory: ``tar -czvf logs.tgz *.log`` +Collecting logs from your cluster can be as simple as creating an archive from the ``logs`` subdirectory: ``tar -czvf logs.tgz *.log``. However, SQream DB comes bundled with a data collection utility and an SQL utility intended for collecting logs and additional information that can help SQream support drill down into possible issues. @@ -289,10 +289,10 @@ SQL Syntax log | db | db_and_log -Command line utility +Command Line Utility -------------------------- -If SQream DB can't be accessed for any reason, a command line tool can also be used to collect the same information: +If you cannot access SQream DB for any reason, you can also use a command line toolto collect the same information: .. code-block:: console @@ -342,17 +342,17 @@ Using the command line utility: $ ./bin/report_collection /home/rhendricks/sqream_storage /home/rhendricks db_and_log -Troubleshooting with logs +Troubleshooting with Logs =============================== -Loading logs with external tables +Loading Logs with Foreign Tables --------------------------------------- Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a database administrator can access the logs using the :ref:`external_tables` concept through SQream DB. .. code-block:: postgres - CREATE EXTERNAL TABLE logs + CREATE FOREIGN TABLE logs ( start_marker VARCHAR(4), row_id BIGINT, @@ -370,13 +370,21 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas message TEXT, end_message VARCHAR(5) ) - USING FORMAT CSV - WITH - PATH '/home/rhendricks/sqream_storage/logs/**/sqream*.log' - FIELD DELIMITER '|' + WRAPPER csv_fdw + OPTIONS + ( + LOCATION = '/home/rhendricks/sqream_storage/logs/**/sqream*.log', + DELIMITER = '|', + CONTINUE_ON_ERROR = true + ) ; + +For more information, see `Loading Logs with Foreign Tables `_. + + + -Count message types +Counting Message Types ------------------------------ .. code-block:: psql @@ -402,7 +410,7 @@ Count message types 1004 | 19 1010 | 5 -Find fatal errors +Finding Fatal Errors ---------------------- .. code-block:: psql @@ -414,7 +422,7 @@ Find fatal errors Mismatch in storage version, upgrade is needed,Storage version: 25, Server version is: 26 Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/LOCK: Resource temporarily unavailable -Count error events within a certain timeframe +Countng Error Events Within a Certain Timeframe --------------------------------------------------- .. code-block:: psql @@ -433,7 +441,7 @@ Count error events within a certain timeframe .. _tracing_errors: -Tracing errors to find offending statements +Tracing Errors to Find Offending Statements ------------------------------------------------- If we know an error occured, but don't know which statement caused it, we can find it using the connection ID and statement ID. @@ -462,6 +470,3 @@ Use the ``connection_id`` and ``statement_id`` to narrow down the results. .. how logs are read with csvkit, find a better working solution - - - From db18a80f522d2d34c03d74c7528ad6980ec0264a Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 24 Oct 2021 14:55:46 +0300 Subject: [PATCH 057/300] Update logging.rst Added missing comma to following line: DELIMITER = '|', --- guides/operations/logging.rst | 51 ++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/guides/operations/logging.rst b/guides/operations/logging.rst index 2a4f5c317..29a743668 100644 --- a/guides/operations/logging.rst +++ b/guides/operations/logging.rst @@ -4,7 +4,7 @@ Logging *********************** -Locating the log files +Locating the Log Files ========================== The :ref:`storage cluster` contains a ``logs`` directory. Each worker produces a log file in its own directory, which can be identified by the worker's hostname and port. @@ -23,7 +23,7 @@ The worker logs contain information messages, warnings, and errors pertaining to * Statement execution success / failure * Statement execution statistics -Log structure and contents +Log Structure and Contents --------------------------------- The log is a CSV, with several fields. @@ -68,7 +68,7 @@ The log is a CSV, with several fields. .. _information_level: -.. list-table:: Information level +.. list-table:: Information Level :widths: auto :header-rows: 1 @@ -87,7 +87,7 @@ The log is a CSV, with several fields. .. _message_type: -.. list-table:: Message type +.. list-table:: Message Type :widths: auto :header-rows: 1 @@ -191,7 +191,7 @@ The log is a CSV, with several fields. - Worker shutdown - ``"Server shutdown"`` -Log naming +Log-Naming --------------------------- Log file name syntax @@ -210,13 +210,13 @@ For example, ``/home/rhendricks/sqream_storage/192.168.1.91_5000``. See the :ref:`log_rotation` below for information about controlling this setting. -Logging control and maintenance +Log Control and Maintenance ====================================== -Change log verbosity +Changing Log Verbosity -------------------------- -A few configuration settings alter the verbosity of the logs +A few configuration settings alter the verbosity of the logs: .. list-table:: Log verbosity configuration :widths: auto @@ -239,10 +239,10 @@ A few configuration settings alter the verbosity of the logs .. _log_rotation: -Change log rotation +Changing Log Rotation ----------------------- -A few configuration settings alter the log rotation policy +A few configuration settings alter the log rotation policy: .. list-table:: Log rotation configuration :widths: auto @@ -267,10 +267,10 @@ A few configuration settings alter the log rotation policy .. _collecting_logs2: -Collect logs from your cluster +Collecting Logs from Your Cluster ==================================== -Collecting logs from your cluster can be as simple as creating an archive from the ``logs`` subdirectory: ``tar -czvf logs.tgz *.log`` +Collecting logs from your cluster can be as simple as creating an archive from the ``logs`` subdirectory: ``tar -czvf logs.tgz *.log``. However, SQream DB comes bundled with a data collection utility and an SQL utility intended for collecting logs and additional information that can help SQream support drill down into possible issues. @@ -289,10 +289,10 @@ SQL Syntax log | db | db_and_log -Command line utility +Command Line Utility -------------------------- -If SQream DB can't be accessed for any reason, a command line tool can also be used to collect the same information: +If you cannot access SQream DB for any reason, you can also use a command line toolto collect the same information: .. code-block:: console @@ -342,10 +342,10 @@ Using the command line utility: $ ./bin/report_collection /home/rhendricks/sqream_storage /home/rhendricks db_and_log -Troubleshooting with logs +Troubleshooting with Logs =============================== -Loading logs with foreign tables +Loading Logs with Foreign Tables --------------------------------------- Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a database administrator can access the logs using the :ref:`external_tables` concept through SQream DB. @@ -374,11 +374,17 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas OPTIONS ( LOCATION = '/home/rhendricks/sqream_storage/logs/**/sqream*.log', - DELIMITER = '|' + DELIMITER = '|', + CONTINUE_ON_ERROR = true ) ; + +For more information, see `Loading Logs with Foreign Tables `_. + + + -Count message types +Counting Message Types ------------------------------ .. code-block:: psql @@ -404,7 +410,7 @@ Count message types 1004 | 19 1010 | 5 -Find fatal errors +Finding Fatal Errors ---------------------- .. code-block:: psql @@ -416,7 +422,7 @@ Find fatal errors Mismatch in storage version, upgrade is needed,Storage version: 25, Server version is: 26 Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/LOCK: Resource temporarily unavailable -Count error events within a certain timeframe +Countng Error Events Within a Certain Timeframe --------------------------------------------------- .. code-block:: psql @@ -435,7 +441,7 @@ Count error events within a certain timeframe .. _tracing_errors: -Tracing errors to find offending statements +Tracing Errors to Find Offending Statements ------------------------------------------------- If we know an error occured, but don't know which statement caused it, we can find it using the connection ID and statement ID. @@ -464,6 +470,3 @@ Use the ``connection_id`` and ``statement_id`` to narrow down the results. .. how logs are read with csvkit, find a better working solution - - - From 9f0aa9abadee6b7fea6b9d9113bb71f3838c485e Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 25 Oct 2021 08:47:32 +0300 Subject: [PATCH 058/300] Update copy_from.rst Removed " from Unsupported Field Delimiters table - SQ-8293: https://sqream.atlassian.net/browse/SQ-8293 --- .../sql_statements/dml_commands/copy_from.rst | 150 ++++++++++++++---- 1 file changed, 117 insertions(+), 33 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 960a3f89c..05d5083aa 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -4,11 +4,7 @@ COPY FROM ********************** -``COPY ... FROM`` is a statement that allows loading data from files on the filesystem and importing them into SQream tables. - -This is the recommended way for bulk loading CSV files into SQream DB. - -In general, ``COPY`` moves data between filesystem files and SQream DB tables. +``COPY ... FROM`` is a statement that allows loading data from files on the filesystem and importing them into SQream tables. This is the recommended way for bulk loading CSV files into SQream DB. In general, ``COPY`` moves data between filesystem files and SQream DB tables. .. note:: * Learn how to migrate from CSV files in the :ref:`csv` guide @@ -41,6 +37,8 @@ Syntax LOCATION = { filename | S3 URI | HDFS URI } + | QUOTE = {'C' | E'\ooo') + | OFFSET = { offset } | LIMIT = { limit } @@ -103,6 +101,10 @@ Elements - None - - Table to copy data into + * - ``QUOTE`` + - " + - + - Specifies an alternative quote character. The quote character must be a single, 1-byte printable ASCII character, and the equivalent octal syntax of the copy command can be used. The quote character cannot be contained in the field delimiter, the record delimiter, or the null marker. ``QUOTE`` can be used with ``csv_fdw`` in **COPY FROM** and foreign tables. * - ``name_fdw`` - - ``csv_fdw``, ``orc_fdw``, or ``parquet_fdw`` @@ -177,7 +179,7 @@ Elements .. _copy_date_parsers: -Supported date formats +Supported Date Formats ========================= .. list-table:: Supported date parsers @@ -251,19 +253,63 @@ Supported date formats .. _field_delimiters: -Supported field delimiters +Supported Field Delimiters ===================================================== Field delimiters can be one or more characters. -Multi-character delimiters +Customizing Quotations Using Alternative Characters +---------------------------- + +Syntax Example 1 - Customizing Quotations Using Alternative Characters +************ + +The following is the correct syntax for customizing quotations using alternative characters: + +.. code-block:: postgres + + copy t from wrapper csv_fdw options (location = '/tmp/source_file.csv', quote='@'); + copy t to wrapper csv_fdw options (location = '/tmp/destination_file.csv', quote='@'); + +Usage Example 1 - Customizing Quotations Using Alternative Characters +************ + +The following is an example of line taken from a CSV when customizing quotations using a character: + +.. code-block:: postgres + + Pepsi-"Cola",@Coca-"Cola"@,Sprite,Fanta + + +Syntax Example 2 - Customizing Quotations Using ASCII Character Codes +************ + +The following is the correct syntax for customizing quotations using ASCII character codes: + +.. code-block:: postgres + + copy t from wrapper csv_fdw options (location = '/tmp/source_file.csv', quote=E'\064'); + copy t to wrapper csv_fdw options (location = '/tmp/destination_file.csv', quote=E'\064'); + +Usage Example 2 - Customizing Quotations Using ASCII Character Codes +************ + +The following is an example of line taken from a CSV when customizing quotations using an ASCII character code: + +.. code-block:: postgres + + Pepsi-"Cola",@Coca-"Cola"@,Sprite,Fanta + + + +Multi-Character Delimiters ---------------------------------- SQream DB supports multi-character field delimiters, sometimes found in non-standard files. A multi-character delimiter can be specified. For example, ``DELIMITER '%%'``, ``DELIMITER '{~}'``, etc. -Printable characters +Printable Characters ----------------------- Any printable ASCII character (or characters) can be used as a delimiter without special syntax. The default CSV field delimiter is a comma (``,``). @@ -272,7 +318,7 @@ A printable character is any ASCII character in the range 32 - 126. :ref:`Literal quoting rules` apply with delimiters. For example, to use ``'`` as a field delimiter, use ``DELIMITER ''''`` -Non-printable characters +Non-Printable Characters ---------------------------- A non-printable character (1 - 31, 127) can be used in its octal form. @@ -283,7 +329,47 @@ For example, ASCII character ``15``, known as "shift in", can be specified using .. _capturing_rejected_rows: -Capturing rejected rows +Unsupported Field Delimiters +========================== +The following ASCII field delimiters (octal range 001 - 176) are not supported: + ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| **Character** | **Decimal** | **Symbol** | **Character** | **Decimal** | **Symbol** | **Character** | **Decimal** | **Symbol** | ++===============+=============+============+===============+=============+============+===============+=============+============+ +| - | 45 | 55 | b | 98 | 142 | q | 113 | 161 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| . | 46 | 56 | c | 99 | 143 | r | 114 | 162 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| : | 58 | 72 | d | 100 | 144 | s | 115 | 163 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| \ | 92 | 134 | e | 101 | 145 | t | 116 | 164 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 0 | 48 | 60 | f | 102 | 146 | u | 117 | 165 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 1 | 49 | 61 | g | 103 | 147 | v | 118 | 166 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 2 | 50 | 62 | h | 104 | 150 | w | 119 | 167 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 3 | 51 | 63 | i | 105 | 151 | x | 120 | 170 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 4 | 52 | 64 | j | 106 | 152 | y | 121 | 171 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 5 | 53 | 65 | k | 107 | 153 | z | 122 | 172 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 6 | 54 | 66 | l | 108 | 154 | N | 78 | 116 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 7 | 55 | 67 | m | 109 | 155 | 10 | 49 | 12 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 8 | 56 | 70 | n | 110 | 156 | 13 | 49 | 13 | ++---------------+-------------+------------+---------------+-------------+------------+ | | | +| 9 | 57 | 71 | o | 111 | 157 | | | | ++---------------+-------------+------------+---------------+-------------+------------+ | | | +| a | 97 | 141 | p | 112 | 160 | | | | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ + + + +Capturing Rejected Rows ========================== Prior to the column process and storage, the ``COPY`` command parses the data. @@ -298,12 +384,12 @@ Whenever the data can’t be parsed because it is improperly formatted or doesn #. When ``ERROR_LOG`` is set and ``ERROR_VERBOSITY`` is set to ``0``, rejected rows are saved to the file path specified, but errors are not logged. This is useful for replaying the file later. -CSV support +CSV Support ================ By default, SQream DB's CSV parser can handle `RFC 4180 standard CSVs `_ , but can also be modified to support non-standard CSVs (with multi-character delimiters, unquoted fields, etc). -All CSV files shoudl be prepared according to these recommendations: +All CSV files should be prepared according to these recommendations: * Files are UTF-8 or ASCII encoded @@ -324,7 +410,7 @@ All CSV files shoudl be prepared according to these recommendations: Other modes of escaping are not supported (e.g. ``1,"What are \"birds\"?"`` is not a valid way of escaping CSV values). -Null markers +Marking Null Markers --------------- ``NULL`` values can be marked in two ways in the CSV: @@ -337,7 +423,7 @@ Null markers Examples =========== -Loading a standard CSV file +Loading a Standard CSV File ------------------------------ .. code-block:: postgres @@ -345,7 +431,7 @@ Loading a standard CSV file COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.csv'); -Skipping faulty rows +Skipping Faulty Rows ------------------------------ .. code-block:: postgres @@ -353,7 +439,7 @@ Skipping faulty rows COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.csv', continue_on_error = true); -Skipping at most 100 faulty rows +Skipping a Maximum of 100 Faulty Rows ----------------------------------- .. code-block:: postgres @@ -361,14 +447,14 @@ Skipping at most 100 faulty rows COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.csv', continue_on_error = true, error_count = 100); -Loading a PSV (pipe separated value) file +Loading a Pipe Separated Value (PSV) File ------------------------------------------- .. code-block:: postgres COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.psv', delimiter = '|'); -Loading a TSV (tab separated value) file +Loading a Tab Separated Value (TSV) File ------------------------------------------- .. code-block:: postgres @@ -376,7 +462,7 @@ Loading a TSV (tab separated value) file COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.tsv', delimiter = '\t'); -Loading a ORC file +Loading an ORC File ------------------------------------------- .. code-block:: postgres @@ -384,7 +470,7 @@ Loading a ORC file COPY table_name FROM WRAPPER orc_fdw OPTIONS (location = '/tmp/file.orc'); -Loading a Parquet file +Loading a Parquet File ------------------------------------------- .. code-block:: postgres @@ -392,7 +478,7 @@ Loading a Parquet file COPY table_name FROM WRAPPER parquet_fdw OPTIONS (location = '/tmp/file.parquet'); -Loading a text file with non-printable delimiter +Loading a Text File with Non-Printable Delimiters ----------------------------------------------------- In the file below, the separator is ``DC1``, which is represented by ASCII 17 decimal or 021 octal. @@ -401,7 +487,7 @@ In the file below, the separator is ``DC1``, which is represented by ASCII 17 de COPY table_name FROM WRAPPER psv_fdw OPTIONS (location = '/tmp/file.txt', delimiter = E'\021'); -Loading a text file with multi-character delimiters +Loading a Text File with Multi-Character Delimiters ----------------------------------------------------- In the file below, the separator is ``^|``. @@ -417,7 +503,7 @@ In the file below, the separator is ``'|``. The quote character has to be repeat COPY table_name FROM WRAPPER psv_fdw OPTIONS (location = '/tmp/file.txt', delimiter = ''''|'); -Loading files with a header row +Loading Files with a Header Row ----------------------------------- Use ``OFFSET`` to skip rows. @@ -428,14 +514,14 @@ Use ``OFFSET`` to skip rows. COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.psv', delimiter = '|', offset = 2); -Loading files formatted for Windows (``\r\n``) +Loading Files Formatted for Windows (``\r\n``) --------------------------------------------------- .. code-block:: postgres COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.psv', delimiter = '\r\n'); -Loading a file from a public S3 bucket +Loading a File from a Public S3 Bucket ------------------------------------------ .. note:: The bucket must be publicly available and objects can be listed @@ -444,14 +530,14 @@ Loading a file from a public S3 bucket COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = 's3://sqream-demo-data/file.csv', delimiter = '\r\n', offset = 2); -Loading files from an authenticated S3 bucket +Loading Files from an Authenticated S3 Bucket --------------------------------------------------- .. code-block:: postgres COPY table_name FROM WRAPPER psv_fdw OPTIONS (location = 's3://secret-bucket/*.csv', DELIMITER = '\r\n', OFFSET = 2, AWS_ID = '12345678', AWS_SECRET = 'super_secretive_secret'); -Saving rejected rows to a file +Saving Rejected Rows to a File ---------------------------------- .. note:: When loading multiple files (e.g. with wildcards), this error threshold is for the entire transaction. @@ -474,14 +560,14 @@ Saving rejected rows to a file ); -Load CSV files from a set of directories +Loading CSV Files from a Set of Directories ------------------------------------------ .. code-block:: postgres COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/2019_08_*/*.csv'); -Rearrange destination columns +Rearranging Destination Columns --------------------------------- When the source of the files does not match the table structure, tell the ``COPY`` command what the order of columns should be @@ -492,7 +578,7 @@ When the source of the files does not match the table structure, tell the ``COPY .. note:: Any column not specified will revert to its default value or ``NULL`` value if nullable -Loading non-standard dates +Loading Non-Standard Dates ---------------------------------- If files contain dates not formatted as ``ISO8601``, tell ``COPY`` how to parse the column. After parsing, the date will appear as ``ISO8601`` inside SQream DB. @@ -504,5 +590,3 @@ In this example, ``date_col1`` and ``date_col2`` in the table are non-standard. .. code-block:: postgres COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/*.csv', datetime_format = 'DMY'); - - From a8c0f7a0e0c7462a8515f87afb611ffe2def3e96 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 25 Oct 2021 08:52:09 +0300 Subject: [PATCH 059/300] Update copy_from.rst Removed " from Unsupported Field Delimiters table - SQ-8293: https://sqream.atlassian.net/browse/SQ-8293 --- .../sql_statements/dml_commands/copy_from.rst | 383 +++++++++++++----- 1 file changed, 289 insertions(+), 94 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index d8e23b7a4..05d5083aa 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -4,18 +4,12 @@ COPY FROM ********************** -``COPY ... FROM`` is a statement that allows reading data from a file into a table. - -This is the recommended method for bulk loading CSV files into SQream DB. - -In general, ``COPY`` moves data between file-system files and SQream DB tables. - - +``COPY ... FROM`` is a statement that allows loading data from files on the filesystem and importing them into SQream tables. This is the recommended way for bulk loading CSV files into SQream DB. In general, ``COPY`` moves data between filesystem files and SQream DB tables. .. note:: * Learn how to migrate from CSV files in the :ref:`csv` guide * To copy data from a table to a file, see :ref:`COPY TO`. - * To load Parquet or ORC files, see :ref:`CREATE EXTERNAL TABLE` + * To load Parquet or ORC files, see :ref:`CREATE FOREIGN TABLE` Permissions ============= @@ -27,34 +21,68 @@ Syntax .. code-block:: postgres - copy_from_stmt ::= COPY ( [schema name.]table_name ) FROM 'filepath_spec' - [ [ WITH ] copy_opt [ ...] ] + COPY [schema name.]table_name + FROM WRAPPER fdw_name + OPTIONS + ( + [ copy_from_option [, ...] ] + ) ; - - schema_name ::= identifier - + + schema_name ::= identifer + table_name ::= identifier - copy_opt ::= - | OFFSET N - | LIMIT N - | DELIMITER '{ delimiter }' - | RECORD DELIMITER '{ record delimiter }' - | ERROR_LOG 'local filepath' - | ERROR_VERBOSITY { 0 | 1 } - | STOP AFTER N ERRORS - | PARSERS { '[column_name=parser_format, ...]' } - | AWS_ID '{ AWS ID }' - | AWS_SECRET '{ AWS secret }' - - filepath_spec ::= - filename - | directory path - | S3 URI - | HDFS URI - - N ::= positive integer + copy_from_option ::= + + LOCATION = { filename | S3 URI | HDFS URI } + + | QUOTE = {'C' | E'\ooo') + + | OFFSET = { offset } + + | LIMIT = { limit } + + | DELIMITER = '{ delimiter }' + + | RECORD_DELIMITER = '{ record delimiter }' + + | ERROR_LOG = '{ local filepath }' + + | REJECTED_DATA = '{ local filepath }' + + | CONTINUE_ON_ERROR = { true | false } + + | ERROR_COUNT = '{ error count }' + + | DATETIME_FORMAT = '{ parser format }' + + | AWS_ID = '{ AWS ID }' + + | AWS_SECRET = '{ AWS Secret }' + + offset ::= positive integer + + limit ::= positive integer + + delimiter ::= string + + record delimiter ::= string + + error count ::= integer + + parser_format ::= see supported parser table below + + AWS ID ::= string + + AWS Secret ::= string + +.. note:: + + Some options are applicable to CSVs only. + These include: + ``OFFSET``, ``LIMIT``, ``DELIMITER``, ``RECORD_DELIMITER``, ``REJECTED_DATA``, ``DATETIME_FORMAT`` .. _copy_from_config_options: @@ -67,44 +95,91 @@ Elements * - Parameter - Default value + - Value range - Description * - ``[schema_name.]table_name`` - None + - - Table to copy data into - * - ``filepath_spec`` + * - ``QUOTE`` + - " + - + - Specifies an alternative quote character. The quote character must be a single, 1-byte printable ASCII character, and the equivalent octal syntax of the copy command can be used. The quote character cannot be contained in the field delimiter, the record delimiter, or the null marker. ``QUOTE`` can be used with ``csv_fdw`` in **COPY FROM** and foreign tables. + * - ``name_fdw`` + - + - ``csv_fdw``, ``orc_fdw``, or ``parquet_fdw`` + - The name of the Foreign Data Wrapper to use + * - ``LOCATION`` - None - - A path on the local filesystem, S3, or HDFS URI. For example, ``/tmp/foo.csv``, ``s3://my-bucket/foo.csv``, or ``hdfs://my-namenode:8020/foo.csv``. The local path must be an absolute path that SQream DB can access. Wildcards are premitted in this field + - + - A path on the local filesystem, S3, or HDFS URI. For example, ``/tmp/foo.csv``, ``s3://my-bucket/foo.csv``, or ``hdfs://my-namenode:8020/foo.csv``. The local path must be an absolute path that SQream DB can access. Wildcards are premitted in this field. * - ``OFFSET`` - ``1`` + - >1, but no more than the number of lines in the first file - The row number to start with. The first row is ``1``. * - ``LIMIT`` - - Unlimited - - When specified, tells SQream DB to stop loading after the specified number of rows. + - unlimited + - 1 to 2147483647. + - When specified, tells SQream DB to stop loading after the specified number of rows. Unlimited if unset. * - ``DELIMITER`` - ``','`` - - Specifies the field terminator - the character or characters that separates fields or columns columns within each row of the file - * - ``RECORD DELIMITER`` + - Almost any ASCII character, :ref:`See field delimiters section below` + - Specifies the field terminator - the character (or characters) that separates fields or columns within each row of the file. + * - ``RECORD_DELIMITER`` - ``\n`` (UNIX style newline) + - ``\n``, ``\r\n``, ``\r`` - Specifies the row terminator - the character that separates lines or rows, also known as a new line separator. * - ``ERROR_LOG`` - - Disabled - - When used, the ``COPY`` process will ignore rows that can't be parsed. Errors will be written to the file specified by the ``ERROR_LOG`` parameter. - * - ``ERROR_VERBOSITY`` - - ``1`` - - Controls the verbosity of the ``ERROR_LOG``. When set to ``0``, only the rejected rows are saved to the ``ERROR_LOG`` file. When set to ``1`` the error message is logged for every rejected row. - * - ``STOP AFTER N ERRORS`` - - ``1000000`` - - Specifies the threshold of rejected rows. When used with ``ERROR_LOG``, the ``COPY FROM`` command will roll back the transaction if the threshold ``N`` is reached. - * - ``PARSERS`` - - ``DEFAULT`` for every column + - No error log + - + - + When used, the ``COPY`` process will write error information from unparsable rows to the file specified by this parameter. + + * If an existing file path is specified, it will be overwritten. + + * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. + + * Specifing an error log when creating a foreign table will write a new error log for every query on the foreign table. + + * - ``REJECTED_DATA`` + - Inactive + - + - + When used, the ``COPY`` process will write the rejected record lines to this file. + + * If an existing file path is specified, it will be overwritten. + + * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. + + * Specifing an error log when creating a foreign table will write a new error log for every query on the foreign table. + + * - ``CONTINUE_ON_ERROR`` + - ``false`` + - true, false + - + Specifies if errors should be ignored or skipped. When set to ``true``, the transaction will continue despite rejected data. + + This parameter should be set together with ``ERROR_COUNT`` + When reading multiple files, if an entire file can't be opened it will be skipped. + * - ``ERROR_COUNT`` + - ``unlimited`` + - 1 to 2147483647 + - + Specifies the threshold for the maximum number of faulty records that will be ignored. + + This setting must be used in conjunction with ``CONTINUE_ON_ERROR``. + * - ``DATETIME_FORMAT`` + - ISO8601 for all columns + - :ref:`See table below` - Allows specifying a non-default date formats for specific columns * - ``AWS_ID``, ``AWS_SECRET`` - None + - - Specifies the authentication details for secured S3 buckets .. _copy_date_parsers: -Supported date formats +Supported Date Formats ========================= .. list-table:: Supported date parsers @@ -178,19 +253,63 @@ Supported date formats .. _field_delimiters: -Supported field delimiters +Supported Field Delimiters ===================================================== Field delimiters can be one or more characters. -Multi-character delimiters +Customizing Quotations Using Alternative Characters +---------------------------- + +Syntax Example 1 - Customizing Quotations Using Alternative Characters +************ + +The following is the correct syntax for customizing quotations using alternative characters: + +.. code-block:: postgres + + copy t from wrapper csv_fdw options (location = '/tmp/source_file.csv', quote='@'); + copy t to wrapper csv_fdw options (location = '/tmp/destination_file.csv', quote='@'); + +Usage Example 1 - Customizing Quotations Using Alternative Characters +************ + +The following is an example of line taken from a CSV when customizing quotations using a character: + +.. code-block:: postgres + + Pepsi-"Cola",@Coca-"Cola"@,Sprite,Fanta + + +Syntax Example 2 - Customizing Quotations Using ASCII Character Codes +************ + +The following is the correct syntax for customizing quotations using ASCII character codes: + +.. code-block:: postgres + + copy t from wrapper csv_fdw options (location = '/tmp/source_file.csv', quote=E'\064'); + copy t to wrapper csv_fdw options (location = '/tmp/destination_file.csv', quote=E'\064'); + +Usage Example 2 - Customizing Quotations Using ASCII Character Codes +************ + +The following is an example of line taken from a CSV when customizing quotations using an ASCII character code: + +.. code-block:: postgres + + Pepsi-"Cola",@Coca-"Cola"@,Sprite,Fanta + + + +Multi-Character Delimiters ---------------------------------- SQream DB supports multi-character field delimiters, sometimes found in non-standard files. A multi-character delimiter can be specified. For example, ``DELIMITER '%%'``, ``DELIMITER '{~}'``, etc. -Printable characters +Printable Characters ----------------------- Any printable ASCII character (or characters) can be used as a delimiter without special syntax. The default CSV field delimiter is a comma (``,``). @@ -199,7 +318,7 @@ A printable character is any ASCII character in the range 32 - 126. :ref:`Literal quoting rules` apply with delimiters. For example, to use ``'`` as a field delimiter, use ``DELIMITER ''''`` -Non-printable characters +Non-Printable Characters ---------------------------- A non-printable character (1 - 31, 127) can be used in its octal form. @@ -210,7 +329,47 @@ For example, ASCII character ``15``, known as "shift in", can be specified using .. _capturing_rejected_rows: -Capturing rejected rows +Unsupported Field Delimiters +========================== +The following ASCII field delimiters (octal range 001 - 176) are not supported: + ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| **Character** | **Decimal** | **Symbol** | **Character** | **Decimal** | **Symbol** | **Character** | **Decimal** | **Symbol** | ++===============+=============+============+===============+=============+============+===============+=============+============+ +| - | 45 | 55 | b | 98 | 142 | q | 113 | 161 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| . | 46 | 56 | c | 99 | 143 | r | 114 | 162 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| : | 58 | 72 | d | 100 | 144 | s | 115 | 163 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| \ | 92 | 134 | e | 101 | 145 | t | 116 | 164 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 0 | 48 | 60 | f | 102 | 146 | u | 117 | 165 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 1 | 49 | 61 | g | 103 | 147 | v | 118 | 166 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 2 | 50 | 62 | h | 104 | 150 | w | 119 | 167 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 3 | 51 | 63 | i | 105 | 151 | x | 120 | 170 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 4 | 52 | 64 | j | 106 | 152 | y | 121 | 171 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 5 | 53 | 65 | k | 107 | 153 | z | 122 | 172 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 6 | 54 | 66 | l | 108 | 154 | N | 78 | 116 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 7 | 55 | 67 | m | 109 | 155 | 10 | 49 | 12 | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +| 8 | 56 | 70 | n | 110 | 156 | 13 | 49 | 13 | ++---------------+-------------+------------+---------------+-------------+------------+ | | | +| 9 | 57 | 71 | o | 111 | 157 | | | | ++---------------+-------------+------------+---------------+-------------+------------+ | | | +| a | 97 | 141 | p | 112 | 160 | | | | ++---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ + + + +Capturing Rejected Rows ========================== Prior to the column process and storage, the ``COPY`` command parses the data. @@ -225,12 +384,12 @@ Whenever the data can’t be parsed because it is improperly formatted or doesn #. When ``ERROR_LOG`` is set and ``ERROR_VERBOSITY`` is set to ``0``, rejected rows are saved to the file path specified, but errors are not logged. This is useful for replaying the file later. -CSV support +CSV Support ================ By default, SQream DB's CSV parser can handle `RFC 4180 standard CSVs `_ , but can also be modified to support non-standard CSVs (with multi-character delimiters, unquoted fields, etc). -All CSV files shoudl be prepared according to these recommendations: +All CSV files should be prepared according to these recommendations: * Files are UTF-8 or ASCII encoded @@ -251,7 +410,7 @@ All CSV files shoudl be prepared according to these recommendations: Other modes of escaping are not supported (e.g. ``1,"What are \"birds\"?"`` is not a valid way of escaping CSV values). -Null markers +Marking Null Markers --------------- ``NULL`` values can be marked in two ways in the CSV: @@ -264,53 +423,87 @@ Null markers Examples =========== -Loading a standard CSV file +Loading a Standard CSV File +------------------------------ + +.. code-block:: postgres + + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.csv'); + + +Skipping Faulty Rows ------------------------------ .. code-block:: postgres - COPY table_name FROM 'file.csv'; + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.csv', continue_on_error = true); + + +Skipping a Maximum of 100 Faulty Rows +----------------------------------- + +.. code-block:: postgres + + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.csv', continue_on_error = true, error_count = 100); -Loading a PSV (pipe separated value) file +Loading a Pipe Separated Value (PSV) File ------------------------------------------- .. code-block:: postgres - COPY table_name FROM 'file.psv' WITH DELIMITER '|'; + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.psv', delimiter = '|'); -Loading a TSV (tab separated value) file +Loading a Tab Separated Value (TSV) File ------------------------------------------- .. code-block:: postgres - COPY table_name FROM 'file.tsv' WITH DELIMITER '\t'; + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.tsv', delimiter = '\t'); + + +Loading an ORC File +------------------------------------------- + +.. code-block:: postgres + + COPY table_name FROM WRAPPER orc_fdw OPTIONS (location = '/tmp/file.orc'); + -Loading a text file with non-printable delimiter +Loading a Parquet File +------------------------------------------- + +.. code-block:: postgres + + COPY table_name FROM WRAPPER parquet_fdw OPTIONS (location = '/tmp/file.parquet'); + + +Loading a Text File with Non-Printable Delimiters ----------------------------------------------------- In the file below, the separator is ``DC1``, which is represented by ASCII 17 decimal or 021 octal. .. code-block:: postgres - COPY table_name FROM 'file.txt' WITH DELIMITER E'\021'; + COPY table_name FROM WRAPPER psv_fdw OPTIONS (location = '/tmp/file.txt', delimiter = E'\021'); -Loading a text file with multi-character delimiters +Loading a Text File with Multi-Character Delimiters ----------------------------------------------------- In the file below, the separator is ``^|``. .. code-block:: postgres - COPY table_name FROM 'file.txt' WITH DELIMITER '^|'; + COPY table_name FROM WRAPPER psv_fdw OPTIONS (location = '/tmp/file.txt', delimiter = '^|'); In the file below, the separator is ``'|``. The quote character has to be repeated, as per the :ref:`literal quoting rules`. .. code-block:: postgres - COPY table_name FROM 'file.txt' WITH DELIMITER ''''|'; + COPY table_name FROM WRAPPER psv_fdw OPTIONS (location = '/tmp/file.txt', delimiter = ''''|'); + -Loading files with a header row +Loading Files with a Header Row ----------------------------------- Use ``OFFSET`` to skip rows. @@ -319,70 +512,73 @@ Use ``OFFSET`` to skip rows. .. code-block:: postgres - COPY table_name FROM 'filename.psv' WITH DELIMITER '|' OFFSET 2; + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.psv', delimiter = '|', offset = 2); -Loading files formatted for Windows (``\r\n``) +Loading Files Formatted for Windows (``\r\n``) --------------------------------------------------- .. code-block:: postgres - COPY table_name FROM 'filename.psv' WITH DELIMITER '|' RECORD DELIMITER '\r\n'; + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.psv', delimiter = '\r\n'); -Loading a file from a public S3 bucket +Loading a File from a Public S3 Bucket ------------------------------------------ .. note:: The bucket must be publicly available and objects can be listed .. code-block:: postgres - COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n'; + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = 's3://sqream-demo-data/file.csv', delimiter = '\r\n', offset = 2); -Loading files from an authenticated S3 bucket +Loading Files from an Authenticated S3 Bucket --------------------------------------------------- .. code-block:: postgres - COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n' AWS_ID '12345678' AWS_SECRET 'super_secretive_secret'; - - -Saving rejected rows to a file + COPY table_name FROM WRAPPER psv_fdw OPTIONS (location = 's3://secret-bucket/*.csv', DELIMITER = '\r\n', OFFSET = 2, AWS_ID = '12345678', AWS_SECRET = 'super_secretive_secret'); + +Saving Rejected Rows to a File ---------------------------------- .. note:: When loading multiple files (e.g. with wildcards), this error threshold is for the entire transaction. .. code-block:: postgres - COPY table_name FROM 'filename.psv' WITH DELIMITER '|' - ERROR_LOG '/temp/load_error.log' -- Save error log - ERROR_VERBOSITY 0; -- Only save rejected rows + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.csv', + ,continue_on_error = true + ,error_log = '/temp/load_error.log' + ); .. code-block:: postgres - COPY table_name FROM 'filename.csv' WITH delimiter '|' - ERROR_LOG '/temp/load_err.log' -- Save error log - OFFSET 2 -- skip header row - LIMIT 100 -- Only load 100 rows - STOP AFTER 5 ERRORS; -- Stop the load if 5 errors reached + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.psv' + ,delimiter '|' + ,error_log = '/temp/load_error.log' -- Save error log + ,rejected_data = '/temp/load_rejected.log' -- Only save rejected rows + ,limit = 100 -- Only load 100 rows + ,error_count = 5 -- Stop the load if 5 errors reached + ); -Load CSV files from a set of directories + +Loading CSV Files from a Set of Directories ------------------------------------------ .. code-block:: postgres - COPY table_name from '/path/to/files/2019_08_*/*.csv'; + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/2019_08_*/*.csv'); -Rearrange destination columns +Rearranging Destination Columns --------------------------------- When the source of the files does not match the table structure, tell the ``COPY`` command what the order of columns should be .. code-block:: postgres - COPY table_name (fifth, first, third) FROM '/path/to/files/*.csv'; + COPY table_name (fifth, first, third) FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/*.csv'); .. note:: Any column not specified will revert to its default value or ``NULL`` value if nullable -Loading non-standard dates +Loading Non-Standard Dates ---------------------------------- If files contain dates not formatted as ``ISO8601``, tell ``COPY`` how to parse the column. After parsing, the date will appear as ``ISO8601`` inside SQream DB. @@ -393,5 +589,4 @@ In this example, ``date_col1`` and ``date_col2`` in the table are non-standard. .. code-block:: postgres - COPY table_name FROM '/path/to/files/*.csv' WITH PARSERS 'date_col1=YMD,date_col2=MDY,date_col3=default'; - + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/*.csv', datetime_format = 'DMY'); From 0125c9f699e96a99962453575a92412dab3ebe15 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 26 Oct 2021 13:24:59 +0300 Subject: [PATCH 060/300] Update recommended_configuration.rst Replaced with pre.... saved original in backup folder --- .../setup/recommended_configuration.rst | 1201 ++++++++++++++--- 1 file changed, 1043 insertions(+), 158 deletions(-) diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst index d56048a57..7075d79cb 100644 --- a/guides/operations/setup/recommended_configuration.rst +++ b/guides/operations/setup/recommended_configuration.rst @@ -1,271 +1,1156 @@ .. _recommended_configuration: ********************************************* -Recommended post-installation configuration +Recommended Pre-Installation Configuration ********************************************* -Once you've :ref:`installed SQream DB`, you can and should tune your system for better performance and stability. +Before :ref:`installing SQream DB`, SQream recommends you to tune your system for better performance and stability. This page provides recommendations for production deployments of SQream DB. .. contents:: In this topic: - :local: + :local: -Recommended BIOS settings +Recommended BIOS Settings ========================== - The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. It is safe to skip any and all of the configuration steps, but this may impact performance. If any doubt arises, consult the documentation for your server or your hardware vendor for the correct way to apply the settings. -.. list-table:: - :widths: auto +.. list-table:: + :widths: 25 25 50 :header-rows: 1 * - Item - Setting - Rationale - * - **Fan speed** or **Thermal Configuration** - - **High**, **Maximum**, or **Increased cooling** - - NVIDIA Tesla GPUs are passively cooled and require high amounts of airflow to function properly + * - **Management console access** + - **Connected** + - Connection to OOB required to preserve continuous network uptime. + * - **All drives.** + - **Connected and displayed on RAID interface** + - Prerequisite for cluster or OS installation. + * - **RAID volumes.** + - **Configured according to project guidelines. Must be rebooted to take effect.** + - Clustered to increase logical volume and provide redundancy. + * - **Fan speed Thermal Configuration.** + - Dell fan speed: **High Maximum**. Specified minimum setting: **60**. HPe thermal configuration: **Increased cooling**. + - NVIDIA Tesla GPUs are passively cooled and require high airflow to operate at full performance. + * - Power regulator or iDRAC power unit policy + - HPe: **HP static high performance** mode enabled. Dell: **iDRAC power unit policy** (power cap policy) disabled. + - Other power profiles (such as "balanced") throttle the CPU and diminishes performance. Throttling may also cause GPU failure. * - **System Profile**, **Power Profile**, or **Performance Profile** - **High Performance** - The Performance profile provides potentially increased performance by maximizing processor frequency, and the disabling certain power saving features such as C-states. Use this setting for environments that are not sensitive to power consumption. * - **Power Cap Policy** or **Dynamic power capping** - **Disabled** - - Other power profiles (like "balanced") throttle CPU performance which diminish performance. This setting may appear together with the above (Power profile or Power regulator). This option allows for disabling System ROM Power Calibration during the boot process. + - Other power profiles (like "balanced") throttle the CPU and may diminish performance or cause GPU failure. This setting may appear together with the above (Power profile or Power regulator). This setting allows disabling system ROM power calibration during the boot process. Power regulator settings are named differently in BIOS and iLO/iDRAC. + +.. + **Comment: is it necessary to show the different power regulator setting names in this document?** * - **Intel Turbo Boost** - - **Enable** - - Intel Turbo Boost allows the processor to be overclocked under high load, which may improve performance in CPU-bound operations, but at the risk of computational jitter if the processor changes its turbo frequency. When that happens, processing stops for a small period of time, introducing uncertainty in application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. - * - **Hyperthreading** or **Logical processor** - - **Enable** - - Hyperthreading doubles the amount of logical processors, which may improve performance generally by ~5-10% in CPU-bound operations - * - **Intel Virtualization Technology** and **VT-d** + - **Enabled** + - Intel Turbo Boost enables overclocking the processor to boost CPU-bound operation performance. Overclocking may risk computational jitter due to changes in the processor's turbo frequency. This causes brief pauses in processor operation, introducing uncertainty into application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. + * - **Logical Processor** + - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** + - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. + * - **Intel Virtualization Technology** (VT-d) - **Disable** - - Unless you are running VMs, disabling this setting boosts performance by up to 10%. - * - **C-States** or **Minimum processor idle power core state** + - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. + * - **Logical Processor** + - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** + - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. + * - **Intel Virtualization Technology** (VT-d) + - **Disable** + - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. + * - **Processor C-States** (Minimum processor idle power core state) - **Disable** - - Processor C-States allows the server to reduce power when the system is idle. This causes slower 'cold-starts' when the system is transitioning from idle to load, and could reduce query performance by up to 15%. - * - **Energy/Performance bias** + - Processor C-States reduce server power when the system is in an idle state. This causes slower cold-starts when the system transitions from an idle to a load state, and may reduce query performance by up to 15%. **Comment: a hyperlinked footnote to an internal source was inserted into the Confluence doc here. Do we want to include this in the final version? Linked URL: https://www.dell.com/support/kbdoc/en-il/000060621/what-is-the-c-state** + * - **HPe**: **Energy/Performance bias** - **Maximum performance** - - Configures processor subsystems for high-performance/low-latency. Other power profiles (like "balanced" or "power savings") throttle CPU performance, which diminish performance. Use this setting for environments that are not sensitive to power consumption. - * - **DIMM voltage** + - Configures processor sub-systems for high-performance and low-latency. Other power profiles (like "balanced") throttle the CPU and may diminish performance. Use this setting for environments that are not sensitive to power consumption. + * - **HPe**: **DIMM voltage** - **Optimized for Performance** - - Setting a higher voltage for DIMMs can increases performance + - Setting a higher voltage for DIMMs may increase performance. * - **Memory Operating Mode** - **Optimizer Mode**, **Disable Node Interleaving**, **Auto Memory Operating Voltage** - - Memory Operating Mode is tuned for performance in Optimizer mode. Other modes may improve reliability but reduce performance. Enabling Node Interleaving means the memory is interleaved between memory nodes, which harms NUMA-aware applications like SQream DB, so leave disabled. - * - **Memory power savings mode** + - Memory Operating Mode is tuned for performance in **Optimizer** mode. Other modes may improve reliability, but reduce performance. **Node Interleaving** should be disabled because enabling it interleaves the memory between memory nodes, which harms NUMA-aware applications such as SQream DB. + * - **HPe**: **Memory power savings mode** - **Maximum performance** - - This option configures several memory parameters to optimize the memory subsystems performance and is configured to Balanced by default. - * - **ACPI SLIT** + - This setting configures several memory parameters to optimize the performance of memory sub-systems. The default setting is **Balanced**. + * - HPe **ACPI SLIT** - **Enabled** - - ACPI SLIT describes the relative access times between processors, memory subsystems, and I/O subsystems. Operating systems that support the SLIT can use this information to improve performance by allocating resources and workloads more efficiently. - * - **QPI Snoop** + - ACPI SLIT sets the relative access times between processors and memory and I/O sub-systems. ACPI SLIT enables operating systems to use this data to improve performance by more efficiently allocating resources and workloads. + * - **QPI Snoop** **Comment: should we write that it is HPe or Intel? HPe: QPI Snoop** - **Cluster on Die** or **Home Snoop** - - This option allows for the configurations of different snoop modes that impact the QPI interconnect. Changing this option may improve performance in certain workloads. Home Snoop provides high memory bandwidth in an average NUMA environment (default setting). Cluster on Die may provide increased memory bandwidth in highly optimized NUMA workloads. Early Snoop may decrease memory latency but may also result in lower overall bandwidth as compared to other modes. + - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. + + + + + + +Installing the Operating System +=================================================== +Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.6-7.9) must be installed before installing the SQream database. Either the customer or a SQream representative can perform the installation. + +.. + **Comment: I recommend leaving contact information here - Please call xxx-xxx-xxxx to contact a SQream representative.** + +**To install the operating system:** + +#. Select a language (English recommended). +#. From **Software Selection**, select **Minimal**. +#. Select the **Development Tools** group checkbox. +#. Continue the installation. +#. Set up the necessary drives and users as per the installation process. + + Using Debugging Tools is recommended for future problem-solving if necessary. + + .. + **Comment: In Step 4, why don't we document the entire procedure? I.e., why do we stop here and say "Continue the installation" and "Set up the necessary drives..."?** + +Selecting the **Development Tools** group installs the following tools: + + * autoconf + * automake + * binutils + * bison + * flex + * gcc + * gcc-c++ + * gettext + * libtool + * make + * patch + * pkgconfig + * redhat-rpm-config + * rpm-build + * rpm-sign + -Use a dedicated SQream DB administration account + +The root user is created and the OS shell is booted up. + +Configuring the Operating System =================================================== +When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. -Create a user for SQream DB, and optionally assign it to the ``wheel`` group for ``sudo`` access. +Logging In to the Server +-------------------------------- +You can log in to the server using the server's IP address and password for the **root** user. The server's IP address and **root** user were created while installing the operating system above. -.. code-block:: console +Automatically Creating a SQream User +------------------------------------ - $ useradd -m -u 1132 -U sqream - $ passwd sqream - $ usermod -aG wheel sqream +**To automatically create a SQream user:** -.. note:: - * The UID (1132 in the example above) is set to ensure all shared files are accessible by all workers. +#. If a SQream user was created during installation, verify that the same ID is used on every server: -Configure the OS locale and timezone -===================================== + .. code-block:: console -#. Set your OS to use UTF-8, which SQream DB uses for non-English language support. + $ sudo id sqream + +The ID **1000** is used on each server in the following example: + + .. code-block:: console + + $ uid=1000(sqream) gid=1000(sqream) groups=1000(sqream) +2. If the ID's are different, delete the SQream user and SQream group from both servers: + .. code-block:: console + + $ sudo userdel sqream + +3. Recreate it using the same ID: + .. code-block:: console + + $ sudo rm /var/spool/mail/sqream + +Manually Creating a SQream User +-------------------------------- + +**To manually create a SQream user:** + +SQream enables you to manually create users. This section shows you how to manually create a user with the UID **1111**. You cannot manually create during the operating system installation procedure. + +1. Add a user with an identical UID on all cluster nodes: + + .. code-block:: console + + $ useradd -u 1111 sqream + +2. Add the user **sqream** to the **wheel** group. + + .. code-block:: console + + $ sudo usermod -aG wheel sqream + +You can remove the SQream user from the **wheel** group when the installation and configuration are complete: + + .. code-block:: console + + $ passwd sqream + +3. Log out and log back in as **sqream**. + +**Note:** If you deleted the **sqream** user and recreated it with different ID, to avoid permission errors, you must change its ownership to /home/sqream. + +4. Change the **sqream** user's ownership to /home/sqream: + + .. code-block:: console + + $ sudo chown -R sqream:sqream /home/sqream + +Setting Up A Locale +-------------------------------- + +SQream enables you to set up a locale. In this example, the locale used is your own location. + +**To set up a locale:** + +1. Set the language of the locale: + + .. code-block:: console + $ sudo localectl set-locale LANG=en_US.UTF-8 -#. Set the correct timezone for your server. - Refer to `the list of available timezones `_ to find a timezone that matches your location. +2. Set the time stamp (time and date) of the locale: + + .. code-block:: console + + $ sudo timedatectl set-timezone Asia/Jerusalem + +If needed, you can run the **timedatectl list-timezones** command to see your current time-zone. + + +Installing the Required Packages +-------------------------------- +You can install the required packages by running the following command: + +.. code-block:: console + + $ sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq + +Installing the Recommended Tools +-------------------------------- +You can install the recommended tools by running the following command: + +.. code-block:: console + + $ sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix + + +Installing Python 3.6.7 +-------------------------------- +1. Download the Python 3.6.7 source code tarball file from the following URL into the **/home/sqream** directory: + .. code-block:: console + + $ wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz - $ sudo timedatectl set-timezone America/New_York +2. Extract the Python 3.6.7 source code into your current directory: + .. code-block:: console -Configure NTP for clock synchronization -========================================= + $ tar -xf Python-3.6.7.tar.xz + +3. Navigate to the Python 3.6.7 directory: -SQream DB clusters rely on clock synchronization to function correctly. + .. code-block:: console + $ cd Python-3.6.7/Python-3 + +4. Run the **./configure** script: .. code-block:: console + + $ ./configure - $ sudo yum install -y ntp ntpdate +5. Build the software: + + .. code-block:: console + + $ make -j30 + +6. Install the software: + + .. code-block:: console + + $ sudo make install + +7. Verify that Python 3.6.7 has been installed: + + .. code-block:: console + + $ python3.6.7 + +Installing NodeJS on CentOS +-------------------------------- +**To install the node.js on CentOS:** + +1. Download the `setup_12.x file `__ as a root user logged in shell: + + .. code-block:: console + + $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - + +2. Clear the YUM cache and update the local metadata: + + .. code-block:: console + + $ sudo yum clean all && sudo yum makecache fast + +3. Install the **node.js**) file: + + .. code-block:: console + + $ sudo yum install -y nodejs + +Installing NodeJS on Ubuntu +-------------------------------- +**To install the node.js file on Ubuntu:** + +1. Download the `setup_12.x file `__ as a root user logged in shell: + + .. code-block:: console + + $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - + +2. Install the node.js file: + + .. code-block:: console + + $ sudo apt-get install -y nodejs + +3. Verify the node version: + +.. + **Comment: - is this step relevant only for installing on Ubuntu, or on CentOS as well?** + + .. code-block:: console + + $ node -v + +Configuring the Network Time Protocol (NTP) +------------------------------------------- +This section describes how to configure your NTP. + +If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server `__. + +.. + **Comment: - Is this the correct procedure on the linked URL: Configure NTP Client to Synchronize with NTP Server?* + +**To configure your NTP:** + +1. Install the NTP file. + + .. code-block:: console + + $ sudo yum install ntp + +2. Enable the **ntpd** program. + + .. code-block:: console + $ sudo systemctl enable ntpd + +3. Start the **ntdp** program. + + .. code-block:: console + $ sudo systemctl start ntpd + +4. Print a list of peers known to the server and a summary of their states. + + .. code-block:: console + + $ sudo ntpq -p + +Configuring the Network Time Protocol Server +-------------------------------------------- +If your organization has an NTP server, you can configure it. -If your organization has an NTP server, configure it by adding records to ``/etc/ntpd.conf``, reloading the service, and checking that synchronization is enabled: +**To configure your NTP server:** + +1. Output your NTP server address and append ``/etc/ntpd.conf`` to the outuput. .. code-block:: console - + $ echo -e "\nserver \n" | sudo tee -a /etc/ntp.conf + +2. Restart the service. + + .. code-block:: console + $ sudo systemctl restart ntpd + +3. Check that synchronization is enabled: + + .. code-block:: console + $ sudo timedatectl - Local time: Sat 2019-10-12 17:26:13 EDT - Universal time: Sat 2019-10-12 21:26:13 UTC - RTC time: Sat 2019-10-12 21:26:13 - Time zone: America/New_York (EDT, -0400) - NTP enabled: yes - NTP synchronized: yes - RTC in local TZ: no - DST active: yes - Last DST change: DST began at - Sun 2019-03-10 01:59:59 EST - Sun 2019-03-10 03:00:00 EDT - Next DST change: DST ends (the clock jumps one hour backwards) at - Sun 2019-11-03 01:59:59 EDT - Sun 2019-11-03 01:00:00 EST + +Checking that synchronization is enabled generates the following output: + .. code-block:: console + $ Local time: Sat 2019-10-12 17:26:13 EDT + Universal time: Sat 2019-10-12 21:26:13 UTC + RTC time: Sat 2019-10-12 21:26:13 + Time zone: America/New_York (EDT, -0400) + NTP enabled: yes + NTP synchronized: yes + RTC in local TZ: no + DST active: yes + Last DST change: DST began at + Sun 2019-03-10 01:59:59 EST + Sun 2019-03-10 03:00:00 EDT + Next DST change: DST ends (the clock jumps one hour backwards) at + Sun 2019-11-03 01:59:59 EDT + Sun 2019-11-03 01:00:00 EST + + + +Configuring the Server to Boot Without the UI +--------------------------------------------- +You can configure your server to boot without a UI in cases when it is not required (recommended) by running the following command: -Install recommended utilities -=============================== +.. code-block:: console + + $ sudo systemctl set-default multi-user.target + +Running this command activates the **NO-UI** server mode. -The following packages contain tools that are recommended but not required for using SQream DB. +Configuring the Security Limits +-------------------------------- +The security limits refers to the number of open files, processes, etc. + +You can configure the security limits by running the **echo -e** command as a root user logged in shell: + +.. code-block:: console + + $ sudo bash + +.. code-block:: console + + $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + +Configuring the Kernel Parameters +--------------------------------- +**To configure the kernel parameters:** + +1. Insert a new line after each kernel parameter: .. code-block:: console - - $ sudo yum install -y bash-completion.noarch vim-enhanced.x86_64 vim-common.x86_64 net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix tuned pciutils + $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf + +**Notice:** In the past, the **vm.zone_reclaim_mode** parameter was set to **7.** In the latest Sqream version, the vm.zone_reclaim_mode parameter must be set to **0**. If it is not set to **0**, when a numa node runs out of memory, the system will get stuck and will be unable to pull memory from other numa nodes. + +2. Check the maximum value of the **fs.file**. + + .. code-block:: console + + $ sysctl -n fs.file-max + +3. *Optional* - If the maximum value of the **fs.file** is smaller than **2097152**, run the following command: + + .. code-block:: console + + $ echo "fs.file-max=2097152" >> /etc/sysctl.conf + +**IP4 forward** must be enabled for Docker and K8s installation only. + +Configuring the Firewall +-------------------------------- +The example in this section shows the open ports for four sqreamd sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. + +**To configure the firewall:** + +1. Start the service and enable FirewallID on boot: + + .. code-block:: console + + $ systemctl start firewalld + +2. Add the following ports to the permanent firewall: + + .. code-block:: console + + $ firewall-cmd --zone=public --permanent --add-port=8080/tcp + $ firewallfirewall-cmd --zone=public --permanent --add-port=3105/tcp + $ firewall-cmd --zone=public --permanent --add-port=3108/tcp + $ firewall-cmd --zone=public --permanent --add-port=5000-5003/tcp + $ firewall-cmd --zone=public --permanent --add-port=5100-5103/tcp + $ firewall-cmd --permanent --list-all + + +.. + **Comment: - does *--list-all* add the entire list of ports to the permanent firewall?** -Tuning OS parameters for performance and stability +3. Reload the firewall: + + .. code-block:: console + + $ firewall-cmd --reload + +4. Start the service and enable FirewallID on boot: + + .. code-block:: console + + $ systemctl start firewalld + + If you do not need the firewall, you can disable it: + + .. code-block:: console + + $ sudo systemctl disable firewalld + + +Disabling selinux +-------------------------------- +**To disable selinux:** + +1. Show the status of **selinux**: + + .. code-block:: console + + $ sudo sestatus + +2. If the output is not **disabled**, edit the **/etc/selinux/config** file: + + .. code-block:: console + + $ sudo vim /etc/selinux/config + +3. Change **SELINUX=enforcing** to **SELINUX=disabled**. + +The above changes will only take effect after rebooting the server. + +You can disable selinux immediately after rebooting the server by running the following command: + +.. code-block:: console + + $ sudo setenforce 0 + +Configuring the /etc/hosts File +-------------------------------- +**To configure the /etc/hosts file:** + +1. Edit the **/etc/hosts** file: + + .. code-block:: console + + $ sudo vim /etc/hosts + +2. Call your local host: + + .. code-block:: console + + $ 127.0.0.1 localhost + $ + +.. + **Comment: - Is the above an output or a step?** + +Configuring the DNS +-------------------------------- +**To configure the DNS:** + +1. Run the **ifconfig** commasnd to check your NIC name. In the following example, **eth0** is the NIC name: + + .. code-block:: console + + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-eth0 + +2. Replace the DNS lines from the example above with your own DNS addresses : + + .. code-block:: console + + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-4.4.4.4 + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-8.8.8.8 + + +.. + **Comment: - is the above input correct?** + +Installing the Nvidia CUDA Driver =================================================== -SQream DB requires certain OS parameters to be set on all hosts in your cluster. -These settings affect: +**Warning:** If your UI runs on the server, the server must be stopped before installing the CUDA drivers. + +CUDA Driver Prerequisites +-------------------------------- +1. Verify that the NVIDIA card has been installed and is detected by the system: + + .. code-block:: console + + $ lspci | grep -i nvidia + +2. Check which version of gcc has been installed: + + .. code-block:: console + + $ gcc --version + +3. If gcc has not been installed, install it for one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console -* Shared memory - Most OS installations may try to limit high throughput software like SQream DB. -* Network - On high throughput operations like ingest, optimizing network connection parameters can boost performance -* User limits - SQream DB may open a large amount of files. The default OS settings may cause some statements to fail if the system runs out of file descriptors. -* Core dump creation rules + $ sudo yum install -y gcc -#. Create a directory for core dumps + * On Ubuntu: - In this step, you will create a directory for writing core dumps - which you will configure in the next step. + .. code-block:: console + + $ sudo apt-get install gcc + + +Updating the Kernel Headers +-------------------------------- +**To update the kernel headers:** + +1. Update the kernel headers on one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console + + $ sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) + + * On Ubuntu: + .. code-block:: console + + $ sudo apt-get install linux-headers-$(uname -r) + +2. Install **wget** one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console + + $ sudo yum install wget + + * On Ubuntu: + + .. code-block:: console + + $ sudo apt-get install wget + +Disabling Nouveau +-------------------------------- +You can disable Nouveau, which is the default driver. + +**To disable Nouveau:** + +1. Check if the Nouveau driver has been loaded: + .. code-block:: console - - $ sudo mkdir /tmp/core_dumps - .. note:: - Core dumps can be large - up to the size of the system memory (i.e. for a machine with 512GB of RAM, the size of the core dump will be 512GB). + $ lsmod | grep nouveau + +If the Nouveau driver has been loaded, the command above generates output. + +2. Blacklist the Nouveau drivers to disable them: + + .. code-block:: console + + $ cat < /dev/null < /dev/null <` + $ sudo vim /etc/rc.local + +3. Add the following lines: + + a. **For V100**: + + .. code-block:: console + + $ nvidia-persistenced + + b. **For IBM (mandatory)**: + + .. code-block:: console + + $ sudo systemctl enable nvidia-persistenced + +**Notice**: Setting up the NVIDIA POWER9 CUDA driver includes additional set-up requirements. The NVIDIA POWER9 CUDA driver will not function properly if the additional set-up requirements are not followed. See `POWER9 Setup `__ for the additional set-up requirements. + + + c. **For K80**: + + .. code-block:: console + + $ nvidia-persistenced + $ nvidia-smi -pm 1 + $ nvidia-smi -acp 0 + $ nvidia-smi --auto-boost-permission=0 + $ nvidia-smi --auto-boost-default=0 + +4. Reboot the server and run the **NVIDIA System Management Interface (NVIDIA SMI)**: + + .. code-block:: console + + $ nvidia-smi + + +Disabling Automatic Bug Reporting Tools +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**To disable automatic bug reporting tools:** + +1. Run the following **abort** commands: + + .. code-block:: console + + $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done + + +The server is ready for the SQream software installation. + + +2. Run the following checks: + + a. Check the OS release: + + .. code-block:: console + + $ cat /etc/os-release + + b. Verify that a SQream user exists and has the same ID on all cluster member services: + + .. code-block:: console + + $ id sqream + + c. Verify that the storage is mounted: + + .. code-block:: console + + $ mount + + d. Verify that the driver has been installed correctly: + + .. code-block:: console + + $ nvidia-smi + + e. Check the maximum value of the **fs.file**: + + .. code-block:: console + + $ sysctl -n fs.file-max + + The desired output when checking the maximum value of the **fs.file** is greater or equal to **2097152**. + + f. Run the following command as a SQream user: + +.. + **Comment: - **Question - what do the following command parameter do? -c?** + + .. code-block:: console + + $ ulimit -c -u -n + +.. + **Comment: - See https://ss64.com/bash/ulimit.html** + + The following shows the desired output when ****: + + .. code-block:: console + + $ core file size (blocks, -c) unlimited + $ max user processes (-u) 1000000 + $ open files (-n) 1000000 + +3. Configure the security limits by running the **echo -e** command as a root user logged in shell: + + .. code-block:: console + + $ sudo bash + $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + +Enabling Core Dumps +=================================================== + +Enabling core dumps is recommended, but optional. + +**To enable core dumps:** + +1. Check the **abrtd** Status + +2. Set the limits + +3. Create the core dumps directory. + + +Checking the abrtd Status +--------------------------------------------------- + +**To check the abrtd status:** + +1. Check if **abrtd** is running: + + .. code-block:: console + + $ sudo ps -ef |grep abrt + +2. If **abrtd** is running, stop it: + + .. code-block:: console + + $ sudo service abrtd stop + $ sudo chkconfig abrt-ccpp off + $ sudo chkconfig abrt-oops off + $ sudo chkconfig abrt-vmcore off + $ sudo chkconfig abrt-xorg off + $ sudo chkconfig abrtd off + + +Setting the Limits +--------------------------------------------------- + +**To set the limits:** + +1. Set the limits: + + .. code-block:: console + + $ ulimit -c + +2. If the output is **0**, add the following lines to the **limits.conf** file (/etc/security): + + .. code-block:: console + + $ * soft core unlimited + $ * hard core unlimited + +3. Log out and log in to apply the limit changes. + +Creating the Core Dumps Directory +--------------------------------------------------- + +**To set the core dumps directory:** + +1. Make the **/tmp/core_dumps** directory: + + .. code-block:: console + + $ mkdir /tmp/core_dumps + +2. Set the ownership of the **/tmp/core_dumps** directory: + + .. code-block:: console + + $ sudo chown sqream.sqream /tmp/core_dumps + +3. Grant read, write, and execute permissions to all users: + + .. code-block:: console + + $ sudo chmod -R 777 /tmp/core_dumps + +Setting the Output Directory of the /etc/sysctl.conf File +----------------------------------------------------------------- + +**To set the output directory of the /etc/sysctl.conf file:** + +1. Edit the **/etc/sysctl.conf** file: + + .. code-block:: console + + $ sudo vim /etc/sysctl.conf + +2. Add the following to the bottom of the file: + + .. code-block:: console + + $ kernel.core_uses_pid = 1 + $ kernel.core_pattern = //core-%e-%s-%u-%g-%p-%t + $ fs.suid_dumpable = 2 + +.. + **Comment: - leave a note that the user can choose his correct location of the folder.** + +3. To apply the changes without rebooting the server, run: + + .. code-block:: console + + $ sudo sysctl -p + +4. Check that the core output directory points to the following: + + .. code-block:: console + + $ sudo cat /proc/sys/kernel/core_pattern + + The following shows the correct generated output: + + .. code-block:: console + + $ /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t + +5. Verify that the core dumping works: + + .. code-block:: console + + $ select abort_server(); + + +Verifying that the Core Dumps Work +--------------------------------------------------- +You can verify that the core dumps work only after installing and running SQream. This causes the server to crash and a new core.xxx file to be included in the folder that is written in **/etc/sysctl.conf** + +**To verify that the core dumps work:** + +1. Stop and restart all SQream services. + +2. Connect to SQream with ClientCmd and run the following command: + + .. code-block:: console + + $ select abort_server(); + + +.. + **Comment: - what did the author mean by "Stage 3"?** + +Troubleshooting Core Dumping +--------------------------------------------------- +This section describes the troubleshooting procedure to be followed if all parameters have been configured correctly, but the cores have not been created. + +**To troubleshoot core dumping:** + +1. Reboot the server. + +2. Verify that you have folder permissions: + + .. code-block:: console + + $ sudo chmod -R 777 /tmp/core_dumps + +3. Verify that the limits have been set correctly: + + .. code-block:: console + + $ ulimit -c + + If all parameters have been configured correctly, the correct output is: + + .. code-block:: console + + $ unlimited + +4. If all parameters have been configured correctly, but running **ulimit -c** outputs **0**, run the following: + + .. code-block:: console + + $ sudo vim /etc/profile + +5. Search for line and tag it with the **hash** symbol: + + .. code-block:: console + + $ ulimit -S -c 0 > /dev/null 2>&1 + + +6. If the line is not found in **/etc/profile** directory, do the following: + + a. Run the following command: + + .. code-block:: console + + $ sudo vim /etc/init.d/functions + + b. Search for the following: + + .. code-block:: console -* :ref:`Connect an external tool to SQream DB ` + $ ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 + c. If the line is found, tag it with the **hash** symbol and reboot the server. From 2a2305ead08a1984ca2d613f522726c10c67eb1c Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 26 Oct 2021 13:27:09 +0300 Subject: [PATCH 061/300] Update recommended_configuration.rst Replaced with pre.... saved original in backup folder --- .../setup/recommended_configuration.rst | 1201 ++++++++++++++--- 1 file changed, 1043 insertions(+), 158 deletions(-) diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst index d56048a57..7075d79cb 100644 --- a/guides/operations/setup/recommended_configuration.rst +++ b/guides/operations/setup/recommended_configuration.rst @@ -1,271 +1,1156 @@ .. _recommended_configuration: ********************************************* -Recommended post-installation configuration +Recommended Pre-Installation Configuration ********************************************* -Once you've :ref:`installed SQream DB`, you can and should tune your system for better performance and stability. +Before :ref:`installing SQream DB`, SQream recommends you to tune your system for better performance and stability. This page provides recommendations for production deployments of SQream DB. .. contents:: In this topic: - :local: + :local: -Recommended BIOS settings +Recommended BIOS Settings ========================== - The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. It is safe to skip any and all of the configuration steps, but this may impact performance. If any doubt arises, consult the documentation for your server or your hardware vendor for the correct way to apply the settings. -.. list-table:: - :widths: auto +.. list-table:: + :widths: 25 25 50 :header-rows: 1 * - Item - Setting - Rationale - * - **Fan speed** or **Thermal Configuration** - - **High**, **Maximum**, or **Increased cooling** - - NVIDIA Tesla GPUs are passively cooled and require high amounts of airflow to function properly + * - **Management console access** + - **Connected** + - Connection to OOB required to preserve continuous network uptime. + * - **All drives.** + - **Connected and displayed on RAID interface** + - Prerequisite for cluster or OS installation. + * - **RAID volumes.** + - **Configured according to project guidelines. Must be rebooted to take effect.** + - Clustered to increase logical volume and provide redundancy. + * - **Fan speed Thermal Configuration.** + - Dell fan speed: **High Maximum**. Specified minimum setting: **60**. HPe thermal configuration: **Increased cooling**. + - NVIDIA Tesla GPUs are passively cooled and require high airflow to operate at full performance. + * - Power regulator or iDRAC power unit policy + - HPe: **HP static high performance** mode enabled. Dell: **iDRAC power unit policy** (power cap policy) disabled. + - Other power profiles (such as "balanced") throttle the CPU and diminishes performance. Throttling may also cause GPU failure. * - **System Profile**, **Power Profile**, or **Performance Profile** - **High Performance** - The Performance profile provides potentially increased performance by maximizing processor frequency, and the disabling certain power saving features such as C-states. Use this setting for environments that are not sensitive to power consumption. * - **Power Cap Policy** or **Dynamic power capping** - **Disabled** - - Other power profiles (like "balanced") throttle CPU performance which diminish performance. This setting may appear together with the above (Power profile or Power regulator). This option allows for disabling System ROM Power Calibration during the boot process. + - Other power profiles (like "balanced") throttle the CPU and may diminish performance or cause GPU failure. This setting may appear together with the above (Power profile or Power regulator). This setting allows disabling system ROM power calibration during the boot process. Power regulator settings are named differently in BIOS and iLO/iDRAC. + +.. + **Comment: is it necessary to show the different power regulator setting names in this document?** * - **Intel Turbo Boost** - - **Enable** - - Intel Turbo Boost allows the processor to be overclocked under high load, which may improve performance in CPU-bound operations, but at the risk of computational jitter if the processor changes its turbo frequency. When that happens, processing stops for a small period of time, introducing uncertainty in application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. - * - **Hyperthreading** or **Logical processor** - - **Enable** - - Hyperthreading doubles the amount of logical processors, which may improve performance generally by ~5-10% in CPU-bound operations - * - **Intel Virtualization Technology** and **VT-d** + - **Enabled** + - Intel Turbo Boost enables overclocking the processor to boost CPU-bound operation performance. Overclocking may risk computational jitter due to changes in the processor's turbo frequency. This causes brief pauses in processor operation, introducing uncertainty into application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. + * - **Logical Processor** + - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** + - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. + * - **Intel Virtualization Technology** (VT-d) - **Disable** - - Unless you are running VMs, disabling this setting boosts performance by up to 10%. - * - **C-States** or **Minimum processor idle power core state** + - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. + * - **Logical Processor** + - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** + - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. + * - **Intel Virtualization Technology** (VT-d) + - **Disable** + - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. + * - **Processor C-States** (Minimum processor idle power core state) - **Disable** - - Processor C-States allows the server to reduce power when the system is idle. This causes slower 'cold-starts' when the system is transitioning from idle to load, and could reduce query performance by up to 15%. - * - **Energy/Performance bias** + - Processor C-States reduce server power when the system is in an idle state. This causes slower cold-starts when the system transitions from an idle to a load state, and may reduce query performance by up to 15%. **Comment: a hyperlinked footnote to an internal source was inserted into the Confluence doc here. Do we want to include this in the final version? Linked URL: https://www.dell.com/support/kbdoc/en-il/000060621/what-is-the-c-state** + * - **HPe**: **Energy/Performance bias** - **Maximum performance** - - Configures processor subsystems for high-performance/low-latency. Other power profiles (like "balanced" or "power savings") throttle CPU performance, which diminish performance. Use this setting for environments that are not sensitive to power consumption. - * - **DIMM voltage** + - Configures processor sub-systems for high-performance and low-latency. Other power profiles (like "balanced") throttle the CPU and may diminish performance. Use this setting for environments that are not sensitive to power consumption. + * - **HPe**: **DIMM voltage** - **Optimized for Performance** - - Setting a higher voltage for DIMMs can increases performance + - Setting a higher voltage for DIMMs may increase performance. * - **Memory Operating Mode** - **Optimizer Mode**, **Disable Node Interleaving**, **Auto Memory Operating Voltage** - - Memory Operating Mode is tuned for performance in Optimizer mode. Other modes may improve reliability but reduce performance. Enabling Node Interleaving means the memory is interleaved between memory nodes, which harms NUMA-aware applications like SQream DB, so leave disabled. - * - **Memory power savings mode** + - Memory Operating Mode is tuned for performance in **Optimizer** mode. Other modes may improve reliability, but reduce performance. **Node Interleaving** should be disabled because enabling it interleaves the memory between memory nodes, which harms NUMA-aware applications such as SQream DB. + * - **HPe**: **Memory power savings mode** - **Maximum performance** - - This option configures several memory parameters to optimize the memory subsystems performance and is configured to Balanced by default. - * - **ACPI SLIT** + - This setting configures several memory parameters to optimize the performance of memory sub-systems. The default setting is **Balanced**. + * - HPe **ACPI SLIT** - **Enabled** - - ACPI SLIT describes the relative access times between processors, memory subsystems, and I/O subsystems. Operating systems that support the SLIT can use this information to improve performance by allocating resources and workloads more efficiently. - * - **QPI Snoop** + - ACPI SLIT sets the relative access times between processors and memory and I/O sub-systems. ACPI SLIT enables operating systems to use this data to improve performance by more efficiently allocating resources and workloads. + * - **QPI Snoop** **Comment: should we write that it is HPe or Intel? HPe: QPI Snoop** - **Cluster on Die** or **Home Snoop** - - This option allows for the configurations of different snoop modes that impact the QPI interconnect. Changing this option may improve performance in certain workloads. Home Snoop provides high memory bandwidth in an average NUMA environment (default setting). Cluster on Die may provide increased memory bandwidth in highly optimized NUMA workloads. Early Snoop may decrease memory latency but may also result in lower overall bandwidth as compared to other modes. + - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. + + + + + + +Installing the Operating System +=================================================== +Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.6-7.9) must be installed before installing the SQream database. Either the customer or a SQream representative can perform the installation. + +.. + **Comment: I recommend leaving contact information here - Please call xxx-xxx-xxxx to contact a SQream representative.** + +**To install the operating system:** + +#. Select a language (English recommended). +#. From **Software Selection**, select **Minimal**. +#. Select the **Development Tools** group checkbox. +#. Continue the installation. +#. Set up the necessary drives and users as per the installation process. + + Using Debugging Tools is recommended for future problem-solving if necessary. + + .. + **Comment: In Step 4, why don't we document the entire procedure? I.e., why do we stop here and say "Continue the installation" and "Set up the necessary drives..."?** + +Selecting the **Development Tools** group installs the following tools: + + * autoconf + * automake + * binutils + * bison + * flex + * gcc + * gcc-c++ + * gettext + * libtool + * make + * patch + * pkgconfig + * redhat-rpm-config + * rpm-build + * rpm-sign + -Use a dedicated SQream DB administration account + +The root user is created and the OS shell is booted up. + +Configuring the Operating System =================================================== +When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. -Create a user for SQream DB, and optionally assign it to the ``wheel`` group for ``sudo`` access. +Logging In to the Server +-------------------------------- +You can log in to the server using the server's IP address and password for the **root** user. The server's IP address and **root** user were created while installing the operating system above. -.. code-block:: console +Automatically Creating a SQream User +------------------------------------ - $ useradd -m -u 1132 -U sqream - $ passwd sqream - $ usermod -aG wheel sqream +**To automatically create a SQream user:** -.. note:: - * The UID (1132 in the example above) is set to ensure all shared files are accessible by all workers. +#. If a SQream user was created during installation, verify that the same ID is used on every server: -Configure the OS locale and timezone -===================================== + .. code-block:: console -#. Set your OS to use UTF-8, which SQream DB uses for non-English language support. + $ sudo id sqream + +The ID **1000** is used on each server in the following example: + + .. code-block:: console + + $ uid=1000(sqream) gid=1000(sqream) groups=1000(sqream) +2. If the ID's are different, delete the SQream user and SQream group from both servers: + .. code-block:: console + + $ sudo userdel sqream + +3. Recreate it using the same ID: + .. code-block:: console + + $ sudo rm /var/spool/mail/sqream + +Manually Creating a SQream User +-------------------------------- + +**To manually create a SQream user:** + +SQream enables you to manually create users. This section shows you how to manually create a user with the UID **1111**. You cannot manually create during the operating system installation procedure. + +1. Add a user with an identical UID on all cluster nodes: + + .. code-block:: console + + $ useradd -u 1111 sqream + +2. Add the user **sqream** to the **wheel** group. + + .. code-block:: console + + $ sudo usermod -aG wheel sqream + +You can remove the SQream user from the **wheel** group when the installation and configuration are complete: + + .. code-block:: console + + $ passwd sqream + +3. Log out and log back in as **sqream**. + +**Note:** If you deleted the **sqream** user and recreated it with different ID, to avoid permission errors, you must change its ownership to /home/sqream. + +4. Change the **sqream** user's ownership to /home/sqream: + + .. code-block:: console + + $ sudo chown -R sqream:sqream /home/sqream + +Setting Up A Locale +-------------------------------- + +SQream enables you to set up a locale. In this example, the locale used is your own location. + +**To set up a locale:** + +1. Set the language of the locale: + + .. code-block:: console + $ sudo localectl set-locale LANG=en_US.UTF-8 -#. Set the correct timezone for your server. - Refer to `the list of available timezones `_ to find a timezone that matches your location. +2. Set the time stamp (time and date) of the locale: + + .. code-block:: console + + $ sudo timedatectl set-timezone Asia/Jerusalem + +If needed, you can run the **timedatectl list-timezones** command to see your current time-zone. + + +Installing the Required Packages +-------------------------------- +You can install the required packages by running the following command: + +.. code-block:: console + + $ sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq + +Installing the Recommended Tools +-------------------------------- +You can install the recommended tools by running the following command: + +.. code-block:: console + + $ sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix + + +Installing Python 3.6.7 +-------------------------------- +1. Download the Python 3.6.7 source code tarball file from the following URL into the **/home/sqream** directory: + .. code-block:: console + + $ wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz - $ sudo timedatectl set-timezone America/New_York +2. Extract the Python 3.6.7 source code into your current directory: + .. code-block:: console -Configure NTP for clock synchronization -========================================= + $ tar -xf Python-3.6.7.tar.xz + +3. Navigate to the Python 3.6.7 directory: -SQream DB clusters rely on clock synchronization to function correctly. + .. code-block:: console + $ cd Python-3.6.7/Python-3 + +4. Run the **./configure** script: .. code-block:: console + + $ ./configure - $ sudo yum install -y ntp ntpdate +5. Build the software: + + .. code-block:: console + + $ make -j30 + +6. Install the software: + + .. code-block:: console + + $ sudo make install + +7. Verify that Python 3.6.7 has been installed: + + .. code-block:: console + + $ python3.6.7 + +Installing NodeJS on CentOS +-------------------------------- +**To install the node.js on CentOS:** + +1. Download the `setup_12.x file `__ as a root user logged in shell: + + .. code-block:: console + + $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - + +2. Clear the YUM cache and update the local metadata: + + .. code-block:: console + + $ sudo yum clean all && sudo yum makecache fast + +3. Install the **node.js**) file: + + .. code-block:: console + + $ sudo yum install -y nodejs + +Installing NodeJS on Ubuntu +-------------------------------- +**To install the node.js file on Ubuntu:** + +1. Download the `setup_12.x file `__ as a root user logged in shell: + + .. code-block:: console + + $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - + +2. Install the node.js file: + + .. code-block:: console + + $ sudo apt-get install -y nodejs + +3. Verify the node version: + +.. + **Comment: - is this step relevant only for installing on Ubuntu, or on CentOS as well?** + + .. code-block:: console + + $ node -v + +Configuring the Network Time Protocol (NTP) +------------------------------------------- +This section describes how to configure your NTP. + +If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server `__. + +.. + **Comment: - Is this the correct procedure on the linked URL: Configure NTP Client to Synchronize with NTP Server?* + +**To configure your NTP:** + +1. Install the NTP file. + + .. code-block:: console + + $ sudo yum install ntp + +2. Enable the **ntpd** program. + + .. code-block:: console + $ sudo systemctl enable ntpd + +3. Start the **ntdp** program. + + .. code-block:: console + $ sudo systemctl start ntpd + +4. Print a list of peers known to the server and a summary of their states. + + .. code-block:: console + + $ sudo ntpq -p + +Configuring the Network Time Protocol Server +-------------------------------------------- +If your organization has an NTP server, you can configure it. -If your organization has an NTP server, configure it by adding records to ``/etc/ntpd.conf``, reloading the service, and checking that synchronization is enabled: +**To configure your NTP server:** + +1. Output your NTP server address and append ``/etc/ntpd.conf`` to the outuput. .. code-block:: console - + $ echo -e "\nserver \n" | sudo tee -a /etc/ntp.conf + +2. Restart the service. + + .. code-block:: console + $ sudo systemctl restart ntpd + +3. Check that synchronization is enabled: + + .. code-block:: console + $ sudo timedatectl - Local time: Sat 2019-10-12 17:26:13 EDT - Universal time: Sat 2019-10-12 21:26:13 UTC - RTC time: Sat 2019-10-12 21:26:13 - Time zone: America/New_York (EDT, -0400) - NTP enabled: yes - NTP synchronized: yes - RTC in local TZ: no - DST active: yes - Last DST change: DST began at - Sun 2019-03-10 01:59:59 EST - Sun 2019-03-10 03:00:00 EDT - Next DST change: DST ends (the clock jumps one hour backwards) at - Sun 2019-11-03 01:59:59 EDT - Sun 2019-11-03 01:00:00 EST + +Checking that synchronization is enabled generates the following output: + .. code-block:: console + $ Local time: Sat 2019-10-12 17:26:13 EDT + Universal time: Sat 2019-10-12 21:26:13 UTC + RTC time: Sat 2019-10-12 21:26:13 + Time zone: America/New_York (EDT, -0400) + NTP enabled: yes + NTP synchronized: yes + RTC in local TZ: no + DST active: yes + Last DST change: DST began at + Sun 2019-03-10 01:59:59 EST + Sun 2019-03-10 03:00:00 EDT + Next DST change: DST ends (the clock jumps one hour backwards) at + Sun 2019-11-03 01:59:59 EDT + Sun 2019-11-03 01:00:00 EST + + + +Configuring the Server to Boot Without the UI +--------------------------------------------- +You can configure your server to boot without a UI in cases when it is not required (recommended) by running the following command: -Install recommended utilities -=============================== +.. code-block:: console + + $ sudo systemctl set-default multi-user.target + +Running this command activates the **NO-UI** server mode. -The following packages contain tools that are recommended but not required for using SQream DB. +Configuring the Security Limits +-------------------------------- +The security limits refers to the number of open files, processes, etc. + +You can configure the security limits by running the **echo -e** command as a root user logged in shell: + +.. code-block:: console + + $ sudo bash + +.. code-block:: console + + $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + +Configuring the Kernel Parameters +--------------------------------- +**To configure the kernel parameters:** + +1. Insert a new line after each kernel parameter: .. code-block:: console - - $ sudo yum install -y bash-completion.noarch vim-enhanced.x86_64 vim-common.x86_64 net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix tuned pciutils + $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf + +**Notice:** In the past, the **vm.zone_reclaim_mode** parameter was set to **7.** In the latest Sqream version, the vm.zone_reclaim_mode parameter must be set to **0**. If it is not set to **0**, when a numa node runs out of memory, the system will get stuck and will be unable to pull memory from other numa nodes. + +2. Check the maximum value of the **fs.file**. + + .. code-block:: console + + $ sysctl -n fs.file-max + +3. *Optional* - If the maximum value of the **fs.file** is smaller than **2097152**, run the following command: + + .. code-block:: console + + $ echo "fs.file-max=2097152" >> /etc/sysctl.conf + +**IP4 forward** must be enabled for Docker and K8s installation only. + +Configuring the Firewall +-------------------------------- +The example in this section shows the open ports for four sqreamd sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. + +**To configure the firewall:** + +1. Start the service and enable FirewallID on boot: + + .. code-block:: console + + $ systemctl start firewalld + +2. Add the following ports to the permanent firewall: + + .. code-block:: console + + $ firewall-cmd --zone=public --permanent --add-port=8080/tcp + $ firewallfirewall-cmd --zone=public --permanent --add-port=3105/tcp + $ firewall-cmd --zone=public --permanent --add-port=3108/tcp + $ firewall-cmd --zone=public --permanent --add-port=5000-5003/tcp + $ firewall-cmd --zone=public --permanent --add-port=5100-5103/tcp + $ firewall-cmd --permanent --list-all + + +.. + **Comment: - does *--list-all* add the entire list of ports to the permanent firewall?** -Tuning OS parameters for performance and stability +3. Reload the firewall: + + .. code-block:: console + + $ firewall-cmd --reload + +4. Start the service and enable FirewallID on boot: + + .. code-block:: console + + $ systemctl start firewalld + + If you do not need the firewall, you can disable it: + + .. code-block:: console + + $ sudo systemctl disable firewalld + + +Disabling selinux +-------------------------------- +**To disable selinux:** + +1. Show the status of **selinux**: + + .. code-block:: console + + $ sudo sestatus + +2. If the output is not **disabled**, edit the **/etc/selinux/config** file: + + .. code-block:: console + + $ sudo vim /etc/selinux/config + +3. Change **SELINUX=enforcing** to **SELINUX=disabled**. + +The above changes will only take effect after rebooting the server. + +You can disable selinux immediately after rebooting the server by running the following command: + +.. code-block:: console + + $ sudo setenforce 0 + +Configuring the /etc/hosts File +-------------------------------- +**To configure the /etc/hosts file:** + +1. Edit the **/etc/hosts** file: + + .. code-block:: console + + $ sudo vim /etc/hosts + +2. Call your local host: + + .. code-block:: console + + $ 127.0.0.1 localhost + $ + +.. + **Comment: - Is the above an output or a step?** + +Configuring the DNS +-------------------------------- +**To configure the DNS:** + +1. Run the **ifconfig** commasnd to check your NIC name. In the following example, **eth0** is the NIC name: + + .. code-block:: console + + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-eth0 + +2. Replace the DNS lines from the example above with your own DNS addresses : + + .. code-block:: console + + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-4.4.4.4 + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-8.8.8.8 + + +.. + **Comment: - is the above input correct?** + +Installing the Nvidia CUDA Driver =================================================== -SQream DB requires certain OS parameters to be set on all hosts in your cluster. -These settings affect: +**Warning:** If your UI runs on the server, the server must be stopped before installing the CUDA drivers. + +CUDA Driver Prerequisites +-------------------------------- +1. Verify that the NVIDIA card has been installed and is detected by the system: + + .. code-block:: console + + $ lspci | grep -i nvidia + +2. Check which version of gcc has been installed: + + .. code-block:: console + + $ gcc --version + +3. If gcc has not been installed, install it for one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console -* Shared memory - Most OS installations may try to limit high throughput software like SQream DB. -* Network - On high throughput operations like ingest, optimizing network connection parameters can boost performance -* User limits - SQream DB may open a large amount of files. The default OS settings may cause some statements to fail if the system runs out of file descriptors. -* Core dump creation rules + $ sudo yum install -y gcc -#. Create a directory for core dumps + * On Ubuntu: - In this step, you will create a directory for writing core dumps - which you will configure in the next step. + .. code-block:: console + + $ sudo apt-get install gcc + + +Updating the Kernel Headers +-------------------------------- +**To update the kernel headers:** + +1. Update the kernel headers on one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console + + $ sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) + + * On Ubuntu: + .. code-block:: console + + $ sudo apt-get install linux-headers-$(uname -r) + +2. Install **wget** one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console + + $ sudo yum install wget + + * On Ubuntu: + + .. code-block:: console + + $ sudo apt-get install wget + +Disabling Nouveau +-------------------------------- +You can disable Nouveau, which is the default driver. + +**To disable Nouveau:** + +1. Check if the Nouveau driver has been loaded: + .. code-block:: console - - $ sudo mkdir /tmp/core_dumps - .. note:: - Core dumps can be large - up to the size of the system memory (i.e. for a machine with 512GB of RAM, the size of the core dump will be 512GB). + $ lsmod | grep nouveau + +If the Nouveau driver has been loaded, the command above generates output. + +2. Blacklist the Nouveau drivers to disable them: + + .. code-block:: console + + $ cat < /dev/null < /dev/null <` + $ sudo vim /etc/rc.local + +3. Add the following lines: + + a. **For V100**: + + .. code-block:: console + + $ nvidia-persistenced + + b. **For IBM (mandatory)**: + + .. code-block:: console + + $ sudo systemctl enable nvidia-persistenced + +**Notice**: Setting up the NVIDIA POWER9 CUDA driver includes additional set-up requirements. The NVIDIA POWER9 CUDA driver will not function properly if the additional set-up requirements are not followed. See `POWER9 Setup `__ for the additional set-up requirements. + + + c. **For K80**: + + .. code-block:: console + + $ nvidia-persistenced + $ nvidia-smi -pm 1 + $ nvidia-smi -acp 0 + $ nvidia-smi --auto-boost-permission=0 + $ nvidia-smi --auto-boost-default=0 + +4. Reboot the server and run the **NVIDIA System Management Interface (NVIDIA SMI)**: + + .. code-block:: console + + $ nvidia-smi + + +Disabling Automatic Bug Reporting Tools +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**To disable automatic bug reporting tools:** + +1. Run the following **abort** commands: + + .. code-block:: console + + $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done + + +The server is ready for the SQream software installation. + + +2. Run the following checks: + + a. Check the OS release: + + .. code-block:: console + + $ cat /etc/os-release + + b. Verify that a SQream user exists and has the same ID on all cluster member services: + + .. code-block:: console + + $ id sqream + + c. Verify that the storage is mounted: + + .. code-block:: console + + $ mount + + d. Verify that the driver has been installed correctly: + + .. code-block:: console + + $ nvidia-smi + + e. Check the maximum value of the **fs.file**: + + .. code-block:: console + + $ sysctl -n fs.file-max + + The desired output when checking the maximum value of the **fs.file** is greater or equal to **2097152**. + + f. Run the following command as a SQream user: + +.. + **Comment: - **Question - what do the following command parameter do? -c?** + + .. code-block:: console + + $ ulimit -c -u -n + +.. + **Comment: - See https://ss64.com/bash/ulimit.html** + + The following shows the desired output when ****: + + .. code-block:: console + + $ core file size (blocks, -c) unlimited + $ max user processes (-u) 1000000 + $ open files (-n) 1000000 + +3. Configure the security limits by running the **echo -e** command as a root user logged in shell: + + .. code-block:: console + + $ sudo bash + $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + +Enabling Core Dumps +=================================================== + +Enabling core dumps is recommended, but optional. + +**To enable core dumps:** + +1. Check the **abrtd** Status + +2. Set the limits + +3. Create the core dumps directory. + + +Checking the abrtd Status +--------------------------------------------------- + +**To check the abrtd status:** + +1. Check if **abrtd** is running: + + .. code-block:: console + + $ sudo ps -ef |grep abrt + +2. If **abrtd** is running, stop it: + + .. code-block:: console + + $ sudo service abrtd stop + $ sudo chkconfig abrt-ccpp off + $ sudo chkconfig abrt-oops off + $ sudo chkconfig abrt-vmcore off + $ sudo chkconfig abrt-xorg off + $ sudo chkconfig abrtd off + + +Setting the Limits +--------------------------------------------------- + +**To set the limits:** + +1. Set the limits: + + .. code-block:: console + + $ ulimit -c + +2. If the output is **0**, add the following lines to the **limits.conf** file (/etc/security): + + .. code-block:: console + + $ * soft core unlimited + $ * hard core unlimited + +3. Log out and log in to apply the limit changes. + +Creating the Core Dumps Directory +--------------------------------------------------- + +**To set the core dumps directory:** + +1. Make the **/tmp/core_dumps** directory: + + .. code-block:: console + + $ mkdir /tmp/core_dumps + +2. Set the ownership of the **/tmp/core_dumps** directory: + + .. code-block:: console + + $ sudo chown sqream.sqream /tmp/core_dumps + +3. Grant read, write, and execute permissions to all users: + + .. code-block:: console + + $ sudo chmod -R 777 /tmp/core_dumps + +Setting the Output Directory of the /etc/sysctl.conf File +----------------------------------------------------------------- + +**To set the output directory of the /etc/sysctl.conf file:** + +1. Edit the **/etc/sysctl.conf** file: + + .. code-block:: console + + $ sudo vim /etc/sysctl.conf + +2. Add the following to the bottom of the file: + + .. code-block:: console + + $ kernel.core_uses_pid = 1 + $ kernel.core_pattern = //core-%e-%s-%u-%g-%p-%t + $ fs.suid_dumpable = 2 + +.. + **Comment: - leave a note that the user can choose his correct location of the folder.** + +3. To apply the changes without rebooting the server, run: + + .. code-block:: console + + $ sudo sysctl -p + +4. Check that the core output directory points to the following: + + .. code-block:: console + + $ sudo cat /proc/sys/kernel/core_pattern + + The following shows the correct generated output: + + .. code-block:: console + + $ /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t + +5. Verify that the core dumping works: + + .. code-block:: console + + $ select abort_server(); + + +Verifying that the Core Dumps Work +--------------------------------------------------- +You can verify that the core dumps work only after installing and running SQream. This causes the server to crash and a new core.xxx file to be included in the folder that is written in **/etc/sysctl.conf** + +**To verify that the core dumps work:** + +1. Stop and restart all SQream services. + +2. Connect to SQream with ClientCmd and run the following command: + + .. code-block:: console + + $ select abort_server(); + + +.. + **Comment: - what did the author mean by "Stage 3"?** + +Troubleshooting Core Dumping +--------------------------------------------------- +This section describes the troubleshooting procedure to be followed if all parameters have been configured correctly, but the cores have not been created. + +**To troubleshoot core dumping:** + +1. Reboot the server. + +2. Verify that you have folder permissions: + + .. code-block:: console + + $ sudo chmod -R 777 /tmp/core_dumps + +3. Verify that the limits have been set correctly: + + .. code-block:: console + + $ ulimit -c + + If all parameters have been configured correctly, the correct output is: + + .. code-block:: console + + $ unlimited + +4. If all parameters have been configured correctly, but running **ulimit -c** outputs **0**, run the following: + + .. code-block:: console + + $ sudo vim /etc/profile + +5. Search for line and tag it with the **hash** symbol: + + .. code-block:: console + + $ ulimit -S -c 0 > /dev/null 2>&1 + + +6. If the line is not found in **/etc/profile** directory, do the following: + + a. Run the following command: + + .. code-block:: console + + $ sudo vim /etc/init.d/functions + + b. Search for the following: + + .. code-block:: console -* :ref:`Connect an external tool to SQream DB ` + $ ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 + c. If the line is found, tag it with the **hash** symbol and reboot the server. From f824330f48d805100f7e3c63c49a69f0ca69d23e Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 26 Oct 2021 15:03:17 +0300 Subject: [PATCH 062/300] Update sql_data_types.rst Changed TO to AS on the following line: CAST( TO ), to convert a value from one type to another. For example, CAST('1997-01-01' TO DATE), CAST(3.45 TO SMALLINT), CAST(some_column TO VARCHAR(30)). --- reference/sql_data_types.rst | 257 ++++++++++++++++++++++------------- 1 file changed, 160 insertions(+), 97 deletions(-) diff --git a/reference/sql_data_types.rst b/reference/sql_data_types.rst index 09291c817..63aaab9bf 100644 --- a/reference/sql_data_types.rst +++ b/reference/sql_data_types.rst @@ -10,16 +10,18 @@ This topic describes the data types that SQream DB supports, and how to convert :local: :depth: 2 -Supported types +Supported Types ================= -.. list-table:: Data types - :widths: auto +The following table shows the supported data types. + +.. list-table:: + :widths: 20 15 20 55 :header-rows: 1 * - Name - Description - - Data size (not null, uncompressed) + - Data Size (Not Null, Uncompressed) - Example * - ``BOOL`` - Boolean values (``true``, ``false``) @@ -53,6 +55,10 @@ Supported types - Variable length string - UTF-8 unicode - Up to ``4*n`` bytes - ``'キウイは楽しい鳥です'`` + * - ``NUMERIC``, ``DECIMAL`` + - 38 digits + - 16 bytes + - ``0.123245678901234567890123456789012345678`` * - ``VARCHAR (n)`` - Variable length string - ASCII only - ``n`` bytes @@ -70,58 +76,100 @@ Supported types .. _cast: -Converting and casting types +Converting and Casting Types ============================== SQream DB supports explicit and implicit casting and type conversion. -Implicit casts may be added automatically by the system when mixing different data types in the same expression. In many cases, the details of this are not important. However, these can affect the results of a query. When necessary, an explicit cast can be used to override the automatic cast added by SQream DB. +The system may automatically add implicit casts when combining different data types in the same expression. In many cases, while the details related to this are not important, they can affect the query results of a query. When necessary, an explicit cast can be used to override the automatic cast added by SQream DB. For example, the ANSI standard defines a ``SUM()`` aggregation over an ``INT`` column as an ``INT``. However, when dealing with large amounts of data this could cause an overflow. -To rectify this, cast the value to a larger data type: +You can rectify this by casting the value to a larger data type: .. code-block:: postgres SUM(some_int_column :: BIGINT) -SQream DB supports three types of data conversion: +SQream DB supports the following three data conversion types: -* ``CAST( TO )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO VARCHAR(30))``. +* ``CAST( AS )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' AS DATE)``, ``CAST(3.45 AS SMALLINT)``, ``CAST(some_column AS VARCHAR(30))``. * `` :: ``, a shorthand for the ``CAST`` syntax. For example, ``'1997-01-01' :: DATE``, ``3.45 :: SMALLINT``, ``(3+5) :: BIGINT``. * See the :ref:`SQL functions reference ` for additional functions that convert from a specific value which is not an SQL type, such as :ref:`from_unixts`, etc. -More details about the supported casts for each type in the following section. +The **Data Type Reference** section below provides more details about the supported casts for each type. -Data type reference +Data Type Reference ====================== +.. _numeric: -Boolean (``BOOL``) -------------------- -A ``BOOL`` datatype is designed to store Boolean values of ``true`` or ``false``. +Numeric (``NUMERIC``, ``DECIMAL``) +----------------------- +The **Numeric** data type (also known as **Decimal**) is recommended for values that tend to occur as exact decimals, such as in Finance. While Numeric has a fixed precision of ``38``, higher than ``REAL`` (``9``) or ``DOUBLE`` (``17``), it runs calculations more slowly. For operations that require faster performance, using :ref:`Floating Point ` is recommended. -Syntax -^^^^^^^^ +The correct syntax for Numeric is ``numeric(p, s)``), where ``p`` is the total number of digits (``38`` maximum), and ``s`` is the total number of decimal digits. -A ``BOOL`` type can accept either ``true`` or ``false`` (case insensitive). +Numeric Examples +^^^^^^^^^^ -When loading from CSV, ``BOOL`` columns can accept ``0`` as ``false`` and ``1`` as ``true``. +The following is an example of the Numeric syntax: -Size -^^^^^^ +.. code-block:: postgres -A ``BOOL`` type is 1 byte, but resulting average data sizes could be lower after compression. + $ create or replace table t(x numeric(20, 10), y numeric(38, 38)); + $ insert into t values(1234567890.1234567890, 0.123245678901234567890123456789012345678); + $ select x + y from t; + +The following table shows information relevant to the Numeric data type: -Examples +.. list-table:: + :widths: 30 30 30 + :header-rows: 1 + + * - Description + - Data Size (Not Null, Uncompressed) + - Example + * - 38 digits + - 16 bytes + - ``0.123245678901234567890123456789012345678`` + +Numeric supports the following operations: + + * All join types. + * All aggregation types (not including Window functions). + * Scalar functions (not including some trigonometric and logarithmic functions). + + + +Boolean (``BOOL``) +------------------- +The following table describes the Boolean data type. + +.. list-table:: + :widths: 30 30 30 + :header-rows: 1 + + * - Values + - Syntax + - Data Size (Not Null, Uncompressed) + * - ``true``, ``false`` (case sensitive) + - When loading from CSV, ``BOOL`` columns can accept ``0`` as ``false`` and ``1`` as ``true``. + - 1 byte, but resulting average data sizes may be lower after compression. + +Boolean Examples ^^^^^^^^^^ +The following is an example of the Boolean syntax: + .. code-block:: postgres - CREATE TABLE animals (name VARCHAR(15), is_angry BOOL); + CREATE TABLE animals (name TEXT, is_angry BOOL); INSERT INTO animals VALUES ('fox',true), ('cat',true), ('kiwi',false); SELECT name, CASE WHEN is_angry THEN 'Is really angry!' else 'Is not angry' END FROM animals; + +The following is an example of the correct output: .. code-block:: text @@ -129,10 +177,10 @@ Examples "cat","Is really angry!" "kiwi","Is not angry" -Casts and conversions +Boolean Casts and Conversions ^^^^^^^^^^^^^^^^^^^^^^^ -A ``BOOL`` value can be converted to: +The following table shows the possible Boolean value conversions: .. list-table:: :widths: auto @@ -155,19 +203,21 @@ A ``BOOL`` value can be converted to: Integers (``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``) ------------------------------------------------------------ -Integer datatypes are designed to store whole numbers. +Integer data types are designed to store whole numbers. -For information about identity sequences (sometimes called auto-increment or auto-numbers), see :ref:`identity`. +For more information about identity sequences (sometimes called auto-increment or auto-numbers), see :ref:`identity`. -Integer types +Integer Types ^^^^^^^^^^^^^^^^^^^ -.. list-table:: Integer types +The following table describes the Integer types. + +.. list-table:: :widths: auto :header-rows: 1 * - Name - Details - - Data size (not null, uncompressed) + - Data Size (Not Null, Uncompressed) - Example * - ``TINYINT`` - Unsigned integer (0 - 255) @@ -184,20 +234,22 @@ Integer types * - ``BIGINT`` - Integer (-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807) - 8 bytes - - ``36124441255243`` - -Syntax -^^^^^^^^ - -An integer can be entered as a regular literal, such as ``12``, ``-365``. - -Size -^^^^^^ - -Integer types range between 1, 2, 4, and 8 bytes - but resulting average data sizes could be lower after compression. + - ``36124441255243`` + +The following table describes the Integer data type. + +.. list-table:: + :widths: 25 25 + :header-rows: 1 + + * - Syntax + - Data Size (Not Null, Uncompressed) + * - An integer can be entered as a regular literal, such as ``12``, ``-365``. + - Integer types range between 1, 2, 4, and 8 bytes - but resulting average data sizes could be lower after compression. -Examples +Integer Examples ^^^^^^^^^^ +The following is an example of the Integer syntax: .. code-block:: postgres @@ -206,16 +258,18 @@ Examples INSERT INTO cool_numbers VALUES (1,2,3,4), (-5, 127, 32000, 45000000000); SELECT * FROM cool_numbers; + +The following is an example of the correct output: .. code-block:: text 1,2,3,4 -5,127,32000,45000000000 -Casts and conversions +Integer Casts and Conversions ^^^^^^^^^^^^^^^^^^^^^^^ -Integer values can be converted to: +The following table shows the possible Integer value conversions: .. list-table:: :widths: auto @@ -227,23 +281,26 @@ Integer values can be converted to: - ``1`` → ``1.0``, ``-32`` → ``-32.0`` * - ``VARCHAR(n)`` (All numberic values must fit in the string length) - ``1`` → ``'1'``, ``2451`` → ``'2451'`` + +.. _floating_point: - -Floating point (``REAL``, ``DOUBLE``) ------------------------------------------------- -``REAL`` and ``DOUBLE`` are inexact floating point data types, designed to store up to 9 or 17 digits of precision respectively. +Floating Point (``REAL``, ``DOUBLE``) +------------------------------------------------ +The **Floating Point** data types (``REAL`` and ``DOUBLE``) store extremely close value approximations, and are therefore recommended for values that tend to be inexact, such as Scientific Notation. While Floating Point generally runs faster than Numeric, it has a lower precision of ``9`` (``REAL``) or ``17`` (``DOUBLE``) compared to Numeric's ``38``. For operations that require a higher level of precision, using :ref:`Numeric ` is recommended. The floating point representation is based on `IEEE 754 `_. -Floating point types +Floating Point Types ^^^^^^^^^^^^^^^^^^^^^^ -.. list-table:: Floating point types +The following table describes the Floating Point data types. + +.. list-table:: :widths: auto :header-rows: 1 * - Name - Details - - Data size (not null, uncompressed) + - Data Size (Not Null, Uncompressed) - Example * - ``REAL`` - Single precision floating point (inexact) @@ -253,26 +310,21 @@ Floating point types - Double precision floating point (inexact) - 8 bytes - ``0.000003`` + +The following table shows information relevant to the Floating Point data types. -Aliases -^^^^^^^^^^ - -``DOUBLE`` is also known as ``FLOAT``. - - -Syntax -^^^^^^^^ - -A double precision floating point can be entered as a regular literal, such as ``3.14``, ``2.718``, ``.34``, ``2.71e-45``. - -To enter a ``REAL`` floating point number, cast the value. For example, ``(3.14 :: REAL)``. - -Size -^^^^^^ - -Floating point types are either 4 or 8 bytes, but size could be lower after compression. - -Examples +.. list-table:: + :widths: 30 30 30 + :header-rows: 1 + + * - Aliases + - Syntax + - Data Size (Not Null, Uncompressed) + * - ``DOUBLE`` is also known as ``FLOAT``. + - A double precision floating point can be entered as a regular literal, such as ``3.14``, ``2.718``, ``.34``, or ``2.71e-45``. To enter a ``REAL`` floating point number, cast the value. For example, ``(3.14 :: REAL)``. + - Floating point types are either 4 or 8 bytes, but size could be lower after compression. + +Floating Point Examples ^^^^^^^^^^ .. code-block:: postgres @@ -290,10 +342,9 @@ Examples .. note:: Most SQL clients control display precision of floating point numbers, and values may appear differently in some clients. -Casts and conversions +Floating Point Casts and Conversions ^^^^^^^^^^^^^^^^^^^^^^^ - -Floating point values can be converted to: +The following table shows the possible Floating Point value conversions: .. list-table:: :widths: auto @@ -310,7 +361,7 @@ Floating point values can be converted to: .. note:: As shown in the above examples, when casting ``real`` to ``int``, we round down. -String types (``TEXT``, ``VARCHAR``) +String (``TEXT``, ``VARCHAR``) ------------------------------------------------ ``TEXT`` and ``VARCHAR`` are types designed for storing text or strings of characters. @@ -318,15 +369,17 @@ SQream DB separates ASCII (``VARCHAR``) and UTF-8 representations (``TEXT``). .. note:: The data type ``NVARCHAR`` has been deprecated by ``TEXT`` as of version 2020.1. -String types +String Types ^^^^^^^^^^^^^^^^^^^^^^ -.. list-table:: String types +The following table describes the String types. + +.. list-table:: :widths: auto :header-rows: 1 * - Name - Details - - Data size (not null, uncompressed) + - Data Size (Not Null, Uncompressed) - Example * - ``TEXT [(n)]``, ``NVARCHAR (n)`` - Varaiable length string - UTF-8 unicode. ``NVARCHAR`` is synonymous with ``TEXT``. @@ -340,23 +393,23 @@ String types Length ^^^^^^^^^ -When using ``TEXT``, specifying a size is optional. If not specified, the text field carries no constraints. +When using ``TEXT``, specifying a size is optional. If not specified, the text field carries no constraints. To limit the size of the input, use ``VARCHAR(n)`` or ``TEXT(n)``, where ``n`` is the permitted number of characters. -To limit the size of the input, use ``VARCHAR(n)`` or ``TEXT(n)``, where n is the number of characters allowed. +The following apply to setting the String type length: * If the data exceeds the column length limit on ``INSERT`` or ``COPY`` operations, SQream DB will return an error. - * When casting or converting, the string has to fit in the target. For example, ``'Kiwis are weird birds' :: VARCHAR(5)`` will return an error. Use ``SUBSTRING`` to truncate the length of the string. - * ``VARCHAR`` strings are padded with spaces. Syntax ^^^^^^^^ String types can be written with standard SQL string literals, which are enclosed with single quotes, such as -``'Kiwi bird'``. To include a single quote in the string, repeat the quote twice: ``'Kiwi bird''s wings are tiny'``. +``'Kiwi bird'``. -String literals can also be dollar-quoted with the dollar sign ``$``. For example: ``$$Kiwi bird's wings are tiny$$`` is the same as ``'Kiwi bird''s wings are tiny'``. +To include a single quote in the string, use double quotations, such as ``'Kiwi bird''s wings are tiny'``. + +String literals can also be dollar-quoted with the dollar sign ``$``, such as ``$$Kiwi bird's wings are tiny$$`` is the same as ``'Kiwi bird''s wings are tiny'``. Size ^^^^^^ @@ -364,30 +417,32 @@ Size ``VARCHAR(n)`` can occupy up to *n* bytes, whereas ``TEXT(n)`` can occupy up to *4*n* bytes. However, the size of strings is variable and is compressed by SQream DB. -Examples +String Examples ^^^^^^^^^^ +The following is an example of the String syntax: .. code-block:: postgres - CREATE TABLE cool_strings (a VARCHAR(25) NOT NULL, b TEXT); + CREATE TABLE cool_strings (a TEXT NOT NULL, b TEXT); INSERT INTO cool_strings VALUES ('hello world', 'Hello to kiwi birds specifically'); INSERT INTO cool_strings VALUES ('This is ASCII only', 'But this column can contain 中文文字'); SELECT * FROM cool_strings; + +The following is an example of the correct output: .. code-block:: text hello world ,Hello to kiwi birds specifically This is ASCII only,But this column can contain 中文文字 -.. note:: Most clients control display precision of floating point numbers, and values may appear differently in some clients. +.. note:: Most clients control the display precision of floating point numbers, and values may appear differently in some clients. -Casts and conversions +String Casts and Conversions ^^^^^^^^^^^^^^^^^^^^^^^ - -String values can be converted to: +The following table shows the possible String value conversions: .. list-table:: :widths: auto @@ -406,23 +461,24 @@ String values can be converted to: -Date types (``DATE``, ``DATETIME``) +Date (``DATE``, ``DATETIME``) ------------------------------------------------ - ``DATE`` is a type designed for storing year, month, and day. ``DATETIME`` is a type designed for storing year, month, day, hour, minute, seconds, and milliseconds in UTC with 1 millisecond precision. -Date types +Date Types ^^^^^^^^^^^^^^^^^^^^^^ +The following table describes the Date types. + .. list-table:: Date types :widths: auto :header-rows: 1 * - Name - Details - - Data size (not null, uncompressed) + - Data Size (Not Null, Uncompressed) - Example * - ``DATE`` - Date @@ -446,7 +502,7 @@ Syntax ``DATETIME`` values are formatted as string literals conforming to `ISO 8601 `_, for example ``'1955-11-05 01:26:00'``. -SQream DB will attempt to guess if the string literal is a date or datetime based on context, for example when used in date-specific functions. +SQream DB attempts to guess if the string literal is a date or datetime based on context, for example when used in date-specific functions. Size ^^^^^^ @@ -455,8 +511,9 @@ A ``DATE`` column is 4 bytes in length, while a ``DATETIME`` column is 8 bytes i However, the size of these values is compressed by SQream DB. -Examples +Date Examples ^^^^^^^^^^ +The following is an example of the Date syntax: .. code-block:: postgres @@ -465,14 +522,20 @@ Examples INSERT INTO important_dates VALUES ('1997-01-01', '1955-11-05 01:24'); SELECT * FROM important_dates; + +The following is an example of the correct output: .. code-block:: text 1997-01-01,1955-11-05 01:24:00.0 + +The following is an example of the Datetime syntax: .. code-block:: postgres SELECT a :: DATETIME, b :: DATE FROM important_dates; + +The following is an example of the correct output: .. code-block:: text @@ -481,10 +544,10 @@ Examples .. warning:: Some client applications may alter the ``DATETIME`` value by modifying the timezone. -Casts and conversions +Date Casts and Conversions ^^^^^^^^^^^^^^^^^^^^^^^ -``DATE`` and ``DATETIME`` values can be converted to: +The following table shows the possible ``DATE`` and ``DATETIME`` value conversions: .. list-table:: :widths: auto From 02211b416fe8a10b19fd8d1a794be1c5e6cfe1ef Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 26 Oct 2021 15:05:38 +0300 Subject: [PATCH 063/300] Update sql_data_types.rst Changed TO to AS on the following line: CAST( TO ), to convert a value from one type to another. For example, CAST('1997-01-01' TO DATE), CAST(3.45 TO SMALLINT), CAST(some_column TO VARCHAR(30)). --- reference/sql_data_types.rst | 260 ++++++++++++++++++++++------------- 1 file changed, 163 insertions(+), 97 deletions(-) diff --git a/reference/sql_data_types.rst b/reference/sql_data_types.rst index 0f3ed3f8e..63aaab9bf 100644 --- a/reference/sql_data_types.rst +++ b/reference/sql_data_types.rst @@ -10,16 +10,18 @@ This topic describes the data types that SQream DB supports, and how to convert :local: :depth: 2 -Supported types +Supported Types ================= -.. list-table:: Data types - :widths: auto +The following table shows the supported data types. + +.. list-table:: + :widths: 20 15 20 55 :header-rows: 1 * - Name - Description - - Data size (not null, uncompressed) + - Data Size (Not Null, Uncompressed) - Example * - ``BOOL`` - Boolean values (``true``, ``false``) @@ -53,6 +55,10 @@ Supported types - Variable length string - UTF-8 unicode - Up to ``4*n`` bytes - ``'キウイは楽しい鳥です'`` + * - ``NUMERIC``, ``DECIMAL`` + - 38 digits + - 16 bytes + - ``0.123245678901234567890123456789012345678`` * - ``VARCHAR (n)`` - Variable length string - ASCII only - ``n`` bytes @@ -70,58 +76,100 @@ Supported types .. _cast: -Converting and casting types +Converting and Casting Types ============================== SQream DB supports explicit and implicit casting and type conversion. -Implicit casts may be added automatically by the system when mixing different data types in the same expression. In many cases, the details of this are not important. However, these can affect the results of a query. When necessary, an explicit cast can be used to override the automatic cast added by SQream DB. +The system may automatically add implicit casts when combining different data types in the same expression. In many cases, while the details related to this are not important, they can affect the query results of a query. When necessary, an explicit cast can be used to override the automatic cast added by SQream DB. For example, the ANSI standard defines a ``SUM()`` aggregation over an ``INT`` column as an ``INT``. However, when dealing with large amounts of data this could cause an overflow. -To rectify this, cast the value to a larger data type: +You can rectify this by casting the value to a larger data type: .. code-block:: postgres SUM(some_int_column :: BIGINT) -SQream DB supports three types of data conversion: +SQream DB supports the following three data conversion types: -* ``CAST( TO )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO VARCHAR(30))``. +* ``CAST( AS )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' AS DATE)``, ``CAST(3.45 AS SMALLINT)``, ``CAST(some_column AS VARCHAR(30))``. * `` :: ``, a shorthand for the ``CAST`` syntax. For example, ``'1997-01-01' :: DATE``, ``3.45 :: SMALLINT``, ``(3+5) :: BIGINT``. * See the :ref:`SQL functions reference ` for additional functions that convert from a specific value which is not an SQL type, such as :ref:`from_unixts`, etc. -More details about the supported casts for each type in the following section. +The **Data Type Reference** section below provides more details about the supported casts for each type. -Data type reference +Data Type Reference ====================== +.. _numeric: -Boolean (``BOOL``) -------------------- -A ``BOOL`` datatype is designed to store Boolean values of ``true`` or ``false``. +Numeric (``NUMERIC``, ``DECIMAL``) +----------------------- +The **Numeric** data type (also known as **Decimal**) is recommended for values that tend to occur as exact decimals, such as in Finance. While Numeric has a fixed precision of ``38``, higher than ``REAL`` (``9``) or ``DOUBLE`` (``17``), it runs calculations more slowly. For operations that require faster performance, using :ref:`Floating Point ` is recommended. -Syntax -^^^^^^^^ +The correct syntax for Numeric is ``numeric(p, s)``), where ``p`` is the total number of digits (``38`` maximum), and ``s`` is the total number of decimal digits. -A ``BOOL`` type can accept either ``true`` or ``false`` (case insensitive). +Numeric Examples +^^^^^^^^^^ -When loading from CSV, ``BOOL`` columns can accept ``0`` as ``false`` and ``1`` as ``true``. +The following is an example of the Numeric syntax: -Size -^^^^^^ +.. code-block:: postgres + + $ create or replace table t(x numeric(20, 10), y numeric(38, 38)); + $ insert into t values(1234567890.1234567890, 0.123245678901234567890123456789012345678); + $ select x + y from t; + +The following table shows information relevant to the Numeric data type: -A ``BOOL`` type is 1 byte, but resulting average data sizes could be lower after compression. +.. list-table:: + :widths: 30 30 30 + :header-rows: 1 + + * - Description + - Data Size (Not Null, Uncompressed) + - Example + * - 38 digits + - 16 bytes + - ``0.123245678901234567890123456789012345678`` + +Numeric supports the following operations: + + * All join types. + * All aggregation types (not including Window functions). + * Scalar functions (not including some trigonometric and logarithmic functions). + + + +Boolean (``BOOL``) +------------------- +The following table describes the Boolean data type. -Examples +.. list-table:: + :widths: 30 30 30 + :header-rows: 1 + + * - Values + - Syntax + - Data Size (Not Null, Uncompressed) + * - ``true``, ``false`` (case sensitive) + - When loading from CSV, ``BOOL`` columns can accept ``0`` as ``false`` and ``1`` as ``true``. + - 1 byte, but resulting average data sizes may be lower after compression. + +Boolean Examples ^^^^^^^^^^ +The following is an example of the Boolean syntax: + .. code-block:: postgres - CREATE TABLE animals (name VARCHAR(15), is_angry BOOL); + CREATE TABLE animals (name TEXT, is_angry BOOL); INSERT INTO animals VALUES ('fox',true), ('cat',true), ('kiwi',false); SELECT name, CASE WHEN is_angry THEN 'Is really angry!' else 'Is not angry' END FROM animals; + +The following is an example of the correct output: .. code-block:: text @@ -129,10 +177,10 @@ Examples "cat","Is really angry!" "kiwi","Is not angry" -Casts and conversions +Boolean Casts and Conversions ^^^^^^^^^^^^^^^^^^^^^^^ -A ``BOOL`` value can be converted to: +The following table shows the possible Boolean value conversions: .. list-table:: :widths: auto @@ -155,19 +203,21 @@ A ``BOOL`` value can be converted to: Integers (``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``) ------------------------------------------------------------ -Integer datatypes are designed to store whole numbers. +Integer data types are designed to store whole numbers. -For information about identity sequences (sometimes called auto-increment or auto-numbers), see :ref:`identity`. +For more information about identity sequences (sometimes called auto-increment or auto-numbers), see :ref:`identity`. -Integer types +Integer Types ^^^^^^^^^^^^^^^^^^^ -.. list-table:: Integer types +The following table describes the Integer types. + +.. list-table:: :widths: auto :header-rows: 1 * - Name - Details - - Data size (not null, uncompressed) + - Data Size (Not Null, Uncompressed) - Example * - ``TINYINT`` - Unsigned integer (0 - 255) @@ -184,20 +234,22 @@ Integer types * - ``BIGINT`` - Integer (-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807) - 8 bytes - - ``36124441255243`` - -Syntax -^^^^^^^^ - -An integer can be entered as a regular literal, such as ``12``, ``-365``. - -Size -^^^^^^ - -Integer types range between 1, 2, 4, and 8 bytes - but resulting average data sizes could be lower after compression. + - ``36124441255243`` + +The following table describes the Integer data type. + +.. list-table:: + :widths: 25 25 + :header-rows: 1 + + * - Syntax + - Data Size (Not Null, Uncompressed) + * - An integer can be entered as a regular literal, such as ``12``, ``-365``. + - Integer types range between 1, 2, 4, and 8 bytes - but resulting average data sizes could be lower after compression. -Examples +Integer Examples ^^^^^^^^^^ +The following is an example of the Integer syntax: .. code-block:: postgres @@ -206,16 +258,18 @@ Examples INSERT INTO cool_numbers VALUES (1,2,3,4), (-5, 127, 32000, 45000000000); SELECT * FROM cool_numbers; + +The following is an example of the correct output: .. code-block:: text 1,2,3,4 -5,127,32000,45000000000 -Casts and conversions +Integer Casts and Conversions ^^^^^^^^^^^^^^^^^^^^^^^ -Integer values can be converted to: +The following table shows the possible Integer value conversions: .. list-table:: :widths: auto @@ -227,23 +281,26 @@ Integer values can be converted to: - ``1`` → ``1.0``, ``-32`` → ``-32.0`` * - ``VARCHAR(n)`` (All numberic values must fit in the string length) - ``1`` → ``'1'``, ``2451`` → ``'2451'`` + +.. _floating_point: - -Floating point (``REAL``, ``DOUBLE``) ------------------------------------------------- -``REAL`` and ``DOUBLE`` are inexact floating point data types, designed to store up to 9 or 17 digits of precision respectively. +Floating Point (``REAL``, ``DOUBLE``) +------------------------------------------------ +The **Floating Point** data types (``REAL`` and ``DOUBLE``) store extremely close value approximations, and are therefore recommended for values that tend to be inexact, such as Scientific Notation. While Floating Point generally runs faster than Numeric, it has a lower precision of ``9`` (``REAL``) or ``17`` (``DOUBLE``) compared to Numeric's ``38``. For operations that require a higher level of precision, using :ref:`Numeric ` is recommended. The floating point representation is based on `IEEE 754 `_. -Floating point types +Floating Point Types ^^^^^^^^^^^^^^^^^^^^^^ -.. list-table:: Floating point types +The following table describes the Floating Point data types. + +.. list-table:: :widths: auto :header-rows: 1 * - Name - Details - - Data size (not null, uncompressed) + - Data Size (Not Null, Uncompressed) - Example * - ``REAL`` - Single precision floating point (inexact) @@ -253,26 +310,21 @@ Floating point types - Double precision floating point (inexact) - 8 bytes - ``0.000003`` + +The following table shows information relevant to the Floating Point data types. -Aliases -^^^^^^^^^^ - -``DOUBLE`` is also known as ``FLOAT``. - - -Syntax -^^^^^^^^ - -A double precision floating point can be entered as a regular literal, such as ``3.14``, ``2.718``, ``.34``, ``2.71e-45``. - -To enter a ``REAL`` floating point number, cast the value. For example, ``(3.14 :: REAL)``. - -Size -^^^^^^ - -Floating point types are either 4 or 8 bytes, but size could be lower after compression. - -Examples +.. list-table:: + :widths: 30 30 30 + :header-rows: 1 + + * - Aliases + - Syntax + - Data Size (Not Null, Uncompressed) + * - ``DOUBLE`` is also known as ``FLOAT``. + - A double precision floating point can be entered as a regular literal, such as ``3.14``, ``2.718``, ``.34``, or ``2.71e-45``. To enter a ``REAL`` floating point number, cast the value. For example, ``(3.14 :: REAL)``. + - Floating point types are either 4 or 8 bytes, but size could be lower after compression. + +Floating Point Examples ^^^^^^^^^^ .. code-block:: postgres @@ -290,10 +342,9 @@ Examples .. note:: Most SQL clients control display precision of floating point numbers, and values may appear differently in some clients. -Casts and conversions +Floating Point Casts and Conversions ^^^^^^^^^^^^^^^^^^^^^^^ - -Floating point values can be converted to: +The following table shows the possible Floating Point value conversions: .. list-table:: :widths: auto @@ -304,12 +355,13 @@ Floating point values can be converted to: * - ``BOOL`` - ``1.0`` → ``true``, ``0.0`` → ``false`` * - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT`` - - ``2.0`` → ``2``, ``3.14159265358979`` → ``3``, ``2.718281828459`` → ``2`` + - ``2.0`` → ``2``, ``3.14159265358979`` → ``3``, ``2.718281828459`` → ``2``, ``0.5`` → ``0``, ``1.5`` → ``1`` * - ``VARCHAR(n)`` (n > 6 recommended) - ``1`` → ``'1.0000'``, ``3.14159265358979`` → ``'3.1416'`` +.. note:: As shown in the above examples, when casting ``real`` to ``int``, we round down. -String types (``TEXT``, ``VARCHAR``) +String (``TEXT``, ``VARCHAR``) ------------------------------------------------ ``TEXT`` and ``VARCHAR`` are types designed for storing text or strings of characters. @@ -317,15 +369,17 @@ SQream DB separates ASCII (``VARCHAR``) and UTF-8 representations (``TEXT``). .. note:: The data type ``NVARCHAR`` has been deprecated by ``TEXT`` as of version 2020.1. -String types +String Types ^^^^^^^^^^^^^^^^^^^^^^ -.. list-table:: String types +The following table describes the String types. + +.. list-table:: :widths: auto :header-rows: 1 * - Name - Details - - Data size (not null, uncompressed) + - Data Size (Not Null, Uncompressed) - Example * - ``TEXT [(n)]``, ``NVARCHAR (n)`` - Varaiable length string - UTF-8 unicode. ``NVARCHAR`` is synonymous with ``TEXT``. @@ -339,21 +393,23 @@ String types Length ^^^^^^^^^ -When using ``TEXT``, specifying a size is optional. If not specified, the text field carries no constraints. To limit the size of the input, use ``VARCHAR(n)`` or ``NVARCHAR(n)``, where n is the number of characters allowed. +When using ``TEXT``, specifying a size is optional. If not specified, the text field carries no constraints. To limit the size of the input, use ``VARCHAR(n)`` or ``TEXT(n)``, where ``n`` is the permitted number of characters. -* If the data exceeds the column length limit on ``INSERT`` or ``COPY`` operations, SQream DB will return an error. +The following apply to setting the String type length: +* If the data exceeds the column length limit on ``INSERT`` or ``COPY`` operations, SQream DB will return an error. * When casting or converting, the string has to fit in the target. For example, ``'Kiwis are weird birds' :: VARCHAR(5)`` will return an error. Use ``SUBSTRING`` to truncate the length of the string. - * ``VARCHAR`` strings are padded with spaces. Syntax ^^^^^^^^ String types can be written with standard SQL string literals, which are enclosed with single quotes, such as -``'Kiwi bird'``. To include a single quote in the string, repeat the quote twice: ``'Kiwi bird''s wings are tiny'``. +``'Kiwi bird'``. -String literals can also be dollar-quoted with the dollar sign ``$``. For example: ``$$Kiwi bird's wings are tiny$$`` is the same as ``'Kiwi bird''s wings are tiny'``. +To include a single quote in the string, use double quotations, such as ``'Kiwi bird''s wings are tiny'``. + +String literals can also be dollar-quoted with the dollar sign ``$``, such as ``$$Kiwi bird's wings are tiny$$`` is the same as ``'Kiwi bird''s wings are tiny'``. Size ^^^^^^ @@ -361,30 +417,32 @@ Size ``VARCHAR(n)`` can occupy up to *n* bytes, whereas ``TEXT(n)`` can occupy up to *4*n* bytes. However, the size of strings is variable and is compressed by SQream DB. -Examples +String Examples ^^^^^^^^^^ +The following is an example of the String syntax: .. code-block:: postgres - CREATE TABLE cool_strings (a VARCHAR(25) NOT NULL, b TEXT); + CREATE TABLE cool_strings (a TEXT NOT NULL, b TEXT); INSERT INTO cool_strings VALUES ('hello world', 'Hello to kiwi birds specifically'); INSERT INTO cool_strings VALUES ('This is ASCII only', 'But this column can contain 中文文字'); SELECT * FROM cool_strings; + +The following is an example of the correct output: .. code-block:: text hello world ,Hello to kiwi birds specifically This is ASCII only,But this column can contain 中文文字 -.. note:: Most clients control display precision of floating point numbers, and values may appear differently in some clients. +.. note:: Most clients control the display precision of floating point numbers, and values may appear differently in some clients. -Casts and conversions +String Casts and Conversions ^^^^^^^^^^^^^^^^^^^^^^^ - -String values can be converted to: +The following table shows the possible String value conversions: .. list-table:: :widths: auto @@ -403,23 +461,24 @@ String values can be converted to: -Date types (``DATE``, ``DATETIME``) +Date (``DATE``, ``DATETIME``) ------------------------------------------------ - ``DATE`` is a type designed for storing year, month, and day. ``DATETIME`` is a type designed for storing year, month, day, hour, minute, seconds, and milliseconds in UTC with 1 millisecond precision. -Date types +Date Types ^^^^^^^^^^^^^^^^^^^^^^ +The following table describes the Date types. + .. list-table:: Date types :widths: auto :header-rows: 1 * - Name - Details - - Data size (not null, uncompressed) + - Data Size (Not Null, Uncompressed) - Example * - ``DATE`` - Date @@ -443,7 +502,7 @@ Syntax ``DATETIME`` values are formatted as string literals conforming to `ISO 8601 `_, for example ``'1955-11-05 01:26:00'``. -SQream DB will attempt to guess if the string literal is a date or datetime based on context, for example when used in date-specific functions. +SQream DB attempts to guess if the string literal is a date or datetime based on context, for example when used in date-specific functions. Size ^^^^^^ @@ -452,8 +511,9 @@ A ``DATE`` column is 4 bytes in length, while a ``DATETIME`` column is 8 bytes i However, the size of these values is compressed by SQream DB. -Examples +Date Examples ^^^^^^^^^^ +The following is an example of the Date syntax: .. code-block:: postgres @@ -462,14 +522,20 @@ Examples INSERT INTO important_dates VALUES ('1997-01-01', '1955-11-05 01:24'); SELECT * FROM important_dates; + +The following is an example of the correct output: .. code-block:: text 1997-01-01,1955-11-05 01:24:00.0 + +The following is an example of the Datetime syntax: .. code-block:: postgres SELECT a :: DATETIME, b :: DATE FROM important_dates; + +The following is an example of the correct output: .. code-block:: text @@ -478,10 +544,10 @@ Examples .. warning:: Some client applications may alter the ``DATETIME`` value by modifying the timezone. -Casts and conversions +Date Casts and Conversions ^^^^^^^^^^^^^^^^^^^^^^^ -``DATE`` and ``DATETIME`` values can be converted to: +The following table shows the possible ``DATE`` and ``DATETIME`` value conversions: .. list-table:: :widths: auto From d18374a0cfa9c64410ef6baed5ee31e1d7f29fba Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 28 Oct 2021 17:04:36 +0300 Subject: [PATCH 064/300] Update requirements.txt Testing build file succeeded with 2021.2. Added this text to permit building file. Tested a modification on the Glossary page. --- requirements.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 609b0b4b1..806fe2730 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,7 @@ +# File: docs/requirements.txt + +# Defining the exact version will make sure things don't break +sphinx==3.5.3 +sphinx_rtd_theme==0.5.2 sphinx-notfound-page -Pygments>=2.4.0 \ No newline at end of file +Pygments>=2.4.0 From bab0924718e0299af06195110d33666feaebfd35 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 28 Oct 2021 17:09:17 +0300 Subject: [PATCH 065/300] Update glossary.rst Testing build file succeeded with 2021.2. Added this text to permit building file. Tested a modification on the Glossary page. --- glossary.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glossary.rst b/glossary.rst index 5a4ee4cb1..660f10252 100644 --- a/glossary.rst +++ b/glossary.rst @@ -33,7 +33,7 @@ Glossary The storage cluster is the directory in which SQream DB stores data, including database objects, metadata database, and logs. UDF - User-defined function + User-Defined Function A feature that extends SQream DB's built in SQL functionality with user-written Python code. - \ No newline at end of file + From e5909ec0abd77ad74da5d21bad6ec76eeee33d02 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 28 Oct 2021 17:16:35 +0300 Subject: [PATCH 066/300] Update glossary.rst Corrected text. Display issue. --- glossary.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/glossary.rst b/glossary.rst index 660f10252..5b434f584 100644 --- a/glossary.rst +++ b/glossary.rst @@ -33,7 +33,5 @@ Glossary The storage cluster is the directory in which SQream DB stores data, including database objects, metadata database, and logs. UDF - User-Defined Function + User-defined function A feature that extends SQream DB's built in SQL functionality with user-written Python code. - - From 52b7e05d1506c9d5b114a8a9b024626c6126af3d Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 28 Oct 2021 17:20:43 +0300 Subject: [PATCH 067/300] Update glossary.rst Changed. --- glossary.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/glossary.rst b/glossary.rst index 5b434f584..660f10252 100644 --- a/glossary.rst +++ b/glossary.rst @@ -33,5 +33,7 @@ Glossary The storage cluster is the directory in which SQream DB stores data, including database objects, metadata database, and logs. UDF - User-defined function + User-Defined Function A feature that extends SQream DB's built in SQL functionality with user-written Python code. + + From 2277c190b91f26a82634b1e73524255a6a6d006c Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 28 Oct 2021 17:26:16 +0300 Subject: [PATCH 068/300] Update requirements.txt Tried again. From 2b4d76b72bc63cff413b10dff446e178adc34716 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 31 Oct 2021 09:02:40 +0200 Subject: [PATCH 069/300] Update glossary.rst Updated page to see if builds correctly. --- glossary.rst | 55 ++++++++++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/glossary.rst b/glossary.rst index 660f10252..c985a48a5 100644 --- a/glossary.rst +++ b/glossary.rst @@ -5,35 +5,26 @@ Glossary .. glossary:: - Cluster - A SQream DB deployment containing several :term:`workers` running on one or more :term:`nodes`. - - Node - A machine running SQream DB :term:`workers`. - - Worker - A SQream DB application that can respond to statements. Several workers can run on one or more :term:`nodes` to form a cluster. - - Metadata - SQream DB's internal storage which contains details about database objects. - - Authentication - Authentication is the process that identifies a user or :term:`role` to verify an identity - to make sure the user is who they say they are. This is done with a username and password. - - Authorization - Authorization defines the set of actions that an authenticaed :term:`role` can perform after gaining access to the system, protecting from threats that :term:`authentication` controls alone are not enough against. - - Role - A role is a group or a user, depending on the permissions granted. A role groups together a set of permissions. - - Catalog - A set of views that contains information (metadata) about the objects in a database (e.g. tables, columns, chunks, etc...). - - Storage cluster - The storage cluster is the directory in which SQream DB stores data, including database objects, metadata database, and logs. - - UDF - User-Defined Function - A feature that extends SQream DB's built in SQL functionality with user-written Python code. - - ++-----------------------+----------------------------------------------------------------------------------------------------------------+ +| **Term** | **Description** | ++=======================+================================================================================================================+ +| Authentication | The process of verifying identity by validating a user or role identity using a username and password. | ++-----------------------+----------------------------------------------------------------------------------------------------------------+ +| Authorization | Defines the set of actions that an authenticaed role can perform after gaining access to the system. | ++-----------------------+----------------------------------------------------------------------------------------------------------------+ +| Catalog | A set of views containing metadata information about objects in a database. | ++-----------------------+----------------------------------------------------------------------------------------------------------------+ +| Cluster | A SQream deployment containing several workers running on one or more nodes. | ++-----------------------+----------------------------------------------------------------------------------------------------------------+ +| Metadata | SQream’s internal storage containing details about database objects. | ++-----------------------+----------------------------------------------------------------------------------------------------------------+ +| Node | A machine used to run SQream workers. | ++-----------------------+----------------------------------------------------------------------------------------------------------------+ +| Role | A group or a user. For more information see SQream Studio. | ++-----------------------+----------------------------------------------------------------------------------------------------------------+ +| Storage cluster | The directory where SQream stores data. | ++-----------------------+----------------------------------------------------------------------------------------------------------------+ +| User-Defined Function | A feature that extends SQream's built-in SQL functionality with user-written Python code. | ++-----------------------+----------------------------------------------------------------------------------------------------------------+ +| Worker | A SQream application that responds to statements. Several workers running on one or more nodes form a cluster. | ++-----------------------+----------------------------------------------------------------------------------------------------------------+ From f1a65cb1c109bc5634b6d14732332eabb9e88aaa Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 31 Oct 2021 09:13:23 +0200 Subject: [PATCH 070/300] Update glossary.rst Fixed table. --- glossary.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/glossary.rst b/glossary.rst index c985a48a5..edcd36a5e 100644 --- a/glossary.rst +++ b/glossary.rst @@ -5,6 +5,8 @@ Glossary .. glossary:: +The following table shows a glossary of commonly-used terms: + +-----------------------+----------------------------------------------------------------------------------------------------------------+ | **Term** | **Description** | +=======================+================================================================================================================+ @@ -16,7 +18,7 @@ Glossary +-----------------------+----------------------------------------------------------------------------------------------------------------+ | Cluster | A SQream deployment containing several workers running on one or more nodes. | +-----------------------+----------------------------------------------------------------------------------------------------------------+ -| Metadata | SQream’s internal storage containing details about database objects. | +| Metadata | SQream's internal storage containing details about database objects. | +-----------------------+----------------------------------------------------------------------------------------------------------------+ | Node | A machine used to run SQream workers. | +-----------------------+----------------------------------------------------------------------------------------------------------------+ From 55e076a03de9d8b69bf67f7cfb76534e824ce9ea Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 31 Oct 2021 11:03:09 +0200 Subject: [PATCH 071/300] Update requirements.txt Added this text to permit building file. Tested a modification on the Glossary page. --- requirements.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index af763a23e..806fe2730 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,7 @@ -sphinx-notfound-page \ No newline at end of file +# File: docs/requirements.txt + +# Defining the exact version will make sure things don't break +sphinx==3.5.3 +sphinx_rtd_theme==0.5.2 +sphinx-notfound-page +Pygments>=2.4.0 From d27dd2eafbd1937dbb81a3c33ff5fc4aaf5969c2 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 31 Oct 2021 11:17:30 +0200 Subject: [PATCH 072/300] Update glossary.rst Updated page to see if builds correctly. --- glossary.rst | 59 ++++++++++++++++++++++------------------------------ 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/glossary.rst b/glossary.rst index 5a4ee4cb1..f4d40dcc6 100644 --- a/glossary.rst +++ b/glossary.rst @@ -3,37 +3,28 @@ Glossary ===================================== -.. glossary:: - - Cluster - A SQream DB deployment containing several :term:`workers` running on one or more :term:`nodes`. - - Node - A machine running SQream DB :term:`workers`. - - Worker - A SQream DB application that can respond to statements. Several workers can run on one or more :term:`nodes` to form a cluster. - - Metadata - SQream DB's internal storage which contains details about database objects. - - Authentication - Authentication is the process that identifies a user or :term:`role` to verify an identity - to make sure the user is who they say they are. This is done with a username and password. - - Authorization - Authorization defines the set of actions that an authenticaed :term:`role` can perform after gaining access to the system, protecting from threats that :term:`authentication` controls alone are not enough against. - - Role - A role is a group or a user, depending on the permissions granted. A role groups together a set of permissions. - - Catalog - A set of views that contains information (metadata) about the objects in a database (e.g. tables, columns, chunks, etc...). - - Storage cluster - The storage cluster is the directory in which SQream DB stores data, including database objects, metadata database, and logs. - - UDF - User-defined function - A feature that extends SQream DB's built in SQL functionality with user-written Python code. - - \ No newline at end of file +The following table shows a glossary of commonly-used terms: + ++---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| **Term** | **Description** | ++=================================+==============================================================================================================================================+ +| Authentication | The process of verifying identity by validating a user or role identity using a username and password. | ++---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| Authorization | Defines the set of actions that an authenticaed role can perform after gaining access to the system. | ++---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| Catalog | A set of views containing metadata information about objects in a database. | ++---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| Cluster | A SQream deployment containing several workers running on one or more nodes. | ++---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| Metadata | SQream's internal storage containing details about database objects. | ++---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| Node | A machine used to run SQream workers. | ++---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| Role | A group or a user. | ++---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| Storage cluster | The directory where SQream stores data. | ++---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| User-Defined Function | A feature that extends SQream's built-in SQL functionality with user-written Python code. | ++---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| Worker | A SQream application that responds to statements. Several workers running on one or more nodes form a cluster. | ++---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ From 348833a7dd8de2e01118cf0517601e84ad928355 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 31 Oct 2021 15:03:02 +0200 Subject: [PATCH 073/300] Updated documentation based on ticket Ticket: https://sqream.atlassian.net/browse/SQ-8735 - Tableau - error on saving data to files --- guides/client_drivers/jdbc/index.rst | 36 +++++++++++++++------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/guides/client_drivers/jdbc/index.rst b/guides/client_drivers/jdbc/index.rst index eceb1c155..4880c056e 100644 --- a/guides/client_drivers/jdbc/index.rst +++ b/guides/client_drivers/jdbc/index.rst @@ -12,7 +12,7 @@ The JDBC driver requires Java 1.8 or newer. .. contents:: In this topic: :local: -Installing the JDBC driver +Installing the JDBC Driver ================================== Prerequisites @@ -40,38 +40,38 @@ Getting the JAR file The JDBC driver is provided as a zipped JAR file, available for download from the :ref:`client drivers download page`. This JAR file can integrate into your Java-based applications or projects. -Extract the zip archive +Extract the ZIP Archive ------------------------- Extract the JAR file from the zip archive .. code-block:: console - $ unzip sqream-jdbc-3.0.0.zip + $ unzip sqream-jdbc-4.3.0.zip Setting up the Class Path ---------------------------- -To use the driver, the JAR named ``sqream-jdbc-.jar`` (for example, ``sqream-jdbc-3.0.0.jar``) needs to be included in the class path, either by putting it in the ``CLASSPATH`` environment variable, or by using flags on the relevant Java command line. +To use the driver, the JAR named ``sqream-jdbc-.jar`` (for example, ``sqream-jdbc-4.3.0.jar``) needs to be included in the class path, either by putting it in the ``CLASSPATH`` environment variable, or by using flags on the relevant Java command line. -For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-3.0.0.jar``, the application should be run as follows: +For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-4.3.0.jar``, the application should be run as follows: .. code-block:: console - $ export CLASSPATH=/home/sqream/sqream-jdbc-3.0.0.jar:$CLASSPATH + $ export CLASSPATH=/home/sqream/sqream-jdbc-4.3.0.jar:$CLASSPATH $ java my_java_app An alternative method is to pass ``-classpath`` to the Java executable: .. code-block:: console - $ java -classpath .:/home/sqream/sqream-jdbc-3.0.0.jar my_java_app + $ java -classpath .:/home/sqream/sqream-jdbc-4.3.0.jar my_java_app -Connect to SQream DB with a JDBC application +Connect to SQream DB with a JDBC Application ============================================== -Driver class +Driver Class -------------- Use ``com.sqream.jdbc.SQDriver`` as the driver class in the JDBC application. @@ -79,16 +79,19 @@ Use ``com.sqream.jdbc.SQDriver`` as the driver class in the JDBC application. .. _connection_string: -Connection string +Connection String -------------------- +JDBC drivers rely on a connection string. -JDBC drivers rely on a connection string. Use the following syntax for SQream DB +The following is the correct syntax for writing a connection string: .. code-block:: text jdbc:Sqream:///;user=;password=sqream;[; ...] + +An **FAB9A2C5** error can occur when saving large quantities of data as files. If you receive this error, see `Troubleshooting - Error Saving Large Quantities of Data as Files `_. -Connection parameters +Connection Parameters ^^^^^^^^^^^^^^^^^^^^^^^^ .. list-table:: @@ -125,10 +128,10 @@ Connection parameters - Specifies SSL for this connection. For example, ``ssl=true`` * - ```` - ✓ - - ``false`` - - Connect via load balancer (use only if exists, and check port). For example, ``cluster=true`` + - ``true`` + - Connect via load balancer (use only if exists, and check port). -Connection string examples +Connection String Examples ^^^^^^^^^^^^^^^^^^^^^^^^^^^ For a SQream DB cluster with load balancer and no service queues, with SSL @@ -150,7 +153,7 @@ For a SQream DB cluster with load balancer and a specific service queue named `` jdbc:Sqream://sqream.mynetwork.co:3108/raviga;user=rhendricks;password=Tr0ub4dor&3;cluster=true;service=etl -Sample Java program +Sample Java Program -------------------- Download this file by right clicking and saving to your computer :download:`sample.java `. @@ -159,4 +162,3 @@ Download this file by right clicking and saving to your computer :download:`samp :language: java :caption: JDBC application sample :linenos: - From a4704b1ad2a638d556d87418b7ba8a400c43115a Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 31 Oct 2021 15:07:22 +0200 Subject: [PATCH 074/300] Updated documentation based on ticket Ticket: https://sqream.atlassian.net/browse/SQ-8735 - Tableau - error on saving data to files --- guides/third_party_tools/tableau.rst | 508 ++++++++++++++++++--------- 1 file changed, 350 insertions(+), 158 deletions(-) diff --git a/guides/third_party_tools/tableau.rst b/guides/third_party_tools/tableau.rst index c185073d3..5d3a6c5e6 100644 --- a/guides/third_party_tools/tableau.rst +++ b/guides/third_party_tools/tableau.rst @@ -1,271 +1,463 @@ .. _connect_to_tableau: ************************* -Connecting to Tableau +Connecting to SQream Using Tableau ************************* -You can use Tableau to connect to a SQream DB cluster. This tutorial is a guide that will show you how to connect to Tableau, as well as provide some guidelines and best practices for exploring data with Tableau and SQream DB. +Overview +===================== +SQream's Tableau connector plugin, based on standard JDBC, enables storing and fast querying large volumes of data. -SQream DB supports both Tableau Desktop and Tableau Server on Windows, MacOS, and Linux distributions. +The **Connecting to SQream Using Tableau** page is a Quick Start Guide that describes how install Tableau and the JDBC and ODBC drivers and connect to SQream using the JDBC and ODBC drivers for data analysis. It also describes using best practices and troubleshoot issues that may occur while installing Tableau. SQream supports both Tableau Desktop and Tableau Server on Windows, MacOS, and Linux distributions. -.. contents:: In this topic: - :local: +For more information on SQream's integration with Tableau, see `Tableau's Extension Gallery `_. -Installing Tableau Desktop -============================ +The Connecting to SQream Using Tableau page describes the following: -SQream DB has been tested with versions 9.2 and newer. -If you do not already have Tableau Desktop installed, download and install Tabelau Desktop. https://www.tableau.com/products/trial +.. contents:: + :local: -Tableau offers a time-limited trial version. +Installing the JDBC Driver and Tableau Connector Plugin +------------------- +This section describes how to install the JDBC driver using the fully-integrated Tableau connector plugin (Tableau Connector, or **.taco** file). SQream has been tested with Tableau versions 9.2 and newer. -Installing the JDBC driver and connector -================================================= +**To connect to SQream using Tableau:** + +#. Install the Tableau Desktop application. -Starting from Tableau v2019.4, SQream DB recommends using the JDBC driver instead of the previously recommended ODBC driver. + For more information about installing the Tableau Desktop application, see the `Tableau products page `_ and click **Download Free Trial**. Note that Tableau offers a 14-day trial version. + + :: -If you have Tableau Desktop on Windows, we recommend using the :ref:`JDBC installer method`. +#. Do one of the following: -If you have Tableau Server or Tableau on MacOS and Linux follow the instructions for a :ref:`manual installation`. + * **For Windows** - See :ref:`Installing Tableau Using the Windows Installer `. + * **For MacOS or Linux** - See :ref:`Installing the JDBC Driver Manually `. -.. _tableau_jdbc_installer: +.. note:: For Tableau **2019.4 versions and later**, SQream recommends installing the JDBC driver instead of the previously recommended ODBC driver. -Installing with the Windows installer ------------------------------------------ +.. _tableau_windows_installer: -1. Close Tableau Desktop +Installing the JDBC Driver Using the Windows Installer +~~~~~~~~~~~~~~~~~~ +If you are using Windows, after installing the Tableau Desktop application you can install the JDBC driver using the Windows installer. The Windows installer is an installation wizard that guides you through the JDBC driver installation steps. When the driver is installed, you can connect to SQream. -2. Download the JDBC installer :ref:`from the client drivers page`. +**To install Tableau using the Windows installer**: -3. - Start the installer, and ensure that the "**Tableau Desktop Connector**" item is selected, as in the image below. - - .. image:: /_static/images/jdbc_windows_installer_screen.png +#. Close Tableau Desktop. -4. Restart Tableau Desktop, continue to :ref:`connecting to SQream DB`. + :: -.. _tableau_manual_installation: +#. Download the most current version of the `SQream JDBC driver `_. -Installing the JDBC driver manually (MacOS, Linux, Tableau Server) ------------------------------------------------------------------------ + :: + +#. Do the following: -Download the JDBC and Tableau Connector (taco) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + #. Start the installer. + #. Verify that the **Tableau Desktop connector** item is selected. + #. Follow the installation steps. -1. Download the JDBC installer :ref:`from the client drivers page`. + :: -2. Download the SQream DB Tableau connector (.taco) :ref:`from the client drivers page`. +You can now restart Tableau Desktop or Server to begin using the SQream driver by :ref:`connecting to SQream `. -Install JDBC driver -^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. _tableau_jdbc_installer: -Unzip the JDBC driver into a Tableau drivers directory. Based on your installation of Tableau, this may be at: +Installing the JDBC Driver Manually +~~~~~~~~~~~~~ +If you are using MacOS, Linux, or the Tableau server, after installing the Tableau Desktop application you can install the JDBC driver manually. When the driver is installed, you can connect to SQream. -* Tableau Desktop on Windows: ``c:\Program Files\Tableau\Drivers`` +**To install the JDBC driver manually:** -* Tableau Desktop on MacOS: ``~/Library/Tableau/Drivers`` +1. Download the JDBC installer and SQream Tableau connector (.taco) file from the :ref:`from the client drivers page`. -* Tableau on Linux: ``/opt/tableau/tableau_driver/jdbc`` + :: -Install taco -^^^^^^^^^^^^^^^^^^ +#. Install the JDBC driver by unzipping the JDBC driver into a Tableau driver directory. + + Based on the installation method that you used, your Tableau driver directory is located in one of the following places: -Place the ``SQreamDB.taco`` file in the Tableau connectors directory. Based on your installation of Tableau, this may be at: + * **Tableau Desktop on Windows:** *C:\\Program Files\\Tableau\\Drivers* + * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* + * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* + +.. note:: If the driver includes only a single .jar file, copy it to *C:\\Program Files\\Tableau/Drivers*. If the driver includes multiple files, create a subfolder *A* in *C:\\Program Files\\Tableau/Drivers* and copy all files to folder *A*. -* Tableau Desktop on Windows: ``C:\Users\\My Tableau Repository\Connectors`` +Note the following when installing the JDBC driver: -* Tableau Desktop on MacOS: ``~/My Tableau Repository/Connectors`` +* You must have read permissions on the .jar file. +* Tableau requires a JDBC 4.0 or later driver. +* Tableau requires a Type 4 JDBC driver. +* The latest 64-bit version of Java 8 is installed. -* Tableau Server: +3. Install the **SQreamDB.taco** file by moving the SQreamDB.taco file into the Tableau connectors directory. - 1. Create a directory for Tableau connectors. For example: ``C:\tableau_connectors`` + Based on the installation method that you used, your Tableau driver directory is located in one of the following places: + + * **Tableau Desktop on Windows:** *C:\\Users\\\\My Tableau Repository\\Connectors* + * **Tableau Desktop on Windows:** *~/My Tableau Repository/Connectors* - 2. Copy the ``SQreamDB.taco`` file into the directory you created + :: + +4. *Optional* - If you are using the Tableau Server, do the following: - 3. Set the ``native_api.connect_plugins_path`` option with ``tsm``. For example: + 1. Create a directory for Tableau connectors and give it a descriptive name, such as *C:\\tableau_connectors*. - ``tsm configuration set -k native_api.connect_plugins_path -v C:/tableau_connectors`` + This directory needs to exist on all Tableau servers. - Then, apply the pending configuration changes with ``tsm pending-changes apply`` + :: + + 2. Copy the SQreamDB.taco file into the new directory. + + :: + + 3. Set the **native_api.connect_plugins_path** option to ``tsm`` as shown in the following example: + + .. code-block:: console + + $ tsm configuration set -k native_api.connect_plugins_path -v C:/tableau_connectors + + If a configuration error is displayed, add ``--force-keys`` to the end of the command as shown in the following example: + + .. code-block:: console + + $ tsm configuration set -k native_api.connect_plugins_path -v C:/tableau_connectors--force-keys + + 4. To apply the pending configuration changes, run the following command: + + .. code-block:: console + + $ tsm pending-changes apply .. warning:: This restarts the server. - +You can now restart Tableau Desktop or Server to begin using the SQream driver by :ref:`connecting to SQream ` as described in the section below. + +.. _tableau_connect_to_sqream: + -You can now restart Tableau Desktop or Server to begin using the SQream DB driver. Continue to :ref:`connecting to SQream DB`. +Installing the ODBC Driver for Tableau Versions 2019.3 and Earlier +-------------- -Legacy method - ODBC for Tableau versions before v2019.3 -================================================================== -Installing the ODBC driver and customizations --------------------------------------------------- +This section describes the installation method for Tableau version 2019.3 or earlier and describes the following: -If you've already installed the SQream DB ODBC driver, we recommend that you :ref:`re-run the ODBC driver installer ` after installing Tableau, and select the Tableau customizations checkbox, as in the image below: +.. contents:: + :local: + +.. note:: SQream recommends installing the JDBC driver to provide improved connectivity. + +Automatically Reconfiguring the ODBC Driver After Initial Installation +~~~~~~~~~~~~~~~~~~ +If you've already installed the SQream ODBC driver and installed Tableau, SQream recommends reinstalling the ODBC driver with the **.TDC Tableau Settings for SQream DB** configuration shown in the image below: .. image:: /_static/images/odbc_windows_installer_tableau.png -This is necessary because by default, Tableau has a tendency to create temporary tables and run lots of discovery queries which could impact performance. -The ODBC driver installer installs customizations for Tableau automatically. +SQream recommends this configuration because Tableau creates temporary tables and runs several discovery queries that may impact performance. The ODBC driver installer avoids this by automatically reconfiguring Tableau. + +For more information about reinstalling the ODBC driver installer, see :ref:`Install and Configure ODBC on Windows `. -If you want to perform this step manually, follow the instructions in the next section. +If you want to manually reconfigure the ODBC driver, see :ref:`Manually Reconfiguring the ODBC Driver After Initial Installation ` below. -The TDC file -^^^^^^^^^^^^^^^^^^^ +.. _manually_reconfigure_odbc_driver: -The TDC file (Tableau Datasource Customization) helps Tableau make full use of SQream DB's features and capabilities. +Manually Reconfiguring the ODBC Driver After Initial Installation +~~~~~~~~~~~~~~~~~~ +The file **Tableau Datasource Customization (TDC)** file lets you use Tableau make full use of SQream DB's features and capabilities. -Before you start, check which version of Tableau is used. The version needs to be placed in the TDC file. +**To manually reconfigure the ODBC driver after initial installation:** -#. Download the TDC file to your computer :download:`odbc-sqream.tdc `. +1. Do one of the following: + + 1. Download the :download:`odbc-sqream.tdc ` file to your machine and open it in a text editor. + + :: - Alternatively, copy the text below to a text editor. + 2. Copy the text below into a text editor: .. literalinclude:: odbc-sqream.tdc :language: xml - :caption: SQream DB ODBC TDC + :caption: SQream ODBC TDC File :emphasize-lines: 2 +#. Check which version of Tableau you are using. -#. Change the highlighted line to match your major Tableau version. For example, if you're on Tableau ``2019.2.1``, writing ``2019.2`` is enough. + :: -#. - * For **Tableau Desktop** - save the TDC file to ``C:\Users\\Documents\My Tableau Repository\Datasources``, where ```` is the Windows username Tableau is installed in. - - * For **Tableau Server** - save the TDC file to ``C:\ProgramData\Tableau\Tableau Server\data\tabsvc\vizqlserver\Datasources``. +#. In the text of the file shown above, in the highlighted line, replace the version number with the **major** version of Tableau that you are using. + + For example, if you are using Tableau vesion **2019.2.1**, replace it with **2019.2**. -Configure the ODBC connection (DSN) ------------------------------------------- + :: + +#. Do one of the following: + + * If you are using **Tableau Desktop** - save the TDC file to *C:\\Users\\\\Documents\\My Tableau Repository\\Datasources*, where ```` is the Windows username that you have installed Tableau under. + + :: + + * If you are using the **Tableau Server** - save the TDC file to *C:\\ProgramData\\Tableau\\Tableau Server\\data\\tabsvc\\vizqlserver\\Datasources*. -Create an ODBC DSN before connecting Tableau with SQream DB. See the section titled :ref:`create_windows_odbc_dsn` for information about creating an ODBC DSN in Windows. +Configuring the ODBC Connection +~~~~~~~~~~~~ +The ODBC connection uses a DSN when connecting to ODBC data sources, and each DSN represents one SQream database. -Remember to test the connectivity before saving the DSN. +**To configure the ODBC connection:** -Connecting Tableau to SQream DB ---------------------------------------- +1. Create an ODBC DSN. -#. Start Tableau Desktop and select "Other Database (ODBC)", by navigating :menuselection:`Connect --> To a server --> More --> Other Database (ODBC)` + :: + +#. Open the Windows menu by pressing the Windows button (:kbd:`⊞ Win`) or clicking the **Windows** menu button. + + :: + +#. Type **ODBC** and select **ODBC Data Sources (64-bit)**. + + During installation, the installer created a sample user DSN named **SQreamDB**. - .. image:: /_static/images/tableau_more_servers.png + :: -#. In the DSN selection window, select the DSN that you created earlier and select :menuselection:`Connect --> OK`. +#. *Optional* - Do one or both of the following: + + * Modify the DSN name. - If prompted by Tableau, you may need to specify the user name and password again after clicking Connect. + :: + + * Create a new DSN name by clicking **Add** and selecting **SQream ODBC Driver**. - .. image:: /_static/images/tableau_choose_dsn_and_connect.png +.. image:: /_static/images/odbc_windows_dsns.png + +5. Click **Finish**. -.. _tableau_connect_to_sqream_db: - -Connecting to SQream DB -=========================== + :: -#. Start Tableau Desktop. +6. Enter your connection parameters. -#. Select "More", by navigating :menuselection:`Connect --> To a server --> More` + The following table describes the connection parameters: + + .. list-table:: + :widths: 15 38 38 + :header-rows: 1 - .. image:: /_static/images/tableau_more_servers_2.png - -#. Select "SQream DB by SQream Technologies" + * - Item + - Description + - Example + * - Data Source Name + - The Data Source Name. SQream recommends using a descriptive and easily recognizable name for referencing your DSN. Once set, the Data Source Name cannot be changed. + - + * - Description + - The description of your DSN. This field is optional. + - + * - User + - The username of a role to use for establishing the connection. + - ``rhendricks`` + * - Password + - The password of the selected role. + - ``Tr0ub4dor`` + * - Database + - The database name to connect to. For example, ``master`` + - ``master`` + * - Service + - The :ref:`service queue` to use. + - For example, ``etl``. For the default service ``sqream``, leave blank. + * - Server + - The hostname of the SQream worker. + - ``127.0.0.1`` or ``sqream.mynetwork.co`` + * - Port + - The TCP port of the SQream worker. + - ``5000`` or ``3108`` + * - User Server Picker + - Uses the load balancer when establishing a connection. Use only if exists, and check port. + - + * - SSL + - Uses SSL when establishing a connection. + - + * - Logging Options + - Lets you modify your logging options when tracking the ODBC connection for connection issues. + - + +.. tip:: Test the connection by clicking **Test** before saving your DSN. + +7. Save the DSN by clicking **OK.** + +Connecting Tableau to SQream +~~~~~~~~~~~~ +**To connect Tableau to SQream:** + +1. Start Tableau Desktop. + + :: + +#. In the **Connect** menu, in the **To a server** sub-menu, click **More Servers** and select **Other Databases (ODBC)**. + + The **Other Databases (ODBC)** window is displayed. - .. image:: /_static/images/tableau_more_servers_3.png + :: + +#. In the Other Databases (ODBC) window, select the DSN that you created in :ref:`Setting Up SQream Tables as Data Sources `. -#. Fill in the details for your SQream DB installation and click :menuselection:`Sign In`. - - .. image:: /_static/images/tableau_new_connection.png - + Tableau may display the **Sqream ODBC Driver Connection Dialog** window and prompt you to provide your username and password. -.. list-table:: Connection parameters reference - :widths: auto - :header-rows: 1 - - * - Item - - Description - * - Server - - Hostname of the SQream DB worker. For example, ``127.0.0.1`` or ``sqream.mynetwork.co`` - * - Port - - TCP port of the SQream DB worker. For example, ``3108`` when using a load balancer or ``5100`` when connecting directly to a worker with SSL - * - Database - - Specifies the database name to connect to. For example, ``master`` - * - Cluster - - Connect via load balancer. Accepts ``true`` and ``false``. Double check the connection port when setting this. - * - Username - - Username of a role to use for connection. For example, ``rhendricks`` - * - Password - - Specifies the password of the selected role. For example, ``Tr0ub4dor&3`` - * - Require SSL - - Specifies SSL for this connection +#. Provide your username and password and click **OK**. + +.. _tableau_connect_to_sqream_db: -Setting up SQream DB tables as data sources -====================================================== -Once connected, you are taken to the data source page. +Connecting to SQream +--------------------- +After installing the JDBC driver you can connect to SQream. -The left side of the screen contains a database and schema drop-down. Select the database name and schema name you wish to use (``public`` is the default schema in SQream DB). +**To connect to SQream:** - .. image:: /_static/images/tableau_data_sources.png +#. Start Tableau Desktop. -Drag tables you wish to use to the main area, marked as **Drag tables here**. This is also where you specify joins and data source filters. + :: + +#. In the **Connect** menu, in the **To a Server** sub-menu, click **More...**. -When data source setup is completed, navigate to a new sheet to start analyzing data. + More connection options are displayed. -.. tip:: - * Read more about configuring data sources, joining, filtering, and more on `Tableau's Set Up Data Sources `_ tutorials. - * Rename the connection with a descriptive name for other users to understand. Alternatively, Tableau will generate a default name based on the DSN and tables. + :: + +#. Select **SQream DB by SQream Technologies**. + + The **New Connection** dialog box is displayed. -Tableau best practices and troubleshooting -================================================= + :: + +#. In the New Connection dialog box, fill in the fields and click **Sign In**. -Cut out what you don't need ------------------------------ + The following table describes the fields: + + .. list-table:: + :widths: 15 38 38 + :header-rows: 1 + + * - Item + - Description + - Example + * - Server + - Defines the server of the SQream worker. + - ``127.0.0.1`` or ``sqream.mynetwork.co`` + * - Port + - Defines the TCP port of the SQream worker. + - ``3108`` when using a load balancer, or ``5100`` when connecting directly to a worker with SSL. + * - Database + - Defines the database to establish a connection with. + - ``master`` + * - Cluster + - Enables (``true``) or disables (``false``) the load balancer. After enabling or disabling the load balance, verify the connection. + - + * - Username + - Specifies the username of a role to use when connecting. + - ``rhendricks`` + * - Password + - Specifies the password of the selected role. + - ``Tr0ub4dor&3`` + * - Require SSL (recommended) + - Sets SSL as a requirement for establishing this connection. + - + +The connection is established and the data source page is displayed. -* Bring only the data sources you need into Tableau. As a best practice, do not bring in tables that you don't intend to explore. +.. tip:: + Tableau automatically assigns your connection a default name based on the DSN and table. SQream recommends giving the connection a more descriptive name. + +.. _set_up_sqream_tables_as_data_sources: -* Add filters before exploring. Every change you make while exploring data will query SQream DB, sometimes several times. Add filters to the datasource before exploring, so that the queries sent to SQream DB run faster. +Setting Up SQream Tables as Data Sources +---------------- +After connecting to SQream you must set up the SQream tables as data sources. -Let Tableau create the queries --------------------------------- +**To set up SQream tables as data sources:** + +1. From the **Table** menu, select the desired database and schema. -Create pre-optimized views (see :ref:`create_view`) and point the datasource at these views. + SQream's default schema is **public**. + + :: + +#. Drag the desired tables into the main area (labeled **Drag tables here**). -In some cases, using views or custom SQL as a datasource can actually degrade performance. + This area is also used for specifying joins and data source filters. + + :: + +#. Open a new sheet to analyze data. -We recommend testing performance of custom SQL and views, and compare with Tableau's generated SQL. +.. tip:: + For more information about configuring data sources, joining, filtering, see Tableau's `Set Up Data Sources `_ tutorials. -Create a separate service for Tableau ---------------------------------------- +Tableau Best Practices and Troubleshooting +--------------- +This section describes the following best practices and troubleshooting procedures when connecting to SQream using Tableau: -SQream recommends that Tableau get a separate service with the DWLM. This will reduce the impact of Tableau on other applications and processes, such as ETL. -This works in conjunction with the load balancer to ensure good performance. +.. contents:: + :local: +Inserting Only Required Data +~~~~~~~~~~~~~~~~~~ +When using Tableau, SQream recommends using only data that you need, as described below: -Troubleshoot workbook performance before deploying to Tableau Server ------------------------------------------------------------------------ +* Insert only the data sources you need into Tableau, excluding tables that don't require analysis. -Tableau has a built in `performance recorder `_ that shows how time is being spent. If you're seeing slow performance, this could be the result of a misconfiguration such as setting concurrency too low. + :: -Use the Tableau Performance Recorder to view the performance of the queries that Tableau runs. Using this information, you can identify queries that can be optimized with the use of views. +* To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQream database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyze and increases query performance. -Troubleshooting ``Error Code: 37CE01A3``, ``No suitable driver installed or the URL is incorrect`` --------------------------------------------------------------------------------------------------------- +Using Tableau's Table Query Syntax +~~~~~~~~~~~~~~~~~~~ +Dragging your desired tables into the main area in Tableau builds queries based on its own syntax. This helps ensure increased performance, while using views or custom SQL may degrade performance. In addition, SQream recommends using the :ref:`create_view` to create pre-optimized views, which your datasources point to. -In some cases, Tableau may have trouble finding the SQream DB JDBC driver. This message explains that the driver can't be found. +Creating a Separate Service for Tableau +~~~~~~~~~~~~~~~~~~~ +SQream recommends creating a separate service for Tableau with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. -To solve this issue, try two things: +Error Saving Large Quantities of Data as Files +~~~~~~~~~~~~~~~~~~~ +An **FAB9A2C5** error can when saving large quantities of data as files. If you receive this error when writing a connection string, add the ``fetchSize`` parameter to ``1``, as shown below: -1. Verify that the JDBC driver was placed in the correct directory: +.. code-block:: text - * Tableau Desktop on Windows: ``c:\Program Files\Tableau\Drivers`` + jdbc:Sqream:///;user=;password=sqream;[; fetchSize=1...] + +For more information on troubleshooting error **FAB9A2C5**, see the `Tableau Knowledge Base `_. + +Troubleshooting Workbook Performance Before Deploying to the Tableau Server +~~~~~~~~~~~~~~~~~~~ +Tableau has a built-in `performance recorder `_ that shows how time is being spent. If you're seeing slow performance, this could be the result of a misconfiguration such as setting concurrency too low. - * Tableau Desktop on MacOS: ``~/Library/Tableau/Drivers`` +Use the Tableau Performance Recorder for viewing the performance of queries run by Tableau. You can use this information to identify queries that can be optimized by using views. - * Tableau on Linux: ``/opt/tableau/tableau_driver/jdbc`` +Troubleshooting Error Codes +~~~~~~~~~~~~~~~~~~~ +Tableau may be unable to locate the SQream JDBC driver. The following message is displayed when Tableau cannot locate the driver: -2. Find the file path for the JDBC driver and add it to the Java classpath: +.. code-block:: console + + Error Code: 37CE01A3, No suitable driver installed or the URL is incorrect - * On Linux, ``export CLASSPATH=;$CLASSPATH`` +**To troubleshoot error codes:** + +If Tableau cannot locate the SQream JDBC driver, do the following: + + 1. Verify that the JDBC driver is located in the correct directory: + + * **Tableau Desktop on Windows:** *C:\Program Files\Tableau\Drivers* + * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* + * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* - * On Windows, add an envrionment variable for the classpath: + 2. Find the file path for the JDBC driver and add it to the Java classpath: - .. image:: /_static/images/set_java_classpath.png + * **For Linux** - ``export CLASSPATH=;$CLASSPATH`` + + :: + + * **For Windows** - add an environment variable for the classpath: + + .. image:: /_static/images/third_party_connectors/tableau/envrionment_variable_for_classpath.png -If you're still experiencing issues after restarting Tableau, we're always happy to help. Visit `SQream's support portal `_ for additional support. +If you experience issues after restarting Tableau, see the `SQream support portal `_. From 418e20322045776e9598adaacc7f196601ee3aa4 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 31 Oct 2021 15:15:05 +0200 Subject: [PATCH 075/300] Update index.rst Updated Line 92 to avoid mentioning Tableau in the JDBC document. Ticket: https://sqream.atlassian.net/browse/SQ-8735 - Tableau - error on saving data to files --- guides/client_drivers/jdbc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/client_drivers/jdbc/index.rst b/guides/client_drivers/jdbc/index.rst index 4880c056e..2e5832795 100644 --- a/guides/client_drivers/jdbc/index.rst +++ b/guides/client_drivers/jdbc/index.rst @@ -89,7 +89,7 @@ The following is the correct syntax for writing a connection string: jdbc:Sqream:///;user=;password=sqream;[; ...] -An **FAB9A2C5** error can occur when saving large quantities of data as files. If you receive this error, see `Troubleshooting - Error Saving Large Quantities of Data as Files `_. +If you receive an error when saving large quantities of data as files, see `Troubleshooting - Error Saving Large Quantities of Data as Files `_. Connection Parameters ^^^^^^^^^^^^^^^^^^^^^^^^ From 1e717e1c8da1ad14f1cbdfc7609f297ad320e742 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 31 Oct 2021 15:21:27 +0200 Subject: [PATCH 076/300] Updated documentation based on ticket Updated Line 92 to avoid mentioning Tableau in the JDBC document. Ticket: https://sqream.atlassian.net/browse/SQ-8735 - Tableau - error on saving data to files --- guides/client_drivers/jdbc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/client_drivers/jdbc/index.rst b/guides/client_drivers/jdbc/index.rst index 2e5832795..b34aa0f59 100644 --- a/guides/client_drivers/jdbc/index.rst +++ b/guides/client_drivers/jdbc/index.rst @@ -89,7 +89,7 @@ The following is the correct syntax for writing a connection string: jdbc:Sqream:///;user=;password=sqream;[; ...] -If you receive an error when saving large quantities of data as files, see `Troubleshooting - Error Saving Large Quantities of Data as Files `_. +If you receive an error when saving large quantities of data as files, see `Troubleshooting - Error Saving Large Quantities of Data as Files `_. Connection Parameters ^^^^^^^^^^^^^^^^^^^^^^^^ From de6452ac280f1db1dd7abffe9b463556aa428250 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 31 Oct 2021 16:02:19 +0200 Subject: [PATCH 077/300] Updated documentation based on ticket Updated Line 92 to avoid mentioning Tableau in the JDBC document. Ticket: https://sqream.atlassian.net/browse/SQ-8735 - Tableau - error on saving data to files --- guides/third_party_tools/tableau.rst | 511 ++++++++++++++++++--------- 1 file changed, 349 insertions(+), 162 deletions(-) diff --git a/guides/third_party_tools/tableau.rst b/guides/third_party_tools/tableau.rst index 3ac0bc549..e68fd1496 100644 --- a/guides/third_party_tools/tableau.rst +++ b/guides/third_party_tools/tableau.rst @@ -1,276 +1,463 @@ .. _connect_to_tableau: ************************* -Connecting to Tableau +Connecting to SQream Using Tableau ************************* -You can use Tableau to connect to a SQream DB cluster. This tutorial is a guide that will show you how to connect to Tableau, as well as provide some guidelines and best practices for exploring data with Tableau and SQream DB. +Overview +===================== +SQream's Tableau connector plugin, based on standard JDBC, enables storing and fast querying large volumes of data. -SQream DB supports both Tableau Desktop and Tableau Server on Windows, MacOS, and Linux distributions. +The **Connecting to SQream Using Tableau** page is a Quick Start Guide that describes how install Tableau and the JDBC and ODBC drivers and connect to SQream using the JDBC and ODBC drivers for data analysis. It also describes using best practices and troubleshoot issues that may occur while installing Tableau. SQream supports both Tableau Desktop and Tableau Server on Windows, MacOS, and Linux distributions. -.. contents:: In this topic: - :local: +For more information on SQream's integration with Tableau, see `Tableau's Extension Gallery `_. -Installing Tableau Desktop -============================ +The Connecting to SQream Using Tableau page describes the following: -SQream DB has been tested with versions 9.2 and newer. -If you do not already have Tableau Desktop installed, download and install Tabelau Desktop. https://www.tableau.com/products/trial +.. contents:: + :local: -Tableau offers a time-limited trial version. +Installing the JDBC Driver and Tableau Connector Plugin +------------------- +This section describes how to install the JDBC driver using the fully-integrated Tableau connector plugin (Tableau Connector, or **.taco** file). SQream has been tested with Tableau versions 9.2 and newer. -Installing the JDBC driver and connector -================================================= +**To connect to SQream using Tableau:** + +#. Install the Tableau Desktop application. -Starting from Tableau v2019.4, SQream DB recommends using the JDBC driver instead of the previously recommended ODBC driver. + For more information about installing the Tableau Desktop application, see the `Tableau products page `_ and click **Download Free Trial**. Note that Tableau offers a 14-day trial version. + + :: -If you have Tableau Desktop on Windows, we recommend using the :ref:`JDBC installer method`. +#. Do one of the following: -If you have Tableau Server or Tableau on MacOS and Linux follow the instructions for a :ref:`manual installation`. + * **For Windows** - See :ref:`Installing Tableau Using the Windows Installer `. + * **For MacOS or Linux** - See :ref:`Installing the JDBC Driver Manually `. -.. _tableau_jdbc_installer: +.. note:: For Tableau **2019.4 versions and later**, SQream recommends installing the JDBC driver instead of the previously recommended ODBC driver. -Installing with the Windows installer ------------------------------------------ +.. _tableau_windows_installer: -1. Close Tableau Desktop +Installing the JDBC Driver Using the Windows Installer +~~~~~~~~~~~~~~~~~~ +If you are using Windows, after installing the Tableau Desktop application you can install the JDBC driver using the Windows installer. The Windows installer is an installation wizard that guides you through the JDBC driver installation steps. When the driver is installed, you can connect to SQream. -2. Download the JDBC installer :ref:`from the client drivers page`. +**To install Tableau using the Windows installer**: -3. - Start the installer, and ensure that the "**Tableau Desktop Connector**" item is selected, as in the image below. - - .. image:: /_static/images/jdbc_windows_installer_screen.png +#. Close Tableau Desktop. -4. Restart Tableau Desktop, continue to :ref:`connecting to SQream DB`. + :: -.. _tableau_manual_installation: +#. Download the most current version of the `SQream JDBC driver `_. -Installing the JDBC driver manually (MacOS, Linux, Tableau Server) ------------------------------------------------------------------------ + :: + +#. Do the following: -Download the JDBC and Tableau Connector (taco) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + #. Start the installer. + #. Verify that the **Tableau Desktop connector** item is selected. + #. Follow the installation steps. -1. Download the JDBC installer :ref:`from the client drivers page`. + :: -2. Download the SQream DB Tableau connector (.taco) :ref:`from the client drivers page`. +You can now restart Tableau Desktop or Server to begin using the SQream driver by :ref:`connecting to SQream `. -Install JDBC driver -^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. _tableau_jdbc_installer: -Unzip the JDBC driver into a Tableau drivers directory. Based on your installation of Tableau, this may be at: +Installing the JDBC Driver Manually +~~~~~~~~~~~~~ +If you are using MacOS, Linux, or the Tableau server, after installing the Tableau Desktop application you can install the JDBC driver manually. When the driver is installed, you can connect to SQream. -* Tableau Desktop on Windows: ``c:\Program Files\Tableau\Drivers`` +**To install the JDBC driver manually:** -* Tableau Desktop on MacOS: ``~/Library/Tableau/Drivers`` +1. Download the JDBC installer and SQream Tableau connector (.taco) file from the :ref:`from the client drivers page`. -* Tableau on Linux: ``/opt/tableau/tableau_driver/jdbc`` + :: -Install taco -^^^^^^^^^^^^^^^^^^ +#. Install the JDBC driver by unzipping the JDBC driver into a Tableau driver directory. + + Based on the installation method that you used, your Tableau driver directory is located in one of the following places: -Place the ``SQreamDB.taco`` file in the Tableau connectors directory. Based on your installation of Tableau, this may be at: + * **Tableau Desktop on Windows:** *C:\\Program Files\\Tableau\\Drivers* + * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* + * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* + +.. note:: If the driver includes only a single .jar file, copy it to *C:\\Program Files\\Tableau/Drivers*. If the driver includes multiple files, create a subfolder *A* in *C:\\Program Files\\Tableau/Drivers* and copy all files to folder *A*. -* Tableau Desktop on Windows: ``C:\Users\\My Tableau Repository\Connectors`` +Note the following when installing the JDBC driver: -* Tableau Desktop on MacOS: ``~/My Tableau Repository/Connectors`` +* You must have read permissions on the .jar file. +* Tableau requires a JDBC 4.0 or later driver. +* Tableau requires a Type 4 JDBC driver. +* The latest 64-bit version of Java 8 is installed. -* Tableau Server: +3. Install the **SQreamDB.taco** file by moving the SQreamDB.taco file into the Tableau connectors directory. - 1. - Create a directory for Tableau connectors. For example: ``C:\tableau_connectors`` - - This directory needs to exist on all Tableau servers + Based on the installation method that you used, your Tableau driver directory is located in one of the following places: + + * **Tableau Desktop on Windows:** *C:\\Users\\\\My Tableau Repository\\Connectors* + * **Tableau Desktop on Windows:** *~/My Tableau Repository/Connectors* - 2. Copy the ``SQreamDB.taco`` file into the directory you created on all servers + :: + +4. *Optional* - If you are using the Tableau Server, do the following: - 3. Set the ``native_api.connect_plugins_path`` option with ``tsm``. For example: + 1. Create a directory for Tableau connectors and give it a descriptive name, such as *C:\\tableau_connectors*. - ``tsm configuration set -k native_api.connect_plugins_path -v C:/tableau_connectors`` + This directory needs to exist on all Tableau servers. - If you get a configuration error during this step, add the ``--force-keys`` option to the end of the command. + :: + + 2. Copy the SQreamDB.taco file into the new directory. + + :: + + 3. Set the **native_api.connect_plugins_path** option to ``tsm`` as shown in the following example: - Then, apply the pending configuration changes with ``tsm pending-changes apply`` + .. code-block:: console + + $ tsm configuration set -k native_api.connect_plugins_path -v C:/tableau_connectors + + If a configuration error is displayed, add ``--force-keys`` to the end of the command as shown in the following example: + + .. code-block:: console + + $ tsm configuration set -k native_api.connect_plugins_path -v C:/tableau_connectors--force-keys + + 4. To apply the pending configuration changes, run the following command: + + .. code-block:: console + + $ tsm pending-changes apply .. warning:: This restarts the server. - +You can now restart Tableau Desktop or Server to begin using the SQream driver by :ref:`connecting to SQream ` as described in the section below. + +.. _tableau_connect_to_sqream: + -You can now restart Tableau Desktop or Server to begin using the SQream DB driver. Continue to :ref:`connecting to SQream DB`. +Installing the ODBC Driver for Tableau Versions 2019.3 and Earlier +-------------- -Legacy method - ODBC for Tableau versions before v2019.3 -================================================================== -Installing the ODBC driver and customizations --------------------------------------------------- +This section describes the installation method for Tableau version 2019.3 or earlier and describes the following: -If you've already installed the SQream DB ODBC driver, we recommend that you :ref:`re-run the ODBC driver installer ` after installing Tableau, and select the Tableau customizations checkbox, as in the image below: +.. contents:: + :local: + +.. note:: SQream recommends installing the JDBC driver to provide improved connectivity. + +Automatically Reconfiguring the ODBC Driver After Initial Installation +~~~~~~~~~~~~~~~~~~ +If you've already installed the SQream ODBC driver and installed Tableau, SQream recommends reinstalling the ODBC driver with the **.TDC Tableau Settings for SQream DB** configuration shown in the image below: .. image:: /_static/images/odbc_windows_installer_tableau.png -This is necessary because by default, Tableau has a tendency to create temporary tables and run lots of discovery queries which could impact performance. -The ODBC driver installer installs customizations for Tableau automatically. +SQream recommends this configuration because Tableau creates temporary tables and runs several discovery queries that may impact performance. The ODBC driver installer avoids this by automatically reconfiguring Tableau. + +For more information about reinstalling the ODBC driver installer, see :ref:`Install and Configure ODBC on Windows `. -If you want to perform this step manually, follow the instructions in the next section. +If you want to manually reconfigure the ODBC driver, see :ref:`Manually Reconfiguring the ODBC Driver After Initial Installation ` below. -The TDC file -^^^^^^^^^^^^^^^^^^^ +.. _manually_reconfigure_odbc_driver: -The TDC file (Tableau Datasource Customization) helps Tableau make full use of SQream DB's features and capabilities. +Manually Reconfiguring the ODBC Driver After Initial Installation +~~~~~~~~~~~~~~~~~~ +The file **Tableau Datasource Customization (TDC)** file lets you use Tableau make full use of SQream DB's features and capabilities. -Before you start, check which version of Tableau is used. The version needs to be placed in the TDC file. +**To manually reconfigure the ODBC driver after initial installation:** -#. Download the TDC file to your computer :download:`odbc-sqream.tdc `. +1. Do one of the following: + + 1. Download the :download:`odbc-sqream.tdc ` file to your machine and open it in a text editor. + + :: - Alternatively, copy the text below to a text editor. + 2. Copy the text below into a text editor: .. literalinclude:: odbc-sqream.tdc :language: xml - :caption: SQream DB ODBC TDC + :caption: SQream ODBC TDC File :emphasize-lines: 2 +#. Check which version of Tableau you are using. -#. Change the highlighted line to match your major Tableau version. For example, if you're on Tableau ``2019.2.1``, writing ``2019.2`` is enough. + :: -#. - * For **Tableau Desktop** - save the TDC file to ``C:\Users\\Documents\My Tableau Repository\Datasources``, where ```` is the Windows username Tableau is installed in. - - * For **Tableau Server** - save the TDC file to ``C:\ProgramData\Tableau\Tableau Server\data\tabsvc\vizqlserver\Datasources``. +#. In the text of the file shown above, in the highlighted line, replace the version number with the **major** version of Tableau that you are using. + + For example, if you are using Tableau vesion **2019.2.1**, replace it with **2019.2**. -Configure the ODBC connection (DSN) ------------------------------------------- + :: + +#. Do one of the following: + + * If you are using **Tableau Desktop** - save the TDC file to *C:\\Users\\\\Documents\\My Tableau Repository\\Datasources*, where ```` is the Windows username that you have installed Tableau under. + + :: + + * If you are using the **Tableau Server** - save the TDC file to *C:\\ProgramData\\Tableau\\Tableau Server\\data\\tabsvc\\vizqlserver\\Datasources*. -Create an ODBC DSN before connecting Tableau with SQream DB. See the section titled :ref:`create_windows_odbc_dsn` for information about creating an ODBC DSN in Windows. +Configuring the ODBC Connection +~~~~~~~~~~~~ +The ODBC connection uses a DSN when connecting to ODBC data sources, and each DSN represents one SQream database. -Remember to test the connectivity before saving the DSN. +**To configure the ODBC connection:** -Connecting Tableau to SQream DB ---------------------------------------- +1. Create an ODBC DSN. -#. Start Tableau Desktop and select "Other Database (ODBC)", by navigating :menuselection:`Connect --> To a server --> More --> Other Database (ODBC)` + :: + +#. Open the Windows menu by pressing the Windows button (:kbd:`⊞ Win`) or clicking the **Windows** menu button. + + :: + +#. Type **ODBC** and select **ODBC Data Sources (64-bit)**. + + During installation, the installer created a sample user DSN named **SQreamDB**. - .. image:: /_static/images/tableau_more_servers.png + :: -#. In the DSN selection window, select the DSN that you created earlier and select :menuselection:`Connect --> OK`. +#. *Optional* - Do one or both of the following: + + * Modify the DSN name. - If prompted by Tableau, you may need to specify the user name and password again after clicking Connect. + :: + + * Create a new DSN name by clicking **Add** and selecting **SQream ODBC Driver**. - .. image:: /_static/images/tableau_choose_dsn_and_connect.png +.. image:: /_static/images/odbc_windows_dsns.png + +5. Click **Finish**. -.. _tableau_connect_to_sqream_db: - -Connecting to SQream DB -=========================== + :: -#. Start Tableau Desktop. +6. Enter your connection parameters. -#. Select "More", by navigating :menuselection:`Connect --> To a server --> More` + The following table describes the connection parameters: + + .. list-table:: + :widths: 15 38 38 + :header-rows: 1 - .. image:: /_static/images/tableau_more_servers_2.png - -#. Select "SQream DB by SQream Technologies" + * - Item + - Description + - Example + * - Data Source Name + - The Data Source Name. SQream recommends using a descriptive and easily recognizable name for referencing your DSN. Once set, the Data Source Name cannot be changed. + - + * - Description + - The description of your DSN. This field is optional. + - + * - User + - The username of a role to use for establishing the connection. + - ``rhendricks`` + * - Password + - The password of the selected role. + - ``Tr0ub4dor`` + * - Database + - The database name to connect to. For example, ``master`` + - ``master`` + * - Service + - The :ref:`service queue` to use. + - For example, ``etl``. For the default service ``sqream``, leave blank. + * - Server + - The hostname of the SQream worker. + - ``127.0.0.1`` or ``sqream.mynetwork.co`` + * - Port + - The TCP port of the SQream worker. + - ``5000`` or ``3108`` + * - User Server Picker + - Uses the load balancer when establishing a connection. Use only if exists, and check port. + - + * - SSL + - Uses SSL when establishing a connection. + - + * - Logging Options + - Lets you modify your logging options when tracking the ODBC connection for connection issues. + - + +.. tip:: Test the connection by clicking **Test** before saving your DSN. + +7. Save the DSN by clicking **OK.** + +Connecting Tableau to SQream +~~~~~~~~~~~~ +**To connect Tableau to SQream:** + +1. Start Tableau Desktop. + + :: + +#. In the **Connect** menu, in the **To a server** sub-menu, click **More Servers** and select **Other Databases (ODBC)**. + + The **Other Databases (ODBC)** window is displayed. - .. image:: /_static/images/tableau_more_servers_3.png + :: + +#. In the Other Databases (ODBC) window, select the DSN that you created in :ref:`Setting Up SQream Tables as Data Sources `. -#. Fill in the details for your SQream DB installation and click :menuselection:`Sign In`. - - .. image:: /_static/images/tableau_new_connection.png - + Tableau may display the **Sqream ODBC Driver Connection Dialog** window and prompt you to provide your username and password. -.. list-table:: Connection parameters reference - :widths: auto - :header-rows: 1 - - * - Item - - Description - * - Server - - Hostname of the SQream DB worker. For example, ``127.0.0.1`` or ``sqream.mynetwork.co`` - * - Port - - TCP port of the SQream DB worker. For example, ``3108`` when using a load balancer or ``5100`` when connecting directly to a worker with SSL - * - Database - - Specifies the database name to connect to. For example, ``master`` - * - Cluster - - Connect via load balancer. Accepts ``true`` and ``false``. Double check the connection port when setting this. - * - Username - - Username of a role to use for connection. For example, ``rhendricks`` - * - Password - - Specifies the password of the selected role. For example, ``Tr0ub4dor&3`` - * - Require SSL - - Specifies SSL for this connection +#. Provide your username and password and click **OK**. + +.. _tableau_connect_to_sqream_db: -Setting up SQream DB tables as data sources -====================================================== -Once connected, you are taken to the data source page. +Connecting to SQream +--------------------- +After installing the JDBC driver you can connect to SQream. -The left side of the screen contains a database and schema drop-down. Select the database name and schema name you wish to use (``public`` is the default schema in SQream DB). +**To connect to SQream:** - .. image:: /_static/images/tableau_data_sources.png +#. Start Tableau Desktop. -Drag tables you wish to use to the main area, marked as **Drag tables here**. This is also where you specify joins and data source filters. + :: + +#. In the **Connect** menu, in the **To a Server** sub-menu, click **More...**. -When data source setup is completed, navigate to a new sheet to start analyzing data. + More connection options are displayed. -.. tip:: - * Read more about configuring data sources, joining, filtering, and more on `Tableau's Set Up Data Sources `_ tutorials. - * Rename the connection with a descriptive name for other users to understand. Alternatively, Tableau will generate a default name based on the DSN and tables. + :: + +#. Select **SQream DB by SQream Technologies**. + + The **New Connection** dialog box is displayed. -Tableau best practices and troubleshooting -================================================= + :: + +#. In the New Connection dialog box, fill in the fields and click **Sign In**. -Cut out what you don't need ------------------------------ + The following table describes the fields: + + .. list-table:: + :widths: 15 38 38 + :header-rows: 1 + + * - Item + - Description + - Example + * - Server + - Defines the server of the SQream worker. + - ``127.0.0.1`` or ``sqream.mynetwork.co`` + * - Port + - Defines the TCP port of the SQream worker. + - ``3108`` when using a load balancer, or ``5100`` when connecting directly to a worker with SSL. + * - Database + - Defines the database to establish a connection with. + - ``master`` + * - Cluster + - Enables (``true``) or disables (``false``) the load balancer. After enabling or disabling the load balance, verify the connection. + - + * - Username + - Specifies the username of a role to use when connecting. + - ``rhendricks`` + * - Password + - Specifies the password of the selected role. + - ``Tr0ub4dor&3`` + * - Require SSL (recommended) + - Sets SSL as a requirement for establishing this connection. + - + +The connection is established and the data source page is displayed. -* Bring only the data sources you need into Tableau. As a best practice, do not bring in tables that you don't intend to explore. +.. tip:: + Tableau automatically assigns your connection a default name based on the DSN and table. SQream recommends giving the connection a more descriptive name. + +.. _set_up_sqream_tables_as_data_sources: -* Add filters before exploring. Every change you make while exploring data will query SQream DB, sometimes several times. Add filters to the datasource before exploring, so that the queries sent to SQream DB run faster. +Setting Up SQream Tables as Data Sources +---------------- +After connecting to SQream you must set up the SQream tables as data sources. -Let Tableau create the queries --------------------------------- +**To set up SQream tables as data sources:** + +1. From the **Table** menu, select the desired database and schema. -Create pre-optimized views (see :ref:`create_view`) and point the datasource at these views. + SQream's default schema is **public**. + + :: + +#. Drag the desired tables into the main area (labeled **Drag tables here**). -In some cases, using views or custom SQL as a datasource can actually degrade performance. + This area is also used for specifying joins and data source filters. + + :: + +#. Open a new sheet to analyze data. -We recommend testing performance of custom SQL and views, and compare with Tableau's generated SQL. +.. tip:: + For more information about configuring data sources, joining, filtering, see Tableau's `Set Up Data Sources `_ tutorials. -Create a separate service for Tableau ---------------------------------------- +Tableau Best Practices and Troubleshooting +--------------- +This section describes the following best practices and troubleshooting procedures when connecting to SQream using Tableau: -SQream recommends that Tableau get a separate service with the DWLM. This will reduce the impact of Tableau on other applications and processes, such as ETL. -This works in conjunction with the load balancer to ensure good performance. +.. contents:: + :local: +Inserting Only Required Data +~~~~~~~~~~~~~~~~~~ +When using Tableau, SQream recommends using only data that you need, as described below: -Troubleshoot workbook performance before deploying to Tableau Server ------------------------------------------------------------------------ +* Insert only the data sources you need into Tableau, excluding tables that don't require analysis. -Tableau has a built in `performance recorder `_ that shows how time is being spent. If you're seeing slow performance, this could be the result of a misconfiguration such as setting concurrency too low. + :: -Use the Tableau Performance Recorder to view the performance of the queries that Tableau runs. Using this information, you can identify queries that can be optimized with the use of views. +* To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQream database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyze and increases query performance. -Troubleshooting ``Error Code: 37CE01A3``, ``No suitable driver installed or the URL is incorrect`` --------------------------------------------------------------------------------------------------------- +Using Tableau's Table Query Syntax +~~~~~~~~~~~~~~~~~~~ +Dragging your desired tables into the main area in Tableau builds queries based on its own syntax. This helps ensure increased performance, while using views or custom SQL may degrade performance. In addition, SQream recommends using the :ref:`create_view` to create pre-optimized views, which your datasources point to. -In some cases, Tableau may have trouble finding the SQream DB JDBC driver. This message explains that the driver can't be found. +Creating a Separate Service for Tableau +~~~~~~~~~~~~~~~~~~~ +SQream recommends creating a separate service for Tableau with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. -To solve this issue, try two things: +Error Saving Large Quantities of Data as Files +~~~~~~~~~~~~~~~~~~~ +An **FAB9A2C5** error can when saving large quantities of data as files. If you receive this error when writing a connection string, add the ``fetchSize`` parameter to ``1``, as shown below: -1. Verify that the JDBC driver was placed in the correct directory: +.. code-block:: text - * Tableau Desktop on Windows: ``c:\Program Files\Tableau\Drivers`` + jdbc:Sqream:///;user=;password=sqream;[; fetchSize=1...] + +For more information on troubleshooting error **FAB9A2C5**, see the `Tableau Knowledge Base `_. + +Troubleshooting Workbook Performance Before Deploying to the Tableau Server +~~~~~~~~~~~~~~~~~~~ +Tableau has a built-in `performance recorder `_ that shows how time is being spent. If you're seeing slow performance, this could be the result of a misconfiguration such as setting concurrency too low. - * Tableau Desktop on MacOS: ``~/Library/Tableau/Drivers`` +Use the Tableau Performance Recorder for viewing the performance of queries run by Tableau. You can use this information to identify queries that can be optimized by using views. - * Tableau on Linux: ``/opt/tableau/tableau_driver/jdbc`` +Troubleshooting Error Codes +~~~~~~~~~~~~~~~~~~~ +Tableau may be unable to locate the SQream JDBC driver. The following message is displayed when Tableau cannot locate the driver: -2. Find the file path for the JDBC driver and add it to the Java classpath: +.. code-block:: console + + Error Code: 37CE01A3, No suitable driver installed or the URL is incorrect - * On Linux, ``export CLASSPATH=;$CLASSPATH`` +**To troubleshoot error codes:** + +If Tableau cannot locate the SQream JDBC driver, do the following: + + 1. Verify that the JDBC driver is located in the correct directory: + + * **Tableau Desktop on Windows:** *C:\Program Files\Tableau\Drivers* + * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* + * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* - * On Windows, add an envrionment variable for the classpath: + 2. Find the file path for the JDBC driver and add it to the Java classpath: - .. image:: /_static/images/set_java_classpath.png + * **For Linux** - ``export CLASSPATH=;$CLASSPATH`` + + :: + + * **For Windows** - add an environment variable for the classpath: + + .. image:: /_static/images/third_party_connectors/tableau/envrionment_variable_for_classpath.png -If you're still experiencing issues after restarting Tableau, we're always happy to help. Visit `SQream's support portal `_ for additional support. +If you experience issues after restarting Tableau, see the `SQream support portal `_. From 93a09bec463996caea5d7af84e8e9785dbf80636 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 31 Oct 2021 16:02:57 +0200 Subject: [PATCH 078/300] Updated documentation based on ticket Updated Line 92 to avoid mentioning Tableau in the JDBC document. Ticket: https://sqream.atlassian.net/browse/SQ-8735 - Tableau - error on saving data to files --- guides/client_drivers/jdbc/index.rst | 36 +++++++++++++++------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/guides/client_drivers/jdbc/index.rst b/guides/client_drivers/jdbc/index.rst index b5fcd4bca..423754c1a 100644 --- a/guides/client_drivers/jdbc/index.rst +++ b/guides/client_drivers/jdbc/index.rst @@ -12,25 +12,25 @@ The JDBC driver requires Java 1.8 or newer. .. contents:: In this topic: :local: -Installing the JDBC driver +Installing the JDBC Driver ================================== Prerequisites ---------------- -The SQream DB JDBC driver requires Java 1.8 or newer. We recommend either Oracle Java or OpenJDK. +The SQream JDBC driver requires Java 1.8 or newer. We recommend either Oracle Java or OpenJDK. **Oracle Java** -Download and install Java 8 from Oracle for your platform +To download and install Java 8 from Oracle for your platform, see `Java Downloads for All Operating Systems `_. + -https://www.java.com/en/download/manual.jsp **OpenJDK** -For Linux and BSD, see https://openjdk.java.net/install/ +For Linux and BSD, see `How to download and install prebuilt OpenJDK packages `_. -For Windows, SQream recommends Zulu 8 https://www.azul.com/downloads/zulu-community/?&version=java-8-lts&architecture=x86-64-bit&package=jdk +For Windows, SQream recommends `Zulu 8 `_. .. _get_jdbc_jar: @@ -40,7 +40,7 @@ Getting the JAR file The JDBC driver is provided as a zipped JAR file, available for download from the :ref:`client drivers download page`. This JAR file can integrate into your Java-based applications or projects. -Extract the zip archive +Extract the ZIP Archive ------------------------- Extract the JAR file from the zip archive @@ -68,10 +68,10 @@ An alternative method is to pass ``-classpath`` to the Java executable: $ java -classpath .:/home/sqream/sqream-jdbc-4.3.0.jar my_java_app -Connect to SQream DB with a JDBC application +Connect to SQream DB with a JDBC Application ============================================== -Driver class +Driver Class -------------- Use ``com.sqream.jdbc.SQDriver`` as the driver class in the JDBC application. @@ -79,16 +79,19 @@ Use ``com.sqream.jdbc.SQDriver`` as the driver class in the JDBC application. .. _connection_string: -Connection string +Connection String -------------------- +JDBC drivers rely on a connection string. -JDBC drivers rely on a connection string. Use the following syntax for SQream DB +The following is the correct syntax for writing a connection string: .. code-block:: text jdbc:Sqream:///;user=;password=sqream;[; ...] + +If you receive an error when saving large quantities of data as files, see `Troubleshooting - Error Saving Large Quantities of Data as Files `_. -Connection parameters +Connection Parameters ^^^^^^^^^^^^^^^^^^^^^^^^ .. list-table:: @@ -125,10 +128,10 @@ Connection parameters - Specifies SSL for this connection. For example, ``ssl=true`` * - ```` - ✓ - - ``false`` - - Connect via load balancer (use only if exists, and check port). For example, ``cluster=true`` + - ``true`` + - Connect via load balancer (use only if exists, and check port). -Connection string examples +Connection String Examples ^^^^^^^^^^^^^^^^^^^^^^^^^^^ For a SQream DB cluster with load balancer and no service queues, with SSL @@ -150,7 +153,7 @@ For a SQream DB cluster with load balancer and a specific service queue named `` jdbc:Sqream://sqream.mynetwork.co:3108/raviga;user=rhendricks;password=Tr0ub4dor&3;cluster=true;service=etl -Sample Java program +Sample Java Program -------------------- Download this file by right clicking and saving to your computer :download:`sample.java `. @@ -159,4 +162,3 @@ Download this file by right clicking and saving to your computer :download:`samp :language: java :caption: JDBC application sample :linenos: - From 1aa20f385a20f999bde49f46190ed5124497ea61 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 31 Oct 2021 16:31:11 +0200 Subject: [PATCH 079/300] Update index.rst Corrected title. --- guides/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/client_drivers/index.rst b/guides/client_drivers/index.rst index 3ebf87b1f..60eb2d9ea 100644 --- a/guides/client_drivers/index.rst +++ b/guides/client_drivers/index.rst @@ -1,7 +1,7 @@ .. _client_drivers: ************************************ -Client drivers for |latest_version| +Client Drivers for 2020.3.2.1 ************************************ These guides explain how to use the SQream DB client drivers, and how to use client applications with SQream DB. From e08bdd8045a5f59c0efc4ef7f736f7eaa6832dff Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 3 Nov 2021 12:02:31 +0200 Subject: [PATCH 080/300] Create running_sqream_in_a_docker_container.rst Created Docker page based on Master. --- .../running_sqream_in_a_docker_container.rst | 1488 +++++++++++++++++ 1 file changed, 1488 insertions(+) create mode 100644 guides/operations/running_sqream_in_a_docker_container.rst diff --git a/guides/operations/running_sqream_in_a_docker_container.rst b/guides/operations/running_sqream_in_a_docker_container.rst new file mode 100644 index 000000000..7750db570 --- /dev/null +++ b/guides/operations/running_sqream_in_a_docker_container.rst @@ -0,0 +1,1488 @@ +.. _running_sqream_in_a_docker_container: + + + +*********************** +Running SQream in a Docker Container +*********************** + + +This document describes how to prepare your machine's environment for installing and running SQream in a Docker container. + +.. contents:: This page describes the following: + :depth: 2 + +Setting Up a Host +==================================== + +Operating System Requirements +------------------------------------ +SQream was tested and verified on the following versions of Linux: + + * x86 CentOS/RHEL 7.6 - 7.9 + * IBM RHEL 7.6 + +SQream recommends installing a clean OS on the host to avoid any installation issues. + +.. warning:: Docker-based installation supports only single host deployment and cannot be used on a multi-node cluster. Installing Docker on a single host you will not be able to scale it to a multi-node cluster. + + +Creating a Local User +---------------- +To run SQream in a Docker container you must create a local user. + +**To create a local user:** + +1. Add a local user: + + .. code-block:: console + + $ useradd -m -U sqream + +2. Set the local user's password: + + .. code-block:: console + + $ passwd sqream + +3. Add the local user to the ``wheel`` group: + + .. code-block:: console + + $ usermod -aG wheel sqream + + You can remove the local user from the ``wheel`` group when you have completed the installation. + +4. Log out and log back in as the local user. + +Setting a Local Language +---------------- +After creating a local user you must set a local language. + +**To set a local language:** + +1. Set the local language: + + .. code-block:: console + + $ sudo localectl set-locale LANG=en_US.UTF-8 + +2. Set the time stamp (time and date) of the locale: + + .. code-block:: console + + $ sudo timedatectl set-timezone Asia/Jerusalem + +You can run the ``timedatectl list-timezones`` command to see your timezone. + +Adding the EPEL Repository +---------------- +After setting a local language you must add the EPEL repository. + +**To add the EPEL repository:** + +1. As a root user, upgrade the **epel-release-latest-7.noarch.rpm** repository: + + 1. RedHat (RHEL 7): + + .. code-block:: console + + $ sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + + 2. CentOS 7 + + .. code-block:: console + + $ sudo yum install epel-release + +Installing the Required NTP Packages +---------------- +After adding the EPEL repository, you must install the required NTP packages. + +You can install the required NTP packages by running the following command: + +.. code-block:: console + + $ sudo yum install ntp pciutils python36 kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc + +Installing the Recommended Tools +---------------- +After installin gthe required NTP packages you must install the recommended tools. + +SQream recommends installing the following recommended tools: + +.. code-block:: console + + $ sudo yum install bash-completion.noarch vim-enhanced.x86_64 vim-common.x86_64 net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix + +Updating to the Current Version of the Operating System +---------------- +After installing the recommended tools you must update to the current version of the operating system. + +SQream recommends updating to the current version of the operating system. This is not recommended if the nvidia driver has **not been installed.** + + + +Configuring the NTP Package +---------------- +After updating to the current version of the operating system you must configure the NTP package. + +**To configure the NTP package:** + +1. Add your local servers to the NTP configuration. + + :: + +2. Configure the **ntpd** service to begin running when your machine is started: + + .. code-block:: console + + $ sudo systemctl enable ntpd + $ sudo systemctl start ntpd + $ sudo ntpq -p + +Configuring the Performance Profile +---------------- +After configuring the NTP package you must configure the performance profile. + +**To configure the performance profile:** + +1. Switch the active profile: + + .. code-block:: console + + $ sudo tuned-adm profile throughput-performance + +2. Change the multi-user's default run level: + + .. code-block:: console + + $ sudo systemctl set-default multi-user.target + +Configuring Your Security Limits +---------------- +After configuring the performance profile you must configure your security limits. Configuring your security limits refers to configuring the number of open files, processes, etc. + +**To configure your security limits:** + +1. Run the **bash** shell as a super-user: + + .. code-block:: console + + $ sudo bash + +2. Run the following command: + + .. code-block:: console + + $ echo -e "sqream soft nproc 500000\nsqream hard nproc 500000\nsqream soft nofile 500000\nsqream hard nofile 500000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + +3. Run the following command: + + .. code-block:: console + + $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.zone_reclaim_mode = 0 \n vm.vfs_cache_pressure = 200 \n" >> /etc/sysctl.conf + +Disabling Automatic Bug-Reporting Tools +---------------- +After configuring your security limits you must disable the following automatic bug-reporting tools: + +* ccpp.service +* oops.service +* pstoreoops.service +* vmcore.service +* xorg.service + +You can abort the above but-reporting tools by running the following command: + +.. code-block:: console + + $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done + +Installing the Nvidia CUDA Driver +------------------------------------- + +1. Verify that the Tesla NVIDIA card has been installed and is detected by the system: + + .. code-block:: console + + $ lspci | grep -i nvidia + + The correct output is a list of Nvidia graphic cards. If you do not receive this output, verify that an NVIDIA GPU card has been installed. + +#. Verify that the open-source upstream Nvidia driver is running: + + .. code-block:: console + + $ lsmod | grep nouveau + + No output should be generated. + +#. If you receive any output, do the following: + + 1. Disable the open-source upstream Nvidia driver: + + .. code-block:: console + + $ sudo bash + $ echo "blacklist nouveau" > /etc/modprobe.d/blacklist-nouveau.conf + $ echo "options nouveau modeset=0" >> /etc/modprobe.d/blacklist-nouveau.conf + $ dracut --force + $ modprobe --showconfig | grep nouveau + + 2. Reboot the server and verify that the Nouveau model has not been loaded: + + .. code-block:: console + + $ lsmod | grep nouveau + +#. Check if the Nvidia CUDA driver has already been installed: + + .. code-block:: console + + $ nvidia-smi + + The following is an example of the correct output: + + .. code-block:: console + + nvidia-smi + Wed Oct 30 14:05:42 2019 + +-----------------------------------------------------------------------------+ + | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + |-------------------------------+----------------------+----------------------+ + | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + |===============================+======================+======================| + | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | + | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | + | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + + +-----------------------------------------------------------------------------+ + | Processes: GPU Memory | + | GPU PID Type Process name Usage | + |=============================================================================| + | No running processes found | + +-----------------------------------------------------------------------------+ + +#. Verify that the installed CUDA version shown in the output above is ``10.1``. + + :: + + +#. Do one of the following: + + :: + + 1. If CUDA version 10.1 has already been installed, skip to Docktime Runtime (Community Edition). + :: + + 2. If CUDA version 10.1 has not been installed yet, continue with Step 7 below. + +#. Do one of the following: + + * Install :ref:`CUDA Driver version 10.1 for x86_64 `. + + :: + + * Install :ref:`CUDA driver version 10.1 for IBM Power9 `. + +.. _CUDA_10.1_x8664: + +Installing the CUDA Driver Version 10.1 for x86_64 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the CUDA driver version 10.1 for x86_64:** + +1. Make the following target platform selections: + + :: + + * **Operating system**: Linux + * **Architecture**: x86_64 + * **Distribution**: CentOS + * **Version**: 7 + * **Installer type**: the relevant installer type + +For installer type, SQream recommends selecting **runfile (local)**. The available selections shows only the supported platforms. + +2. Download the base installer for Linux CentOS 7 x86_64: + + .. code-block:: console + + wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm + + +3. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: + + .. code-block:: console + + $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm + $ sudo yum clean all + $ sudo yum install nvidia-driver-latest-dkms + +.. warning:: Verify that the output indicates that driver **418.87** will be installed. + +4. Follow the command line prompts. + + + :: + + +5. Enable the Nvidia service to start at boot and start it: + + .. code-block:: console + + $ sudo systemctl enable nvidia-persistenced.service && sudo systemctl start nvidia-persistenced.service + +6. Create a symbolic link from the **/etc/systemd/system/multi-user.target.wants/nvidia-persistenced.service** file to the **/usr/lib/systemd/system/nvidia-persistenced.service** file. + + :: + +7. Reboot the server. + + :: +8. Verify that the Nvidia driver has been installed and shows all available GPU's: + + .. code-block:: console + + $ nvidia-smi + + The following is the correct output: + + .. code-block:: console + + nvidia-smi + Wed Oct 30 14:05:42 2019 + +-----------------------------------------------------------------------------+ + | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + |-------------------------------+----------------------+----------------------+ + | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + |===============================+======================+======================| + | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | + | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | + | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + + +-----------------------------------------------------------------------------+ + | Processes: GPU Memory | + | GPU PID Type Process name Usage | + |=============================================================================| + | No running processes found | + +-----------------------------------------------------------------------------+ + +.. _CUDA_10.1_IBMPower9: + +Installing the CUDA Driver Version 10.1 for IBM Power9 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the CUDA driver version 10.1 for IBM Power9:** + +1. Download the base installer for Linux CentOS 7 PPC64le: + + .. code-block:: console + + wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm + + +#. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: + + .. code-block:: console + + $ sudo rpm -i cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm + $ sudo yum clean all + $ sudo yum install nvidia-driver-latest-dkms + +.. warning:: Verify that the output indicates that driver **418.87** will be installed. + + + +3. Copy the file to the **/etc/udev/rules.d** directory. + + :: + +4. If you are using RHEL 7 version (7.6 or later), comment out, remove, or change the hot-pluggable memory rule located in file copied to the **/etc/udev/rules.d** directory by running the following command: + + .. code-block:: console + + $ sudo cp /lib/udev/rules.d/40-redhat.rules /etc/udev/rules.d + $ sudo sed -i 's/SUBSYSTEM!="memory",.*GOTO="memory_hotplug_end"/SUBSYSTEM=="*", GOTO="memory_hotplug_end"/' /etc/udev/rules.d/40-redhat.rules + +#. Enable the **nvidia-persisted.service** file: + + .. code-block:: console + + $ sudo systemctl enable nvidia-persistenced.service + +#. Create a symbolic link from the **/etc/systemd/system/multi-user.target.wants/nvidia-persistenced.service** file to the **/usr/lib/systemd/system/nvidia-persistenced.service** file. + + :: + +#. Reboot your system to initialize the above modifications. + + :: + +#. Verify that the Nvidia driver and the **nvidia-persistenced.service** files are running: + + .. code-block:: console + + $ nvidia smi + + The following is the correct output: + + .. code-block:: console + + nvidia-smi + Wed Oct 30 14:05:42 2019 + +-----------------------------------------------------------------------------+ + | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + |-------------------------------+----------------------+----------------------+ + | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + |===============================+======================+======================| + | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | + | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | + | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + + +-----------------------------------------------------------------------------+ + | Processes: GPU Memory | + | GPU PID Type Process name Usage | + |=============================================================================| + | No running processes found | + +-----------------------------------------------------------------------------+ + +#. Verify that the **nvidia-persistenced** service is running: + + .. code-block:: console + + $ systemctl status nvidia-persistenced + + The following is the correct output: + + .. code-block:: console + + root@gpudb ~]systemctl status nvidia-persistenced + nvidia-persistenced.service - NVIDIA Persistence Daemon + Loaded: loaded (/usr/lib/systemd/system/nvidia-persistenced.service; enabled; vendor preset: disabled) + Active: active (running) since Tue 2019-10-15 21:43:19 KST; 11min ago + Process: 8257 ExecStart=/usr/bin/nvidia-persistenced --verbose (code=exited, status=0/SUCCESS) + Main PID: 8265 (nvidia-persiste) + Tasks: 1 + Memory: 21.0M + CGroup: /system.slice/nvidia-persistenced.service + └─8265 /usr/bin/nvidia-persistenced --verbose + +Installing the Docker Engine (Community Edition) +======================= +After installing the Nvidia CUDA driver you must install the Docker engine. + +This section describes how to install the Docker engine using the following processors: + +* :ref:`Using x86_64 processor on CentOS ` +* :ref:`Using x86_64 processor on Ubuntu ` +* :ref:`Using IBM Power9 (PPC64le) processor ` + + +.. _dockerx8664centos: + +Installing the Docker Engine Using an x86_64 Processor on CentOS +--------------------------------- +The x86_64 processor supports installing the **Docker Community Edition (CE)** versions 18.03 and higher. + +For more information on installing the Docker Engine CE on an x86_64 processor, see `Install Docker Engine on CentOS `_ + + + +.. _dockerx8664ubuntu: + +Installing the Docker Engine Using an x86_64 Processor on Ubuntu +----------------------------------------------------- + + +The x86_64 processor supports installing the **Docker Community Edition (CE)** versions 18.03 and higher. + +For more information on installing the Docker Engine CE on an x86_64 processor, see `Install Docker Engine on Ubuntu `_ + +.. _docker_ibmpower9: + +Installing the Docker Engine on an IBM Power9 Processor +---------------------------------------- +The x86_64 processor only supports installing the **Docker Community Edition (CE)** version 18.03. + + +**To install the Docker Engine on an IBM Power9 processor:** + +You can install the Docker Engine on an IBM Power9 processor by running the following command: + +.. code-block:: console + + $ wget + $ http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm + $ wget + $ http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm + $ yum install -y container-selinux-2.9-4.el7.noarch.rpm + $ docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm + + + +For more information on installing the Docker Engine CE on an IBM Power9 processor, see `Install Docker Engine on Ubuntu `_. + +Docker Post-Installation +================================= +After installing the Docker engine you must configure Docker on your local machine. + +**To configure Docker on your local machine:** + +1. Enable Docker to start on boot: + + .. code-block:: console + + $ sudo systemctl enable docker && sudo systemctl start docker + +2. Enable managing Docker as a non-root user: + + .. code-block:: console + + $ sudo usermod -aG docker $USER + +3. Log out and log back in via SSH. This causes Docker to re-evaluate your group membership. + + :: + +4. Verify that you can run the following Docker command as a non-root user (without ``sudo``): + + .. code-block:: console + + $ docker run hello-world + +If you can run the above Docker command as a non-root user, the following occur: + +* Docker downloads a test image and runs it in a container. +* When the container runs, it prints an informational message and exits. + +For more information on installing the Docker Post-Installation, see `Docker Post-Installation `_. + +Installing the Nvidia Docker2 ToolKit +========================================== +After configuring Docker on your local machine you must install the Nvidia Docker2 ToolKit. The NVIDIA Docker2 Toolkit lets you build and run GPU-accelerated Docker containers. The Toolkit includes a container runtime library and related utilities for automatically configuring containers to leverage NVIDIA GPU's. + +This section describes the following: + +* :ref:`Installing the NVIDIA Docker2 Toolkit on an x86_64 processor. ` +* :ref:`Installing the NVIDIA Docker2 Toolkit on a PPC64le processor. ` + +.. _install_nvidia_docker2_toolkit_x8664_processor: + +Installing the NVIDIA Docker2 Toolkit on an x86_64 Processor +---------------------------------------- + +This section describes the following: + +* :ref:`Installing the NVIDIA Docker2 Toolkit on a CentOS operating system ` + +* :ref:`Installing the NVIDIA Docker2 Toolkit on an Ubuntu operating system ` + +.. _install_nvidia_docker2_toolkit_centos: + +Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the NVIDIA Docker2 Toolkit on a CentOS operating system:** + +1. Install the repository for your distribution: + + .. code-block:: console + + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L + $ https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ + $ sudo tee /etc/yum.repos.d/nvidia-docker.repo + +2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: + + .. code-block:: console + + $ sudo yum install nvidia-docker2 + $ sudo pkill -SIGHUP dockerd + +3. Do one of the following: + + * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 `. + * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 `. + +.. _step_4_centos: + +4. Do the following: + + 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: + + + .. code-block:: console + + https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: + [Errno -1] repomd.xml signature could not be verified for nvidia-docker + + 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. + +.. _step_5_centos: + +5. Verify that the NVIDIA-Docker run has been installed correctly: + + .. code-block:: console + + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + +For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on a CentOS operating system ` + + +.. _install_nvidia_docker2_toolkit_ubuntu: + +Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the NVIDIA Docker2 Toolkit on an Ubuntu operating system:** + +1. Install the repository for your distribution: + + .. code-block:: console + + $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \ + $ sudo apt-key add - + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L + $ https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \ + $ sudo tee /etc/apt/sources.list.d/nvidia-docker.list + $ sudo apt-get update + +2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: + + .. code-block:: console + + $ sudo apt-get install nvidia-docker2 + $ sudo pkill -SIGHUP dockerd +3. Do one of the following: + * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 `. + * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 `. + + .. _step_4_ubuntu: + +4. Do the following: + + 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: + + .. code-block:: console + + https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: + [Errno -1] repomd.xml signature could not be verified for nvidia-docker + + 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. + +.. _step_5_ubuntu: + +5. Verify that the NVIDIA-Docker run has been installed correctly: + + .. code-block:: console + + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + +For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on an Ubuntu operating system ` + +.. _install_nvidia_docker2_toolkit_ppc64le_processor: + +Installing the NVIDIA Docker2 Toolkit on a PPC64le Processor +-------------------------------------- + +This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL operating system: + +**To install the NVIDIA Docker2 Toolkit on an IBM RHEL operating system:** + +1. Import the repository and install the ``libnvidia-container`` and the ``nvidia-container-runtime`` containers. + + .. code-block:: console + + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ + sudo tee /etc/yum.repos.d/nvidia-docker.repo + $ sudo yum install -y libnvidia-container* + +2. Do one of the following: + + * If you received an error when installing the containers, skip to :ref:`Step 3 `. + * If you successfully installed the containers, skip to :ref:`Step 4 `. + +.. _step_3_installing_nvidia_docker2_toolkit_ppc64le_processor: + +3. Do the following: + + 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the containers: + + .. code-block:: console + + https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: + [Errno -1] repomd.xml signature could not be verified for nvidia-docker + + 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. + + :: + + 3. Install the ``libnvidia-container`` container. + + .. code-block:: console + + $ sudo yum install -y libnvidia-container* + + .. _step_4_installing_nvidia_docker2_toolkit_ppc64le_processor: + +4. Install the ``nvidia-container-runtime`` container: + + .. code-block:: console + + $ sudo yum install -y nvidia-container-runtime* + +5. Add ``nvidia runtime`` to the Docker daemon: + + .. code-block:: console + + $ sudo mkdir -p /etc/systemd/system/docker.service.d/ + $ sudo vi /etc/systemd/system/docker.service.d/override.conf + + $ [Service] + $ ExecStart= + $ ExecStart=/usr/bin/dockerd + +6. Restart Docker: + + .. code-block:: console + + $ sudo systemctl daemon-reload + $ sudo systemctl restart docker + +7. Verify that the NVIDIA-Docker run has been installed correctly: + + .. code-block:: console + + $ docker run --runtime=nvidia --rm nvidia/cuda-ppc64le nvidia-smi + +.. _accessing_hadoop_kubernetes_configuration_files: + +Accessing the Hadoop and Kubernetes Configuration Files +-------------------------------------- +The information this section is optional and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, contact your IT department for access to the following configuration files: + +* Hadoop configuration files: + + * core-site.xml + * hdfs-site.xml + + :: + +* Kubernetes files: + + * Configuration file - krb.conf + * Kubernetes Hadoop client certificate - hdfs.keytab + +Once you have the above files, you must copy them into the correct folders in your working directory. + +For more information about the correct directory to copy the above files into, see the :ref:`Installing the SQream Software ` section below. + +For related information, see the following sections: + +* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. +* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + +.. _installing_sqream_software: + +Installing the SQream Software +============================== + +Preparing Your Local Environment +------------------------- +After installing the Nvidia Docker2 toolKit you must prepare your local environment. + +The Linux user preparing the local environment must have **read/write** access to the following directories for the SQream software to correctly read and write the required resources: + +* **Log directory** - default: /var/log/sqream/ +* **Configuration directory** - default: /etc/sqream/ +* **Cluster directory** - the location where SQream writes its DB system, such as */mnt/sqreamdb* +* **Ingest directory** - the location where the required data is loaded, such as */mnt/data_source/* + +.. _download_sqream_software: + +Deploying the SQream Software +------------------------- +After preparing your local environment you must deploy the SQream software. Deploying the SQream software requires you to access and extract the required files and to place them in the correct directory. + +**To deploy the SQream software:** + +1. Contact the SQream Support team for access to the **sqream_installer-nnn-DBnnn-COnnn-EDnnn-.tar.gz** file. + +The **sqream_installer-nnn-DBnnn-COnnn-EDnnn-.tar.gz** file includes the following parameter values: + +* **sqream_installer-nnn** - sqream installer version +* **DBnnn** - SQreamDB version +* **COnnn** - SQream console version +* **EDnnn** - SQream editor version +* **arch** - server arch (applicable to X86.64 and ppc64le) + +2. Extract the tarball file: + + .. code-block:: console + + $ tar -xvf sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz + +When the tarball file has been extracted, a new folder will be created. The new folder is automatically given the name of the tarball file: + + .. code-block:: console + + drwxrwxr-x 9 sqream sqream 4096 Aug 11 11:51 sqream_istaller-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64/ + -rw-rw-r-- 1 sqream sqream 3130398797 Aug 11 11:20 sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz + +3. Change the directory to the new folder that you created in the previous step. + +:: + +4. Verify that the folder you just created contains all of the required files. + + .. code-block:: console + + $ ls -la + + The following is an example of the files included in the new folder: + + .. code-block:: console + + drwxrwxr-x. 10 sqream sqream 198 Jun 3 17:57 . + drwx------. 25 sqream sqream 4096 Jun 7 18:11 .. + drwxrwxr-x. 2 sqream sqream 226 Jun 7 18:09 .docker + drwxrwxr-x. 2 sqream sqream 64 Jun 3 12:55 .hadoop + drwxrwxr-x. 2 sqream sqream 4096 May 31 14:18 .install + drwxrwxr-x. 2 sqream sqream 39 Jun 3 12:53 .krb5 + drwxrwxr-x. 2 sqream sqream 22 May 31 14:18 license + drwxrwxr-x. 2 sqream sqream 82 May 31 14:18 .sqream + -rwxrwxr-x. 1 sqream sqream 1712 May 31 14:18 sqream-console + -rwxrwxr-x. 1 sqream sqream 4608 May 31 14:18 sqream-install + +For information relevant to Hadoop users, see the following sections: + +* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. +* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. +* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + +.. _configure_hadoop_kubernetes_configuration_files: + +Configuring the Hadoop and Kubernetes Configuration Files +----------------------------- +The information in this section is optional and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, you must copy the Hadoop and Kubernetes files into the correct folders in your working directory as shown below: + +* .hadoop/core-site.xml +* .hadoop/hdfs-site.xml +* .krb5/krb5.conf +* .krb5/hdfs.keytab + +For related information, see the following sections: + +* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. +* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + +Configuring the SQream Software +------------------------------- +After deploying the SQream software, and optionally configuring the Hadoop and Kubernetes configuration files, you must configure the SQream software. + +Configuring the SQream software requires you to do the following: + +* Configure your local environment +* Understand the ``sqream-install`` flags +* Install your SQream license +* Validate your SQream icense +* Change your data ingest folder + +Configuring Your Local Environment +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've downloaded the SQream software, you can begin configuring your local environment. The following commands must be run (as **sudo**) from the same directory that you located your packages. + +For example, you may have saved your packages in **/home/sqream/sqream-console-package/**. + +The following table shows the flags that you can use to configure your local directory: + +.. list-table:: + :widths: 10 50 40 + :header-rows: 1 + + * - Flag + - Function + - Note + * - **-i** + - Loads all software from the hidden folder **.docker**. + - Mandatory + * - **-k** + - Loads all license packages from the **/license** directory. + - Mandatory + * - **-f** + - Overwrites existing folders. **Note** Using ``-f`` overwrites **all files** located in mounted directories. + - Mandatory + * - **-c** + - Defines the origin path for writing/reading SQream configuration files. The default location is ``/etc/sqream/``. + - If you are installing the Docker version on a server that already works with SQream, do not use the default path. + * - **-v** + - The SQream cluster location. If a cluster does not exist yet, ``-v`` creates one. If a cluster already exists, ``-v`` mounts it. + - Mandatory + * - **-l** + - SQream system startup logs location, including startup logs and docker logs. The default location is ``/var/log/sqream/``. + - + * - **-d** + - The directory containing customer data to be imported and/or copied to SQream. + - + * - **-s** + - Shows system settings. + - + * - **-r** + - Resets the system configuration. This value is run without any other variables. + - Mandatory + * - **-h** + - Help. Shows the available flags. + - Mandatory + * - **-K** + - Runs license validation + - + * - **-e** + - Used for inserting your RKrb5 server DNS name. For more information on setting your Kerberos configuration parameters, see :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + - + * - **-p** + - Used for inserting your Kerberos user name. For more information on setting your Kerberos configuration parameters, see :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + - + + +Installing Your License +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've configured your local environment, you must install your license by copying it into the SQream installation package folder located in the **./license** folder: + +.. code-block:: console + + $ sudo ./sqream-install -k + +You do not need to extract this folder after uploading into the **./license**. + + +Validating Your License +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You can copy your license package into the SQream console folder located in the **/license** folder by running the following command: + +.. code-block:: console + + $ sudo ./sqream-install -K + +The following mandatory flags must be used in the first run: + +.. code-block:: console + + $ sudo ./sqream-install -i -k -v + +The following is an example of the correct command syntax: + +.. code-block:: console + + $ sudo ./sqream-install -i -k -c /etc/sqream -v /home/sqream/sqreamdb -l + $ /var/log/sqream -d /home/sqream/data_ingest + +.. _setting_hadoop_kubernetes_connectivity_parameters: + +Setting the Hadoop and Kubernetes Connectivity Parameters +------------------------------- +The information in this section is optional, and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, you must set their connectivity parameters. + +The following is the correct syntax when setting the Hadoop and Kubernetes connectivity parameters: + +.. code-block:: console + + $ sudo ./sqream-install -p -e : + +The following is an example of setting the Hadoop and Kubernetes connectivity parameters: + +.. code-block:: console + + $ sudo ./sqream-install -p -e kdc.sq.com:<192.168.1.111> + +For related information, see the following sections: + +* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. +* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. + +Modifying Your Data Ingest Folder +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've validated your license, you can modify your data ingest folder after the first run by running the following command: + +.. code-block:: console + + $ sudo ./sqream-install -d /home/sqream/data_in + +Configuring Your Network for Docker +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've modified your data ingest folder (if needed), you must validate that the server network and Docker network that you are setting up do not overlap. + +**To configure your network for Docker:** + +1. To verify that your server network and Docker network do not overlap, run the following command: + +.. code-block:: console + + $ ifconfig | grep 172. + +2. Do one of the following: + + * If running the above command output no results, continue the installation process. + * If running the above command output results, run the following command: + + .. code-block:: console + + $ ifconfig | grep 192.168. + + +Checking and Verifying Your System Settings +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've configured your network for Docker, you can check and verify your system settings. + +Running the following command shows you all the variables used by your SQream system: + +.. code-block:: console + + $ ./sqream-install -s + +The following is an example of the correct output: + +.. code-block:: console + + SQREAM_CONSOLE_TAG=1.5.4 + SQREAM_TAG=2019.2.1 + SQREAM_EDITOR_TAG=3.0.0 + license_worker_0=f0:cc: + license_worker_1=26:91: + license_worker_2=20:26: + license_worker_3=00:36: + SQREAM_VOLUME=/media/sqreamdb + SQREAM_DATA_INGEST=/media/sqreamdb/data_in + SQREAM_CONFIG_DIR=/etc/sqream/ + LICENSE_VALID=true + SQREAM_LOG_DIR=/var/log/sqream/ + SQREAM_USER=sqream + SQREAM_HOME=/home/sqream + SQREAM_ENV_PATH=/home/sqream/.sqream/env_file + PROCESSOR=x86_64 + METADATA_PORT=3105 + PICKER_PORT=3108 + NUM_OF_GPUS=2 + CUDA_VERSION=10.1 + NVIDIA_SMI_PATH=/usr/bin/nvidia-smi + DOCKER_PATH=/usr/bin/docker + NVIDIA_DRIVER=418 + SQREAM_MODE=single_host + +Using the SQream Console +========================= +After configuring the SQream software and veriying your system settings you can begin using the SQream console. + +SQream Console - Basic Commands +--------------------------------- +The SQream console offers the following basic commands: + +* :ref:`Starting your SQream console ` +* :ref:`Starting Metadata and Picker ` +* :ref:`Starting the running services ` +* :ref:`Listing the running services ` +* :ref:`Stopping the running services ` +* :ref:`Using the SQream editor ` +* :ref:`Using the SQream Client ` + +.. _starting_sqream_console: + +Starting Your SQream Console +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can start your SQream console by running the following command: + +.. code-block:: console + + $ ./sqream-console + +.. _starting_metadata_and_picker: + +Starting the SQream Master +~~~~~~~~~~~~~~~~~ + +**To listen to metadata and picker:** + +1. Start the metadata server (default port 3105) and picker (default port 3108) by running the following command: + + .. code-block:: console + + $ sqream master --start + + The following is the correct output: + + .. code-block:: console + + sqream-console> sqream master --start + starting master server in single_host mode ... + sqream_single_host_master is up and listening on ports: 3105,3108 + + +2. *Optional* - Change the metadata and server picker ports by adding ``-p `` and ``-m ``: + + .. code-block:: console + + $ sqream-console>sqream master --start -p 4105 -m 43108 + $ starting master server in single_host mode ... + $ sqream_single_host_master is up and listening on ports: 4105,4108 + + + +.. _starting_running_services: + +Starting SQream Workers +~~~~~~~~~~~~~~~~~ + + +When starting SQream workers, setting the ```` value sets how many workers to start. Leaving the ```` value unspecified runs all of the available resources. + + +.. code-block:: console + + $ sqream worker --start + + The following is an example of expected output when setting the ```` value to ``2``: + + .. code-block:: console + + sqream-console>sqream worker --start 2 + started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 + started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 + + +.. _listing_running_services: + +Listing the Running Services +~~~~~~~~~~~~~~~~~ + +You can list running SQream services to look for container names and ID's by running the following command: + +.. code-block:: console + + $ sqream master --list + +The following is an example of the expected output: + +.. code-block:: console + + sqream-console>sqream master --list + container name: sqream_single_host_worker_0, container id: c919e8fb78c8 + container name: sqream_single_host_master, container id: ea7eef80e038-- + + +.. _stopping_running_services: + +Stopping the Running Services +~~~~~~~~~~~~~~~~~ + +You can stop running services either for a single SQream worker, or all SQream services for both master and worker. + +The following is the command for stopping a running service for a single SQream worker: + +.. code-block:: console + + $ sqream worker --stop + +The following is an example of expected output when stopping a running service for a single SQream worker: + +.. code-block:: console + + sqream worker stop + stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 + + +You can stop all running SQream services (both master and worker) by running the following command: + +.. code-block:: console + + $ sqream-console>sqream master --stop --all + +The following is an example of expected output when stopping all running services: + +.. code-block:: console + + sqream-console>sqream master --stop --all + stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 + stopped container sqream_single_host_master, id: 55cb7e38eb22 + + +.. _using_sqream_editor: + +Using SQream Studio +~~~~~~~~~~~~~~~~~ +SQream Studio is an SQL statement editor. + +**To start SQream Studio:** + +1. Run the following command: + + .. code-block:: console + + $ sqream studio --start + +The following is an example of the expected output: + + .. code-block:: console + + SQream Acceleration Studio is available at http://192.168.1.62:8080 + +2. Click the ``http://192.168.1.62:8080`` link shown in the CLI. + + +**To stop SQream Studio:** + +You can stop your SQream Studio by running the following command: + +.. code-block:: console + + $ sqream studio --stop + +The following is an example of the expected output: + +.. code-block:: console + + sqream_admin stopped + + +.. _using_sqream_client: + +Using the SQream Client +~~~~~~~~~~~~~~~~~ + + +You can use the embedded SQream Client on the following nodes: + +* Master node +* Worker node + + +When using the SQream Client on the Master node, the following default settings are used: + +* **Default port**: 3108. You can change the default port using the ``-p`` variable. +* **Default database**: master. You can change the default database using the ``-d`` variable. + +The following is an example: + +.. code-block:: console + + $ sqream client --master -u sqream -w sqream + + +When using the SQream Client on a Worker node (or nodes), you should use the ``-p`` variable for Worker ports. The default database is ``master``, but you can use the ``-d`` variable to change databases. + +The following is an example: + +.. code-block:: console + + $ sqream client --worker -p 5000 -u sqream -w sqream + + +Moving from Docker Installation to Standard On-Premises Installation +----------------------------------------------- + +Because Docker creates all files and directories on the host at the **root** level, you must grant ownership of the SQream storage folder to the working directory user. + +SQream Console - Advanced Commands +----------------------------- + +The SQream console offers the following advanced commands: + + +* :ref:`Controlling the spool size ` +* :ref:`Splitting a GPU ` +* :ref:`Splitting a GPU and setting the spool size ` +* :ref:`Using a custom configuration file ` +* :ref:`Clustering your Docker environment ` + + + + +.. _controlling_spool_size: + +Controlling the Spool Size +~~~~~~~~~~~~~~~~~~ + +From the console you can define a spool size value. + +The following example shows the spool size being set to ``50``: + +.. code-block:: console + + $ sqream-console>sqream worker --start 2 -m 50 + + +If you don't define the SQream spool size, the SQream console automatically distributes the available RAM between all running workers. + +.. _splitting_gpu: + +Splitting a GPU +~~~~~~~~~~~~~~~~~~ + +You can start more than one sqreamd on a single GPU by splitting it. + + +The following example shows the GPU being split into **two** sqreamd's on the GPU in **slot 0**: + +.. code-block:: console + + $ sqream-console>sqream worker --start 2 -g 0 + +.. _splitting_gpu_setting_spool_size: + +Splitting GPU and Setting the Spool Size +~~~~~~~~~~~~~~~~~~ + +You can simultaneously split a GPU and set the spool size by appending the ``-m`` flag: + +.. code-block:: console + + $ sqream-console>sqream worker --start 2 -g 0 -m 50 + +.. note:: The console does not validate whether the user-defined spool size is available. Before setting the spool size, verify that the requested resources are available. + +.. _using_custom_configuration_file: + +Using a Custom Configuration File +~~~~~~~~~~~~~~~~~~ + +SQream lets you use your own external custom configuration json files. You must place these json files in the path mounted in the installation. SQream recommends placing the json file in the Configuration folder. + +The SQream console does not validate the integrity of your external configuration files. + +When using your custom configuration file, you can use the ``-j`` flag to define the full path to the Configuration file, as in the example below: + +.. code-block:: console + + $ sqream-console>sqream worker --start 1 -j /etc/sqream/configfile.json + +.. note:: To start more than one sqream daemon, you must provide files for each daemon, as in the example below: + +.. code-block:: console + + $ sqream worker --start 2 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json + +.. note:: To split a specific GPU, you must also list the GPU flag, as in the example below: + +.. code-block:: console + + $ sqream worker --start 2 -g 0 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json + +.. _clustering_docker_environment: + +Clustering Your Docker Environment +~~~~~~~~~~~~~~~~~~ + +SQream lets you connect to a remote Master node to start Docker in Distributed mode. If you have already connected to a Slave node server in Distributed mode, the **sqream Master** and **Client** commands are only available on the Master node. + +.. code-block:: console + + $ --master-host + $ sqream-console>sqream worker --start 1 --master-host 192.168.0.1020 + +Checking the Status of SQream Services +--------------------------- +SQream lets you check the status of SQream services from the following locations: + +* :ref:`From the Sqream console ` +* :ref:`From outside the Sqream console ` + +.. _inside_sqream_console: + +Checking the Status of SQream Services from the SQream Console +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +From the SQream console, you can check the status of SQream services by running the following command: + +.. code-block:: console + + $ sqream-console>sqream master --list + +The following is an example of the expected output: + +.. code-block:: console + + $ sqream-console>sqream master --list + $ checking 3 sqream services: + $ sqream_single_host_worker_1 up, listens on port: 5001 allocated gpu: 1 + $ sqream_single_host_worker_0 up, listens on port: 5000 allocated gpu: 1 + $ sqream_single_host_master up listens on ports: 3105,3108 + +.. _outside_sqream_console: + +Checking the Status of SQream Services from Outside the SQream Console +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +From outside the Sqream Console, you can check the status of SQream services by running the following commands: + +.. code-block:: console + + $ sqream-status + $ NAMES STATUS PORTS + $ sqream_single_host_worker_1 Up 3 minutes 0.0.0.0:5001->5001/tcp + $ sqream_single_host_worker_0 Up 3 minutes 0.0.0.0:5000->5000/tcp + $ sqream_single_host_master Up 3 minutes 0.0.0.0:3105->3105/tcp, 0.0.0.0:3108->3108/tcp + $ sqream_editor_3.0.0 Up 3 hours (healthy) 0.0.0.0:3000->3000/tcp + +Upgrading Your SQream System +---------------------------- +This section describes how to upgrade your SQream system. + +**To upgrade your SQream system:** + +1. Contact the SQream Support team for access to the new SQream package tarball file. + + :: + +2. Set a maintenance window to enable stopping the system while upgrading it. + + :: + +3. Extract the following tarball file received from the SQream Support team, under it with the same user and in the same folder that you used while :ref:`Downloading the SQream Software <_download_sqream_software>`. + + + .. code-block:: console + + $ tar -xvf sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ + +4. Navigate to the new folder created as a result of extracting the tarball file: + + .. code-block:: console + + $ cd sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ + +5. Initiate the upgrade process: + + .. code-block:: console + + $ ./sqream-install -i + + Initiating the upgrade process checks if any SQream services are running. If any services are running, you will be prompted to stop them. + +6. Do one of the following: + + * Select **Yes** to stop all running SQream workers (Master and Editor) and continue the upgrade process. + * Select **No** to stop the upgrade process. + + SQream periodically upgrades the metadata structure. If an upgrade version includes a change to the metadata structure, you will be prompted with an approval request message. Your approval is required to finish the upgrade process. + + Because SQream supports only certain metadata versions, all SQream services must be upgraded at the same time. + +7. When the upgrade is complete, load the SQream console and restart your services. + + For assistance, contact SQream Support. From 7f9bf30e39733bdc4bf62898f557559c1c00237b Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 3 Nov 2021 12:03:59 +0200 Subject: [PATCH 081/300] Update index.rst Included running_sqream_in_a_docker_container in index. --- guides/operations/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/guides/operations/index.rst b/guides/operations/index.rst index 16aeca767..3942838e3 100644 --- a/guides/operations/index.rst +++ b/guides/operations/index.rst @@ -15,6 +15,7 @@ The guides in this section include information about best practices, monitoring, xxmonitoring monitoring_query_performance launching_sqream_with_monit + running_sqream_in_a_docker_container logging configuration troubleshooting From 900c7e1d8ad5236103efb1b30255eee943025152 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 3 Nov 2021 12:15:15 +0200 Subject: [PATCH 082/300] Update first_steps.rst Updated page according to Master. --- first_steps.rst | 291 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 212 insertions(+), 79 deletions(-) diff --git a/first_steps.rst b/first_steps.rst index 160d6f11a..b20147c2d 100644 --- a/first_steps.rst +++ b/first_steps.rst @@ -1,35 +1,54 @@ .. _first_steps: **************************** -First steps with SQream DB +Getting Started **************************** -.. TODO: part one of the tutorial is how to connect with clientcmd, -.. and create some tables, insert data and query it -.. part 2: expand on this -.. how to run sqream/check it's running -.. how to add a database and do roles and permissions (to get started) -.. options for inserting data - overview of all of them -.. deleting/managing data overview (including storage reorg) +The **Getting Started** page describes the following: -This tutorial takes you through a few basic operations in SQream DB. - -.. contents:: In this topic: +.. contents:: :local: + :depth: 1 + +Before Installing SQream +============================ +Before installing SQream, you must set up your local machine according to SQream's recommended pre-installation configurations. + +For more information, see the following: + +* `Hardware Guide `_. +* `Recommended Pre-Installation Configuration `_. -Preparing for this tutorial -=============================== -This tutorial assumes you already have a SQream DB cluster running and the SQream command line client installed on the machine you are on. -.. rubric:: If you haven't already: -* :ref:`Set up a SQream DB cluster` -* :ref:`Install SQream SQL CLI` +Installing SQream +============================ +The **Installing SQream** section includes the following SQream installation methods: + +* `Installing SQream natively `_ - Describes installing SQream using binary packages provided by SQream. +* `Installing SQream with Kubernetes `_ - Describes installing SQream using the Kubernetes open source platform. +* `Installing and running SQream in a Docker container `_ - Describes how to run SQream in a Docker container. + +Using the SQream SQL Command Line Interface +============================================ +SQream includes a built-in client for executing SQL statements either interactively or using the Command Line Interface (CLI). The **SQream SQL CLI Reference** page provides a reference for the options and parameters. +For more information, see `SQream SQL CLI Reference `_. -Run the SQream SQL client like this. It will interactively ask for the password. +Performing Basic SQream Operations +==================================== +After installing SQream you can perform the operations described in the **Performing Basic SQream Operations** section: + +.. contents:: + :local: + :depth: 1 + + +Running the SQream SQL Client +--------------------------------- +The following example shows how to run the SQream SQL client: .. code-block:: psql @@ -41,46 +60,57 @@ Run the SQream SQL client like this. It will interactively ask for the password. master=> _ -You should use a username and password that you have set up or your DBA has given you. +Running the SQream SQL client prompts you to provide your password. Use the username and password that you have set up, or your DBA has provided. .. tip:: - * To exit the shell, type ``\q`` or :kbd:`Ctrl-d`. - * A new SQream DB cluster contains a database named `master`. We will start with this database. + * You can exit the shell by typing ``\q`` or :kbd:`Ctrl-d`. + * A new SQream cluster contains a database named `master,` which is the database used in the examples on this page. -Create a new database for playing around in -======================================================= +Creating a New Database +-------------------------- +**To create a new database:** -To create a database, we will use the :ref:`create_database` syntax. +1. Write a :ref:`create_database` statement. -.. code-block:: psql + The following is an example of creating a new database: - master=> CREATE DATABASE test; - executed + .. code-block:: psql -Now, reconnect to the newly created database. + master=> CREATE DATABASE test; + executed -First, exit the client by typing ``\q`` and hitting enter. +2. Reconnect to the newly created database. -From the Linux shell, restart the client with the new database name: + 1. Exit the client by typing ``\q`` and pressing **Enter**. + 2. From the Linux shell, restart the client with the new database name: -.. code-block:: psql + .. code-block:: psql - $ sqream sql --port=5000 --username=rhendricks -d test - Password: + $ sqream sql --port=5000 --username=rhendricks -d test + Password: - Interactive client mode - To quit, use ^D or \q. + Interactive client mode + To quit, use ^D or \q. - test=> _ + test=> _ -The new database name appears in the prompt. This lets you know which database you're connected to. + The name of the new database that you are connected to is displayed in the prompt. -Creating your first table -============================ +Creating Your First Table +------------------------------ +The **Creating Your First Table** section describes the following: -To create a table, we will use the :ref:`create_table` syntax, with a table name and some column specifications. +* :ref:`Creating a table` +* :ref:`Replacing a table` +* :ref:`Listing a CREATE TABLE statement` +* :ref:`Dropping a table` -For example, + +.. _creating_a_table: + +**Creating a Table** + +The ``CREATE TABLE`` syntax is used to create your first table. This table includes a table name and column specifications, as shown in the following example: .. code-block:: postgres @@ -90,7 +120,13 @@ For example, weight INT ); -If the table already exists and you want to drop the current table and create a new one, you can add ``OR REPLACE`` after the ``CREATE`` keyword. +For more information on creating a table, see :ref:`create_table`. + +.. _replacing_a_table: + +**Replacing a Table** + +You can drop an existing table and create a new one by adding the ``OR REPLACE`` parameter after the ``CREATE`` keyword, as shown in the following example: .. code-block:: postgres @@ -101,9 +137,12 @@ If the table already exists and you want to drop the current table and create a ); .. TODO: cool_animals? I think we need to decide if the customer for this documenation is 12 years old, or an IT professional. - -You can ask SQream DB to list the full, verbose ``CREATE TABLE`` statement for any table, by using the :ref:`get_ddl` function, with the table name. +.. _listing_a_create_table_statement: + +**Listing a CREATE TABLE Statement** + +You can list the full, verbose ``CREATE TABLE`` statement for a table by using the **GET DDL** function with the table name as shown in the following example: .. code-block:: psql @@ -114,22 +153,30 @@ You can ask SQream DB to list the full, verbose ``CREATE TABLE`` statement for a "weight" int ); -.. note: +.. note:: + * SQream DB identifier names such as table names and column names are not case sensitive. SQream DB lowercases all identifiers bu default. If you want to maintain case, enclose the identifiers with double-quotes. * SQream DB places all tables in the `public` schema, unless another schema is created and specified as part of the table name. + +For information on listing a ``CREATE TABLE`` statement, see :ref:`get_ddl`. + +.. _dropping_a_table: -If you are done with this table, you can use :ref:`drop_table` to remove the table and all of its data. +**Dropping a Table** + +When you have finished working with your table, you can drop the table to remove it table and its content, as shown in the following example: .. code-block:: psql test=> DROP TABLE cool_animals; executed + +For more information on dropping tables, see :ref:`drop_table`. -Listing tables -================= - -To see the tables in the current database, we will query the catalog +Listing Tables +------------------ +To see the tables in the current database you can query the catalog, as shown in the following example: .. code-block:: psql @@ -138,12 +185,21 @@ To see the tables in the current database, we will query the catalog 1 rows +Inserting Rows +------------------- +The **Inserting Rows** section describes the following: + +* :ref:`Inserting basic rows` +* :ref:`Changing value order` +* :ref:`Inserting multiple rows` +* :ref:`Omitting columns` + + +.. _inserting_basic_rows: -Inserting rows -================= +**Inserting Basic Rows** -Inserting rows into a table can be performed with the :ref:`insert` statement. -The statement includes the table name, an optional list of column names, and column values listed in the same order as the column names: +You can insert basic rows into a table using the ``INSERT`` statement. The inserted statement includes the table name, an optional list of column names, and column values listed in the same order as the column names, as shown in the following example: .. code-block:: psql @@ -151,7 +207,11 @@ The statement includes the table name, an optional list of column names, and col executed -To change the order of values, specify the column order: +.. _changing_value_order: + +**Changing Value Order** + +You can change the order of values by specifying the column order, as shown in the following example: .. code-block:: psql @@ -159,7 +219,11 @@ To change the order of values, specify the column order: executed -You can use ``INSERT`` to insert multiple rows too. Here, you use sets of parentheses separated by commas: +.. _inserting_multiple_rows: + +**Inserting Multiple Rows** + +You can insert multiple rows using the ``INSERT`` statement by using sets of parentheses separated by commas, as shown in the following example: .. code-block:: psql @@ -170,9 +234,13 @@ You can use ``INSERT`` to insert multiple rows too. Here, you use sets of parent executed -.. note:: To load big data sets, use bulk loading methods instead. See our :ref:`inserting_data` guide for more information. +.. note:: You can load large data sets using bulk loading methods instead. For more information, see :ref:`inserting_data`. + +.. _omitting_columns: -When you leave out columns that have a :ref:`default value` (including default ``NULL`` value) the default value is used. +**Omitting Columns** + +Omitting columns that have a default values (including default ``NULL`` values) uses the default value, as shown in the following example: .. code-block:: psql @@ -197,10 +265,28 @@ When you leave out columns that have a :ref:`default value` (inc .. note:: Null row values are represented as ``\N`` -Queries -========= +For more information on inserting rows, see :ref:`insert`. + +For more information on default values, see :ref:`default value`. + + +Running Queries +------------------ +The **Running Queries** section describes the following: -For querying, use the :ref:`select` keyword, followed by a list of columns and values to be returned, and the table to get the data from. +* :ref:`Running basic queries` +* :ref:`Outputting all columns` +* :ref:`Outputting shorthand table values` +* :ref:`Filtering results` +* :ref:`Sorting results` +* :ref:`Filtering null rows` + + +.. _running_basic_queries: + +**Running Basic Queries** + +You can run a basic query using the ``SELECT`` keyword, followed by a list of columns and values to be returned, and the table to get the data from, as shown in the following example: .. code-block:: psql @@ -213,8 +299,14 @@ For querying, use the :ref:`select` keyword, followed by a list of columns and v 6,\N,\N 6 rows + +For more information on the ``SELECT`` keyword, see :ref:`select`. -To get all columns without specifying them, use the star operator ``*``: +.. _outputting_all_columns: + +**To Output All Columns** + +You can output all columns without specifying them using the star operator ``*``, as shown in the following example: .. code-block:: psql @@ -228,7 +320,11 @@ To get all columns without specifying them, use the star operator ``*``: 6 rows -To get the number of values in a table without getting the full result set, use :ref:`COUNT(*)`: +.. _outputting_shorthand_table_values: + +**Outputting Shorthand Table Values** + +You can output the number of values in a table without getting the full result set by using the ``COUNT`` statement: .. code-block:: psql @@ -237,8 +333,11 @@ To get the number of values in a table without getting the full result set, use 1 row +.. _filtering_results: -Filter results by adding a :ref:`WHERE` clause and specifying the filter condition: +**Filtering Results** + +You can filter results by adding a ``WHERE`` clause and specifying the filter condition, as shown in the following example: .. code-block:: psql @@ -248,7 +347,11 @@ Filter results by adding a :ref:`WHERE` clause and specifying the filter 2 rows -Sort the results by adding an :ref:`ORDER BY` clause, and specifying ascending (``ASC``) or descending (``DESC``) order: +.. _sorting_results: + +**Sorting Results** + +You can sort results by adding an ``ORDER BY`` clause and specifying ascending (``ASC``) or descending (``DESC``) order, as shown in the following example: .. code-block:: psql @@ -262,7 +365,11 @@ Sort the results by adding an :ref:`ORDER BY` clause, and specifying a 6 rows -Filter null rows by adding a filter :ref:`IS NOT NULL`: +.. _filtering_null_rows: + +**Filtering Null Rows** + +You can filter null rows by adding an ``IS NOT NULL`` filter, as shown in the following example: .. code-block:: psql @@ -274,11 +381,28 @@ Filter null rows by adding a filter :ref:`IS NOT NULL`: 2,Possum ,3 5 rows + +For more information, see the following: + +* Outputting the number of values in a table without getting the full result set - :ref:`COUNT(*)`. +* Filtering results - :ref:`WHERE` +* Sorting results - :ref:`ORDER BY` +* Filtering rows - :ref:`IS NOT NULL` + + -Deleting rows -============== +Deleting Rows +----------------- +The **Deleting Rows** section describes the following: -To delete rows in a table selectively, use the :ref:`DELETE` command, with a table name and a `WHERE` clause to specify which rows are to be deleted: +* :ref:`Deleting selected rows` +* :ref:`Deleting all rows` + +.. _deleting_selected_rows: + +**Deleting Selected Rows** + +You can delete rows in a table selectively using the ``DELETE`` command. You must include a table name and `WHERE` clause to specify the rows to delete, as shown in the following example: .. code-block:: psql @@ -294,7 +418,11 @@ To delete rows in a table selectively, use the :ref:`DELETE` command, wi 5 rows -To delete all rows in a table, use the :ref:`TRUNCATE` command followed by the table name: +.. _deleting_all_rows: + +**Deleting All Rows** + +You can delete all rows in a table using the ``TRUNCATE`` command followed by the table name, as shown in the following example: .. code-block:: psql @@ -302,12 +430,18 @@ To delete all rows in a table, use the :ref:`TRUNCATE` command followe executed -.. note:: While :ref:`truncate` deletes data from disk immediately, :ref:`delete` does not physically remove the deleted rows. For more information on removing the rows from disk, see :ref:`delete`. +.. note:: While :ref:`truncate` deletes data from disk immediately, :ref:`delete` does not physically remove the deleted rows. -Saving query results to a CSV or PSV file -============================================== +For more information, see the following: -The command line client :ref:`sqream sql` can be used to save query results to a CSV or other delimited file format. +* Deleting selected rows - :ref:`DELETE` +* Deleting all rows - :ref:`TRUNCATE` + +Saving Query Results to a CSV or PSV File +-------------------------------------------- + + +You can save query results to a CSV or PSV file using the ``sqream sql`` command from a CLI client. This saves your query results to the selected delimited file format, as shown in the following example: .. code-block:: console @@ -319,11 +453,10 @@ The command line client :ref:`sqream sql` can be used R.J. Hunter |Boston Celtics |28|SG|22|6-5 |185|Georgia State |1148640 Jonas Jerebko |Boston Celtics |8|PF|29|6-10|231|\N|5000000 - -See the :ref:`Controlling the output of the client` section of the reference for more options. +For more output options, see :ref:`Controlling the Client Output`. .. rubric:: What's next? -* Explore all of SQream DB's :ref:`SQL Syntax ` -* See the full :ref:`SQream SQL CLI reference ` -* Connect a :ref:`third party tool to SQream DB ` and start analyzing data +* Explore all of SQream DB's :ref:`SQL Syntax `. +* See the full :ref:`SQream SQL CLI reference `. +* Connect a :ref:`third party tool ` to start analyzing data. From 91d70c5054d0a51afbf89caa65462cf1b6f81d28 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 3 Nov 2021 12:53:57 +0200 Subject: [PATCH 083/300] Create running_sqream_in_a_docker_container.rst Created Docker page based on Master. --- .../running_sqream_in_a_docker_container.rst | 1488 +++++++++++++++++ 1 file changed, 1488 insertions(+) create mode 100644 guides/operations/running_sqream_in_a_docker_container.rst diff --git a/guides/operations/running_sqream_in_a_docker_container.rst b/guides/operations/running_sqream_in_a_docker_container.rst new file mode 100644 index 000000000..7750db570 --- /dev/null +++ b/guides/operations/running_sqream_in_a_docker_container.rst @@ -0,0 +1,1488 @@ +.. _running_sqream_in_a_docker_container: + + + +*********************** +Running SQream in a Docker Container +*********************** + + +This document describes how to prepare your machine's environment for installing and running SQream in a Docker container. + +.. contents:: This page describes the following: + :depth: 2 + +Setting Up a Host +==================================== + +Operating System Requirements +------------------------------------ +SQream was tested and verified on the following versions of Linux: + + * x86 CentOS/RHEL 7.6 - 7.9 + * IBM RHEL 7.6 + +SQream recommends installing a clean OS on the host to avoid any installation issues. + +.. warning:: Docker-based installation supports only single host deployment and cannot be used on a multi-node cluster. Installing Docker on a single host you will not be able to scale it to a multi-node cluster. + + +Creating a Local User +---------------- +To run SQream in a Docker container you must create a local user. + +**To create a local user:** + +1. Add a local user: + + .. code-block:: console + + $ useradd -m -U sqream + +2. Set the local user's password: + + .. code-block:: console + + $ passwd sqream + +3. Add the local user to the ``wheel`` group: + + .. code-block:: console + + $ usermod -aG wheel sqream + + You can remove the local user from the ``wheel`` group when you have completed the installation. + +4. Log out and log back in as the local user. + +Setting a Local Language +---------------- +After creating a local user you must set a local language. + +**To set a local language:** + +1. Set the local language: + + .. code-block:: console + + $ sudo localectl set-locale LANG=en_US.UTF-8 + +2. Set the time stamp (time and date) of the locale: + + .. code-block:: console + + $ sudo timedatectl set-timezone Asia/Jerusalem + +You can run the ``timedatectl list-timezones`` command to see your timezone. + +Adding the EPEL Repository +---------------- +After setting a local language you must add the EPEL repository. + +**To add the EPEL repository:** + +1. As a root user, upgrade the **epel-release-latest-7.noarch.rpm** repository: + + 1. RedHat (RHEL 7): + + .. code-block:: console + + $ sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + + 2. CentOS 7 + + .. code-block:: console + + $ sudo yum install epel-release + +Installing the Required NTP Packages +---------------- +After adding the EPEL repository, you must install the required NTP packages. + +You can install the required NTP packages by running the following command: + +.. code-block:: console + + $ sudo yum install ntp pciutils python36 kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc + +Installing the Recommended Tools +---------------- +After installin gthe required NTP packages you must install the recommended tools. + +SQream recommends installing the following recommended tools: + +.. code-block:: console + + $ sudo yum install bash-completion.noarch vim-enhanced.x86_64 vim-common.x86_64 net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix + +Updating to the Current Version of the Operating System +---------------- +After installing the recommended tools you must update to the current version of the operating system. + +SQream recommends updating to the current version of the operating system. This is not recommended if the nvidia driver has **not been installed.** + + + +Configuring the NTP Package +---------------- +After updating to the current version of the operating system you must configure the NTP package. + +**To configure the NTP package:** + +1. Add your local servers to the NTP configuration. + + :: + +2. Configure the **ntpd** service to begin running when your machine is started: + + .. code-block:: console + + $ sudo systemctl enable ntpd + $ sudo systemctl start ntpd + $ sudo ntpq -p + +Configuring the Performance Profile +---------------- +After configuring the NTP package you must configure the performance profile. + +**To configure the performance profile:** + +1. Switch the active profile: + + .. code-block:: console + + $ sudo tuned-adm profile throughput-performance + +2. Change the multi-user's default run level: + + .. code-block:: console + + $ sudo systemctl set-default multi-user.target + +Configuring Your Security Limits +---------------- +After configuring the performance profile you must configure your security limits. Configuring your security limits refers to configuring the number of open files, processes, etc. + +**To configure your security limits:** + +1. Run the **bash** shell as a super-user: + + .. code-block:: console + + $ sudo bash + +2. Run the following command: + + .. code-block:: console + + $ echo -e "sqream soft nproc 500000\nsqream hard nproc 500000\nsqream soft nofile 500000\nsqream hard nofile 500000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + +3. Run the following command: + + .. code-block:: console + + $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.zone_reclaim_mode = 0 \n vm.vfs_cache_pressure = 200 \n" >> /etc/sysctl.conf + +Disabling Automatic Bug-Reporting Tools +---------------- +After configuring your security limits you must disable the following automatic bug-reporting tools: + +* ccpp.service +* oops.service +* pstoreoops.service +* vmcore.service +* xorg.service + +You can abort the above but-reporting tools by running the following command: + +.. code-block:: console + + $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done + +Installing the Nvidia CUDA Driver +------------------------------------- + +1. Verify that the Tesla NVIDIA card has been installed and is detected by the system: + + .. code-block:: console + + $ lspci | grep -i nvidia + + The correct output is a list of Nvidia graphic cards. If you do not receive this output, verify that an NVIDIA GPU card has been installed. + +#. Verify that the open-source upstream Nvidia driver is running: + + .. code-block:: console + + $ lsmod | grep nouveau + + No output should be generated. + +#. If you receive any output, do the following: + + 1. Disable the open-source upstream Nvidia driver: + + .. code-block:: console + + $ sudo bash + $ echo "blacklist nouveau" > /etc/modprobe.d/blacklist-nouveau.conf + $ echo "options nouveau modeset=0" >> /etc/modprobe.d/blacklist-nouveau.conf + $ dracut --force + $ modprobe --showconfig | grep nouveau + + 2. Reboot the server and verify that the Nouveau model has not been loaded: + + .. code-block:: console + + $ lsmod | grep nouveau + +#. Check if the Nvidia CUDA driver has already been installed: + + .. code-block:: console + + $ nvidia-smi + + The following is an example of the correct output: + + .. code-block:: console + + nvidia-smi + Wed Oct 30 14:05:42 2019 + +-----------------------------------------------------------------------------+ + | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + |-------------------------------+----------------------+----------------------+ + | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + |===============================+======================+======================| + | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | + | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | + | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + + +-----------------------------------------------------------------------------+ + | Processes: GPU Memory | + | GPU PID Type Process name Usage | + |=============================================================================| + | No running processes found | + +-----------------------------------------------------------------------------+ + +#. Verify that the installed CUDA version shown in the output above is ``10.1``. + + :: + + +#. Do one of the following: + + :: + + 1. If CUDA version 10.1 has already been installed, skip to Docktime Runtime (Community Edition). + :: + + 2. If CUDA version 10.1 has not been installed yet, continue with Step 7 below. + +#. Do one of the following: + + * Install :ref:`CUDA Driver version 10.1 for x86_64 `. + + :: + + * Install :ref:`CUDA driver version 10.1 for IBM Power9 `. + +.. _CUDA_10.1_x8664: + +Installing the CUDA Driver Version 10.1 for x86_64 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the CUDA driver version 10.1 for x86_64:** + +1. Make the following target platform selections: + + :: + + * **Operating system**: Linux + * **Architecture**: x86_64 + * **Distribution**: CentOS + * **Version**: 7 + * **Installer type**: the relevant installer type + +For installer type, SQream recommends selecting **runfile (local)**. The available selections shows only the supported platforms. + +2. Download the base installer for Linux CentOS 7 x86_64: + + .. code-block:: console + + wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm + + +3. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: + + .. code-block:: console + + $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm + $ sudo yum clean all + $ sudo yum install nvidia-driver-latest-dkms + +.. warning:: Verify that the output indicates that driver **418.87** will be installed. + +4. Follow the command line prompts. + + + :: + + +5. Enable the Nvidia service to start at boot and start it: + + .. code-block:: console + + $ sudo systemctl enable nvidia-persistenced.service && sudo systemctl start nvidia-persistenced.service + +6. Create a symbolic link from the **/etc/systemd/system/multi-user.target.wants/nvidia-persistenced.service** file to the **/usr/lib/systemd/system/nvidia-persistenced.service** file. + + :: + +7. Reboot the server. + + :: +8. Verify that the Nvidia driver has been installed and shows all available GPU's: + + .. code-block:: console + + $ nvidia-smi + + The following is the correct output: + + .. code-block:: console + + nvidia-smi + Wed Oct 30 14:05:42 2019 + +-----------------------------------------------------------------------------+ + | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + |-------------------------------+----------------------+----------------------+ + | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + |===============================+======================+======================| + | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | + | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | + | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + + +-----------------------------------------------------------------------------+ + | Processes: GPU Memory | + | GPU PID Type Process name Usage | + |=============================================================================| + | No running processes found | + +-----------------------------------------------------------------------------+ + +.. _CUDA_10.1_IBMPower9: + +Installing the CUDA Driver Version 10.1 for IBM Power9 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the CUDA driver version 10.1 for IBM Power9:** + +1. Download the base installer for Linux CentOS 7 PPC64le: + + .. code-block:: console + + wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm + + +#. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: + + .. code-block:: console + + $ sudo rpm -i cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm + $ sudo yum clean all + $ sudo yum install nvidia-driver-latest-dkms + +.. warning:: Verify that the output indicates that driver **418.87** will be installed. + + + +3. Copy the file to the **/etc/udev/rules.d** directory. + + :: + +4. If you are using RHEL 7 version (7.6 or later), comment out, remove, or change the hot-pluggable memory rule located in file copied to the **/etc/udev/rules.d** directory by running the following command: + + .. code-block:: console + + $ sudo cp /lib/udev/rules.d/40-redhat.rules /etc/udev/rules.d + $ sudo sed -i 's/SUBSYSTEM!="memory",.*GOTO="memory_hotplug_end"/SUBSYSTEM=="*", GOTO="memory_hotplug_end"/' /etc/udev/rules.d/40-redhat.rules + +#. Enable the **nvidia-persisted.service** file: + + .. code-block:: console + + $ sudo systemctl enable nvidia-persistenced.service + +#. Create a symbolic link from the **/etc/systemd/system/multi-user.target.wants/nvidia-persistenced.service** file to the **/usr/lib/systemd/system/nvidia-persistenced.service** file. + + :: + +#. Reboot your system to initialize the above modifications. + + :: + +#. Verify that the Nvidia driver and the **nvidia-persistenced.service** files are running: + + .. code-block:: console + + $ nvidia smi + + The following is the correct output: + + .. code-block:: console + + nvidia-smi + Wed Oct 30 14:05:42 2019 + +-----------------------------------------------------------------------------+ + | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + |-------------------------------+----------------------+----------------------+ + | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + |===============================+======================+======================| + | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | + | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | + | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + + +-----------------------------------------------------------------------------+ + | Processes: GPU Memory | + | GPU PID Type Process name Usage | + |=============================================================================| + | No running processes found | + +-----------------------------------------------------------------------------+ + +#. Verify that the **nvidia-persistenced** service is running: + + .. code-block:: console + + $ systemctl status nvidia-persistenced + + The following is the correct output: + + .. code-block:: console + + root@gpudb ~]systemctl status nvidia-persistenced + nvidia-persistenced.service - NVIDIA Persistence Daemon + Loaded: loaded (/usr/lib/systemd/system/nvidia-persistenced.service; enabled; vendor preset: disabled) + Active: active (running) since Tue 2019-10-15 21:43:19 KST; 11min ago + Process: 8257 ExecStart=/usr/bin/nvidia-persistenced --verbose (code=exited, status=0/SUCCESS) + Main PID: 8265 (nvidia-persiste) + Tasks: 1 + Memory: 21.0M + CGroup: /system.slice/nvidia-persistenced.service + └─8265 /usr/bin/nvidia-persistenced --verbose + +Installing the Docker Engine (Community Edition) +======================= +After installing the Nvidia CUDA driver you must install the Docker engine. + +This section describes how to install the Docker engine using the following processors: + +* :ref:`Using x86_64 processor on CentOS ` +* :ref:`Using x86_64 processor on Ubuntu ` +* :ref:`Using IBM Power9 (PPC64le) processor ` + + +.. _dockerx8664centos: + +Installing the Docker Engine Using an x86_64 Processor on CentOS +--------------------------------- +The x86_64 processor supports installing the **Docker Community Edition (CE)** versions 18.03 and higher. + +For more information on installing the Docker Engine CE on an x86_64 processor, see `Install Docker Engine on CentOS `_ + + + +.. _dockerx8664ubuntu: + +Installing the Docker Engine Using an x86_64 Processor on Ubuntu +----------------------------------------------------- + + +The x86_64 processor supports installing the **Docker Community Edition (CE)** versions 18.03 and higher. + +For more information on installing the Docker Engine CE on an x86_64 processor, see `Install Docker Engine on Ubuntu `_ + +.. _docker_ibmpower9: + +Installing the Docker Engine on an IBM Power9 Processor +---------------------------------------- +The x86_64 processor only supports installing the **Docker Community Edition (CE)** version 18.03. + + +**To install the Docker Engine on an IBM Power9 processor:** + +You can install the Docker Engine on an IBM Power9 processor by running the following command: + +.. code-block:: console + + $ wget + $ http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm + $ wget + $ http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm + $ yum install -y container-selinux-2.9-4.el7.noarch.rpm + $ docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm + + + +For more information on installing the Docker Engine CE on an IBM Power9 processor, see `Install Docker Engine on Ubuntu `_. + +Docker Post-Installation +================================= +After installing the Docker engine you must configure Docker on your local machine. + +**To configure Docker on your local machine:** + +1. Enable Docker to start on boot: + + .. code-block:: console + + $ sudo systemctl enable docker && sudo systemctl start docker + +2. Enable managing Docker as a non-root user: + + .. code-block:: console + + $ sudo usermod -aG docker $USER + +3. Log out and log back in via SSH. This causes Docker to re-evaluate your group membership. + + :: + +4. Verify that you can run the following Docker command as a non-root user (without ``sudo``): + + .. code-block:: console + + $ docker run hello-world + +If you can run the above Docker command as a non-root user, the following occur: + +* Docker downloads a test image and runs it in a container. +* When the container runs, it prints an informational message and exits. + +For more information on installing the Docker Post-Installation, see `Docker Post-Installation `_. + +Installing the Nvidia Docker2 ToolKit +========================================== +After configuring Docker on your local machine you must install the Nvidia Docker2 ToolKit. The NVIDIA Docker2 Toolkit lets you build and run GPU-accelerated Docker containers. The Toolkit includes a container runtime library and related utilities for automatically configuring containers to leverage NVIDIA GPU's. + +This section describes the following: + +* :ref:`Installing the NVIDIA Docker2 Toolkit on an x86_64 processor. ` +* :ref:`Installing the NVIDIA Docker2 Toolkit on a PPC64le processor. ` + +.. _install_nvidia_docker2_toolkit_x8664_processor: + +Installing the NVIDIA Docker2 Toolkit on an x86_64 Processor +---------------------------------------- + +This section describes the following: + +* :ref:`Installing the NVIDIA Docker2 Toolkit on a CentOS operating system ` + +* :ref:`Installing the NVIDIA Docker2 Toolkit on an Ubuntu operating system ` + +.. _install_nvidia_docker2_toolkit_centos: + +Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the NVIDIA Docker2 Toolkit on a CentOS operating system:** + +1. Install the repository for your distribution: + + .. code-block:: console + + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L + $ https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ + $ sudo tee /etc/yum.repos.d/nvidia-docker.repo + +2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: + + .. code-block:: console + + $ sudo yum install nvidia-docker2 + $ sudo pkill -SIGHUP dockerd + +3. Do one of the following: + + * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 `. + * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 `. + +.. _step_4_centos: + +4. Do the following: + + 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: + + + .. code-block:: console + + https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: + [Errno -1] repomd.xml signature could not be verified for nvidia-docker + + 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. + +.. _step_5_centos: + +5. Verify that the NVIDIA-Docker run has been installed correctly: + + .. code-block:: console + + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + +For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on a CentOS operating system ` + + +.. _install_nvidia_docker2_toolkit_ubuntu: + +Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the NVIDIA Docker2 Toolkit on an Ubuntu operating system:** + +1. Install the repository for your distribution: + + .. code-block:: console + + $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \ + $ sudo apt-key add - + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L + $ https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \ + $ sudo tee /etc/apt/sources.list.d/nvidia-docker.list + $ sudo apt-get update + +2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: + + .. code-block:: console + + $ sudo apt-get install nvidia-docker2 + $ sudo pkill -SIGHUP dockerd +3. Do one of the following: + * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 `. + * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 `. + + .. _step_4_ubuntu: + +4. Do the following: + + 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: + + .. code-block:: console + + https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: + [Errno -1] repomd.xml signature could not be verified for nvidia-docker + + 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. + +.. _step_5_ubuntu: + +5. Verify that the NVIDIA-Docker run has been installed correctly: + + .. code-block:: console + + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + +For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on an Ubuntu operating system ` + +.. _install_nvidia_docker2_toolkit_ppc64le_processor: + +Installing the NVIDIA Docker2 Toolkit on a PPC64le Processor +-------------------------------------- + +This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL operating system: + +**To install the NVIDIA Docker2 Toolkit on an IBM RHEL operating system:** + +1. Import the repository and install the ``libnvidia-container`` and the ``nvidia-container-runtime`` containers. + + .. code-block:: console + + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ + sudo tee /etc/yum.repos.d/nvidia-docker.repo + $ sudo yum install -y libnvidia-container* + +2. Do one of the following: + + * If you received an error when installing the containers, skip to :ref:`Step 3 `. + * If you successfully installed the containers, skip to :ref:`Step 4 `. + +.. _step_3_installing_nvidia_docker2_toolkit_ppc64le_processor: + +3. Do the following: + + 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the containers: + + .. code-block:: console + + https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: + [Errno -1] repomd.xml signature could not be verified for nvidia-docker + + 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. + + :: + + 3. Install the ``libnvidia-container`` container. + + .. code-block:: console + + $ sudo yum install -y libnvidia-container* + + .. _step_4_installing_nvidia_docker2_toolkit_ppc64le_processor: + +4. Install the ``nvidia-container-runtime`` container: + + .. code-block:: console + + $ sudo yum install -y nvidia-container-runtime* + +5. Add ``nvidia runtime`` to the Docker daemon: + + .. code-block:: console + + $ sudo mkdir -p /etc/systemd/system/docker.service.d/ + $ sudo vi /etc/systemd/system/docker.service.d/override.conf + + $ [Service] + $ ExecStart= + $ ExecStart=/usr/bin/dockerd + +6. Restart Docker: + + .. code-block:: console + + $ sudo systemctl daemon-reload + $ sudo systemctl restart docker + +7. Verify that the NVIDIA-Docker run has been installed correctly: + + .. code-block:: console + + $ docker run --runtime=nvidia --rm nvidia/cuda-ppc64le nvidia-smi + +.. _accessing_hadoop_kubernetes_configuration_files: + +Accessing the Hadoop and Kubernetes Configuration Files +-------------------------------------- +The information this section is optional and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, contact your IT department for access to the following configuration files: + +* Hadoop configuration files: + + * core-site.xml + * hdfs-site.xml + + :: + +* Kubernetes files: + + * Configuration file - krb.conf + * Kubernetes Hadoop client certificate - hdfs.keytab + +Once you have the above files, you must copy them into the correct folders in your working directory. + +For more information about the correct directory to copy the above files into, see the :ref:`Installing the SQream Software ` section below. + +For related information, see the following sections: + +* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. +* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + +.. _installing_sqream_software: + +Installing the SQream Software +============================== + +Preparing Your Local Environment +------------------------- +After installing the Nvidia Docker2 toolKit you must prepare your local environment. + +The Linux user preparing the local environment must have **read/write** access to the following directories for the SQream software to correctly read and write the required resources: + +* **Log directory** - default: /var/log/sqream/ +* **Configuration directory** - default: /etc/sqream/ +* **Cluster directory** - the location where SQream writes its DB system, such as */mnt/sqreamdb* +* **Ingest directory** - the location where the required data is loaded, such as */mnt/data_source/* + +.. _download_sqream_software: + +Deploying the SQream Software +------------------------- +After preparing your local environment you must deploy the SQream software. Deploying the SQream software requires you to access and extract the required files and to place them in the correct directory. + +**To deploy the SQream software:** + +1. Contact the SQream Support team for access to the **sqream_installer-nnn-DBnnn-COnnn-EDnnn-.tar.gz** file. + +The **sqream_installer-nnn-DBnnn-COnnn-EDnnn-.tar.gz** file includes the following parameter values: + +* **sqream_installer-nnn** - sqream installer version +* **DBnnn** - SQreamDB version +* **COnnn** - SQream console version +* **EDnnn** - SQream editor version +* **arch** - server arch (applicable to X86.64 and ppc64le) + +2. Extract the tarball file: + + .. code-block:: console + + $ tar -xvf sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz + +When the tarball file has been extracted, a new folder will be created. The new folder is automatically given the name of the tarball file: + + .. code-block:: console + + drwxrwxr-x 9 sqream sqream 4096 Aug 11 11:51 sqream_istaller-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64/ + -rw-rw-r-- 1 sqream sqream 3130398797 Aug 11 11:20 sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz + +3. Change the directory to the new folder that you created in the previous step. + +:: + +4. Verify that the folder you just created contains all of the required files. + + .. code-block:: console + + $ ls -la + + The following is an example of the files included in the new folder: + + .. code-block:: console + + drwxrwxr-x. 10 sqream sqream 198 Jun 3 17:57 . + drwx------. 25 sqream sqream 4096 Jun 7 18:11 .. + drwxrwxr-x. 2 sqream sqream 226 Jun 7 18:09 .docker + drwxrwxr-x. 2 sqream sqream 64 Jun 3 12:55 .hadoop + drwxrwxr-x. 2 sqream sqream 4096 May 31 14:18 .install + drwxrwxr-x. 2 sqream sqream 39 Jun 3 12:53 .krb5 + drwxrwxr-x. 2 sqream sqream 22 May 31 14:18 license + drwxrwxr-x. 2 sqream sqream 82 May 31 14:18 .sqream + -rwxrwxr-x. 1 sqream sqream 1712 May 31 14:18 sqream-console + -rwxrwxr-x. 1 sqream sqream 4608 May 31 14:18 sqream-install + +For information relevant to Hadoop users, see the following sections: + +* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. +* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. +* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + +.. _configure_hadoop_kubernetes_configuration_files: + +Configuring the Hadoop and Kubernetes Configuration Files +----------------------------- +The information in this section is optional and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, you must copy the Hadoop and Kubernetes files into the correct folders in your working directory as shown below: + +* .hadoop/core-site.xml +* .hadoop/hdfs-site.xml +* .krb5/krb5.conf +* .krb5/hdfs.keytab + +For related information, see the following sections: + +* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. +* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + +Configuring the SQream Software +------------------------------- +After deploying the SQream software, and optionally configuring the Hadoop and Kubernetes configuration files, you must configure the SQream software. + +Configuring the SQream software requires you to do the following: + +* Configure your local environment +* Understand the ``sqream-install`` flags +* Install your SQream license +* Validate your SQream icense +* Change your data ingest folder + +Configuring Your Local Environment +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've downloaded the SQream software, you can begin configuring your local environment. The following commands must be run (as **sudo**) from the same directory that you located your packages. + +For example, you may have saved your packages in **/home/sqream/sqream-console-package/**. + +The following table shows the flags that you can use to configure your local directory: + +.. list-table:: + :widths: 10 50 40 + :header-rows: 1 + + * - Flag + - Function + - Note + * - **-i** + - Loads all software from the hidden folder **.docker**. + - Mandatory + * - **-k** + - Loads all license packages from the **/license** directory. + - Mandatory + * - **-f** + - Overwrites existing folders. **Note** Using ``-f`` overwrites **all files** located in mounted directories. + - Mandatory + * - **-c** + - Defines the origin path for writing/reading SQream configuration files. The default location is ``/etc/sqream/``. + - If you are installing the Docker version on a server that already works with SQream, do not use the default path. + * - **-v** + - The SQream cluster location. If a cluster does not exist yet, ``-v`` creates one. If a cluster already exists, ``-v`` mounts it. + - Mandatory + * - **-l** + - SQream system startup logs location, including startup logs and docker logs. The default location is ``/var/log/sqream/``. + - + * - **-d** + - The directory containing customer data to be imported and/or copied to SQream. + - + * - **-s** + - Shows system settings. + - + * - **-r** + - Resets the system configuration. This value is run without any other variables. + - Mandatory + * - **-h** + - Help. Shows the available flags. + - Mandatory + * - **-K** + - Runs license validation + - + * - **-e** + - Used for inserting your RKrb5 server DNS name. For more information on setting your Kerberos configuration parameters, see :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + - + * - **-p** + - Used for inserting your Kerberos user name. For more information on setting your Kerberos configuration parameters, see :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + - + + +Installing Your License +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've configured your local environment, you must install your license by copying it into the SQream installation package folder located in the **./license** folder: + +.. code-block:: console + + $ sudo ./sqream-install -k + +You do not need to extract this folder after uploading into the **./license**. + + +Validating Your License +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You can copy your license package into the SQream console folder located in the **/license** folder by running the following command: + +.. code-block:: console + + $ sudo ./sqream-install -K + +The following mandatory flags must be used in the first run: + +.. code-block:: console + + $ sudo ./sqream-install -i -k -v + +The following is an example of the correct command syntax: + +.. code-block:: console + + $ sudo ./sqream-install -i -k -c /etc/sqream -v /home/sqream/sqreamdb -l + $ /var/log/sqream -d /home/sqream/data_ingest + +.. _setting_hadoop_kubernetes_connectivity_parameters: + +Setting the Hadoop and Kubernetes Connectivity Parameters +------------------------------- +The information in this section is optional, and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, you must set their connectivity parameters. + +The following is the correct syntax when setting the Hadoop and Kubernetes connectivity parameters: + +.. code-block:: console + + $ sudo ./sqream-install -p -e : + +The following is an example of setting the Hadoop and Kubernetes connectivity parameters: + +.. code-block:: console + + $ sudo ./sqream-install -p -e kdc.sq.com:<192.168.1.111> + +For related information, see the following sections: + +* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. +* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. + +Modifying Your Data Ingest Folder +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've validated your license, you can modify your data ingest folder after the first run by running the following command: + +.. code-block:: console + + $ sudo ./sqream-install -d /home/sqream/data_in + +Configuring Your Network for Docker +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've modified your data ingest folder (if needed), you must validate that the server network and Docker network that you are setting up do not overlap. + +**To configure your network for Docker:** + +1. To verify that your server network and Docker network do not overlap, run the following command: + +.. code-block:: console + + $ ifconfig | grep 172. + +2. Do one of the following: + + * If running the above command output no results, continue the installation process. + * If running the above command output results, run the following command: + + .. code-block:: console + + $ ifconfig | grep 192.168. + + +Checking and Verifying Your System Settings +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've configured your network for Docker, you can check and verify your system settings. + +Running the following command shows you all the variables used by your SQream system: + +.. code-block:: console + + $ ./sqream-install -s + +The following is an example of the correct output: + +.. code-block:: console + + SQREAM_CONSOLE_TAG=1.5.4 + SQREAM_TAG=2019.2.1 + SQREAM_EDITOR_TAG=3.0.0 + license_worker_0=f0:cc: + license_worker_1=26:91: + license_worker_2=20:26: + license_worker_3=00:36: + SQREAM_VOLUME=/media/sqreamdb + SQREAM_DATA_INGEST=/media/sqreamdb/data_in + SQREAM_CONFIG_DIR=/etc/sqream/ + LICENSE_VALID=true + SQREAM_LOG_DIR=/var/log/sqream/ + SQREAM_USER=sqream + SQREAM_HOME=/home/sqream + SQREAM_ENV_PATH=/home/sqream/.sqream/env_file + PROCESSOR=x86_64 + METADATA_PORT=3105 + PICKER_PORT=3108 + NUM_OF_GPUS=2 + CUDA_VERSION=10.1 + NVIDIA_SMI_PATH=/usr/bin/nvidia-smi + DOCKER_PATH=/usr/bin/docker + NVIDIA_DRIVER=418 + SQREAM_MODE=single_host + +Using the SQream Console +========================= +After configuring the SQream software and veriying your system settings you can begin using the SQream console. + +SQream Console - Basic Commands +--------------------------------- +The SQream console offers the following basic commands: + +* :ref:`Starting your SQream console ` +* :ref:`Starting Metadata and Picker ` +* :ref:`Starting the running services ` +* :ref:`Listing the running services ` +* :ref:`Stopping the running services ` +* :ref:`Using the SQream editor ` +* :ref:`Using the SQream Client ` + +.. _starting_sqream_console: + +Starting Your SQream Console +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can start your SQream console by running the following command: + +.. code-block:: console + + $ ./sqream-console + +.. _starting_metadata_and_picker: + +Starting the SQream Master +~~~~~~~~~~~~~~~~~ + +**To listen to metadata and picker:** + +1. Start the metadata server (default port 3105) and picker (default port 3108) by running the following command: + + .. code-block:: console + + $ sqream master --start + + The following is the correct output: + + .. code-block:: console + + sqream-console> sqream master --start + starting master server in single_host mode ... + sqream_single_host_master is up and listening on ports: 3105,3108 + + +2. *Optional* - Change the metadata and server picker ports by adding ``-p `` and ``-m ``: + + .. code-block:: console + + $ sqream-console>sqream master --start -p 4105 -m 43108 + $ starting master server in single_host mode ... + $ sqream_single_host_master is up and listening on ports: 4105,4108 + + + +.. _starting_running_services: + +Starting SQream Workers +~~~~~~~~~~~~~~~~~ + + +When starting SQream workers, setting the ```` value sets how many workers to start. Leaving the ```` value unspecified runs all of the available resources. + + +.. code-block:: console + + $ sqream worker --start + + The following is an example of expected output when setting the ```` value to ``2``: + + .. code-block:: console + + sqream-console>sqream worker --start 2 + started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 + started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 + + +.. _listing_running_services: + +Listing the Running Services +~~~~~~~~~~~~~~~~~ + +You can list running SQream services to look for container names and ID's by running the following command: + +.. code-block:: console + + $ sqream master --list + +The following is an example of the expected output: + +.. code-block:: console + + sqream-console>sqream master --list + container name: sqream_single_host_worker_0, container id: c919e8fb78c8 + container name: sqream_single_host_master, container id: ea7eef80e038-- + + +.. _stopping_running_services: + +Stopping the Running Services +~~~~~~~~~~~~~~~~~ + +You can stop running services either for a single SQream worker, or all SQream services for both master and worker. + +The following is the command for stopping a running service for a single SQream worker: + +.. code-block:: console + + $ sqream worker --stop + +The following is an example of expected output when stopping a running service for a single SQream worker: + +.. code-block:: console + + sqream worker stop + stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 + + +You can stop all running SQream services (both master and worker) by running the following command: + +.. code-block:: console + + $ sqream-console>sqream master --stop --all + +The following is an example of expected output when stopping all running services: + +.. code-block:: console + + sqream-console>sqream master --stop --all + stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 + stopped container sqream_single_host_master, id: 55cb7e38eb22 + + +.. _using_sqream_editor: + +Using SQream Studio +~~~~~~~~~~~~~~~~~ +SQream Studio is an SQL statement editor. + +**To start SQream Studio:** + +1. Run the following command: + + .. code-block:: console + + $ sqream studio --start + +The following is an example of the expected output: + + .. code-block:: console + + SQream Acceleration Studio is available at http://192.168.1.62:8080 + +2. Click the ``http://192.168.1.62:8080`` link shown in the CLI. + + +**To stop SQream Studio:** + +You can stop your SQream Studio by running the following command: + +.. code-block:: console + + $ sqream studio --stop + +The following is an example of the expected output: + +.. code-block:: console + + sqream_admin stopped + + +.. _using_sqream_client: + +Using the SQream Client +~~~~~~~~~~~~~~~~~ + + +You can use the embedded SQream Client on the following nodes: + +* Master node +* Worker node + + +When using the SQream Client on the Master node, the following default settings are used: + +* **Default port**: 3108. You can change the default port using the ``-p`` variable. +* **Default database**: master. You can change the default database using the ``-d`` variable. + +The following is an example: + +.. code-block:: console + + $ sqream client --master -u sqream -w sqream + + +When using the SQream Client on a Worker node (or nodes), you should use the ``-p`` variable for Worker ports. The default database is ``master``, but you can use the ``-d`` variable to change databases. + +The following is an example: + +.. code-block:: console + + $ sqream client --worker -p 5000 -u sqream -w sqream + + +Moving from Docker Installation to Standard On-Premises Installation +----------------------------------------------- + +Because Docker creates all files and directories on the host at the **root** level, you must grant ownership of the SQream storage folder to the working directory user. + +SQream Console - Advanced Commands +----------------------------- + +The SQream console offers the following advanced commands: + + +* :ref:`Controlling the spool size ` +* :ref:`Splitting a GPU ` +* :ref:`Splitting a GPU and setting the spool size ` +* :ref:`Using a custom configuration file ` +* :ref:`Clustering your Docker environment ` + + + + +.. _controlling_spool_size: + +Controlling the Spool Size +~~~~~~~~~~~~~~~~~~ + +From the console you can define a spool size value. + +The following example shows the spool size being set to ``50``: + +.. code-block:: console + + $ sqream-console>sqream worker --start 2 -m 50 + + +If you don't define the SQream spool size, the SQream console automatically distributes the available RAM between all running workers. + +.. _splitting_gpu: + +Splitting a GPU +~~~~~~~~~~~~~~~~~~ + +You can start more than one sqreamd on a single GPU by splitting it. + + +The following example shows the GPU being split into **two** sqreamd's on the GPU in **slot 0**: + +.. code-block:: console + + $ sqream-console>sqream worker --start 2 -g 0 + +.. _splitting_gpu_setting_spool_size: + +Splitting GPU and Setting the Spool Size +~~~~~~~~~~~~~~~~~~ + +You can simultaneously split a GPU and set the spool size by appending the ``-m`` flag: + +.. code-block:: console + + $ sqream-console>sqream worker --start 2 -g 0 -m 50 + +.. note:: The console does not validate whether the user-defined spool size is available. Before setting the spool size, verify that the requested resources are available. + +.. _using_custom_configuration_file: + +Using a Custom Configuration File +~~~~~~~~~~~~~~~~~~ + +SQream lets you use your own external custom configuration json files. You must place these json files in the path mounted in the installation. SQream recommends placing the json file in the Configuration folder. + +The SQream console does not validate the integrity of your external configuration files. + +When using your custom configuration file, you can use the ``-j`` flag to define the full path to the Configuration file, as in the example below: + +.. code-block:: console + + $ sqream-console>sqream worker --start 1 -j /etc/sqream/configfile.json + +.. note:: To start more than one sqream daemon, you must provide files for each daemon, as in the example below: + +.. code-block:: console + + $ sqream worker --start 2 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json + +.. note:: To split a specific GPU, you must also list the GPU flag, as in the example below: + +.. code-block:: console + + $ sqream worker --start 2 -g 0 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json + +.. _clustering_docker_environment: + +Clustering Your Docker Environment +~~~~~~~~~~~~~~~~~~ + +SQream lets you connect to a remote Master node to start Docker in Distributed mode. If you have already connected to a Slave node server in Distributed mode, the **sqream Master** and **Client** commands are only available on the Master node. + +.. code-block:: console + + $ --master-host + $ sqream-console>sqream worker --start 1 --master-host 192.168.0.1020 + +Checking the Status of SQream Services +--------------------------- +SQream lets you check the status of SQream services from the following locations: + +* :ref:`From the Sqream console ` +* :ref:`From outside the Sqream console ` + +.. _inside_sqream_console: + +Checking the Status of SQream Services from the SQream Console +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +From the SQream console, you can check the status of SQream services by running the following command: + +.. code-block:: console + + $ sqream-console>sqream master --list + +The following is an example of the expected output: + +.. code-block:: console + + $ sqream-console>sqream master --list + $ checking 3 sqream services: + $ sqream_single_host_worker_1 up, listens on port: 5001 allocated gpu: 1 + $ sqream_single_host_worker_0 up, listens on port: 5000 allocated gpu: 1 + $ sqream_single_host_master up listens on ports: 3105,3108 + +.. _outside_sqream_console: + +Checking the Status of SQream Services from Outside the SQream Console +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +From outside the Sqream Console, you can check the status of SQream services by running the following commands: + +.. code-block:: console + + $ sqream-status + $ NAMES STATUS PORTS + $ sqream_single_host_worker_1 Up 3 minutes 0.0.0.0:5001->5001/tcp + $ sqream_single_host_worker_0 Up 3 minutes 0.0.0.0:5000->5000/tcp + $ sqream_single_host_master Up 3 minutes 0.0.0.0:3105->3105/tcp, 0.0.0.0:3108->3108/tcp + $ sqream_editor_3.0.0 Up 3 hours (healthy) 0.0.0.0:3000->3000/tcp + +Upgrading Your SQream System +---------------------------- +This section describes how to upgrade your SQream system. + +**To upgrade your SQream system:** + +1. Contact the SQream Support team for access to the new SQream package tarball file. + + :: + +2. Set a maintenance window to enable stopping the system while upgrading it. + + :: + +3. Extract the following tarball file received from the SQream Support team, under it with the same user and in the same folder that you used while :ref:`Downloading the SQream Software <_download_sqream_software>`. + + + .. code-block:: console + + $ tar -xvf sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ + +4. Navigate to the new folder created as a result of extracting the tarball file: + + .. code-block:: console + + $ cd sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ + +5. Initiate the upgrade process: + + .. code-block:: console + + $ ./sqream-install -i + + Initiating the upgrade process checks if any SQream services are running. If any services are running, you will be prompted to stop them. + +6. Do one of the following: + + * Select **Yes** to stop all running SQream workers (Master and Editor) and continue the upgrade process. + * Select **No** to stop the upgrade process. + + SQream periodically upgrades the metadata structure. If an upgrade version includes a change to the metadata structure, you will be prompted with an approval request message. Your approval is required to finish the upgrade process. + + Because SQream supports only certain metadata versions, all SQream services must be upgraded at the same time. + +7. When the upgrade is complete, load the SQream console and restart your services. + + For assistance, contact SQream Support. From 5fcb9167a7aab027978cf1cb8e6e394c565599e5 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 3 Nov 2021 12:54:26 +0200 Subject: [PATCH 084/300] Update index.rst Added running_sqream_in_a_docker_container to index. --- guides/operations/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/guides/operations/index.rst b/guides/operations/index.rst index 96f6a6338..de2a98202 100644 --- a/guides/operations/index.rst +++ b/guides/operations/index.rst @@ -13,6 +13,7 @@ The guides in this section include information about best practices, monitoring, optimization_best_practices xxmonitoring + running_sqream_in_a_docker_container logging configuration troubleshooting From bb2320c697b06dd80698296d762e2cfdda193c19 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 3 Nov 2021 12:57:15 +0200 Subject: [PATCH 085/300] Update first_steps.rst Used new Getting Started page format. Updated links. --- first_steps.rst | 291 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 212 insertions(+), 79 deletions(-) diff --git a/first_steps.rst b/first_steps.rst index 160d6f11a..5e5cce808 100644 --- a/first_steps.rst +++ b/first_steps.rst @@ -1,35 +1,54 @@ .. _first_steps: **************************** -First steps with SQream DB +Getting Started **************************** -.. TODO: part one of the tutorial is how to connect with clientcmd, -.. and create some tables, insert data and query it -.. part 2: expand on this -.. how to run sqream/check it's running -.. how to add a database and do roles and permissions (to get started) -.. options for inserting data - overview of all of them -.. deleting/managing data overview (including storage reorg) +The **Getting Started** page describes the following: -This tutorial takes you through a few basic operations in SQream DB. - -.. contents:: In this topic: +.. contents:: :local: + :depth: 1 + +Before Installing SQream +============================ +Before installing SQream, you must set up your local machine according to SQream's recommended pre-installation configurations. + +For more information, see the following: + +* `Hardware Guide `_. +* `Recommended Pre-Installation Configuration `_. -Preparing for this tutorial -=============================== -This tutorial assumes you already have a SQream DB cluster running and the SQream command line client installed on the machine you are on. -.. rubric:: If you haven't already: -* :ref:`Set up a SQream DB cluster` -* :ref:`Install SQream SQL CLI` +Installing SQream +============================ +The **Installing SQream** section includes the following SQream installation methods: + +* `Installing SQream natively `_ - Describes installing SQream using binary packages provided by SQream. +* `Installing SQream with Kubernetes `_ - Describes installing SQream using the Kubernetes open source platform. +* `Installing and running SQream in a Docker container `_ - Describes how to run SQream in a Docker container. + +Using the SQream SQL Command Line Interface +============================================ +SQream includes a built-in client for executing SQL statements either interactively or using the Command Line Interface (CLI). The **SQream SQL CLI Reference** page provides a reference for the options and parameters. +For more information, see `SQream SQL CLI Reference `_. -Run the SQream SQL client like this. It will interactively ask for the password. +Performing Basic SQream Operations +==================================== +After installing SQream you can perform the operations described in the **Performing Basic SQream Operations** section: + +.. contents:: + :local: + :depth: 1 + + +Running the SQream SQL Client +--------------------------------- +The following example shows how to run the SQream SQL client: .. code-block:: psql @@ -41,46 +60,57 @@ Run the SQream SQL client like this. It will interactively ask for the password. master=> _ -You should use a username and password that you have set up or your DBA has given you. +Running the SQream SQL client prompts you to provide your password. Use the username and password that you have set up, or your DBA has provided. .. tip:: - * To exit the shell, type ``\q`` or :kbd:`Ctrl-d`. - * A new SQream DB cluster contains a database named `master`. We will start with this database. + * You can exit the shell by typing ``\q`` or :kbd:`Ctrl-d`. + * A new SQream cluster contains a database named `master,` which is the database used in the examples on this page. -Create a new database for playing around in -======================================================= +Creating a New Database +-------------------------- +**To create a new database:** -To create a database, we will use the :ref:`create_database` syntax. +1. Write a :ref:`create_database` statement. -.. code-block:: psql + The following is an example of creating a new database: - master=> CREATE DATABASE test; - executed + .. code-block:: psql -Now, reconnect to the newly created database. + master=> CREATE DATABASE test; + executed -First, exit the client by typing ``\q`` and hitting enter. +2. Reconnect to the newly created database. -From the Linux shell, restart the client with the new database name: + 1. Exit the client by typing ``\q`` and pressing **Enter**. + 2. From the Linux shell, restart the client with the new database name: -.. code-block:: psql + .. code-block:: psql - $ sqream sql --port=5000 --username=rhendricks -d test - Password: + $ sqream sql --port=5000 --username=rhendricks -d test + Password: - Interactive client mode - To quit, use ^D or \q. + Interactive client mode + To quit, use ^D or \q. - test=> _ + test=> _ -The new database name appears in the prompt. This lets you know which database you're connected to. + The name of the new database that you are connected to is displayed in the prompt. -Creating your first table -============================ +Creating Your First Table +------------------------------ +The **Creating Your First Table** section describes the following: -To create a table, we will use the :ref:`create_table` syntax, with a table name and some column specifications. +* :ref:`Creating a table` +* :ref:`Replacing a table` +* :ref:`Listing a CREATE TABLE statement` +* :ref:`Dropping a table` -For example, + +.. _creating_a_table: + +**Creating a Table** + +The ``CREATE TABLE`` syntax is used to create your first table. This table includes a table name and column specifications, as shown in the following example: .. code-block:: postgres @@ -90,7 +120,13 @@ For example, weight INT ); -If the table already exists and you want to drop the current table and create a new one, you can add ``OR REPLACE`` after the ``CREATE`` keyword. +For more information on creating a table, see :ref:`create_table`. + +.. _replacing_a_table: + +**Replacing a Table** + +You can drop an existing table and create a new one by adding the ``OR REPLACE`` parameter after the ``CREATE`` keyword, as shown in the following example: .. code-block:: postgres @@ -101,9 +137,12 @@ If the table already exists and you want to drop the current table and create a ); .. TODO: cool_animals? I think we need to decide if the customer for this documenation is 12 years old, or an IT professional. - -You can ask SQream DB to list the full, verbose ``CREATE TABLE`` statement for any table, by using the :ref:`get_ddl` function, with the table name. +.. _listing_a_create_table_statement: + +**Listing a CREATE TABLE Statement** + +You can list the full, verbose ``CREATE TABLE`` statement for a table by using the **GET DDL** function with the table name as shown in the following example: .. code-block:: psql @@ -114,22 +153,30 @@ You can ask SQream DB to list the full, verbose ``CREATE TABLE`` statement for a "weight" int ); -.. note: +.. note:: + * SQream DB identifier names such as table names and column names are not case sensitive. SQream DB lowercases all identifiers bu default. If you want to maintain case, enclose the identifiers with double-quotes. * SQream DB places all tables in the `public` schema, unless another schema is created and specified as part of the table name. + +For information on listing a ``CREATE TABLE`` statement, see :ref:`get_ddl`. + +.. _dropping_a_table: -If you are done with this table, you can use :ref:`drop_table` to remove the table and all of its data. +**Dropping a Table** + +When you have finished working with your table, you can drop the table to remove it table and its content, as shown in the following example: .. code-block:: psql test=> DROP TABLE cool_animals; executed + +For more information on dropping tables, see :ref:`drop_table`. -Listing tables -================= - -To see the tables in the current database, we will query the catalog +Listing Tables +------------------ +To see the tables in the current database you can query the catalog, as shown in the following example: .. code-block:: psql @@ -138,12 +185,21 @@ To see the tables in the current database, we will query the catalog 1 rows +Inserting Rows +------------------- +The **Inserting Rows** section describes the following: + +* :ref:`Inserting basic rows` +* :ref:`Changing value order` +* :ref:`Inserting multiple rows` +* :ref:`Omitting columns` + + +.. _inserting_basic_rows: -Inserting rows -================= +**Inserting Basic Rows** -Inserting rows into a table can be performed with the :ref:`insert` statement. -The statement includes the table name, an optional list of column names, and column values listed in the same order as the column names: +You can insert basic rows into a table using the ``INSERT`` statement. The inserted statement includes the table name, an optional list of column names, and column values listed in the same order as the column names, as shown in the following example: .. code-block:: psql @@ -151,7 +207,11 @@ The statement includes the table name, an optional list of column names, and col executed -To change the order of values, specify the column order: +.. _changing_value_order: + +**Changing Value Order** + +You can change the order of values by specifying the column order, as shown in the following example: .. code-block:: psql @@ -159,7 +219,11 @@ To change the order of values, specify the column order: executed -You can use ``INSERT`` to insert multiple rows too. Here, you use sets of parentheses separated by commas: +.. _inserting_multiple_rows: + +**Inserting Multiple Rows** + +You can insert multiple rows using the ``INSERT`` statement by using sets of parentheses separated by commas, as shown in the following example: .. code-block:: psql @@ -170,9 +234,13 @@ You can use ``INSERT`` to insert multiple rows too. Here, you use sets of parent executed -.. note:: To load big data sets, use bulk loading methods instead. See our :ref:`inserting_data` guide for more information. +.. note:: You can load large data sets using bulk loading methods instead. For more information, see :ref:`inserting_data`. + +.. _omitting_columns: -When you leave out columns that have a :ref:`default value` (including default ``NULL`` value) the default value is used. +**Omitting Columns** + +Omitting columns that have a default values (including default ``NULL`` values) uses the default value, as shown in the following example: .. code-block:: psql @@ -197,10 +265,28 @@ When you leave out columns that have a :ref:`default value` (inc .. note:: Null row values are represented as ``\N`` -Queries -========= +For more information on inserting rows, see :ref:`insert`. + +For more information on default values, see :ref:`default value`. + + +Running Queries +------------------ +The **Running Queries** section describes the following: -For querying, use the :ref:`select` keyword, followed by a list of columns and values to be returned, and the table to get the data from. +* :ref:`Running basic queries` +* :ref:`Outputting all columns` +* :ref:`Outputting shorthand table values` +* :ref:`Filtering results` +* :ref:`Sorting results` +* :ref:`Filtering null rows` + + +.. _running_basic_queries: + +**Running Basic Queries** + +You can run a basic query using the ``SELECT`` keyword, followed by a list of columns and values to be returned, and the table to get the data from, as shown in the following example: .. code-block:: psql @@ -213,8 +299,14 @@ For querying, use the :ref:`select` keyword, followed by a list of columns and v 6,\N,\N 6 rows + +For more information on the ``SELECT`` keyword, see :ref:`select`. -To get all columns without specifying them, use the star operator ``*``: +.. _outputting_all_columns: + +**To Output All Columns** + +You can output all columns without specifying them using the star operator ``*``, as shown in the following example: .. code-block:: psql @@ -228,7 +320,11 @@ To get all columns without specifying them, use the star operator ``*``: 6 rows -To get the number of values in a table without getting the full result set, use :ref:`COUNT(*)`: +.. _outputting_shorthand_table_values: + +**Outputting Shorthand Table Values** + +You can output the number of values in a table without getting the full result set by using the ``COUNT`` statement: .. code-block:: psql @@ -237,8 +333,11 @@ To get the number of values in a table without getting the full result set, use 1 row +.. _filtering_results: -Filter results by adding a :ref:`WHERE` clause and specifying the filter condition: +**Filtering Results** + +You can filter results by adding a ``WHERE`` clause and specifying the filter condition, as shown in the following example: .. code-block:: psql @@ -248,7 +347,11 @@ Filter results by adding a :ref:`WHERE` clause and specifying the filter 2 rows -Sort the results by adding an :ref:`ORDER BY` clause, and specifying ascending (``ASC``) or descending (``DESC``) order: +.. _sorting_results: + +**Sorting Results** + +You can sort results by adding an ``ORDER BY`` clause and specifying ascending (``ASC``) or descending (``DESC``) order, as shown in the following example: .. code-block:: psql @@ -262,7 +365,11 @@ Sort the results by adding an :ref:`ORDER BY` clause, and specifying a 6 rows -Filter null rows by adding a filter :ref:`IS NOT NULL`: +.. _filtering_null_rows: + +**Filtering Null Rows** + +You can filter null rows by adding an ``IS NOT NULL`` filter, as shown in the following example: .. code-block:: psql @@ -274,11 +381,28 @@ Filter null rows by adding a filter :ref:`IS NOT NULL`: 2,Possum ,3 5 rows + +For more information, see the following: + +* Outputting the number of values in a table without getting the full result set - :ref:`COUNT(*)`. +* Filtering results - :ref:`WHERE` +* Sorting results - :ref:`ORDER BY` +* Filtering rows - :ref:`IS NOT NULL` + + -Deleting rows -============== +Deleting Rows +----------------- +The **Deleting Rows** section describes the following: -To delete rows in a table selectively, use the :ref:`DELETE` command, with a table name and a `WHERE` clause to specify which rows are to be deleted: +* :ref:`Deleting selected rows` +* :ref:`Deleting all rows` + +.. _deleting_selected_rows: + +**Deleting Selected Rows** + +You can delete rows in a table selectively using the ``DELETE`` command. You must include a table name and `WHERE` clause to specify the rows to delete, as shown in the following example: .. code-block:: psql @@ -294,7 +418,11 @@ To delete rows in a table selectively, use the :ref:`DELETE` command, wi 5 rows -To delete all rows in a table, use the :ref:`TRUNCATE` command followed by the table name: +.. _deleting_all_rows: + +**Deleting All Rows** + +You can delete all rows in a table using the ``TRUNCATE`` command followed by the table name, as shown in the following example: .. code-block:: psql @@ -302,12 +430,18 @@ To delete all rows in a table, use the :ref:`TRUNCATE` command followe executed -.. note:: While :ref:`truncate` deletes data from disk immediately, :ref:`delete` does not physically remove the deleted rows. For more information on removing the rows from disk, see :ref:`delete`. +.. note:: While :ref:`truncate` deletes data from disk immediately, :ref:`delete` does not physically remove the deleted rows. -Saving query results to a CSV or PSV file -============================================== +For more information, see the following: -The command line client :ref:`sqream sql` can be used to save query results to a CSV or other delimited file format. +* Deleting selected rows - :ref:`DELETE` +* Deleting all rows - :ref:`TRUNCATE` + +Saving Query Results to a CSV or PSV File +-------------------------------------------- + + +You can save query results to a CSV or PSV file using the ``sqream sql`` command from a CLI client. This saves your query results to the selected delimited file format, as shown in the following example: .. code-block:: console @@ -319,11 +453,10 @@ The command line client :ref:`sqream sql` can be used R.J. Hunter |Boston Celtics |28|SG|22|6-5 |185|Georgia State |1148640 Jonas Jerebko |Boston Celtics |8|PF|29|6-10|231|\N|5000000 - -See the :ref:`Controlling the output of the client` section of the reference for more options. +For more output options, see :ref:`Controlling the Client Output`. .. rubric:: What's next? -* Explore all of SQream DB's :ref:`SQL Syntax ` -* See the full :ref:`SQream SQL CLI reference ` -* Connect a :ref:`third party tool to SQream DB ` and start analyzing data +* Explore all of SQream DB's :ref:`SQL Syntax `. +* See the full :ref:`SQream SQL CLI reference `. +* Connect a :ref:`third party tool ` to start analyzing data. From 05feb803c1953453e84d7f04ee282407b3a17d78 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 3 Nov 2021 17:48:55 +0200 Subject: [PATCH 086/300] Update hardware_guide.rst Updated with Slavi. --- guides/operations/hardware_guide.rst | 141 ++++++++++----------------- 1 file changed, 52 insertions(+), 89 deletions(-) diff --git a/guides/operations/hardware_guide.rst b/guides/operations/hardware_guide.rst index 24ada0c4f..99e0d9265 100644 --- a/guides/operations/hardware_guide.rst +++ b/guides/operations/hardware_guide.rst @@ -4,7 +4,7 @@ Hardware Guide *********************** -This guide describes the SQream DB reference architecture, emphasizing the benefits to the technical audience, and provides guidance for end-users on selecting the right configuration for a SQream DB installation. +This guide describes the SQream reference architecture, emphasizing the benefits to the technical audience, and provides guidance for end-users on selecting the right configuration for a SQream installation. .. rubric:: Need help? @@ -13,12 +13,12 @@ This page is intended as a "reference" to suggested hardware. However, different Visit `SQream's support portal `_ for additional support. -A SQream DB cluster +A SQream Cluster ============================ SQream recommends rackmount servers by server manufacturers Dell, Lenovo, HP, Cisco, Supermicro, IBM, and others. -A typical SQream DB cluster includes one or more nodes, consisting of +A typical SQream cluster includes one or more nodes, consisting of * Two-socket enterprise processors, like the Intel® Xeon® Gold processor family or an IBM® POWER9 processors, providing the high performance required for compute-bound database workloads. @@ -26,10 +26,10 @@ A typical SQream DB cluster includes one or more nodes, consisting of * High density chassis design, offering between 2 and 4 GPUs in a 1U, 2U, or 3U package, for best-in-class performance per cm\ :sup:`2`. -Example for a single-node cluster +Single-Node Cluster Example ----------------------------------- -A single-node SQream DB cluster can handle between 1 and 8 concurrent users, with up to 1PB of data storage (when connected via NAS). +A single-node SQream cluster can handle between 1 and 8 concurrent users, with up to 1PB of data storage (when connected via NAS). An average single-node cluster can be a rackmount server or workstation, containing the following components: @@ -40,32 +40,32 @@ An average single-node cluster can be a rackmount server or workstation, contain * - Component - Type * - Server - - Rackmount or workstation, like the Dell T640, Dell R740, Dell R940xa, HP ProLiant DL380 Gen10 + - Dell T640, Dell R750, Dell R940xa, HP ProLiant DL380 Gen10 or similar * - Processor - 2x Intel Xeon Gold 6240 (18C/36HT) 2.6GHz * - RAM - - 384 GB LRDIMM 2666MT/s, ECC registered + - 512 GB * - Onboard storage - * 2x 960GB SSD 2.5in Hot-plug for OS, RAID1 - * 14x 3.84TB SSD 2.5in Hot-plug for storage, RAID10 - * - Networking - - Intel X710 DP 10Gb DA/SFP+ + * 14x 3.84TB SSD 2.5in Hot-plug for storage, RAID6 + * 2x 2TB SSD or NVMe, for temporary spooling, RAID1 + * - GPU - - 2x or 4x NVIDIA Tesla T4 or P100 + - 2x or 4x NVIDIA Tesla T4, V100, or A100 -In this system configuration, SQream DB can store about 200TB of raw data (assuming average compression ratio and ~50TB of usable raw storage). +.. note:: If you are using internal storage, your volumes must be formatted as xfs. + +In this system configuration, SQream can store about 200TB of raw data (assuming average compression ratio and ~50TB of usable raw storage). If a NAS is used, the 14x SSD drives can be omitted, but SQream recommends 2TB of local spool space on SSD or NVMe drives. -Example for multi-node clusters +Multi-Node Cluster Example ----------------------------------- -Multi-node clusters can handle any number of concurrent users. - -A typical SQream DB cluster relies on a shared storage connected over a network fabric like InfiniBand EDR, 40GbE, or 100GbE +Multi-node clusters can handle any number of concurrent users. A typical SQream cluster relies on several GPU-enabled servers and shared storage connected over a network fabric, such as InfiniBand EDR, 40GbE, or 100GbE. -An example of a cluster node providing the best performance: +The following table shows SQream's recommended hardware specifications: .. list-table:: :widths: auto @@ -74,43 +74,50 @@ An example of a cluster node providing the best performance: * - Component - Type * - Server - - High-density GPU-capable rackmount server, like Dell C4140, IBM AC922, Lenovo SR650. + - High-density GPU-capable rackmount server, like Dell C4140, Dell R940xa, Dell R750, Lenovo SR650 or similar. * - Processor - - 2x Intel Platinum 8180M (28C/56HT) 3.8GHz or 2x IBM POWER9 + - 2x Intel Xeon Gold 6240 (18C/36HT) 2.6GHz or 2x IBM POWER9 * - RAM - - 1024 GB RDIMM 2933T/s, ECC registered + - 1 - 2TB * - Onboard storage - * 2x 960GB SSD 2.5in, for OS, RAID1 * 2x 2TB SSD or NVMe, for temporary spooling, RAID1 * - Networking - - Intel X710 DP 10Gb DA/SFP+ for BI fabric + - Mellanox ConnectX-4, EDR for storage fabric + Mellanox Connectx 5 100 Gbps for storage fabric or similar. * - GPU - - 4x NVIDIA Tesla V100 32GB + - 4x NVIDIA Tesla V100 32GB or A100 -.. note:: With a NAS connected over GPFS, Lustre, or NFS - each SQream DB worker can read data at up to 5GB/s. +.. note:: With a NAS connected over GPFS, Lustre, or NFS, each SQream worker can read data at up to 5GB/s. -Considerations in cluster design + + +Cluster Design Considerations ==================================== -* In a SQream DB installation, the storage and compute are logically separated. While they may reside on the same machine in a standalone installation, they may also reside on different hosts, providing additional flexibility and scalability. +* In a SQream installation, the storage and compute are logically separated. While they may reside on the same machine in a standalone installation, they may also reside on different hosts, providing additional flexibility and scalability. -* SQream DB uses all resources in a machine, including CPU, RAM, and GPU to deliver the best performance. 256GB of RAM per physical GPU is recommended, but not required. + :: -* Local disk space is required for good performance temporary spooling - particularly when performing intensive larger-than-RAM operations like sorting. SQream recommends an SSD or NVMe drive, in mirrored RAID 1 configuration, with about 2x the RAM size available for temporary storage. This can be shared with the operating system drive if necessary. +* SQream uses all resources in a machine, including CPU, RAM, and GPU to deliver the best performance. At least 256GB of RAM per physical GPU is recommended. -* When using SAN or NAS devices, SQream recommends around 5GB/s of burst throughput from storage, per GPU. + :: -Balancing cost and performance --------------------------------- +* Local disk space is required for good temporary spooling performance, particularly when performing intensive operations exceeding the available RAM, such as sorting. SQream recommends an SSD or NVMe drive in RAID 1 configuration with about twice the RAM size available for temporary storage. This can be shared with the operating system drive if necessary. -Prior to designing and deploying a SQream DB cluster, there are a number of important factors to consider. + :: -This section provides a breakdown of deployment details intended to help ensure that this installation exceeds or meets the stated requirements. The rationale provided includes the necessary information for modifying configurations to suit the customer use-case scenario. +* When using SAN or NAS devices, SQream recommends approximately 5GB/s of burst throughput from storage per GPU. + +Balancing Cost and Performance +-------------------------------- +Prior to designing and deploying a SQream cluster, a number of important factors must be considered. + +The **Balancing Cost and Performance** section provides a breakdown of deployment details to ensure that this installation exceeds or meets the stated requirements. The rationale provided includes the necessary information for modifying configurations to suit the customer use-case scenario, as shown in the following table: .. list-table:: :widths: auto @@ -133,35 +140,28 @@ This section provides a breakdown of deployment details intended to help ensure * - Network - Balance price and performance -CPU compute +CPU Compute ------------- -SQream DB relies on multi-core Intel® Xeon® processors or IBM® POWER9 processors. - -SQream recommends a dual-socket machine populated with CPUs with 18C/36HT or better. - -While a higher core count may not necessarily affect query performance, more cores will enable higher concurrency and better load performance. +SQream relies on multi-core Intel Gold Xeon processors or IBM POWER9 processors, and recommends a dual-socket machine populated with CPUs with 18C/36HT or better. While a higher core count may not necessarily affect query performance, more cores will enable higher concurrency and better load performance. -GPU compute and RAM +GPU Compute and RAM ------------------------- -The NVIDIA Tesla range of high-throughput GPU accelerators provides the best performance for enterprise environments. Most cards have ECC memory, which is crucial for delivering correct results every time. +The NVIDIA Tesla range of high-throughput GPU accelerators provides the best performance for enterprise environments. Most cards have ECC memory, which is crucial for delivering correct results every time. SQream recommends the NVIDIA Tesla V100 32GB or NVIDIA Tesla A100 40GB GPU for best performance and highest concurrent user support. -SQream recommends the NVIDIA Tesla V100 32GB GPU for best performance and highest concurrent user support. - -GPU RAM, sometimes called GRAM or VRAM is used for processing queries. It is possible to select GPUs with less RAM, like the NVIDIA Tesla V100 16GB or P100 16GB. However, the smaller GPU RAM available will result in reduced concurrency, as the GPU RAM is used extensively in operations like JOINs, ORDER BY, GROUP BY, and all SQL transforms. +GPU RAM, sometimes called GRAM or VRAM, is used for processing queries. It is possible to select GPUs with less RAM, like the NVIDIA Tesla V100 16GB or P100 16GB, or T4 16GB. However, the smaller GPU RAM results in reduced concurrency, as the GPU RAM is used extensively in operations like JOINs, ORDER BY, GROUP BY, and all SQL transforms. RAM -------- -Use of error-correcting code memory (ECC) is a practical requirement for SQream DB and is standard on most enterprise server. SQream DB benefits from having large amounts of memory for improved performance on large 'external' operations like sorting and joining. +SQream requires using **Error-Correcting Code memory (ECC)**, standard on most enterprise servers. Large amounts of memory are required for improved performance for heavy external operations, such as sorting and joining. -Although SQream DB can function with less, we recommend a key of 256GB of RAM per GPU in the machine. +SQream recommends at least 256GB of RAM per GPU on your machine. -Operating system +Operating System --------------------- - -SQream DB can run on 64-bit Linux operating systems: +SQream can run on the following 64-bit Linux operating systems: * Red Hat Enterprise Linux (RHEL) v7 * CentOS v7 @@ -171,45 +171,8 @@ SQream DB can run on 64-bit Linux operating systems: Storage ----------- +For clustered scale-out installations, SQream relies on NAS/SAN storage. For stand-alone installations, SQream relies on redundant disk configurations, such as RAID 5, 6, or 10. These RAID configurations replicate blocks of data between disks to avoid data loss or system unavailability. -For clustered scale-out installations, SQream DB relies on NAS/SAN storage. These devices have extremely high reliability and durability, with five 9s of up-time. - -For stand-alone installations, SQream DB relies on redundant disk configurations, like RAID 10/50. These RAID configurations ensure that blocks of data are replicated between disks, so that failure of a number of disks will not result in data loss or availability of the system. - -Because storage reliability is important, SQream recommends enterprise-grade SAS SSD drives. However, as with other components – there is a tradeoff for cost/performance. When performance and reliability are important, SQream recommends SAS SSD or NVMe drives. - -SQream DB functions well with more cost-effective SATA drives and even large spinning-disk arrays. - - -Example cluster supporting 32 concurrent active users -========================================================== - -For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream DB recommends 1 Tesla V100 GPU per 2 users, for full, uninterrupted dedicated access. - -Each of these servers can support about 8 users on average. The actual number of concurrent users can be higher, depending on the workload. - -A SQream DB cluster for 32 users consists of the following components: - -#. - 4 high-density GPU-enabled servers, like the Dell C4140 (Configuration C) with 4x NVIDIA Tesla V100 32GB PCIe GPUs. - - Each server is equipped with dual Intel ® Xeon ® Gold 6240 CPU, and 1,024GB of RAM. - -#. - NAS/SAN storage, capable of delivering 1 GB/s per GPU. - - For the system above, with 4x4 NVIDIA Tesla V100 GPUs, this results in 16GB/s, over multiple bonded, 40GigE or InfiniBand links via a fabric switch. - -#. Top-of-Rack (ToR) 10GigE ethernet switch for the BI fabric - -#. 40GigE or InfiniBand switches for the storage fabric - -#. At least 1 PDU - -.. figure:: /_static/images/reference_architecture_30u.png - :alt: A 4-node system, supporting up to 30 users with 1PB of storage - - -.. rubric:: Read more +SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla V100 or A100 GPU per 2 users, for full, uninterrupted dedicated access. -Download the full `SQream DB Reference Architecture `_ document. +Download the full `SQream Reference Architecture `_ document. From fda758224c18ba9cf50f150ccc3e110bbc63242b Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 3 Nov 2021 17:58:20 +0200 Subject: [PATCH 087/300] Update hardware_guide.rst Updated with Slavi. --- guides/operations/hardware_guide.rst | 143 ++++++++++----------------- 1 file changed, 53 insertions(+), 90 deletions(-) diff --git a/guides/operations/hardware_guide.rst b/guides/operations/hardware_guide.rst index bccb6da53..99e0d9265 100644 --- a/guides/operations/hardware_guide.rst +++ b/guides/operations/hardware_guide.rst @@ -4,21 +4,21 @@ Hardware Guide *********************** -This guide describes the SQream DB reference architecture, emphasizing the benefits to the technical audience, and provides guidance for end-users on selecting the right configuration for a SQream DB installation. +This guide describes the SQream reference architecture, emphasizing the benefits to the technical audience, and provides guidance for end-users on selecting the right configuration for a SQream installation. .. rubric:: Need help? This page is intended as a "reference" to suggested hardware. However, different workloads require different solution sizes. SQream's experienced customer support has the experience to advise on these matters to ensure the best experience. -Visit `SQream's support portal `_ for additional support. +Visit `SQream's support portal `_ for additional support. -A SQream DB cluster +A SQream Cluster ============================ SQream recommends rackmount servers by server manufacturers Dell, Lenovo, HP, Cisco, Supermicro, IBM, and others. -A typical SQream DB cluster includes one or more nodes, consisting of +A typical SQream cluster includes one or more nodes, consisting of * Two-socket enterprise processors, like the Intel® Xeon® Gold processor family or an IBM® POWER9 processors, providing the high performance required for compute-bound database workloads. @@ -26,10 +26,10 @@ A typical SQream DB cluster includes one or more nodes, consisting of * High density chassis design, offering between 2 and 4 GPUs in a 1U, 2U, or 3U package, for best-in-class performance per cm\ :sup:`2`. -Example for a single-node cluster +Single-Node Cluster Example ----------------------------------- -A single-node SQream DB cluster can handle between 1 and 8 concurrent users, with up to 1PB of data storage (when connected via NAS). +A single-node SQream cluster can handle between 1 and 8 concurrent users, with up to 1PB of data storage (when connected via NAS). An average single-node cluster can be a rackmount server or workstation, containing the following components: @@ -40,32 +40,32 @@ An average single-node cluster can be a rackmount server or workstation, contain * - Component - Type * - Server - - Rackmount or workstation, like the Dell T640, Dell R740, Dell R940xa, HP ProLiant DL380 Gen10 + - Dell T640, Dell R750, Dell R940xa, HP ProLiant DL380 Gen10 or similar * - Processor - 2x Intel Xeon Gold 6240 (18C/36HT) 2.6GHz * - RAM - - 384 GB LRDIMM 2666MT/s, ECC registered + - 512 GB * - Onboard storage - * 2x 960GB SSD 2.5in Hot-plug for OS, RAID1 - * 14x 3.84TB SSD 2.5in Hot-plug for storage, RAID10 - * - Networking - - Intel X710 DP 10Gb DA/SFP+ + * 14x 3.84TB SSD 2.5in Hot-plug for storage, RAID6 + * 2x 2TB SSD or NVMe, for temporary spooling, RAID1 + * - GPU - - 2x or 4x NVIDIA Tesla T4 or P100 + - 2x or 4x NVIDIA Tesla T4, V100, or A100 -In this system configuration, SQream DB can store about 200TB of raw data (assuming average compression ratio and ~50TB of usable raw storage). +.. note:: If you are using internal storage, your volumes must be formatted as xfs. + +In this system configuration, SQream can store about 200TB of raw data (assuming average compression ratio and ~50TB of usable raw storage). If a NAS is used, the 14x SSD drives can be omitted, but SQream recommends 2TB of local spool space on SSD or NVMe drives. -Example for multi-node clusters +Multi-Node Cluster Example ----------------------------------- -Multi-node clusters can handle any number of concurrent users. - -A typical SQream DB cluster relies on a shared storage connected over a network fabric like InfiniBand EDR, 40GbE, or 100GbE +Multi-node clusters can handle any number of concurrent users. A typical SQream cluster relies on several GPU-enabled servers and shared storage connected over a network fabric, such as InfiniBand EDR, 40GbE, or 100GbE. -An example of a cluster node providing the best performance: +The following table shows SQream's recommended hardware specifications: .. list-table:: :widths: auto @@ -74,43 +74,50 @@ An example of a cluster node providing the best performance: * - Component - Type * - Server - - High-density GPU-capable rackmount server, like Dell C4140, IBM AC922, Lenovo SR650. + - High-density GPU-capable rackmount server, like Dell C4140, Dell R940xa, Dell R750, Lenovo SR650 or similar. * - Processor - - 2x Intel Platinum 8180M (28C/56HT) 3.8GHz or 2x IBM POWER9 + - 2x Intel Xeon Gold 6240 (18C/36HT) 2.6GHz or 2x IBM POWER9 * - RAM - - 1024 GB RDIMM 2933T/s, ECC registered + - 1 - 2TB * - Onboard storage - * 2x 960GB SSD 2.5in, for OS, RAID1 * 2x 2TB SSD or NVMe, for temporary spooling, RAID1 * - Networking - - Intel X710 DP 10Gb DA/SFP+ for BI fabric + - Mellanox ConnectX-4, EDR for storage fabric + Mellanox Connectx 5 100 Gbps for storage fabric or similar. * - GPU - - 4x NVIDIA Tesla V100 32GB + - 4x NVIDIA Tesla V100 32GB or A100 -.. note:: With a NAS connected over GPFS, Lustre, or NFS - each SQream DB worker can read data at up to 5GB/s. +.. note:: With a NAS connected over GPFS, Lustre, or NFS, each SQream worker can read data at up to 5GB/s. -Considerations in cluster design + + +Cluster Design Considerations ==================================== -* In a SQream DB installation, the storage and compute are logically separated. While they may reside on the same machine in a standalone installation, they may also reside on different hosts, providing additional flexibility and scalability. +* In a SQream installation, the storage and compute are logically separated. While they may reside on the same machine in a standalone installation, they may also reside on different hosts, providing additional flexibility and scalability. -* SQream DB uses all resources in a machine, including CPU, RAM, and GPU to deliver the best performance. 256GB of RAM per physical GPU is recommended, but not required. + :: -* Local disk space is required for good performance temporary spooling - particularly when performing intensive larger-than-RAM operations like sorting. SQream recommends an SSD or NVMe drive, in mirrored RAID 1 configuration, with about 2x the RAM size available for temporary storage. This can be shared with the operating system drive if necessary. +* SQream uses all resources in a machine, including CPU, RAM, and GPU to deliver the best performance. At least 256GB of RAM per physical GPU is recommended. -* When using SAN or NAS devices, SQream recommends around 5GB/s of burst throughput from storage, per GPU. + :: -Balancing cost and performance --------------------------------- +* Local disk space is required for good temporary spooling performance, particularly when performing intensive operations exceeding the available RAM, such as sorting. SQream recommends an SSD or NVMe drive in RAID 1 configuration with about twice the RAM size available for temporary storage. This can be shared with the operating system drive if necessary. -Prior to designing and deploying a SQream DB cluster, there are a number of important factors to consider. + :: -This section provides a breakdown of deployment details intended to help ensure that this installation exceeds or meets the stated requirements. The rationale provided includes the necessary information for modifying configurations to suit the customer use-case scenario. +* When using SAN or NAS devices, SQream recommends approximately 5GB/s of burst throughput from storage per GPU. + +Balancing Cost and Performance +-------------------------------- +Prior to designing and deploying a SQream cluster, a number of important factors must be considered. + +The **Balancing Cost and Performance** section provides a breakdown of deployment details to ensure that this installation exceeds or meets the stated requirements. The rationale provided includes the necessary information for modifying configurations to suit the customer use-case scenario, as shown in the following table: .. list-table:: :widths: auto @@ -133,35 +140,28 @@ This section provides a breakdown of deployment details intended to help ensure * - Network - Balance price and performance -CPU compute +CPU Compute ------------- -SQream DB relies on multi-core Intel® Xeon® processors or IBM® POWER9 processors. - -SQream recommends a dual-socket machine populated with CPUs with 18C/36HT or better. - -While a higher core count may not necessarily affect query performance, more cores will enable higher concurrency and better load performance. +SQream relies on multi-core Intel Gold Xeon processors or IBM POWER9 processors, and recommends a dual-socket machine populated with CPUs with 18C/36HT or better. While a higher core count may not necessarily affect query performance, more cores will enable higher concurrency and better load performance. -GPU compute and RAM +GPU Compute and RAM ------------------------- -The NVIDIA Tesla range of high-throughput GPU accelerators provides the best performance for enterprise environments. Most cards have ECC memory, which is crucial for delivering correct results every time. +The NVIDIA Tesla range of high-throughput GPU accelerators provides the best performance for enterprise environments. Most cards have ECC memory, which is crucial for delivering correct results every time. SQream recommends the NVIDIA Tesla V100 32GB or NVIDIA Tesla A100 40GB GPU for best performance and highest concurrent user support. -SQream recommends the NVIDIA Tesla V100 32GB GPU for best performance and highest concurrent user support. - -GPU RAM, sometimes called GRAM or VRAM is used for processing queries. It is possible to select GPUs with less RAM, like the NVIDIA Tesla V100 16GB or P100 16GB. However, the smaller GPU RAM available will result in reduced concurrency, as the GPU RAM is used extensively in operations like JOINs, ORDER BY, GROUP BY, and all SQL transforms. +GPU RAM, sometimes called GRAM or VRAM, is used for processing queries. It is possible to select GPUs with less RAM, like the NVIDIA Tesla V100 16GB or P100 16GB, or T4 16GB. However, the smaller GPU RAM results in reduced concurrency, as the GPU RAM is used extensively in operations like JOINs, ORDER BY, GROUP BY, and all SQL transforms. RAM -------- -Use of error-correcting code memory (ECC) is a practical requirement for SQream DB and is standard on most enterprise server. SQream DB benefits from having large amounts of memory for improved performance on large 'external' operations like sorting and joining. +SQream requires using **Error-Correcting Code memory (ECC)**, standard on most enterprise servers. Large amounts of memory are required for improved performance for heavy external operations, such as sorting and joining. -Although SQream DB can function with less, we recommend a key of 256GB of RAM per GPU in the machine. +SQream recommends at least 256GB of RAM per GPU on your machine. -Operating system +Operating System --------------------- - -SQream DB can run on 64-bit Linux operating systems: +SQream can run on the following 64-bit Linux operating systems: * Red Hat Enterprise Linux (RHEL) v7 * CentOS v7 @@ -171,45 +171,8 @@ SQream DB can run on 64-bit Linux operating systems: Storage ----------- +For clustered scale-out installations, SQream relies on NAS/SAN storage. For stand-alone installations, SQream relies on redundant disk configurations, such as RAID 5, 6, or 10. These RAID configurations replicate blocks of data between disks to avoid data loss or system unavailability. -For clustered scale-out installations, SQream DB relies on NAS/SAN storage. These devices have extremely high reliability and durability, with five 9s of up-time. - -For stand-alone installations, SQream DB relies on redundant disk configurations, like RAID 10/50. These RAID configurations ensure that blocks of data are replicated between disks, so that failure of a number of disks will not result in data loss or availability of the system. - -Because storage reliability is important, SQream recommends enterprise-grade SAS SSD drives. However, as with other components – there is a tradeoff for cost/performance. When performance and reliability are important, SQream recommends SAS SSD or NVMe drives. - -SQream DB functions well with more cost-effective SATA drives and even large spinning-disk arrays. - - -Example cluster supporting 32 concurrent active users -========================================================== - -For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream DB recommends 1 Tesla V100 GPU per 2 users, for full, uninterrupted dedicated access. - -Each of these servers can support about 8 users on average. The actual number of concurrent users can be higher, depending on the workload. - -A SQream DB cluster for 32 users consists of the following components: - -#. - 4 high-density GPU-enabled servers, like the Dell C4140 (Configuration C) with 4x NVIDIA Tesla V100 32GB PCIe GPUs. - - Each server is equipped with dual Intel ® Xeon ® Gold 6240 CPU, and 1,024GB of RAM. - -#. - NAS/SAN storage, capable of delivering 1 GB/s per GPU. - - For the system above, with 4x4 NVIDIA Tesla V100 GPUs, this results in 16GB/s, over multiple bonded, 40GigE or InfiniBand links via a fabric switch. - -#. Top-of-Rack (ToR) 10GigE ethernet switch for the BI fabric - -#. 40GigE or InfiniBand switches for the storage fabric - -#. At least 1 PDU - -.. figure:: /_static/images/reference_architecture_30u.png - :alt: A 4-node system, supporting up to 30 users with 1PB of storage - - -.. rubric:: Read more +SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla V100 or A100 GPU per 2 users, for full, uninterrupted dedicated access. -Download the full `SQream DB Reference Architecture `_ document. +Download the full `SQream Reference Architecture `_ document. From 3cb82c655a5c6681d318c041339efcd00733931e Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 4 Nov 2021 09:57:59 +0200 Subject: [PATCH 088/300] Update count.rst Corrected Line 52 according to https://sqream.atlassian.net/browse/SQ-8782. --- reference/sql/sql_functions/aggregate_functions/count.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/aggregate_functions/count.rst b/reference/sql/sql_functions/aggregate_functions/count.rst index 5a056d9fe..ab7f492e1 100644 --- a/reference/sql/sql_functions/aggregate_functions/count.rst +++ b/reference/sql/sql_functions/aggregate_functions/count.rst @@ -49,7 +49,7 @@ Notes * ``NULL`` values are *not* ignored by ``COUNT`` -* When all rows contain ``NULL`` values, the function returns ``NULL``. +* When all rows contain ``NULL`` values, the function returns the amount of rows in the table. Examples From e159759c9a2d851c8a735c1ff9ba2a020e611451 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 4 Nov 2021 09:59:34 +0200 Subject: [PATCH 089/300] Update count.rst Corrected Line 52 according to https://sqream.atlassian.net/browse/SQ-8782. --- .../sql/sql_functions/aggregate_functions/count.rst | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/reference/sql/sql_functions/aggregate_functions/count.rst b/reference/sql/sql_functions/aggregate_functions/count.rst index eb047c92f..ab7f492e1 100644 --- a/reference/sql/sql_functions/aggregate_functions/count.rst +++ b/reference/sql/sql_functions/aggregate_functions/count.rst @@ -13,7 +13,7 @@ Syntax .. code-block:: postgres -- As an aggregate - COUNT( { [ DISTINCT ] expr | * } ) --> INT + COUNT( { [ DISTINCT ] expr | * } ) --> BIGINT -- As a window function COUNT ( { [ DISTINCT ] expr | * } ) OVER ( @@ -41,21 +41,16 @@ Arguments Returns ============ -Return type is dependant on the argument. +* Count returns ``BIGINT``. -* Count returns ``INT`` for all types except ``BIGINT``. - -* For ``BIGINT``, the return type is ``BIGINT``. Notes ======= * ``NULL`` values are *not* ignored by ``COUNT`` -* When all rows contain ``NULL`` values, the function returns ``NULL``. - +* When all rows contain ``NULL`` values, the function returns the amount of rows in the table. -* ``COUNT`` can very quickly overflow on large data sets. If the count is over 2\ :sup:`31`, up-cast to a larger type like ``BIGINT``: ``COUNT(expr :: BIGINT)`` Examples =========== From ef65536dce53df0e3d97c25378d51cf5a1da6186 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 11:44:07 +0200 Subject: [PATCH 090/300] Create recommended_pre-installation_configurations.rst Created recommended_pre-installation_configurations.rst. --- ...mended_pre-installation_configurations.rst | 1156 +++++++++++++++++ 1 file changed, 1156 insertions(+) create mode 100644 guides/operations/recommended_pre-installation_configurations.rst diff --git a/guides/operations/recommended_pre-installation_configurations.rst b/guides/operations/recommended_pre-installation_configurations.rst new file mode 100644 index 000000000..b84a48c9d --- /dev/null +++ b/guides/operations/recommended_pre-installation_configurations.rst @@ -0,0 +1,1156 @@ +.. _recommended_pre-installation_configurations: + +********************************************* +Recommended Pre-Installation Configuration +********************************************* + +Before :ref:`installing SQream DB`, SQream recommends you to tune your system for better performance and stability. + +This page provides recommendations for production deployments of SQream DB. + +.. contents:: In this topic: + :local: + +Recommended BIOS Settings +========================== +The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. + +It is safe to skip any and all of the configuration steps, but this may impact performance. + +If any doubt arises, consult the documentation for your server or your hardware vendor for the correct way to apply the settings. + +.. list-table:: + :widths: 25 25 50 + :header-rows: 1 + + * - Item + - Setting + - Rationale + * - **Management console access** + - **Connected** + - Connection to OOB required to preserve continuous network uptime. + * - **All drives.** + - **Connected and displayed on RAID interface** + - Prerequisite for cluster or OS installation. + * - **RAID volumes.** + - **Configured according to project guidelines. Must be rebooted to take effect.** + - Clustered to increase logical volume and provide redundancy. + * - **Fan speed Thermal Configuration.** + - Dell fan speed: **High Maximum**. Specified minimum setting: **60**. HPe thermal configuration: **Increased cooling**. + - NVIDIA Tesla GPUs are passively cooled and require high airflow to operate at full performance. + * - Power regulator or iDRAC power unit policy + - HPe: **HP static high performance** mode enabled. Dell: **iDRAC power unit policy** (power cap policy) disabled. + - Other power profiles (such as "balanced") throttle the CPU and diminishes performance. Throttling may also cause GPU failure. + * - **System Profile**, **Power Profile**, or **Performance Profile** + - **High Performance** + - The Performance profile provides potentially increased performance by maximizing processor frequency, and the disabling certain power saving features such as C-states. Use this setting for environments that are not sensitive to power consumption. + * - **Power Cap Policy** or **Dynamic power capping** + - **Disabled** + - Other power profiles (like "balanced") throttle the CPU and may diminish performance or cause GPU failure. This setting may appear together with the above (Power profile or Power regulator). This setting allows disabling system ROM power calibration during the boot process. Power regulator settings are named differently in BIOS and iLO/iDRAC. + +.. + **Comment: is it necessary to show the different power regulator setting names in this document?** + * - **Intel Turbo Boost** + - **Enabled** + - Intel Turbo Boost enables overclocking the processor to boost CPU-bound operation performance. Overclocking may risk computational jitter due to changes in the processor's turbo frequency. This causes brief pauses in processor operation, introducing uncertainty into application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. + * - **Logical Processor** + - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** + - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. + * - **Intel Virtualization Technology** (VT-d) + - **Disable** + - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. + * - **Logical Processor** + - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** + - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. + * - **Intel Virtualization Technology** (VT-d) + - **Disable** + - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. + * - **Processor C-States** (Minimum processor idle power core state) + - **Disable** + - Processor C-States reduce server power when the system is in an idle state. This causes slower cold-starts when the system transitions from an idle to a load state, and may reduce query performance by up to 15%. **Comment: a hyperlinked footnote to an internal source was inserted into the Confluence doc here. Do we want to include this in the final version? Linked URL: https://www.dell.com/support/kbdoc/en-il/000060621/what-is-the-c-state** + * - **HPe**: **Energy/Performance bias** + - **Maximum performance** + - Configures processor sub-systems for high-performance and low-latency. Other power profiles (like "balanced") throttle the CPU and may diminish performance. Use this setting for environments that are not sensitive to power consumption. + * - **HPe**: **DIMM voltage** + - **Optimized for Performance** + - Setting a higher voltage for DIMMs may increase performance. + * - **Memory Operating Mode** + - **Optimizer Mode**, **Disable Node Interleaving**, **Auto Memory Operating Voltage** + - Memory Operating Mode is tuned for performance in **Optimizer** mode. Other modes may improve reliability, but reduce performance. **Node Interleaving** should be disabled because enabling it interleaves the memory between memory nodes, which harms NUMA-aware applications such as SQream DB. + * - **HPe**: **Memory power savings mode** + - **Maximum performance** + - This setting configures several memory parameters to optimize the performance of memory sub-systems. The default setting is **Balanced**. + * - HPe **ACPI SLIT** + - **Enabled** + - ACPI SLIT sets the relative access times between processors and memory and I/O sub-systems. ACPI SLIT enables operating systems to use this data to improve performance by more efficiently allocating resources and workloads. + * - **QPI Snoop** **Comment: should we write that it is HPe or Intel? HPe: QPI Snoop** + - **Cluster on Die** or **Home Snoop** + - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. + + + + + + +Installing the Operating System +=================================================== +Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.6-7.9) must be installed before installing the SQream database. Either the customer or a SQream representative can perform the installation. + +.. + **Comment: I recommend leaving contact information here - Please call xxx-xxx-xxxx to contact a SQream representative.** + +**To install the operating system:** + +#. Select a language (English recommended). +#. From **Software Selection**, select **Minimal**. +#. Select the **Development Tools** group checkbox. +#. Continue the installation. +#. Set up the necessary drives and users as per the installation process. + + Using Debugging Tools is recommended for future problem-solving if necessary. + + .. + **Comment: In Step 4, why don't we document the entire procedure? I.e., why do we stop here and say "Continue the installation" and "Set up the necessary drives..."?** + +Selecting the **Development Tools** group installs the following tools: + + * autoconf + * automake + * binutils + * bison + * flex + * gcc + * gcc-c++ + * gettext + * libtool + * make + * patch + * pkgconfig + * redhat-rpm-config + * rpm-build + * rpm-sign + + + +The root user is created and the OS shell is booted up. + +Configuring the Operating System +=================================================== +When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. + +Logging In to the Server +-------------------------------- +You can log in to the server using the server's IP address and password for the **root** user. The server's IP address and **root** user were created while installing the operating system above. + +Automatically Creating a SQream User +------------------------------------ + +**To automatically create a SQream user:** + +#. If a SQream user was created during installation, verify that the same ID is used on every server: + + .. code-block:: console + + $ sudo id sqream + +The ID **1000** is used on each server in the following example: + + .. code-block:: console + + $ uid=1000(sqream) gid=1000(sqream) groups=1000(sqream) + +2. If the ID's are different, delete the SQream user and SQream group from both servers: + + .. code-block:: console + + $ sudo userdel sqream + +3. Recreate it using the same ID: + + .. code-block:: console + + $ sudo rm /var/spool/mail/sqream + +Manually Creating a SQream User +-------------------------------- + +**To manually create a SQream user:** + +SQream enables you to manually create users. This section shows you how to manually create a user with the UID **1111**. You cannot manually create during the operating system installation procedure. + +1. Add a user with an identical UID on all cluster nodes: + + .. code-block:: console + + $ useradd -u 1111 sqream + +2. Add the user **sqream** to the **wheel** group. + + .. code-block:: console + + $ sudo usermod -aG wheel sqream + +You can remove the SQream user from the **wheel** group when the installation and configuration are complete: + + .. code-block:: console + + $ passwd sqream + +3. Log out and log back in as **sqream**. + +**Note:** If you deleted the **sqream** user and recreated it with different ID, to avoid permission errors, you must change its ownership to /home/sqream. + +4. Change the **sqream** user's ownership to /home/sqream: + + .. code-block:: console + + $ sudo chown -R sqream:sqream /home/sqream + +Setting Up A Locale +-------------------------------- + +SQream enables you to set up a locale. In this example, the locale used is your own location. + +**To set up a locale:** + +1. Set the language of the locale: + + .. code-block:: console + + $ sudo localectl set-locale LANG=en_US.UTF-8 + +2. Set the time stamp (time and date) of the locale: + + .. code-block:: console + + $ sudo timedatectl set-timezone Asia/Jerusalem + +If needed, you can run the **timedatectl list-timezones** command to see your current time-zone. + + +Installing the Required Packages +-------------------------------- +You can install the required packages by running the following command: + +.. code-block:: console + + $ sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq + + +Installing the Recommended Tools +-------------------------------- +You can install the recommended tools by running the following command: + +.. code-block:: console + + $ sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix + + +Installing Python 3.6.7 +-------------------------------- +1. Download the Python 3.6.7 source code tarball file from the following URL into the **/home/sqream** directory: + + .. code-block:: console + + $ wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz + +2. Extract the Python 3.6.7 source code into your current directory: + + .. code-block:: console + + $ tar -xf Python-3.6.7.tar.xz + +3. Navigate to the Python 3.6.7 directory: + + .. code-block:: console + + $ cd Python-3.6.7/Python-3 + +4. Run the **./configure** script: + + .. code-block:: console + + $ ./configure + +5. Build the software: + + .. code-block:: console + + $ make -j30 + +6. Install the software: + + .. code-block:: console + + $ sudo make install + +7. Verify that Python 3.6.7 has been installed: + + .. code-block:: console + + $ python3.6.7 + +Installing NodeJS on CentOS +-------------------------------- +**To install the node.js on CentOS:** + +1. Download the `setup_12.x file `__ as a root user logged in shell: + + .. code-block:: console + + $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - + +2. Clear the YUM cache and update the local metadata: + + .. code-block:: console + + $ sudo yum clean all && sudo yum makecache fast + +3. Install the **node.js**) file: + + .. code-block:: console + + $ sudo yum install -y nodejs + +Installing NodeJS on Ubuntu +-------------------------------- +**To install the node.js file on Ubuntu:** + +1. Download the `setup_12.x file `__ as a root user logged in shell: + + .. code-block:: console + + $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - + +2. Install the node.js file: + + .. code-block:: console + + $ sudo apt-get install -y nodejs + +3. Verify the node version: + +.. + **Comment: - is this step relevant only for installing on Ubuntu, or on CentOS as well?** + + .. code-block:: console + + $ node -v + +Configuring the Network Time Protocol (NTP) +------------------------------------------- +This section describes how to configure your NTP. + +If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server `__. + +.. + **Comment: - Is this the correct procedure on the linked URL: Configure NTP Client to Synchronize with NTP Server?* + +**To configure your NTP:** + +1. Install the NTP file. + + .. code-block:: console + + $ sudo yum install ntp + +2. Enable the **ntpd** program. + + .. code-block:: console + + $ sudo systemctl enable ntpd + +3. Start the **ntdp** program. + + .. code-block:: console + + $ sudo systemctl start ntpd + +4. Print a list of peers known to the server and a summary of their states. + + .. code-block:: console + + $ sudo ntpq -p + +Configuring the Network Time Protocol Server +-------------------------------------------- +If your organization has an NTP server, you can configure it. + +**To configure your NTP server:** + +1. Output your NTP server address and append ``/etc/ntpd.conf`` to the outuput. + + .. code-block:: console + + $ echo -e "\nserver \n" | sudo tee -a /etc/ntp.conf + +2. Restart the service. + + .. code-block:: console + + $ sudo systemctl restart ntpd + +3. Check that synchronization is enabled: + + .. code-block:: console + + $ sudo timedatectl + +Checking that synchronization is enabled generates the following output: + + .. code-block:: console + + $ Local time: Sat 2019-10-12 17:26:13 EDT + Universal time: Sat 2019-10-12 21:26:13 UTC + RTC time: Sat 2019-10-12 21:26:13 + Time zone: America/New_York (EDT, -0400) + NTP enabled: yes + NTP synchronized: yes + RTC in local TZ: no + DST active: yes + Last DST change: DST began at + Sun 2019-03-10 01:59:59 EST + Sun 2019-03-10 03:00:00 EDT + Next DST change: DST ends (the clock jumps one hour backwards) at + Sun 2019-11-03 01:59:59 EDT + Sun 2019-11-03 01:00:00 EST + + + +Configuring the Server to Boot Without the UI +--------------------------------------------- +You can configure your server to boot without a UI in cases when it is not required (recommended) by running the following command: + +.. code-block:: console + + $ sudo systemctl set-default multi-user.target + +Running this command activates the **NO-UI** server mode. + +Configuring the Security Limits +-------------------------------- +The security limits refers to the number of open files, processes, etc. + +You can configure the security limits by running the **echo -e** command as a root user logged in shell: + +.. code-block:: console + + $ sudo bash + +.. code-block:: console + + $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + +Configuring the Kernel Parameters +--------------------------------- +**To configure the kernel parameters:** + +1. Insert a new line after each kernel parameter: + + .. code-block:: console + + $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf + +**Notice:** In the past, the **vm.zone_reclaim_mode** parameter was set to **7.** In the latest Sqream version, the vm.zone_reclaim_mode parameter must be set to **0**. If it is not set to **0**, when a numa node runs out of memory, the system will get stuck and will be unable to pull memory from other numa nodes. + +2. Check the maximum value of the **fs.file**. + + .. code-block:: console + + $ sysctl -n fs.file-max + +3. *Optional* - If the maximum value of the **fs.file** is smaller than **2097152**, run the following command: + + .. code-block:: console + + $ echo "fs.file-max=2097152" >> /etc/sysctl.conf + +**IP4 forward** must be enabled for Docker and K8s installation only. + +Configuring the Firewall +-------------------------------- +The example in this section shows the open ports for four sqreamd sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. + +**To configure the firewall:** + +1. Start the service and enable FirewallID on boot: + + .. code-block:: console + + $ systemctl start firewalld + +2. Add the following ports to the permanent firewall: + + .. code-block:: console + + $ firewall-cmd --zone=public --permanent --add-port=8080/tcp + $ firewallfirewall-cmd --zone=public --permanent --add-port=3105/tcp + $ firewall-cmd --zone=public --permanent --add-port=3108/tcp + $ firewall-cmd --zone=public --permanent --add-port=5000-5003/tcp + $ firewall-cmd --zone=public --permanent --add-port=5100-5103/tcp + $ firewall-cmd --permanent --list-all + + +.. + **Comment: - does *--list-all* add the entire list of ports to the permanent firewall?** + +3. Reload the firewall: + + .. code-block:: console + + $ firewall-cmd --reload + +4. Start the service and enable FirewallID on boot: + + .. code-block:: console + + $ systemctl start firewalld + + If you do not need the firewall, you can disable it: + + .. code-block:: console + + $ sudo systemctl disable firewalld + + +Disabling selinux +-------------------------------- +**To disable selinux:** + +1. Show the status of **selinux**: + + .. code-block:: console + + $ sudo sestatus + +2. If the output is not **disabled**, edit the **/etc/selinux/config** file: + + .. code-block:: console + + $ sudo vim /etc/selinux/config + +3. Change **SELINUX=enforcing** to **SELINUX=disabled**. + +The above changes will only take effect after rebooting the server. + +You can disable selinux immediately after rebooting the server by running the following command: + +.. code-block:: console + + $ sudo setenforce 0 + +Configuring the /etc/hosts File +-------------------------------- +**To configure the /etc/hosts file:** + +1. Edit the **/etc/hosts** file: + + .. code-block:: console + + $ sudo vim /etc/hosts + +2. Call your local host: + + .. code-block:: console + + $ 127.0.0.1 localhost + $ + +.. + **Comment: - Is the above an output or a step?** + +Configuring the DNS +-------------------------------- +**To configure the DNS:** + +1. Run the **ifconfig** commasnd to check your NIC name. In the following example, **eth0** is the NIC name: + + .. code-block:: console + + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-eth0 + +2. Replace the DNS lines from the example above with your own DNS addresses : + + .. code-block:: console + + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-4.4.4.4 + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-8.8.8.8 + + +.. + **Comment: - is the above input correct?** + +Installing the Nvidia CUDA Driver +=================================================== + + +**Warning:** If your UI runs on the server, the server must be stopped before installing the CUDA drivers. + +CUDA Driver Prerequisites +-------------------------------- +1. Verify that the NVIDIA card has been installed and is detected by the system: + + .. code-block:: console + + $ lspci | grep -i nvidia + +2. Check which version of gcc has been installed: + + .. code-block:: console + + $ gcc --version + +3. If gcc has not been installed, install it for one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console + + $ sudo yum install -y gcc + + * On Ubuntu: + + .. code-block:: console + + $ sudo apt-get install gcc + + +Updating the Kernel Headers +-------------------------------- +**To update the kernel headers:** + +1. Update the kernel headers on one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console + + $ sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) + + * On Ubuntu: + + .. code-block:: console + + $ sudo apt-get install linux-headers-$(uname -r) + +2. Install **wget** one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console + + $ sudo yum install wget + + * On Ubuntu: + + .. code-block:: console + + $ sudo apt-get install wget + +Disabling Nouveau +-------------------------------- +You can disable Nouveau, which is the default driver. + +**To disable Nouveau:** + +1. Check if the Nouveau driver has been loaded: + + .. code-block:: console + + $ lsmod | grep nouveau + +If the Nouveau driver has been loaded, the command above generates output. + +2. Blacklist the Nouveau drivers to disable them: + + .. code-block:: console + + $ cat <`__ for the additional set-up requirements. + + + c. **For K80**: + + .. code-block:: console + + $ nvidia-persistenced + $ nvidia-smi -pm 1 + $ nvidia-smi -acp 0 + $ nvidia-smi --auto-boost-permission=0 + $ nvidia-smi --auto-boost-default=0 + +4. Reboot the server and run the **NVIDIA System Management Interface (NVIDIA SMI)**: + + .. code-block:: console + + $ nvidia-smi + + +Disabling Automatic Bug Reporting Tools +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**To disable automatic bug reporting tools:** + +1. Run the following **abort** commands: + + .. code-block:: console + + $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done + + +The server is ready for the SQream software installation. + + +2. Run the following checks: + + a. Check the OS release: + + .. code-block:: console + + $ cat /etc/os-release + + b. Verify that a SQream user exists and has the same ID on all cluster member services: + + .. code-block:: console + + $ id sqream + + c. Verify that the storage is mounted: + + .. code-block:: console + + $ mount + + d. Verify that the driver has been installed correctly: + + .. code-block:: console + + $ nvidia-smi + + e. Check the maximum value of the **fs.file**: + + .. code-block:: console + + $ sysctl -n fs.file-max + + The desired output when checking the maximum value of the **fs.file** is greater or equal to **2097152**. + + f. Run the following command as a SQream user: + +.. + **Comment: - **Question - what do the following command parameter do? -c?** + + .. code-block:: console + + $ ulimit -c -u -n + +.. + **Comment: - See https://ss64.com/bash/ulimit.html** + + The following shows the desired output when ****: + + .. code-block:: console + + $ core file size (blocks, -c) unlimited + $ max user processes (-u) 1000000 + $ open files (-n) 1000000 + +3. Configure the security limits by running the **echo -e** command as a root user logged in shell: + + .. code-block:: console + + $ sudo bash + $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + +Enabling Core Dumps +=================================================== + +Enabling core dumps is recommended, but optional. + +**To enable core dumps:** + +1. Check the **abrtd** Status + +2. Set the limits + +3. Create the core dumps directory. + + +Checking the abrtd Status +--------------------------------------------------- + +**To check the abrtd status:** + +1. Check if **abrtd** is running: + + .. code-block:: console + + $ sudo ps -ef |grep abrt + +2. If **abrtd** is running, stop it: + + .. code-block:: console + + $ sudo service abrtd stop + $ sudo chkconfig abrt-ccpp off + $ sudo chkconfig abrt-oops off + $ sudo chkconfig abrt-vmcore off + $ sudo chkconfig abrt-xorg off + $ sudo chkconfig abrtd off + + +Setting the Limits +--------------------------------------------------- + +**To set the limits:** + +1. Set the limits: + + .. code-block:: console + + $ ulimit -c + +2. If the output is **0**, add the following lines to the **limits.conf** file (/etc/security): + + .. code-block:: console + + $ * soft core unlimited + $ * hard core unlimited + +3. Log out and log in to apply the limit changes. + +Creating the Core Dumps Directory +--------------------------------------------------- + +**To set the core dumps directory:** + +1. Make the **/tmp/core_dumps** directory: + + .. code-block:: console + + $ mkdir /tmp/core_dumps + +2. Set the ownership of the **/tmp/core_dumps** directory: + + .. code-block:: console + + $ sudo chown sqream.sqream /tmp/core_dumps + +3. Grant read, write, and execute permissions to all users: + + .. code-block:: console + + $ sudo chmod -R 777 /tmp/core_dumps + +Setting the Output Directory of the /etc/sysctl.conf File +----------------------------------------------------------------- + +**To set the output directory of the /etc/sysctl.conf file:** + +1. Edit the **/etc/sysctl.conf** file: + + .. code-block:: console + + $ sudo vim /etc/sysctl.conf + +2. Add the following to the bottom of the file: + + .. code-block:: console + + $ kernel.core_uses_pid = 1 + $ kernel.core_pattern = //core-%e-%s-%u-%g-%p-%t + $ fs.suid_dumpable = 2 + +.. + **Comment: - leave a note that the user can choose his correct location of the folder.** + +3. To apply the changes without rebooting the server, run: + + .. code-block:: console + + $ sudo sysctl -p + +4. Check that the core output directory points to the following: + + .. code-block:: console + + $ sudo cat /proc/sys/kernel/core_pattern + + The following shows the correct generated output: + + .. code-block:: console + + $ /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t + +5. Verify that the core dumping works: + + .. code-block:: console + + $ select abort_server(); + + +Verifying that the Core Dumps Work +--------------------------------------------------- +You can verify that the core dumps work only after installing and running SQream. This causes the server to crash and a new core.xxx file to be included in the folder that is written in **/etc/sysctl.conf** + +**To verify that the core dumps work:** + +1. Stop and restart all SQream services. + +2. Connect to SQream with ClientCmd and run the following command: + + .. code-block:: console + + $ select abort_server(); + + +.. + **Comment: - what did the author mean by "Stage 3"?** + +Troubleshooting Core Dumping +--------------------------------------------------- +This section describes the troubleshooting procedure to be followed if all parameters have been configured correctly, but the cores have not been created. + +**To troubleshoot core dumping:** + +1. Reboot the server. + +2. Verify that you have folder permissions: + + .. code-block:: console + + $ sudo chmod -R 777 /tmp/core_dumps + +3. Verify that the limits have been set correctly: + + .. code-block:: console + + $ ulimit -c + + If all parameters have been configured correctly, the correct output is: + + .. code-block:: console + + $ unlimited + +4. If all parameters have been configured correctly, but running **ulimit -c** outputs **0**, run the following: + + .. code-block:: console + + $ sudo vim /etc/profile + +5. Search for line and tag it with the **hash** symbol: + + .. code-block:: console + + $ ulimit -S -c 0 > /dev/null 2>&1 + + +6. If the line is not found in **/etc/profile** directory, do the following: + + a. Run the following command: + + .. code-block:: console + + $ sudo vim /etc/init.d/functions + + b. Search for the following: + + .. code-block:: console + + $ ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 + + c. If the line is found, tag it with the **hash** symbol and reboot the server. From 45a33cee10456db635bea92e082402029f42591f Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 11:45:18 +0200 Subject: [PATCH 091/300] Update index.rst Added recommended_pre-installation_configurations. Removed setup/index. --- guides/operations/index.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/guides/operations/index.rst b/guides/operations/index.rst index 3942838e3..4df9c0314 100644 --- a/guides/operations/index.rst +++ b/guides/operations/index.rst @@ -12,6 +12,7 @@ The guides in this section include information about best practices, monitoring, :glob: optimization_best_practices + recommended_pre-installation_configurations xxmonitoring monitoring_query_performance launching_sqream_with_monit @@ -26,5 +27,3 @@ The guides in this section include information about best practices, monitoring, statement_editor hardware_guide security - setup/index - From 1bcfdd062d71211fe5650971841287e25d5807ec Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 11:46:16 +0200 Subject: [PATCH 092/300] Update first_steps.rst Updated Getting Started page. --- first_steps.rst | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/first_steps.rst b/first_steps.rst index b20147c2d..a3a37fa33 100644 --- a/first_steps.rst +++ b/first_steps.rst @@ -12,12 +12,43 @@ The **Getting Started** page describes the following: Before Installing SQream ============================ -Before installing SQream, you must set up your local machine according to SQream's recommended pre-installation configurations. +Before installing SQream, do the following: + * Set up your local machine according to SQream's recommended pre-installation configurations. + + :: + + * Verify you have an NVIDIA-capable server, either on-premise or on supported cloud platforms: + + * Red Hat Enterprise Linux v7.x + + + * CentOS v7.x + + + * Ubuntu 18.04 + + + * Amazon Linux + + * Verify that you have the following: + + * An NVIDIA GPU - SQream recommends using a Tesla GPU. + + + * An SSH connection to your server. + + + * SUDO permissions for installation and configuration purposes. + + + * A SQream license - Contact support@sqream.com or your SQream account manager for your license key. For more information, see the following: -* `Hardware Guide `_. -* `Recommended Pre-Installation Configuration `_. +* `Hardware Guide `_ +* `Recommended Pre-Installation Configuration `_ + + From ceda1058aed663404815a5fbcb2ee54568a4b796 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 7 Nov 2021 11:47:28 +0200 Subject: [PATCH 093/300] Deleted Setup folder (sqream_docs\guides\operations\setup). Folder was not necessary because it contains files that are either outdated or are irrelevant: before_you_begin - irrelevant. The content on this page was moved to Getting Started page. index - irrelevant installing_monit - this page already exists in Operations. local_docker - there is an updated Docker page in the Operations menu. I've backed up this file. recommended_configuration - there is an updated page in the Operations menu. --- guides/operations/setup/before_you_begin.rst | 49 - guides/operations/setup/index.rst | 19 - guides/operations/setup/local_docker.rst | 529 -------- .../setup/recommended_configuration.rst | 1156 ----------------- 4 files changed, 1753 deletions(-) delete mode 100644 guides/operations/setup/before_you_begin.rst delete mode 100644 guides/operations/setup/index.rst delete mode 100644 guides/operations/setup/local_docker.rst delete mode 100644 guides/operations/setup/recommended_configuration.rst diff --git a/guides/operations/setup/before_you_begin.rst b/guides/operations/setup/before_you_begin.rst deleted file mode 100644 index 9c307ce8b..000000000 --- a/guides/operations/setup/before_you_begin.rst +++ /dev/null @@ -1,49 +0,0 @@ -.. _before_you_begin: - -*********************** -Before you begin -*********************** - -Before you install or deploy SQream DB, please verify you have the following: - -* An NVIDIA-capable server, either on-premise or on supported cloud platforms. - - * Supported operating systems: Red Hat Enterprise Linux v7.x / CentOS v7.x / Ubuntu 18.04 / Amazon Linux - * NVIDIA GPU. A Tesla GPU is highly recommended. See more information in our :ref:`hardware_guide`. - * A privileged SSH connection to the server (sudo) - -* A SQream DB license (contact support@sqream.com or your SQream account manager for your license key) - -* A 3rd party tool that can connect to SQream DB via JDBC, ODBC, or Python - -If you do not have a SQream DB license, visit our website and `sign up for SQream DB`_ today! - -Refer to our :ref:`hardware_guide` for more information about supported and recommended configurations. - -What does the installation process look like? ----------------------------------------------- - -To install SQream DB, we will go through the following steps: - -#. Prepare the host OS for NVIDIA driver installation - -#. Install the NVIDIA driver - -#. Install Docker CE - -#. Install nvidia-docker2 - -#. Prepare disk space for SQream DB - -#. Install SQream DB - -#. Additional system configuration for performance and stability - - -.. rubric:: What's next? - -* When ready, start :ref:`installing SQream DB ` - -.. _`sign up for SQream DB`: https://sqream.com/try-sqream-db - -.. TODO Links for if the user has already installed SQream DB but wants to configure, upgrade, or scale out the system further \ No newline at end of file diff --git a/guides/operations/setup/index.rst b/guides/operations/setup/index.rst deleted file mode 100644 index b422d9c5b..000000000 --- a/guides/operations/setup/index.rst +++ /dev/null @@ -1,19 +0,0 @@ -.. _setup: - -*********************** -Setting up SQream DB -*********************** - -The guides below cover installing SQream DB. - -.. toctree:: - :maxdepth: 4 - :caption: In this section: - :titlesonly: - :glob: - - before_you_begin - local_docker - recommended_configuration - - diff --git a/guides/operations/setup/local_docker.rst b/guides/operations/setup/local_docker.rst deleted file mode 100644 index a6f0d9adc..000000000 --- a/guides/operations/setup/local_docker.rst +++ /dev/null @@ -1,529 +0,0 @@ -.. _installing_sqream_db_docker: - -********************************************* -Start a local SQream DB cluster with Docker -********************************************* - -See :ref:`Release Notes ` to learn about what's new in the latest release of SQream DB. To upgrade to this release, see :ref:`Upgrading SQream DB with Docker`. - -SQream DB is installed on your hosts with NVIDIA Docker. There are several preparation steps to ensure before installing SQream DB, so follow these instructions carefully. - -.. note:: Installing SQream DB requires a license key. Go to `SQream Support `_ or contact your SQream account manager for your license key. - -.. contents:: In this topic: - :local: - -Preparing your machine for NVIDIA Docker -========================================= -To install NVIDIA Docker, we must first install the NVIDIA driver. - -.. note:: SQream DB works best on NVIDIA Tesla series GPUs, which provide better reliability, performance, and stability. The instructions below are written for NVIDIA Tesla GPUs, but other NVIDIA GPUs may work. - -.. contents:: Follow the instructions for your OS and architecture: - :local: - -CentOS 7 / RHEL 7 / Amazon Linux ---------------------------------------------------------------- - -.. admonition:: Recommended - - Follow the installation instructions on `NVIDIA's CUDA Installation Guide`_ for full instructions suitable for your platform. The information listed below is a summary of the necessary steps, and does not cover the full range of options available. - -#. Enable EPEL - - EPEL provides additional open-source and free packages from the RHEL ecosystem. The NVIDIA driver depends on packages such as DKMS and libvdpau which are only available on third-party repositories, such as EPEL. - - .. code-block:: console - - $ sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm - -.. There are other ways of installing EPEL: $ sudo yum -y install epel-release -.. Do we need DKMS? $ sudo yum -y install dkms - -#. Install the kernel headers and development tools necessary to compile the NVIDIA driver - - .. code-block:: console - - $ sudo yum -y install kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc - -#. Install the CUDA repository and install the latest display driver - - .. code-block:: console - - $ sudo rpm -Uvh https://developer.download.nvidia.com/compute/cuda/repos/rhel7/x86_64/cuda-repo-rhel7-10.1.243-1.x86_64.rpm - $ sudo yum install -y nvidia-driver-latest - -.. note:: If Linux is running with X, switch to text-only mode before installing the display driver. - - .. code-block:: console - - $ sudo systemctl set-default multi-user.target - - This change permanently disables X. If you need X, change ``set-default`` to ``isolate``. This will re-enable X on the next reboot. - -#. Restart your machine - - .. code-block:: console - - ``sudo reboot`` - - -#. Verify the installation completed correctly, by asking ``nvidia-smi``, NVIDIA's system management interface application, to list the available GPUs. - - .. code-block:: console - - $ nvidia-smi -L - GPU 0: Tesla V100-PCIE-16GB (UUID: GPU-...) - GPU 1: Tesla V100-PCIE-16GB (UUID: GPU-...) - -#. Enable NVIDIA's persistence daemon. This is mandatory for IBM POWER, but is recommended for other platforms as well. - - .. code-block:: console - - $ sudo systemctl enable nvidia-persistenced && sudo systemctl start nvidia-persistenced - - .. Important:: On POWER9 systems only, disable the udev rule for hot-pluggable memory probing. - - For Red Hat 7 this rule can be found in ``/lib/udev/rules.d/40-redhat.rules`` - - For Ubuntu, this rule can be found in in ``/lib/udev/rules.d/40-vm-hotadd.rules`` - The rule generally takes a form where it detects the addition of a memory block and changes the 'state' attribute to online. For example, in RHEL7, the rule looks like this: - - ``SUBSYSTEM=="memory", ACTION=="add", PROGRAM="/bin/uname -p", RESULT!="s390*", ATTR{state}=="offline", ATTR{state}="online"`` - - This rule must be disabled by copying the file to ``/etc/udev/rules.d`` and commenting out, removing, or changing the hot-pluggable memory rule in the ``/etc`` copy so that it does not apply to NVIDIA devices on POWER9. - - * On RHEL 7.5 or earlier versions: - - .. code-block:: console - - $ sudo cp /lib/udev/rules.d/40-redhat.rules /etc/udev/rules.d - $ sudo sed -i '/SUBSYSTEM=="memory", ACTION=="add"/d' /etc/udev/rules.d/40-redhat.rules - - * On RHEL 7.6 and later versions: - - .. code-block:: console - - $ sudo cp /lib/udev/rules.d/40-redhat.rules /etc/udev/rules.d - $ sudo sed -i 's/SUBSYSTEM!="memory", ACTION!="add", GOTO="memory_hotplug_end"/SUBSYSTEM=="*", GOTO="memory_hotplug_end"/' /etc/udev/rules.d/40-redhat.rules - - *Reboot the system to initialize the above changes* - -#. Continue to :ref:`installing NVIDIA Docker for RHEL ` - -Ubuntu 18.04 ---------------------------------------------------------------- - -.. admonition:: Recommended - - Follow the installation instructions on `NVIDIA's CUDA Installation Guide`_ for full instructions suitable for your platform. The information listed below is a summary of the necessary steps, and does not cover the full range of options available. - -#. Install the kernel headers and development tools necessary - - .. code-block:: console - - $ sudo apt-get update - $ sudo apt-get install linux-headers-$(uname -r) gcc - -#. Install the CUDA repository and driver on Ubuntu - - .. code-block:: console - - $ curl -O https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-repo-ubuntu1804_10.1.243-1_amd64.deb - $ sudo dpkg -i cuda-repo-ubuntu1804_10.1.243-1_amd64.deb - $ sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub - $ sudo apt-get update && sudo apt-get install -y nvidia-driver-418 - -#. Restart your machine - - ``sudo reboot`` - -#. Verify the installation completed correctly, by asking ``nvidia-smi``, NVIDIA's system management interface application, to list the available GPUs. - - .. code-block:: console - - $ nvidia-smi -L - GPU 0: Tesla V100-PCIE-16GB (UUID: GPU-...) - GPU 1: Tesla V100-PCIE-16GB (UUID: GPU-...) - -#. Enable NVIDIA's persistence daemon. This is mandatory for IBM POWER, but is recommended for other platforms as well. - - .. code-block:: console - - $ sudo systemctl enable nvidia-persistenced - -#. Continue to :ref:`installing NVIDIA Docker for Ubuntu ` - -Install Docker CE and NVIDIA docker -==================================== - -.. contents:: Follow the instructions for your OS and architecture: - :local: - -.. _docker_rhel: - -CentOS 7 / RHEL 7 / Amazon Linux (x64) --------------------------------------- - -.. note:: For IBM POWER9, see the next section :ref:`installing NVIDIA Docker for IBM POWER ` - -#. Follow the instructions for Docker CE for your platform at `Get Docker Engine - Community for CentOS`_ - -#. Tell Docker to start after a reboot - - .. code-block:: console - - $ sudo systemctl enable docker && sudo systemctl start docker - -#. Verify that docker is running - - .. code-block:: console - :emphasize-lines: 4 - - $ sudo systemctl status docker - ● docker.service - Docker Application Container Engine - Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled) - Active: active (running) since Mon 2019-08-12 08:22:30 IDT; 1 months 27 days ago - Docs: https://docs.docker.com - Main PID: 65794 (dockerd) - Tasks: 76 - Memory: 124.5M - CGroup: /system.slice/docker.service - └─65794 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock - -#. Let your current user manage Docker, without requiring `sudo` - - .. code-block:: console - - $ sudo usermod -aG docker $USER - - Then, log out and log back in: - - .. code-block:: console - - $ exit - -#. Install nvidia-docker - - .. code-block:: console - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | sudo tee /etc/yum.repos.d/nvidia-docker.repo - $ sudo yum install -y nvidia-container-toolkit - $ sudo yum install nvidia-docker2 - $ sudo pkill -SIGHUP dockerd - $ sudo systemctl restart docker - - .. note:: - - Occasionally, there may be a signature verification error while obtaining ``nvidia-docker``. - The error looks something like this: - ``[Errno -1] repomd.xml signature could not be verified for nvidia-docker`` - - Run the following commands to update the repository keys: - - .. code-block:: console - - $ DIST=$(sed -n 's/releasever=//p' /etc/yum.conf) - $ DIST=${DIST:-$(. /etc/os-release; echo $VERSION_ID)} - $ sudo rpm -e gpg-pubkey-f796ecb0 - $ sudo gpg --homedir /var/lib/yum/repos/$(uname -m)/$DIST/*/gpgdir --delete-key f796ecb0 - $ sudo gpg --homedir /var/lib/yum/repos/$(uname -m)/latest/nvidia-docker/gpgdir --delete-key f796ecb0 - $ sudo gpg --homedir /var/lib/yum/repos/$(uname -m)/latest/nvidia-container-runtime/gpgdir --delete-key f796ecb0 - $ sudo gpg --homedir /var/lib/yum/repos/$(uname -m)/latest/libnvidia-container/gpgdir --delete-key f796ecb0 - -#. Verify the NVIDIA docker installation - - .. code-block:: console - - $ sudo docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi -L - GPU 0: Tesla V100-PCIE-16GB (UUID: GPU-...) - GPU 1: Tesla V100-PCIE-16GB (UUID: GPU-...) - -#. Continue to :ref:`Installing the SQream DB Docker container ` - -.. _docker_power: - -CentOS 7.6 / RHEL 7.6 (IBM POWER) ------------------------------------- - -On POWER9, SQream DB is supported only on RHEL 7.6. - -#. Install Docker for IBM POWER - - .. code-block:: console - - $ wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm - $ wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - $ yum install -y container-selinux-2.9-4.el7.noarch.rpm docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - -#. Tell Docker to start after a reboot - - .. code-block:: console - - $ sudo systemctl enable docker && sudo systemctl start docker - -#. Verify that docker is running - - .. code-block:: console - :linenos: - :emphasize-lines: 4 - - $ sudo systemctl status docker - ● docker.service - Docker Application Container Engine - Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled) - Active: active (running) since Mon 2019-08-12 08:22:30 IDT; 1 months 27 days ago - Docs: https://docs.docker.com - Main PID: 65794 (dockerd) - Tasks: 76 - Memory: 124.5M - CGroup: /system.slice/docker.service - └─65794 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock - -#. Let your current user manage Docker, without requiring `sudo` - - .. code-block:: console - - $ sudo usermod -aG docker $USER - - .. Note:: Log out and log back in again after this action - -#. Install nvidia-docker - - * Install the NVIDIA container and container runtime packages from NVIDIA's repository: - - .. code-block:: console - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | sudo tee /etc/yum.repos.d/nvidia-docker.repo - - $ sudo yum install -y libnvidia-container* nvidia-container-runtime* - - * Add the NVIDIA runtime to the Docker daemon and restart docker: - - .. code-block:: console - - $ sudo mkdir -p /etc/systemd/system/docker.service.d/ - $ echo -e "[Service]\nExecStart\nExecStart=/usr/bin/dockerd --add-runtime=nvidia=/usr/bin/nvidia-container-runtime" | sudo tee /etc/systemd/system/docker.service.d/override.conf - - $ sudo systemctl daemon-reload && sudo systemctl restart docker - - .. note:: - - Occasionally, there may be a signature verification error while obtaining ``nvidia-docker``. - The error looks something like this: - ``[Errno -1] repomd.xml signature could not be verified for nvidia-docker`` - - Run the following commands to update the repository keys: - - .. code-block:: console - - $ DIST=$(sed -n 's/releasever=//p' /etc/yum.conf) - $ DIST=${DIST:-$(. /etc/os-release; echo $VERSION_ID)} - $ sudo rpm -e gpg-pubkey-f796ecb0 - $ sudo gpg --homedir /var/lib/yum/repos/$(uname -m)/$DIST/*/gpgdir --delete-key f796ecb0 - $ sudo gpg --homedir /var/lib/yum/repos/$(uname -m)/latest/nvidia-docker/gpgdir --delete-key f796ecb0 - $ sudo gpg --homedir /var/lib/yum/repos/$(uname -m)/latest/nvidia-container-runtime/gpgdir --delete-key f796ecb0 - $ sudo gpg --homedir /var/lib/yum/repos/$(uname -m)/latest/libnvidia-container/gpgdir --delete-key f796ecb0 - -#. Verify the NVIDIA docker installation succeeded - - .. code-block:: console - - $ docker run --runtime=nvidia --rm nvidia/cuda-ppc64le:10.1-base nvidia-smi -L - GPU 0: Tesla V100-SXM2-16GB (UUID: GPU-...) - GPU 1: Tesla V100-SXM2-16GB (UUID: GPU-...) - -#. Continue to :ref:`Installing the SQream DB Docker container` - -.. _docker_ubuntu: - -Ubuntu 18.04 (x64) ------------------------------------ - -#. Follow the instructions for Docker CE for your platform at `Get Docker Engine - Community for CentOS`_ - -#. Tell Docker to start after a reboot - - .. code-block:: console - - $ sudo systemctl enable docker && sudo systemctl start docker - -#. Verify that docker is running - - .. code-block:: console - :linenos: - :emphasize-lines: 4 - - $ sudo systemctl status docker - ● docker.service - Docker Application Container Engine - Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled) - Active: active (running) since Mon 2019-08-12 08:22:30 IDT; 1 months 27 days ago - Docs: https://docs.docker.com - Main PID: 65794 (dockerd) - Tasks: 76 - Memory: 124.5M - CGroup: /system.slice/docker.service - └─65794 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock - -#. Let your current user manage Docker, without requiring `sudo` - - .. code-block:: console - - $ sudo usermod -aG docker $USER - - .. Note:: Log out and log back in again after this action - -#. Install nvidia-docker - - .. code-block:: console - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list - - $ sudo apt-get update - - $ sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit nvidia-docker2 - $ sudo pkill -SIGHUP dockerd - $ sudo systemctl restart docker - - -#. Verify the NVIDIA docker installation - - .. code-block:: console - - $ sudo docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi -L - GPU 0: Tesla V100-PCIE-16GB (UUID: GPU-...) - GPU 1: Tesla V100-PCIE-16GB (UUID: GPU-...) - -#. Continue to :ref:`Installing the SQream DB Docker container ` - - -.. _preparing_mounts: - -Preparing directories and mounts for SQream DB -=============================================== - -SQream DB contains several directories that need to be defined - -.. list-table:: Directories and paths - :widths: 40 60 - :header-rows: 1 - - * - Path name - - Definition - * - ``storage`` - - The location where SQream DB stores data, metadata, and logs - * - ``exposed path`` - - A location that SQream DB can read and write to. Used for allowing access to shared raw files like CSVs on local or NFS drives - * - ``logs`` - - Optional location for debug logs - -.. note:: By default, SQream DB can't access any OS path. You must explicitly allow it. - - -.. _installing_sqream_db_container: - -Install the SQream DB Docker container -========================================= - -#. Download the SQream DB tarball and license package - - In the e-mail from your account manager at SQream, you have received a download link for the SQream DB installer and a license package. - Download the SQream DB tarball to the user home directory. For example: - - .. code-block:: console - - $ cd ~ - $ curl -O {download URL} - -#. Extract the tarball into your home directory - - .. code-block:: console - - $ tar xf sqream_installer-2.0.7-DB2019.2.1.4-CO1.7.5-ED3.0.1-x86_64.tar.gz - -#. Copy the license package - - Copy the license package from your home directory to the license subdirectory which is located in the newly created SQream installer directory. - - For example, if the licence package is titled ``license_package.tar.gz``: - - .. code-block:: console - - $ cp ~/license_package.tar.gz sqream_installer-2.0.7-DB2019.2.1.4-CO1.7.5-ED3.0.1-x86_64/license - -#. Enter the installer directory - - .. code-block:: console - - $ cd sqream_installer-2.0.7-DB2019.2.1.4-CO1.7.5-ED3.0.1-x86_64 - -#. Install SQream DB - - In most cases, the installation command will look like this: - - .. code-block:: console - - $ ./sqream-install -i -k -v -d -l - - For example, if the main storage path for SQream DB is ``/mnt/largedrive`` and the desired shared access path is ``/mnt/nfs/source_files``, the command will look like: - - .. code-block:: console - - $ ./sqream-install -i -k -v /mnt/largedrive -d /mnt/nfs/source_files - - For a full list of options and commands, see the :ref:`sqream-installer reference ` - -#. SQream DB is now successfully installed, but not yet running. - - -.. _start_local_cluster: - -Starting your first local cluster -========================================= - -#. Enter the :ref:`sqream console utility`, which helps coordinate SQream DB components - - .. code-block:: console - - $ ./sqream-console - -#. Start the master components: - - .. code-block:: console - - sqream-console>sqream master --start - starting master server in single_host mode ... - sqream_single_host_master is up and listening on ports: 3105,3108 - - -#. Start workers to join the cluster: - - .. code-block:: console - - sqream-console>sqream worker --start 2 - started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 - started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 - - .. note:: By default, each worker is allocated a full GPU. To launch more workers than available GPUs, see the :ref:`sqream console reference ` - -#. SQream DB is now running! (Exit the console by typing ``exit`` when done.) - -.. rubric:: What's next? - -* :ref:`Test your SQream DB installation by creating your first table` - -* :ref:`Connect an external tool to SQream DB ` - -* :ref:`Additional system configuration for performance and stability ` - - -.. Some replacements: - -.. _`Latest Tesla driver for Linux x64`: https://www.nvidia.com/Download/driverResults.aspx/152242/en-us -.. _`Latest Tesla driver for Linux x64 POWER LE`: https://www.nvidia.com/Download/driverResults.aspx/152241/en-us -.. _`NVIDIA's CUDA Installation Guide`: https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#pre-installation-actions -.. _`Get Docker Engine - Community for CentOS`: https://docs.docker.com/install/linux/docker-ce/centos/ -.. _`Get Docker Engine - Community for Ubuntu`: https://docs.docker.com/install/linux/docker-ce/ubuntu/ diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst deleted file mode 100644 index 7075d79cb..000000000 --- a/guides/operations/setup/recommended_configuration.rst +++ /dev/null @@ -1,1156 +0,0 @@ -.. _recommended_configuration: - -********************************************* -Recommended Pre-Installation Configuration -********************************************* - -Before :ref:`installing SQream DB`, SQream recommends you to tune your system for better performance and stability. - -This page provides recommendations for production deployments of SQream DB. - -.. contents:: In this topic: - :local: - -Recommended BIOS Settings -========================== -The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. - -It is safe to skip any and all of the configuration steps, but this may impact performance. - -If any doubt arises, consult the documentation for your server or your hardware vendor for the correct way to apply the settings. - -.. list-table:: - :widths: 25 25 50 - :header-rows: 1 - - * - Item - - Setting - - Rationale - * - **Management console access** - - **Connected** - - Connection to OOB required to preserve continuous network uptime. - * - **All drives.** - - **Connected and displayed on RAID interface** - - Prerequisite for cluster or OS installation. - * - **RAID volumes.** - - **Configured according to project guidelines. Must be rebooted to take effect.** - - Clustered to increase logical volume and provide redundancy. - * - **Fan speed Thermal Configuration.** - - Dell fan speed: **High Maximum**. Specified minimum setting: **60**. HPe thermal configuration: **Increased cooling**. - - NVIDIA Tesla GPUs are passively cooled and require high airflow to operate at full performance. - * - Power regulator or iDRAC power unit policy - - HPe: **HP static high performance** mode enabled. Dell: **iDRAC power unit policy** (power cap policy) disabled. - - Other power profiles (such as "balanced") throttle the CPU and diminishes performance. Throttling may also cause GPU failure. - * - **System Profile**, **Power Profile**, or **Performance Profile** - - **High Performance** - - The Performance profile provides potentially increased performance by maximizing processor frequency, and the disabling certain power saving features such as C-states. Use this setting for environments that are not sensitive to power consumption. - * - **Power Cap Policy** or **Dynamic power capping** - - **Disabled** - - Other power profiles (like "balanced") throttle the CPU and may diminish performance or cause GPU failure. This setting may appear together with the above (Power profile or Power regulator). This setting allows disabling system ROM power calibration during the boot process. Power regulator settings are named differently in BIOS and iLO/iDRAC. - -.. - **Comment: is it necessary to show the different power regulator setting names in this document?** - * - **Intel Turbo Boost** - - **Enabled** - - Intel Turbo Boost enables overclocking the processor to boost CPU-bound operation performance. Overclocking may risk computational jitter due to changes in the processor's turbo frequency. This causes brief pauses in processor operation, introducing uncertainty into application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. - * - **Logical Processor** - - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** - - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. - * - **Intel Virtualization Technology** (VT-d) - - **Disable** - - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. - * - **Logical Processor** - - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** - - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. - * - **Intel Virtualization Technology** (VT-d) - - **Disable** - - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. - * - **Processor C-States** (Minimum processor idle power core state) - - **Disable** - - Processor C-States reduce server power when the system is in an idle state. This causes slower cold-starts when the system transitions from an idle to a load state, and may reduce query performance by up to 15%. **Comment: a hyperlinked footnote to an internal source was inserted into the Confluence doc here. Do we want to include this in the final version? Linked URL: https://www.dell.com/support/kbdoc/en-il/000060621/what-is-the-c-state** - * - **HPe**: **Energy/Performance bias** - - **Maximum performance** - - Configures processor sub-systems for high-performance and low-latency. Other power profiles (like "balanced") throttle the CPU and may diminish performance. Use this setting for environments that are not sensitive to power consumption. - * - **HPe**: **DIMM voltage** - - **Optimized for Performance** - - Setting a higher voltage for DIMMs may increase performance. - * - **Memory Operating Mode** - - **Optimizer Mode**, **Disable Node Interleaving**, **Auto Memory Operating Voltage** - - Memory Operating Mode is tuned for performance in **Optimizer** mode. Other modes may improve reliability, but reduce performance. **Node Interleaving** should be disabled because enabling it interleaves the memory between memory nodes, which harms NUMA-aware applications such as SQream DB. - * - **HPe**: **Memory power savings mode** - - **Maximum performance** - - This setting configures several memory parameters to optimize the performance of memory sub-systems. The default setting is **Balanced**. - * - HPe **ACPI SLIT** - - **Enabled** - - ACPI SLIT sets the relative access times between processors and memory and I/O sub-systems. ACPI SLIT enables operating systems to use this data to improve performance by more efficiently allocating resources and workloads. - * - **QPI Snoop** **Comment: should we write that it is HPe or Intel? HPe: QPI Snoop** - - **Cluster on Die** or **Home Snoop** - - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. - - - - - - -Installing the Operating System -=================================================== -Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.6-7.9) must be installed before installing the SQream database. Either the customer or a SQream representative can perform the installation. - -.. - **Comment: I recommend leaving contact information here - Please call xxx-xxx-xxxx to contact a SQream representative.** - -**To install the operating system:** - -#. Select a language (English recommended). -#. From **Software Selection**, select **Minimal**. -#. Select the **Development Tools** group checkbox. -#. Continue the installation. -#. Set up the necessary drives and users as per the installation process. - - Using Debugging Tools is recommended for future problem-solving if necessary. - - .. - **Comment: In Step 4, why don't we document the entire procedure? I.e., why do we stop here and say "Continue the installation" and "Set up the necessary drives..."?** - -Selecting the **Development Tools** group installs the following tools: - - * autoconf - * automake - * binutils - * bison - * flex - * gcc - * gcc-c++ - * gettext - * libtool - * make - * patch - * pkgconfig - * redhat-rpm-config - * rpm-build - * rpm-sign - - - -The root user is created and the OS shell is booted up. - -Configuring the Operating System -=================================================== -When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. - -Logging In to the Server --------------------------------- -You can log in to the server using the server's IP address and password for the **root** user. The server's IP address and **root** user were created while installing the operating system above. - -Automatically Creating a SQream User ------------------------------------- - -**To automatically create a SQream user:** - -#. If a SQream user was created during installation, verify that the same ID is used on every server: - - .. code-block:: console - - $ sudo id sqream - -The ID **1000** is used on each server in the following example: - - .. code-block:: console - - $ uid=1000(sqream) gid=1000(sqream) groups=1000(sqream) - -2. If the ID's are different, delete the SQream user and SQream group from both servers: - - .. code-block:: console - - $ sudo userdel sqream - -3. Recreate it using the same ID: - - .. code-block:: console - - $ sudo rm /var/spool/mail/sqream - -Manually Creating a SQream User --------------------------------- - -**To manually create a SQream user:** - -SQream enables you to manually create users. This section shows you how to manually create a user with the UID **1111**. You cannot manually create during the operating system installation procedure. - -1. Add a user with an identical UID on all cluster nodes: - - .. code-block:: console - - $ useradd -u 1111 sqream - -2. Add the user **sqream** to the **wheel** group. - - .. code-block:: console - - $ sudo usermod -aG wheel sqream - -You can remove the SQream user from the **wheel** group when the installation and configuration are complete: - - .. code-block:: console - - $ passwd sqream - -3. Log out and log back in as **sqream**. - -**Note:** If you deleted the **sqream** user and recreated it with different ID, to avoid permission errors, you must change its ownership to /home/sqream. - -4. Change the **sqream** user's ownership to /home/sqream: - - .. code-block:: console - - $ sudo chown -R sqream:sqream /home/sqream - -Setting Up A Locale --------------------------------- - -SQream enables you to set up a locale. In this example, the locale used is your own location. - -**To set up a locale:** - -1. Set the language of the locale: - - .. code-block:: console - - $ sudo localectl set-locale LANG=en_US.UTF-8 - -2. Set the time stamp (time and date) of the locale: - - .. code-block:: console - - $ sudo timedatectl set-timezone Asia/Jerusalem - -If needed, you can run the **timedatectl list-timezones** command to see your current time-zone. - - -Installing the Required Packages --------------------------------- -You can install the required packages by running the following command: - -.. code-block:: console - - $ sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq - - -Installing the Recommended Tools --------------------------------- -You can install the recommended tools by running the following command: - -.. code-block:: console - - $ sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix - - -Installing Python 3.6.7 --------------------------------- -1. Download the Python 3.6.7 source code tarball file from the following URL into the **/home/sqream** directory: - - .. code-block:: console - - $ wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz - -2. Extract the Python 3.6.7 source code into your current directory: - - .. code-block:: console - - $ tar -xf Python-3.6.7.tar.xz - -3. Navigate to the Python 3.6.7 directory: - - .. code-block:: console - - $ cd Python-3.6.7/Python-3 - -4. Run the **./configure** script: - - .. code-block:: console - - $ ./configure - -5. Build the software: - - .. code-block:: console - - $ make -j30 - -6. Install the software: - - .. code-block:: console - - $ sudo make install - -7. Verify that Python 3.6.7 has been installed: - - .. code-block:: console - - $ python3.6.7 - -Installing NodeJS on CentOS --------------------------------- -**To install the node.js on CentOS:** - -1. Download the `setup_12.x file `__ as a root user logged in shell: - - .. code-block:: console - - $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - - -2. Clear the YUM cache and update the local metadata: - - .. code-block:: console - - $ sudo yum clean all && sudo yum makecache fast - -3. Install the **node.js**) file: - - .. code-block:: console - - $ sudo yum install -y nodejs - -Installing NodeJS on Ubuntu --------------------------------- -**To install the node.js file on Ubuntu:** - -1. Download the `setup_12.x file `__ as a root user logged in shell: - - .. code-block:: console - - $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - - -2. Install the node.js file: - - .. code-block:: console - - $ sudo apt-get install -y nodejs - -3. Verify the node version: - -.. - **Comment: - is this step relevant only for installing on Ubuntu, or on CentOS as well?** - - .. code-block:: console - - $ node -v - -Configuring the Network Time Protocol (NTP) -------------------------------------------- -This section describes how to configure your NTP. - -If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server `__. - -.. - **Comment: - Is this the correct procedure on the linked URL: Configure NTP Client to Synchronize with NTP Server?* - -**To configure your NTP:** - -1. Install the NTP file. - - .. code-block:: console - - $ sudo yum install ntp - -2. Enable the **ntpd** program. - - .. code-block:: console - - $ sudo systemctl enable ntpd - -3. Start the **ntdp** program. - - .. code-block:: console - - $ sudo systemctl start ntpd - -4. Print a list of peers known to the server and a summary of their states. - - .. code-block:: console - - $ sudo ntpq -p - -Configuring the Network Time Protocol Server --------------------------------------------- -If your organization has an NTP server, you can configure it. - -**To configure your NTP server:** - -1. Output your NTP server address and append ``/etc/ntpd.conf`` to the outuput. - - .. code-block:: console - - $ echo -e "\nserver \n" | sudo tee -a /etc/ntp.conf - -2. Restart the service. - - .. code-block:: console - - $ sudo systemctl restart ntpd - -3. Check that synchronization is enabled: - - .. code-block:: console - - $ sudo timedatectl - -Checking that synchronization is enabled generates the following output: - - .. code-block:: console - - $ Local time: Sat 2019-10-12 17:26:13 EDT - Universal time: Sat 2019-10-12 21:26:13 UTC - RTC time: Sat 2019-10-12 21:26:13 - Time zone: America/New_York (EDT, -0400) - NTP enabled: yes - NTP synchronized: yes - RTC in local TZ: no - DST active: yes - Last DST change: DST began at - Sun 2019-03-10 01:59:59 EST - Sun 2019-03-10 03:00:00 EDT - Next DST change: DST ends (the clock jumps one hour backwards) at - Sun 2019-11-03 01:59:59 EDT - Sun 2019-11-03 01:00:00 EST - - - -Configuring the Server to Boot Without the UI ---------------------------------------------- -You can configure your server to boot without a UI in cases when it is not required (recommended) by running the following command: - -.. code-block:: console - - $ sudo systemctl set-default multi-user.target - -Running this command activates the **NO-UI** server mode. - -Configuring the Security Limits --------------------------------- -The security limits refers to the number of open files, processes, etc. - -You can configure the security limits by running the **echo -e** command as a root user logged in shell: - -.. code-block:: console - - $ sudo bash - -.. code-block:: console - - $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf - -Configuring the Kernel Parameters ---------------------------------- -**To configure the kernel parameters:** - -1. Insert a new line after each kernel parameter: - - .. code-block:: console - - $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf - -**Notice:** In the past, the **vm.zone_reclaim_mode** parameter was set to **7.** In the latest Sqream version, the vm.zone_reclaim_mode parameter must be set to **0**. If it is not set to **0**, when a numa node runs out of memory, the system will get stuck and will be unable to pull memory from other numa nodes. - -2. Check the maximum value of the **fs.file**. - - .. code-block:: console - - $ sysctl -n fs.file-max - -3. *Optional* - If the maximum value of the **fs.file** is smaller than **2097152**, run the following command: - - .. code-block:: console - - $ echo "fs.file-max=2097152" >> /etc/sysctl.conf - -**IP4 forward** must be enabled for Docker and K8s installation only. - -Configuring the Firewall --------------------------------- -The example in this section shows the open ports for four sqreamd sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. - -**To configure the firewall:** - -1. Start the service and enable FirewallID on boot: - - .. code-block:: console - - $ systemctl start firewalld - -2. Add the following ports to the permanent firewall: - - .. code-block:: console - - $ firewall-cmd --zone=public --permanent --add-port=8080/tcp - $ firewallfirewall-cmd --zone=public --permanent --add-port=3105/tcp - $ firewall-cmd --zone=public --permanent --add-port=3108/tcp - $ firewall-cmd --zone=public --permanent --add-port=5000-5003/tcp - $ firewall-cmd --zone=public --permanent --add-port=5100-5103/tcp - $ firewall-cmd --permanent --list-all - - -.. - **Comment: - does *--list-all* add the entire list of ports to the permanent firewall?** - -3. Reload the firewall: - - .. code-block:: console - - $ firewall-cmd --reload - -4. Start the service and enable FirewallID on boot: - - .. code-block:: console - - $ systemctl start firewalld - - If you do not need the firewall, you can disable it: - - .. code-block:: console - - $ sudo systemctl disable firewalld - - -Disabling selinux --------------------------------- -**To disable selinux:** - -1. Show the status of **selinux**: - - .. code-block:: console - - $ sudo sestatus - -2. If the output is not **disabled**, edit the **/etc/selinux/config** file: - - .. code-block:: console - - $ sudo vim /etc/selinux/config - -3. Change **SELINUX=enforcing** to **SELINUX=disabled**. - -The above changes will only take effect after rebooting the server. - -You can disable selinux immediately after rebooting the server by running the following command: - -.. code-block:: console - - $ sudo setenforce 0 - -Configuring the /etc/hosts File --------------------------------- -**To configure the /etc/hosts file:** - -1. Edit the **/etc/hosts** file: - - .. code-block:: console - - $ sudo vim /etc/hosts - -2. Call your local host: - - .. code-block:: console - - $ 127.0.0.1 localhost - $ - -.. - **Comment: - Is the above an output or a step?** - -Configuring the DNS --------------------------------- -**To configure the DNS:** - -1. Run the **ifconfig** commasnd to check your NIC name. In the following example, **eth0** is the NIC name: - - .. code-block:: console - - $ sudo vim /etc/sysconfig/network-scripts/ifcfg-eth0 - -2. Replace the DNS lines from the example above with your own DNS addresses : - - .. code-block:: console - - $ sudo vim /etc/sysconfig/network-scripts/ifcfg-4.4.4.4 - $ sudo vim /etc/sysconfig/network-scripts/ifcfg-8.8.8.8 - - -.. - **Comment: - is the above input correct?** - -Installing the Nvidia CUDA Driver -=================================================== - - -**Warning:** If your UI runs on the server, the server must be stopped before installing the CUDA drivers. - -CUDA Driver Prerequisites --------------------------------- -1. Verify that the NVIDIA card has been installed and is detected by the system: - - .. code-block:: console - - $ lspci | grep -i nvidia - -2. Check which version of gcc has been installed: - - .. code-block:: console - - $ gcc --version - -3. If gcc has not been installed, install it for one of the following operating systems: - - * On RHEL/CentOS: - - .. code-block:: console - - $ sudo yum install -y gcc - - * On Ubuntu: - - .. code-block:: console - - $ sudo apt-get install gcc - - -Updating the Kernel Headers --------------------------------- -**To update the kernel headers:** - -1. Update the kernel headers on one of the following operating systems: - - * On RHEL/CentOS: - - .. code-block:: console - - $ sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) - - * On Ubuntu: - - .. code-block:: console - - $ sudo apt-get install linux-headers-$(uname -r) - -2. Install **wget** one of the following operating systems: - - * On RHEL/CentOS: - - .. code-block:: console - - $ sudo yum install wget - - * On Ubuntu: - - .. code-block:: console - - $ sudo apt-get install wget - -Disabling Nouveau --------------------------------- -You can disable Nouveau, which is the default driver. - -**To disable Nouveau:** - -1. Check if the Nouveau driver has been loaded: - - .. code-block:: console - - $ lsmod | grep nouveau - -If the Nouveau driver has been loaded, the command above generates output. - -2. Blacklist the Nouveau drivers to disable them: - - .. code-block:: console - - $ cat <`__ for the additional set-up requirements. - - - c. **For K80**: - - .. code-block:: console - - $ nvidia-persistenced - $ nvidia-smi -pm 1 - $ nvidia-smi -acp 0 - $ nvidia-smi --auto-boost-permission=0 - $ nvidia-smi --auto-boost-default=0 - -4. Reboot the server and run the **NVIDIA System Management Interface (NVIDIA SMI)**: - - .. code-block:: console - - $ nvidia-smi - - -Disabling Automatic Bug Reporting Tools -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -**To disable automatic bug reporting tools:** - -1. Run the following **abort** commands: - - .. code-block:: console - - $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done - - -The server is ready for the SQream software installation. - - -2. Run the following checks: - - a. Check the OS release: - - .. code-block:: console - - $ cat /etc/os-release - - b. Verify that a SQream user exists and has the same ID on all cluster member services: - - .. code-block:: console - - $ id sqream - - c. Verify that the storage is mounted: - - .. code-block:: console - - $ mount - - d. Verify that the driver has been installed correctly: - - .. code-block:: console - - $ nvidia-smi - - e. Check the maximum value of the **fs.file**: - - .. code-block:: console - - $ sysctl -n fs.file-max - - The desired output when checking the maximum value of the **fs.file** is greater or equal to **2097152**. - - f. Run the following command as a SQream user: - -.. - **Comment: - **Question - what do the following command parameter do? -c?** - - .. code-block:: console - - $ ulimit -c -u -n - -.. - **Comment: - See https://ss64.com/bash/ulimit.html** - - The following shows the desired output when ****: - - .. code-block:: console - - $ core file size (blocks, -c) unlimited - $ max user processes (-u) 1000000 - $ open files (-n) 1000000 - -3. Configure the security limits by running the **echo -e** command as a root user logged in shell: - - .. code-block:: console - - $ sudo bash - $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf - -Enabling Core Dumps -=================================================== - -Enabling core dumps is recommended, but optional. - -**To enable core dumps:** - -1. Check the **abrtd** Status - -2. Set the limits - -3. Create the core dumps directory. - - -Checking the abrtd Status ---------------------------------------------------- - -**To check the abrtd status:** - -1. Check if **abrtd** is running: - - .. code-block:: console - - $ sudo ps -ef |grep abrt - -2. If **abrtd** is running, stop it: - - .. code-block:: console - - $ sudo service abrtd stop - $ sudo chkconfig abrt-ccpp off - $ sudo chkconfig abrt-oops off - $ sudo chkconfig abrt-vmcore off - $ sudo chkconfig abrt-xorg off - $ sudo chkconfig abrtd off - - -Setting the Limits ---------------------------------------------------- - -**To set the limits:** - -1. Set the limits: - - .. code-block:: console - - $ ulimit -c - -2. If the output is **0**, add the following lines to the **limits.conf** file (/etc/security): - - .. code-block:: console - - $ * soft core unlimited - $ * hard core unlimited - -3. Log out and log in to apply the limit changes. - -Creating the Core Dumps Directory ---------------------------------------------------- - -**To set the core dumps directory:** - -1. Make the **/tmp/core_dumps** directory: - - .. code-block:: console - - $ mkdir /tmp/core_dumps - -2. Set the ownership of the **/tmp/core_dumps** directory: - - .. code-block:: console - - $ sudo chown sqream.sqream /tmp/core_dumps - -3. Grant read, write, and execute permissions to all users: - - .. code-block:: console - - $ sudo chmod -R 777 /tmp/core_dumps - -Setting the Output Directory of the /etc/sysctl.conf File ------------------------------------------------------------------ - -**To set the output directory of the /etc/sysctl.conf file:** - -1. Edit the **/etc/sysctl.conf** file: - - .. code-block:: console - - $ sudo vim /etc/sysctl.conf - -2. Add the following to the bottom of the file: - - .. code-block:: console - - $ kernel.core_uses_pid = 1 - $ kernel.core_pattern = //core-%e-%s-%u-%g-%p-%t - $ fs.suid_dumpable = 2 - -.. - **Comment: - leave a note that the user can choose his correct location of the folder.** - -3. To apply the changes without rebooting the server, run: - - .. code-block:: console - - $ sudo sysctl -p - -4. Check that the core output directory points to the following: - - .. code-block:: console - - $ sudo cat /proc/sys/kernel/core_pattern - - The following shows the correct generated output: - - .. code-block:: console - - $ /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t - -5. Verify that the core dumping works: - - .. code-block:: console - - $ select abort_server(); - - -Verifying that the Core Dumps Work ---------------------------------------------------- -You can verify that the core dumps work only after installing and running SQream. This causes the server to crash and a new core.xxx file to be included in the folder that is written in **/etc/sysctl.conf** - -**To verify that the core dumps work:** - -1. Stop and restart all SQream services. - -2. Connect to SQream with ClientCmd and run the following command: - - .. code-block:: console - - $ select abort_server(); - - -.. - **Comment: - what did the author mean by "Stage 3"?** - -Troubleshooting Core Dumping ---------------------------------------------------- -This section describes the troubleshooting procedure to be followed if all parameters have been configured correctly, but the cores have not been created. - -**To troubleshoot core dumping:** - -1. Reboot the server. - -2. Verify that you have folder permissions: - - .. code-block:: console - - $ sudo chmod -R 777 /tmp/core_dumps - -3. Verify that the limits have been set correctly: - - .. code-block:: console - - $ ulimit -c - - If all parameters have been configured correctly, the correct output is: - - .. code-block:: console - - $ unlimited - -4. If all parameters have been configured correctly, but running **ulimit -c** outputs **0**, run the following: - - .. code-block:: console - - $ sudo vim /etc/profile - -5. Search for line and tag it with the **hash** symbol: - - .. code-block:: console - - $ ulimit -S -c 0 > /dev/null 2>&1 - - -6. If the line is not found in **/etc/profile** directory, do the following: - - a. Run the following command: - - .. code-block:: console - - $ sudo vim /etc/init.d/functions - - b. Search for the following: - - .. code-block:: console - - $ ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 - - c. If the line is found, tag it with the **hash** symbol and reboot the server. From 5cf97a69a7cf3e68a63e48f13e16cc6f856b3cf1 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 12:48:44 +0200 Subject: [PATCH 094/300] Update first_steps.rst Updated Getting Started page. --- first_steps.rst | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/first_steps.rst b/first_steps.rst index 5e5cce808..0dde6de84 100644 --- a/first_steps.rst +++ b/first_steps.rst @@ -12,12 +12,43 @@ The **Getting Started** page describes the following: Before Installing SQream ============================ -Before installing SQream, you must set up your local machine according to SQream's recommended pre-installation configurations. +Before installing SQream, do the following: + * Set up your local machine according to SQream's recommended pre-installation configurations. + + :: + + * Verify you have an NVIDIA-capable server, either on-premise or on supported cloud platforms: + + * Red Hat Enterprise Linux v7.x + + + * CentOS v7.x + + + * Ubuntu 18.04 + + + * Amazon Linux + + * Verify that you have the following: + + * An NVIDIA GPU - SQream recommends using a Tesla GPU. + + + * An SSH connection to your server. + + + * SUDO permissions for installation and configuration purposes. + + + * A SQream license - Contact support@sqream.com or your SQream account manager for your license key. For more information, see the following: -* `Hardware Guide `_. -* `Recommended Pre-Installation Configuration `_. +* `Hardware Guide `_ +* `Recommended Pre-Installation Configuration `_ + + From 46cfc2cee96c461527618b6e71a3a54d6868c2dc Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 12:49:44 +0200 Subject: [PATCH 095/300] Create recommended_pre-installation_configurations.rst Created recommended_pre-installation_configurations.rst. --- ...mended_pre-installation_configurations.rst | 1156 +++++++++++++++++ 1 file changed, 1156 insertions(+) create mode 100644 guides/operations/recommended_pre-installation_configurations.rst diff --git a/guides/operations/recommended_pre-installation_configurations.rst b/guides/operations/recommended_pre-installation_configurations.rst new file mode 100644 index 000000000..782694c4a --- /dev/null +++ b/guides/operations/recommended_pre-installation_configurations.rst @@ -0,0 +1,1156 @@ +.. _recommended_pre-installation_configurations: + +********************************************* +Recommended Pre-Installation Configuration +********************************************* + +Before installing SQream, we recommend you to tune your system for better performance and stability. + +This page provides recommendations for production deployments of SQream DB. + +.. contents:: In this topic: + :local: + +Recommended BIOS Settings +========================== +The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. + +It is safe to skip any and all of the configuration steps, but this may impact performance. + +If any doubt arises, consult the documentation for your server or your hardware vendor for the correct way to apply the settings. + +.. list-table:: + :widths: 25 25 50 + :header-rows: 1 + + * - Item + - Setting + - Rationale + * - **Management console access** + - **Connected** + - Connection to OOB required to preserve continuous network uptime. + * - **All drives.** + - **Connected and displayed on RAID interface** + - Prerequisite for cluster or OS installation. + * - **RAID volumes.** + - **Configured according to project guidelines. Must be rebooted to take effect.** + - Clustered to increase logical volume and provide redundancy. + * - **Fan speed Thermal Configuration.** + - Dell fan speed: **High Maximum**. Specified minimum setting: **60**. HPe thermal configuration: **Increased cooling**. + - NVIDIA Tesla GPUs are passively cooled and require high airflow to operate at full performance. + * - Power regulator or iDRAC power unit policy + - HPe: **HP static high performance** mode enabled. Dell: **iDRAC power unit policy** (power cap policy) disabled. + - Other power profiles (such as "balanced") throttle the CPU and diminishes performance. Throttling may also cause GPU failure. + * - **System Profile**, **Power Profile**, or **Performance Profile** + - **High Performance** + - The Performance profile provides potentially increased performance by maximizing processor frequency, and the disabling certain power saving features such as C-states. Use this setting for environments that are not sensitive to power consumption. + * - **Power Cap Policy** or **Dynamic power capping** + - **Disabled** + - Other power profiles (like "balanced") throttle the CPU and may diminish performance or cause GPU failure. This setting may appear together with the above (Power profile or Power regulator). This setting allows disabling system ROM power calibration during the boot process. Power regulator settings are named differently in BIOS and iLO/iDRAC. + +.. + **Comment: is it necessary to show the different power regulator setting names in this document?** + * - **Intel Turbo Boost** + - **Enabled** + - Intel Turbo Boost enables overclocking the processor to boost CPU-bound operation performance. Overclocking may risk computational jitter due to changes in the processor's turbo frequency. This causes brief pauses in processor operation, introducing uncertainty into application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. + * - **Logical Processor** + - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** + - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. + * - **Intel Virtualization Technology** (VT-d) + - **Disable** + - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. + * - **Logical Processor** + - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** + - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. + * - **Intel Virtualization Technology** (VT-d) + - **Disable** + - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. + * - **Processor C-States** (Minimum processor idle power core state) + - **Disable** + - Processor C-States reduce server power when the system is in an idle state. This causes slower cold-starts when the system transitions from an idle to a load state, and may reduce query performance by up to 15%. **Comment: a hyperlinked footnote to an internal source was inserted into the Confluence doc here. Do we want to include this in the final version? Linked URL: https://www.dell.com/support/kbdoc/en-il/000060621/what-is-the-c-state** + * - **HPe**: **Energy/Performance bias** + - **Maximum performance** + - Configures processor sub-systems for high-performance and low-latency. Other power profiles (like "balanced") throttle the CPU and may diminish performance. Use this setting for environments that are not sensitive to power consumption. + * - **HPe**: **DIMM voltage** + - **Optimized for Performance** + - Setting a higher voltage for DIMMs may increase performance. + * - **Memory Operating Mode** + - **Optimizer Mode**, **Disable Node Interleaving**, **Auto Memory Operating Voltage** + - Memory Operating Mode is tuned for performance in **Optimizer** mode. Other modes may improve reliability, but reduce performance. **Node Interleaving** should be disabled because enabling it interleaves the memory between memory nodes, which harms NUMA-aware applications such as SQream DB. + * - **HPe**: **Memory power savings mode** + - **Maximum performance** + - This setting configures several memory parameters to optimize the performance of memory sub-systems. The default setting is **Balanced**. + * - HPe **ACPI SLIT** + - **Enabled** + - ACPI SLIT sets the relative access times between processors and memory and I/O sub-systems. ACPI SLIT enables operating systems to use this data to improve performance by more efficiently allocating resources and workloads. + * - **QPI Snoop** **Comment: should we write that it is HPe or Intel? HPe: QPI Snoop** + - **Cluster on Die** or **Home Snoop** + - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. + + + + + + +Installing the Operating System +=================================================== +Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.6-7.9) must be installed before installing the SQream database. Either the customer or a SQream representative can perform the installation. + +.. + **Comment: I recommend leaving contact information here - Please call xxx-xxx-xxxx to contact a SQream representative.** + +**To install the operating system:** + +#. Select a language (English recommended). +#. From **Software Selection**, select **Minimal**. +#. Select the **Development Tools** group checkbox. +#. Continue the installation. +#. Set up the necessary drives and users as per the installation process. + + Using Debugging Tools is recommended for future problem-solving if necessary. + + .. + **Comment: In Step 4, why don't we document the entire procedure? I.e., why do we stop here and say "Continue the installation" and "Set up the necessary drives..."?** + +Selecting the **Development Tools** group installs the following tools: + + * autoconf + * automake + * binutils + * bison + * flex + * gcc + * gcc-c++ + * gettext + * libtool + * make + * patch + * pkgconfig + * redhat-rpm-config + * rpm-build + * rpm-sign + + + +The root user is created and the OS shell is booted up. + +Configuring the Operating System +=================================================== +When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. + +Logging In to the Server +-------------------------------- +You can log in to the server using the server's IP address and password for the **root** user. The server's IP address and **root** user were created while installing the operating system above. + +Automatically Creating a SQream User +------------------------------------ + +**To automatically create a SQream user:** + +#. If a SQream user was created during installation, verify that the same ID is used on every server: + + .. code-block:: console + + $ sudo id sqream + +The ID **1000** is used on each server in the following example: + + .. code-block:: console + + $ uid=1000(sqream) gid=1000(sqream) groups=1000(sqream) + +2. If the ID's are different, delete the SQream user and SQream group from both servers: + + .. code-block:: console + + $ sudo userdel sqream + +3. Recreate it using the same ID: + + .. code-block:: console + + $ sudo rm /var/spool/mail/sqream + +Manually Creating a SQream User +-------------------------------- + +**To manually create a SQream user:** + +SQream enables you to manually create users. This section shows you how to manually create a user with the UID **1111**. You cannot manually create during the operating system installation procedure. + +1. Add a user with an identical UID on all cluster nodes: + + .. code-block:: console + + $ useradd -u 1111 sqream + +2. Add the user **sqream** to the **wheel** group. + + .. code-block:: console + + $ sudo usermod -aG wheel sqream + +You can remove the SQream user from the **wheel** group when the installation and configuration are complete: + + .. code-block:: console + + $ passwd sqream + +3. Log out and log back in as **sqream**. + +**Note:** If you deleted the **sqream** user and recreated it with different ID, to avoid permission errors, you must change its ownership to /home/sqream. + +4. Change the **sqream** user's ownership to /home/sqream: + + .. code-block:: console + + $ sudo chown -R sqream:sqream /home/sqream + +Setting Up A Locale +-------------------------------- + +SQream enables you to set up a locale. In this example, the locale used is your own location. + +**To set up a locale:** + +1. Set the language of the locale: + + .. code-block:: console + + $ sudo localectl set-locale LANG=en_US.UTF-8 + +2. Set the time stamp (time and date) of the locale: + + .. code-block:: console + + $ sudo timedatectl set-timezone Asia/Jerusalem + +If needed, you can run the **timedatectl list-timezones** command to see your current time-zone. + + +Installing the Required Packages +-------------------------------- +You can install the required packages by running the following command: + +.. code-block:: console + + $ sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq + + +Installing the Recommended Tools +-------------------------------- +You can install the recommended tools by running the following command: + +.. code-block:: console + + $ sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix + + +Installing Python 3.6.7 +-------------------------------- +1. Download the Python 3.6.7 source code tarball file from the following URL into the **/home/sqream** directory: + + .. code-block:: console + + $ wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz + +2. Extract the Python 3.6.7 source code into your current directory: + + .. code-block:: console + + $ tar -xf Python-3.6.7.tar.xz + +3. Navigate to the Python 3.6.7 directory: + + .. code-block:: console + + $ cd Python-3.6.7/Python-3 + +4. Run the **./configure** script: + + .. code-block:: console + + $ ./configure + +5. Build the software: + + .. code-block:: console + + $ make -j30 + +6. Install the software: + + .. code-block:: console + + $ sudo make install + +7. Verify that Python 3.6.7 has been installed: + + .. code-block:: console + + $ python3.6.7 + +Installing NodeJS on CentOS +-------------------------------- +**To install the node.js on CentOS:** + +1. Download the `setup_12.x file `__ as a root user logged in shell: + + .. code-block:: console + + $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - + +2. Clear the YUM cache and update the local metadata: + + .. code-block:: console + + $ sudo yum clean all && sudo yum makecache fast + +3. Install the **node.js**) file: + + .. code-block:: console + + $ sudo yum install -y nodejs + +Installing NodeJS on Ubuntu +-------------------------------- +**To install the node.js file on Ubuntu:** + +1. Download the `setup_12.x file `__ as a root user logged in shell: + + .. code-block:: console + + $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - + +2. Install the node.js file: + + .. code-block:: console + + $ sudo apt-get install -y nodejs + +3. Verify the node version: + +.. + **Comment: - is this step relevant only for installing on Ubuntu, or on CentOS as well?** + + .. code-block:: console + + $ node -v + +Configuring the Network Time Protocol (NTP) +------------------------------------------- +This section describes how to configure your NTP. + +If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server `__. + +.. + **Comment: - Is this the correct procedure on the linked URL: Configure NTP Client to Synchronize with NTP Server?* + +**To configure your NTP:** + +1. Install the NTP file. + + .. code-block:: console + + $ sudo yum install ntp + +2. Enable the **ntpd** program. + + .. code-block:: console + + $ sudo systemctl enable ntpd + +3. Start the **ntdp** program. + + .. code-block:: console + + $ sudo systemctl start ntpd + +4. Print a list of peers known to the server and a summary of their states. + + .. code-block:: console + + $ sudo ntpq -p + +Configuring the Network Time Protocol Server +-------------------------------------------- +If your organization has an NTP server, you can configure it. + +**To configure your NTP server:** + +1. Output your NTP server address and append ``/etc/ntpd.conf`` to the outuput. + + .. code-block:: console + + $ echo -e "\nserver \n" | sudo tee -a /etc/ntp.conf + +2. Restart the service. + + .. code-block:: console + + $ sudo systemctl restart ntpd + +3. Check that synchronization is enabled: + + .. code-block:: console + + $ sudo timedatectl + +Checking that synchronization is enabled generates the following output: + + .. code-block:: console + + $ Local time: Sat 2019-10-12 17:26:13 EDT + Universal time: Sat 2019-10-12 21:26:13 UTC + RTC time: Sat 2019-10-12 21:26:13 + Time zone: America/New_York (EDT, -0400) + NTP enabled: yes + NTP synchronized: yes + RTC in local TZ: no + DST active: yes + Last DST change: DST began at + Sun 2019-03-10 01:59:59 EST + Sun 2019-03-10 03:00:00 EDT + Next DST change: DST ends (the clock jumps one hour backwards) at + Sun 2019-11-03 01:59:59 EDT + Sun 2019-11-03 01:00:00 EST + + + +Configuring the Server to Boot Without the UI +--------------------------------------------- +You can configure your server to boot without a UI in cases when it is not required (recommended) by running the following command: + +.. code-block:: console + + $ sudo systemctl set-default multi-user.target + +Running this command activates the **NO-UI** server mode. + +Configuring the Security Limits +-------------------------------- +The security limits refers to the number of open files, processes, etc. + +You can configure the security limits by running the **echo -e** command as a root user logged in shell: + +.. code-block:: console + + $ sudo bash + +.. code-block:: console + + $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + +Configuring the Kernel Parameters +--------------------------------- +**To configure the kernel parameters:** + +1. Insert a new line after each kernel parameter: + + .. code-block:: console + + $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf + +**Notice:** In the past, the **vm.zone_reclaim_mode** parameter was set to **7.** In the latest Sqream version, the vm.zone_reclaim_mode parameter must be set to **0**. If it is not set to **0**, when a numa node runs out of memory, the system will get stuck and will be unable to pull memory from other numa nodes. + +2. Check the maximum value of the **fs.file**. + + .. code-block:: console + + $ sysctl -n fs.file-max + +3. *Optional* - If the maximum value of the **fs.file** is smaller than **2097152**, run the following command: + + .. code-block:: console + + $ echo "fs.file-max=2097152" >> /etc/sysctl.conf + +**IP4 forward** must be enabled for Docker and K8s installation only. + +Configuring the Firewall +-------------------------------- +The example in this section shows the open ports for four sqreamd sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. + +**To configure the firewall:** + +1. Start the service and enable FirewallID on boot: + + .. code-block:: console + + $ systemctl start firewalld + +2. Add the following ports to the permanent firewall: + + .. code-block:: console + + $ firewall-cmd --zone=public --permanent --add-port=8080/tcp + $ firewallfirewall-cmd --zone=public --permanent --add-port=3105/tcp + $ firewall-cmd --zone=public --permanent --add-port=3108/tcp + $ firewall-cmd --zone=public --permanent --add-port=5000-5003/tcp + $ firewall-cmd --zone=public --permanent --add-port=5100-5103/tcp + $ firewall-cmd --permanent --list-all + + +.. + **Comment: - does *--list-all* add the entire list of ports to the permanent firewall?** + +3. Reload the firewall: + + .. code-block:: console + + $ firewall-cmd --reload + +4. Start the service and enable FirewallID on boot: + + .. code-block:: console + + $ systemctl start firewalld + + If you do not need the firewall, you can disable it: + + .. code-block:: console + + $ sudo systemctl disable firewalld + + +Disabling selinux +-------------------------------- +**To disable selinux:** + +1. Show the status of **selinux**: + + .. code-block:: console + + $ sudo sestatus + +2. If the output is not **disabled**, edit the **/etc/selinux/config** file: + + .. code-block:: console + + $ sudo vim /etc/selinux/config + +3. Change **SELINUX=enforcing** to **SELINUX=disabled**. + +The above changes will only take effect after rebooting the server. + +You can disable selinux immediately after rebooting the server by running the following command: + +.. code-block:: console + + $ sudo setenforce 0 + +Configuring the /etc/hosts File +-------------------------------- +**To configure the /etc/hosts file:** + +1. Edit the **/etc/hosts** file: + + .. code-block:: console + + $ sudo vim /etc/hosts + +2. Call your local host: + + .. code-block:: console + + $ 127.0.0.1 localhost + $ + +.. + **Comment: - Is the above an output or a step?** + +Configuring the DNS +-------------------------------- +**To configure the DNS:** + +1. Run the **ifconfig** commasnd to check your NIC name. In the following example, **eth0** is the NIC name: + + .. code-block:: console + + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-eth0 + +2. Replace the DNS lines from the example above with your own DNS addresses : + + .. code-block:: console + + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-4.4.4.4 + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-8.8.8.8 + + +.. + **Comment: - is the above input correct?** + +Installing the Nvidia CUDA Driver +=================================================== + + +**Warning:** If your UI runs on the server, the server must be stopped before installing the CUDA drivers. + +CUDA Driver Prerequisites +-------------------------------- +1. Verify that the NVIDIA card has been installed and is detected by the system: + + .. code-block:: console + + $ lspci | grep -i nvidia + +2. Check which version of gcc has been installed: + + .. code-block:: console + + $ gcc --version + +3. If gcc has not been installed, install it for one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console + + $ sudo yum install -y gcc + + * On Ubuntu: + + .. code-block:: console + + $ sudo apt-get install gcc + + +Updating the Kernel Headers +-------------------------------- +**To update the kernel headers:** + +1. Update the kernel headers on one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console + + $ sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) + + * On Ubuntu: + + .. code-block:: console + + $ sudo apt-get install linux-headers-$(uname -r) + +2. Install **wget** one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console + + $ sudo yum install wget + + * On Ubuntu: + + .. code-block:: console + + $ sudo apt-get install wget + +Disabling Nouveau +-------------------------------- +You can disable Nouveau, which is the default driver. + +**To disable Nouveau:** + +1. Check if the Nouveau driver has been loaded: + + .. code-block:: console + + $ lsmod | grep nouveau + +If the Nouveau driver has been loaded, the command above generates output. + +2. Blacklist the Nouveau drivers to disable them: + + .. code-block:: console + + $ cat <`__ for the additional set-up requirements. + + + c. **For K80**: + + .. code-block:: console + + $ nvidia-persistenced + $ nvidia-smi -pm 1 + $ nvidia-smi -acp 0 + $ nvidia-smi --auto-boost-permission=0 + $ nvidia-smi --auto-boost-default=0 + +4. Reboot the server and run the **NVIDIA System Management Interface (NVIDIA SMI)**: + + .. code-block:: console + + $ nvidia-smi + + +Disabling Automatic Bug Reporting Tools +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**To disable automatic bug reporting tools:** + +1. Run the following **abort** commands: + + .. code-block:: console + + $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done + + +The server is ready for the SQream software installation. + + +2. Run the following checks: + + a. Check the OS release: + + .. code-block:: console + + $ cat /etc/os-release + + b. Verify that a SQream user exists and has the same ID on all cluster member services: + + .. code-block:: console + + $ id sqream + + c. Verify that the storage is mounted: + + .. code-block:: console + + $ mount + + d. Verify that the driver has been installed correctly: + + .. code-block:: console + + $ nvidia-smi + + e. Check the maximum value of the **fs.file**: + + .. code-block:: console + + $ sysctl -n fs.file-max + + The desired output when checking the maximum value of the **fs.file** is greater or equal to **2097152**. + + f. Run the following command as a SQream user: + +.. + **Comment: - **Question - what do the following command parameter do? -c?** + + .. code-block:: console + + $ ulimit -c -u -n + +.. + **Comment: - See https://ss64.com/bash/ulimit.html** + + The following shows the desired output when ****: + + .. code-block:: console + + $ core file size (blocks, -c) unlimited + $ max user processes (-u) 1000000 + $ open files (-n) 1000000 + +3. Configure the security limits by running the **echo -e** command as a root user logged in shell: + + .. code-block:: console + + $ sudo bash + $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + +Enabling Core Dumps +=================================================== + +Enabling core dumps is recommended, but optional. + +**To enable core dumps:** + +1. Check the **abrtd** Status + +2. Set the limits + +3. Create the core dumps directory. + + +Checking the abrtd Status +--------------------------------------------------- + +**To check the abrtd status:** + +1. Check if **abrtd** is running: + + .. code-block:: console + + $ sudo ps -ef |grep abrt + +2. If **abrtd** is running, stop it: + + .. code-block:: console + + $ sudo service abrtd stop + $ sudo chkconfig abrt-ccpp off + $ sudo chkconfig abrt-oops off + $ sudo chkconfig abrt-vmcore off + $ sudo chkconfig abrt-xorg off + $ sudo chkconfig abrtd off + + +Setting the Limits +--------------------------------------------------- + +**To set the limits:** + +1. Set the limits: + + .. code-block:: console + + $ ulimit -c + +2. If the output is **0**, add the following lines to the **limits.conf** file (/etc/security): + + .. code-block:: console + + $ * soft core unlimited + $ * hard core unlimited + +3. Log out and log in to apply the limit changes. + +Creating the Core Dumps Directory +--------------------------------------------------- + +**To set the core dumps directory:** + +1. Make the **/tmp/core_dumps** directory: + + .. code-block:: console + + $ mkdir /tmp/core_dumps + +2. Set the ownership of the **/tmp/core_dumps** directory: + + .. code-block:: console + + $ sudo chown sqream.sqream /tmp/core_dumps + +3. Grant read, write, and execute permissions to all users: + + .. code-block:: console + + $ sudo chmod -R 777 /tmp/core_dumps + +Setting the Output Directory of the /etc/sysctl.conf File +----------------------------------------------------------------- + +**To set the output directory of the /etc/sysctl.conf file:** + +1. Edit the **/etc/sysctl.conf** file: + + .. code-block:: console + + $ sudo vim /etc/sysctl.conf + +2. Add the following to the bottom of the file: + + .. code-block:: console + + $ kernel.core_uses_pid = 1 + $ kernel.core_pattern = //core-%e-%s-%u-%g-%p-%t + $ fs.suid_dumpable = 2 + +.. + **Comment: - leave a note that the user can choose his correct location of the folder.** + +3. To apply the changes without rebooting the server, run: + + .. code-block:: console + + $ sudo sysctl -p + +4. Check that the core output directory points to the following: + + .. code-block:: console + + $ sudo cat /proc/sys/kernel/core_pattern + + The following shows the correct generated output: + + .. code-block:: console + + $ /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t + +5. Verify that the core dumping works: + + .. code-block:: console + + $ select abort_server(); + + +Verifying that the Core Dumps Work +--------------------------------------------------- +You can verify that the core dumps work only after installing and running SQream. This causes the server to crash and a new core.xxx file to be included in the folder that is written in **/etc/sysctl.conf** + +**To verify that the core dumps work:** + +1. Stop and restart all SQream services. + +2. Connect to SQream with ClientCmd and run the following command: + + .. code-block:: console + + $ select abort_server(); + + +.. + **Comment: - what did the author mean by "Stage 3"?** + +Troubleshooting Core Dumping +--------------------------------------------------- +This section describes the troubleshooting procedure to be followed if all parameters have been configured correctly, but the cores have not been created. + +**To troubleshoot core dumping:** + +1. Reboot the server. + +2. Verify that you have folder permissions: + + .. code-block:: console + + $ sudo chmod -R 777 /tmp/core_dumps + +3. Verify that the limits have been set correctly: + + .. code-block:: console + + $ ulimit -c + + If all parameters have been configured correctly, the correct output is: + + .. code-block:: console + + $ unlimited + +4. If all parameters have been configured correctly, but running **ulimit -c** outputs **0**, run the following: + + .. code-block:: console + + $ sudo vim /etc/profile + +5. Search for line and tag it with the **hash** symbol: + + .. code-block:: console + + $ ulimit -S -c 0 > /dev/null 2>&1 + + +6. If the line is not found in **/etc/profile** directory, do the following: + + a. Run the following command: + + .. code-block:: console + + $ sudo vim /etc/init.d/functions + + b. Search for the following: + + .. code-block:: console + + $ ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 + + c. If the line is found, tag it with the **hash** symbol and reboot the server. From 30635fa757f8cd153056f0019fe632cdd8bb0f29 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 12:50:13 +0200 Subject: [PATCH 096/300] Update index.rst Added recommended_pre-installation_configurations. Removed setup/index. --- guides/operations/index.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/guides/operations/index.rst b/guides/operations/index.rst index de2a98202..5c21a2f71 100644 --- a/guides/operations/index.rst +++ b/guides/operations/index.rst @@ -12,6 +12,7 @@ The guides in this section include information about best practices, monitoring, :glob: optimization_best_practices + recommended_pre-installation_configurations xxmonitoring running_sqream_in_a_docker_container logging @@ -23,5 +24,3 @@ The guides in this section include information about best practices, monitoring, statement_editor hardware_guide security - setup/index - From 65142ebeff31b894dfb5a49a26dd31b52b4a6e9c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 7 Nov 2021 12:50:57 +0200 Subject: [PATCH 097/300] Deleted Setup folder (sqream_docs\guides\operations\setup). Folder was not necessary because it contains files that are either outdated or are irrelevant: before_you_begin - irrelevant. The content on this page was moved to Getting Started page. index - irrelevant installing_monit - this page already exists in Operations. local_docker - there is an updated Docker page in the Operations menu. I've backed up this file. recommended_configuration - there is an updated page in the Operations menu. --- guides/operations/setup/before_you_begin.rst | 49 - guides/operations/setup/index.rst | 19 - guides/operations/setup/local_docker.rst | 491 ------- .../setup/recommended_configuration.rst | 1156 ----------------- 4 files changed, 1715 deletions(-) delete mode 100644 guides/operations/setup/before_you_begin.rst delete mode 100644 guides/operations/setup/index.rst delete mode 100644 guides/operations/setup/local_docker.rst delete mode 100644 guides/operations/setup/recommended_configuration.rst diff --git a/guides/operations/setup/before_you_begin.rst b/guides/operations/setup/before_you_begin.rst deleted file mode 100644 index 9c307ce8b..000000000 --- a/guides/operations/setup/before_you_begin.rst +++ /dev/null @@ -1,49 +0,0 @@ -.. _before_you_begin: - -*********************** -Before you begin -*********************** - -Before you install or deploy SQream DB, please verify you have the following: - -* An NVIDIA-capable server, either on-premise or on supported cloud platforms. - - * Supported operating systems: Red Hat Enterprise Linux v7.x / CentOS v7.x / Ubuntu 18.04 / Amazon Linux - * NVIDIA GPU. A Tesla GPU is highly recommended. See more information in our :ref:`hardware_guide`. - * A privileged SSH connection to the server (sudo) - -* A SQream DB license (contact support@sqream.com or your SQream account manager for your license key) - -* A 3rd party tool that can connect to SQream DB via JDBC, ODBC, or Python - -If you do not have a SQream DB license, visit our website and `sign up for SQream DB`_ today! - -Refer to our :ref:`hardware_guide` for more information about supported and recommended configurations. - -What does the installation process look like? ----------------------------------------------- - -To install SQream DB, we will go through the following steps: - -#. Prepare the host OS for NVIDIA driver installation - -#. Install the NVIDIA driver - -#. Install Docker CE - -#. Install nvidia-docker2 - -#. Prepare disk space for SQream DB - -#. Install SQream DB - -#. Additional system configuration for performance and stability - - -.. rubric:: What's next? - -* When ready, start :ref:`installing SQream DB ` - -.. _`sign up for SQream DB`: https://sqream.com/try-sqream-db - -.. TODO Links for if the user has already installed SQream DB but wants to configure, upgrade, or scale out the system further \ No newline at end of file diff --git a/guides/operations/setup/index.rst b/guides/operations/setup/index.rst deleted file mode 100644 index b422d9c5b..000000000 --- a/guides/operations/setup/index.rst +++ /dev/null @@ -1,19 +0,0 @@ -.. _setup: - -*********************** -Setting up SQream DB -*********************** - -The guides below cover installing SQream DB. - -.. toctree:: - :maxdepth: 4 - :caption: In this section: - :titlesonly: - :glob: - - before_you_begin - local_docker - recommended_configuration - - diff --git a/guides/operations/setup/local_docker.rst b/guides/operations/setup/local_docker.rst deleted file mode 100644 index 3e87db0ab..000000000 --- a/guides/operations/setup/local_docker.rst +++ /dev/null @@ -1,491 +0,0 @@ -.. _installing_sqream_db_docker: - -********************************************* -Start a local SQream DB cluster with Docker -********************************************* - -See :ref:`Release Notes ` to learn about what's new in the latest release of SQream DB. To upgrade to this release, see :ref:`Upgrading SQream DB with Docker`. - -SQream DB is installed on your hosts with NVIDIA Docker. There are several preparation steps to ensure before installing SQream DB, so follow these instructions carefully. - -.. Note:: Installing SQream DB requires a license key. Go to `SQream Support `_ or contact your SQream account manager for your license key. - -.. contents:: In this topic: - :local: - -Preparing your machine for NVIDIA Docker -========================================= -To install NVIDIA Docker, we must first install the NVIDIA driver. - -.. Note:: SQream DB works best on NVIDIA Tesla series GPUs, which provide better reliability, performance, and stability. The instructions below are written for NVIDIA Tesla GPUs, but other NVIDIA GPUs may work. - -.. contents:: Follow the instructions for your OS and architecture: - :local: - -CentOS 7 / RHEL 7 / Amazon Linux ---------------------------------------------------------------- - -.. admonition:: Recommended - - Follow the installation instructions on `NVIDIA's CUDA Installation Guide`_ for full instructions suitable for your platform. The information listed below is a summary of the necessary steps, and does not cover the full range of options available. - -#. Enable EPEL - - EPEL provides additional open-source and free packages from the RHEL ecosystem. The NVIDIA driver depends on packages such as DKMS and libvdpau which are only available on third-party repositories, such as EPEL. - - .. code-block:: console - - $ sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm - -.. There are other ways of installing EPEL: $ sudo yum -y install epel-release -.. Do we need DKMS? $ sudo yum -y install dkms - -#. Install the kernel headers and development tools necessary to compile the NVIDIA driver - - .. code-block:: console - - $ sudo yum -y install kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc - -#. Install the CUDA repository and install the latest display driver - - .. code-block:: console - - $ sudo rpm -Uvh https://developer.download.nvidia.com/compute/cuda/repos/rhel7/x86_64/cuda-repo-rhel7-10.1.243-1.x86_64.rpm - $ sudo yum install -y nvidia-driver-latest - -.. note:: If Linux is running with X, switch to text-only mode before installing the display driver. - - .. code-block:: console - - $ sudo systemctl set-default multi-user.target - - This change permanently disables X. If you need X, change ``set-default`` to ``isolate``. This will re-enable X on the next reboot. - -#. Restart your machine - - .. code-block:: console - - ``sudo reboot`` - - -#. Verify the installation completed correctly, by asking ``nvidia-smi``, NVIDIA's system management interface application, to list the available GPUs. - - .. code-block:: console - - $ nvidia-smi -L - GPU 0: Tesla V100-PCIE-16GB (UUID: GPU-...) - GPU 1: Tesla V100-PCIE-16GB (UUID: GPU-...) - -#. Enable NVIDIA's persistence daemon. This is mandatory for IBM POWER, but is recommended for other platforms as well. - - .. code-block:: console - - $ sudo systemctl enable nvidia-persistenced && sudo systemctl start nvidia-persistenced - - .. Important:: On POWER9 systems only, disable the udev rule for hot-pluggable memory probing. - - For Red Hat 7 this rule can be found in ``/lib/udev/rules.d/40-redhat.rules`` - - For Ubuntu, this rule can be found in in ``/lib/udev/rules.d/40-vm-hotadd.rules`` - The rule generally takes a form where it detects the addition of a memory block and changes the 'state' attribute to online. For example, in RHEL7, the rule looks like this: - - ``SUBSYSTEM=="memory", ACTION=="add", PROGRAM="/bin/uname -p", RESULT!="s390*", ATTR{state}=="offline", ATTR{state}="online"`` - - This rule must be disabled by copying the file to ``/etc/udev/rules.d`` and commenting out, removing, or changing the hot-pluggable memory rule in the ``/etc`` copy so that it does not apply to NVIDIA devices on POWER9. - - * On RHEL 7.5 or earlier versions: - - .. code-block:: console - - $ sudo cp /lib/udev/rules.d/40-redhat.rules /etc/udev/rules.d - $ sudo sed -i '/SUBSYSTEM=="memory", ACTION=="add"/d' /etc/udev/rules.d/40-redhat.rules - - * On RHEL 7.6 and later versions: - - .. code-block:: console - - $ sudo cp /lib/udev/rules.d/40-redhat.rules /etc/udev/rules.d - $ sudo sed -i 's/SUBSYSTEM!="memory", ACTION!="add", GOTO="memory_hotplug_end"/SUBSYSTEM=="*", GOTO="memory_hotplug_end"/' /etc/udev/rules.d/40-redhat.rules - - *Reboot the system to initialize the above changes* - -#. Continue to :ref:`installing NVIDIA Docker for RHEL ` - -Ubuntu 18.04 ---------------------------------------------------------------- - -.. admonition:: Recommended - - Follow the installation instructions on `NVIDIA's CUDA Installation Guide`_ for full instructions suitable for your platform. The information listed below is a summary of the necessary steps, and does not cover the full range of options available. - -#. Install the kernel headers and development tools necessary - - .. code-block:: console - - $ sudo apt-get update - $ sudo apt-get install linux-headers-$(uname -r) gcc - -#. Install the CUDA repository and driver on Ubuntu - - .. code-block:: console - - $ curl -O https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-repo-ubuntu1804_10.1.243-1_amd64.deb - $ sudo dpkg -i cuda-repo-ubuntu1804_10.1.243-1_amd64.deb - $ sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub - $ sudo apt-get update && sudo apt-get install -y nvidia-driver-418 - -#. Restart your machine - - ``sudo reboot`` - -#. Verify the installation completed correctly, by asking ``nvidia-smi``, NVIDIA's system management interface application, to list the available GPUs. - - .. code-block:: console - - $ nvidia-smi -L - GPU 0: Tesla V100-PCIE-16GB (UUID: GPU-...) - GPU 1: Tesla V100-PCIE-16GB (UUID: GPU-...) - -#. Enable NVIDIA's persistence daemon. This is mandatory for IBM POWER, but is recommended for other platforms as well. - - .. code-block:: console - - $ sudo systemctl enable nvidia-persistenced - -#. Continue to :ref:`installing NVIDIA Docker for Ubuntu ` - -Install Docker CE and NVIDIA docker -==================================== - -.. contents:: Follow the instructions for your OS and architecture: - :local: - -.. _docker_rhel: - -CentOS 7 / RHEL 7 / Amazon Linux (x64) --------------------------------------- - -.. note:: For IBM POWER9, see the next section :ref:`installing NVIDIA Docker for IBM POWER ` - -#. Follow the instructions for Docker CE for your platform at `Get Docker Engine - Community for CentOS`_ - -#. Tell Docker to start after a reboot - - .. code-block:: console - - $ sudo systemctl enable docker && sudo systemctl start docker - -#. Verify that docker is running - - .. code-block:: console - :emphasize-lines: 4 - - $ sudo systemctl status docker - ● docker.service - Docker Application Container Engine - Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled) - Active: active (running) since Mon 2019-08-12 08:22:30 IDT; 1 months 27 days ago - Docs: https://docs.docker.com - Main PID: 65794 (dockerd) - Tasks: 76 - Memory: 124.5M - CGroup: /system.slice/docker.service - └─65794 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock - -#. Let your current user manage Docker, without requiring `sudo` - - .. code-block:: console - - $ sudo usermod -aG docker $USER - - Then, log out and log back in: - - .. code-block:: console - - $ exit - -#. Install nvidia-docker - - .. code-block:: console - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | sudo tee /etc/yum.repos.d/nvidia-docker.repo - - $ sudo yum install -y nvidia-container-toolkit - $ sudo systemctl restart docker - $ sudo yum install nvidia-docker2 - $ sudo pkill -SIGHUP dockerd - $ sudo systemctl restart docker - -#. Verify the NVIDIA docker installation - - .. code-block:: console - - $ sudo docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi -L - GPU 0: Tesla V100-PCIE-16GB (UUID: GPU-...) - GPU 1: Tesla V100-PCIE-16GB (UUID: GPU-...) - -#. Continue to :ref:`Installing the SQream DB Docker container ` - -.. _docker_power: - -CentOS 7 / RHEL 7 (IBM POWER) -------------------------------- - -#. Install Docker for IBM POWER - - .. code-block:: console - - $ wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm - $ wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - $ yum install -y container-selinux-2.9-4.el7.noarch.rpm docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - -#. Tell Docker to start after a reboot - - .. code-block:: console - - $ sudo systemctl enable docker && sudo systemctl start docker - -#. Verify that docker is running - - .. code-block:: console - :linenos: - :emphasize-lines: 4 - - $ sudo systemctl status docker - ● docker.service - Docker Application Container Engine - Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled) - Active: active (running) since Mon 2019-08-12 08:22:30 IDT; 1 months 27 days ago - Docs: https://docs.docker.com - Main PID: 65794 (dockerd) - Tasks: 76 - Memory: 124.5M - CGroup: /system.slice/docker.service - └─65794 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock - -#. Let your current user manage Docker, without requiring `sudo` - - .. code-block:: console - - $ sudo usermod -aG docker $USER - - .. Note:: Log out and log back in again after this action - -#. Install nvidia-docker - - * Install the NVIDIA container and container runtime packages from NVIDIA's repository: - - .. code-block:: console - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | sudo tee /etc/yum.repos.d/nvidia-docker.repo - - $ sudo yum install -y libnvidia-container* nvidia-container-runtime* - - * Add the NVIDIA runtime to the Docker daemon and restart docker: - - .. code-block:: console - - $ sudo mkdir -p /etc/systemd/system/docker.service.d/ - $ echo -e "[Service]\nExecStart\nExecStart=/usr/bin/dockerd --add-runtime=nvidia=/usr/bin/nvidia-container-runtime" | sudo tee /etc/systemd/system/docker.service.d/override.conf - - $ sudo systemctl daemon-reload && sudo systemctl restart docker - -#. Verify the NVIDIA docker installation succeeded - - .. code-block:: console - - $ docker run --runtime=nvidia --rm nvidia/cuda-ppc64le nvidia-smi -L - GPU 0: Tesla V100-SXM2-16GB (UUID: GPU-...) - GPU 1: Tesla V100-SXM2-16GB (UUID: GPU-...) - -#. Continue to :ref:`Installing the SQream DB Docker container` - -.. _docker_ubuntu: - -Ubuntu 18.04 (x64) ------------------------------------ - -#. Follow the instructions for Docker CE for your platform at `Get Docker Engine - Community for CentOS`_ - -#. Tell Docker to start after a reboot - - .. code-block:: console - - $ sudo systemctl enable docker && sudo systemctl start docker - -#. Verify that docker is running - - .. code-block:: console - :linenos: - :emphasize-lines: 4 - - $ sudo systemctl status docker - ● docker.service - Docker Application Container Engine - Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled) - Active: active (running) since Mon 2019-08-12 08:22:30 IDT; 1 months 27 days ago - Docs: https://docs.docker.com - Main PID: 65794 (dockerd) - Tasks: 76 - Memory: 124.5M - CGroup: /system.slice/docker.service - └─65794 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock - -#. Let your current user manage Docker, without requiring `sudo` - - .. code-block:: console - - $ sudo usermod -aG docker $USER - - .. Note:: Log out and log back in again after this action - -#. Install nvidia-docker - - .. code-block:: console - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list - - $ sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit nvidia-docker2 - $ sudo pkill -SIGHUP dockerd - $ sudo systemctl restart docker - - -#. Verify the NVIDIA docker installation - - .. code-block:: console - - $ sudo docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi -L - GPU 0: Tesla V100-PCIE-16GB (UUID: GPU-...) - GPU 1: Tesla V100-PCIE-16GB (UUID: GPU-...) - -#. Continue to :ref:`Installing the SQream DB Docker container ` - - -.. _preparing_mounts: - -Preparing directories and mounts for SQream DB -=============================================== - -SQream DB contains several directories that need to be defined - -.. list-table:: Directories and paths - :widths: 40 60 - :header-rows: 1 - - * - Path name - - Definition - * - ``storage`` - - The location where SQream DB stores data, metadata, and logs - * - ``exposed path`` - - A location that SQream DB can read and write to. Used for allowing access to shared raw files like CSVs on local or NFS drives - * - ``logs`` - - Optional location for debug logs - -.. note:: By default, SQream DB can't access any OS path. You must explicitly allow it. - - -.. _installing_sqream_db_container: - -Install the SQream DB Docker container -========================================= - -#. Download the SQream DB tarball and license package - - In the e-mail from your account manager at SQream, you have received a download link for the SQream DB installer and a license package. - Download the SQream DB tarball to the user home directory. For example: - - .. code-block:: console - - $ cd ~ - $ curl -O https://get.sqream.com/x86/sqream_installer-2.0.7-DB2019.2.1.4-CO1.7.5-ED3.0.1-x86_64.tar.gz - -#. Extract the tarball into your home directory - - .. code-block:: console - - $ tar xf sqream_installer-2.0.7-DB2019.2.1.4-CO1.7.5-ED3.0.1-x86_64.tar.gz - -#. Copy the license package - - Copy the license package from your home directory to the license subdirectory which is located in the newly created SQream installer directory. - - For example, if the licence package is titled ``license_package.tar.gz``: - - .. code-block:: console - - $ cp ~/license_package.tar.gz sqream_installer-2.0.7-DB2019.2.1.4-CO1.7.5-ED3.0.1-x86_64/license - -#. Enter the installer directory - - .. code-block:: console - - $ cd sqream_installer-2.0.7-DB2019.2.1.4-CO1.7.5-ED3.0.1-x86_64 - -#. Install SQream DB - - In most cases, the installation command will look like this: - - .. code-block:: console - - $ ./sqream-install -i -k -v -d -l - - For example, if the main storage path for SQream DB is ``/mnt/largedrive`` and the desired shared access path is ``/mnt/nfs/source_files``, the command will look like: - - .. code-block:: console - - $ ./sqream-install -i -k -v /mnt/largedrive -d /mnt/nfs/source_files - - For a full list of options and commands, see the :ref:`sqream-installer reference ` - -#. SQream DB is now successfully installed, but not yet running. - - -.. _start_local_cluster: - -Starting your first local cluster -========================================= - -#. Enter the :ref:`sqream console utility`, which helps coordinate SQream DB components - - .. code-block:: console - - $ ./sqream-console - -#. Start the master components: - - .. code-block:: console - - sqream-console>sqream master --start - starting master server in single_host mode ... - sqream_single_host_master is up and listening on ports: 3105,3108 - - -#. Start workers to join the cluster: - - .. code-block:: console - - sqream-console>sqream worker --start 2 - started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 - started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 - - .. note:: By default, each worker is allocated a full GPU. To launch more workers than available GPUs, see the :ref:`sqream console reference ` - -#. SQream DB is now running! (Exit the console by typing ``exit`` when done.) - -.. rubric:: What's next? - -* :ref:`Test your SQream DB installation by creating your first table` - -* :ref:`Connect an external tool to SQream DB ` - -* :ref:`Additional system configuration for performance and stability ` - - -.. Some replacements: - -.. _`Latest Tesla driver for Linux x64`: https://www.nvidia.com/Download/driverResults.aspx/152242/en-us -.. _`Latest Tesla driver for Linux x64 POWER LE`: https://www.nvidia.com/Download/driverResults.aspx/152241/en-us -.. _`NVIDIA's CUDA Installation Guide`: https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#pre-installation-actions -.. _`Get Docker Engine - Community for CentOS`: https://docs.docker.com/install/linux/docker-ce/centos/ -.. _`Get Docker Engine - Community for Ubuntu`: https://docs.docker.com/install/linux/docker-ce/ubuntu/ diff --git a/guides/operations/setup/recommended_configuration.rst b/guides/operations/setup/recommended_configuration.rst deleted file mode 100644 index 7075d79cb..000000000 --- a/guides/operations/setup/recommended_configuration.rst +++ /dev/null @@ -1,1156 +0,0 @@ -.. _recommended_configuration: - -********************************************* -Recommended Pre-Installation Configuration -********************************************* - -Before :ref:`installing SQream DB`, SQream recommends you to tune your system for better performance and stability. - -This page provides recommendations for production deployments of SQream DB. - -.. contents:: In this topic: - :local: - -Recommended BIOS Settings -========================== -The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. - -It is safe to skip any and all of the configuration steps, but this may impact performance. - -If any doubt arises, consult the documentation for your server or your hardware vendor for the correct way to apply the settings. - -.. list-table:: - :widths: 25 25 50 - :header-rows: 1 - - * - Item - - Setting - - Rationale - * - **Management console access** - - **Connected** - - Connection to OOB required to preserve continuous network uptime. - * - **All drives.** - - **Connected and displayed on RAID interface** - - Prerequisite for cluster or OS installation. - * - **RAID volumes.** - - **Configured according to project guidelines. Must be rebooted to take effect.** - - Clustered to increase logical volume and provide redundancy. - * - **Fan speed Thermal Configuration.** - - Dell fan speed: **High Maximum**. Specified minimum setting: **60**. HPe thermal configuration: **Increased cooling**. - - NVIDIA Tesla GPUs are passively cooled and require high airflow to operate at full performance. - * - Power regulator or iDRAC power unit policy - - HPe: **HP static high performance** mode enabled. Dell: **iDRAC power unit policy** (power cap policy) disabled. - - Other power profiles (such as "balanced") throttle the CPU and diminishes performance. Throttling may also cause GPU failure. - * - **System Profile**, **Power Profile**, or **Performance Profile** - - **High Performance** - - The Performance profile provides potentially increased performance by maximizing processor frequency, and the disabling certain power saving features such as C-states. Use this setting for environments that are not sensitive to power consumption. - * - **Power Cap Policy** or **Dynamic power capping** - - **Disabled** - - Other power profiles (like "balanced") throttle the CPU and may diminish performance or cause GPU failure. This setting may appear together with the above (Power profile or Power regulator). This setting allows disabling system ROM power calibration during the boot process. Power regulator settings are named differently in BIOS and iLO/iDRAC. - -.. - **Comment: is it necessary to show the different power regulator setting names in this document?** - * - **Intel Turbo Boost** - - **Enabled** - - Intel Turbo Boost enables overclocking the processor to boost CPU-bound operation performance. Overclocking may risk computational jitter due to changes in the processor's turbo frequency. This causes brief pauses in processor operation, introducing uncertainty into application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. - * - **Logical Processor** - - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** - - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. - * - **Intel Virtualization Technology** (VT-d) - - **Disable** - - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. - * - **Logical Processor** - - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** - - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. - * - **Intel Virtualization Technology** (VT-d) - - **Disable** - - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. - * - **Processor C-States** (Minimum processor idle power core state) - - **Disable** - - Processor C-States reduce server power when the system is in an idle state. This causes slower cold-starts when the system transitions from an idle to a load state, and may reduce query performance by up to 15%. **Comment: a hyperlinked footnote to an internal source was inserted into the Confluence doc here. Do we want to include this in the final version? Linked URL: https://www.dell.com/support/kbdoc/en-il/000060621/what-is-the-c-state** - * - **HPe**: **Energy/Performance bias** - - **Maximum performance** - - Configures processor sub-systems for high-performance and low-latency. Other power profiles (like "balanced") throttle the CPU and may diminish performance. Use this setting for environments that are not sensitive to power consumption. - * - **HPe**: **DIMM voltage** - - **Optimized for Performance** - - Setting a higher voltage for DIMMs may increase performance. - * - **Memory Operating Mode** - - **Optimizer Mode**, **Disable Node Interleaving**, **Auto Memory Operating Voltage** - - Memory Operating Mode is tuned for performance in **Optimizer** mode. Other modes may improve reliability, but reduce performance. **Node Interleaving** should be disabled because enabling it interleaves the memory between memory nodes, which harms NUMA-aware applications such as SQream DB. - * - **HPe**: **Memory power savings mode** - - **Maximum performance** - - This setting configures several memory parameters to optimize the performance of memory sub-systems. The default setting is **Balanced**. - * - HPe **ACPI SLIT** - - **Enabled** - - ACPI SLIT sets the relative access times between processors and memory and I/O sub-systems. ACPI SLIT enables operating systems to use this data to improve performance by more efficiently allocating resources and workloads. - * - **QPI Snoop** **Comment: should we write that it is HPe or Intel? HPe: QPI Snoop** - - **Cluster on Die** or **Home Snoop** - - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. - - - - - - -Installing the Operating System -=================================================== -Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.6-7.9) must be installed before installing the SQream database. Either the customer or a SQream representative can perform the installation. - -.. - **Comment: I recommend leaving contact information here - Please call xxx-xxx-xxxx to contact a SQream representative.** - -**To install the operating system:** - -#. Select a language (English recommended). -#. From **Software Selection**, select **Minimal**. -#. Select the **Development Tools** group checkbox. -#. Continue the installation. -#. Set up the necessary drives and users as per the installation process. - - Using Debugging Tools is recommended for future problem-solving if necessary. - - .. - **Comment: In Step 4, why don't we document the entire procedure? I.e., why do we stop here and say "Continue the installation" and "Set up the necessary drives..."?** - -Selecting the **Development Tools** group installs the following tools: - - * autoconf - * automake - * binutils - * bison - * flex - * gcc - * gcc-c++ - * gettext - * libtool - * make - * patch - * pkgconfig - * redhat-rpm-config - * rpm-build - * rpm-sign - - - -The root user is created and the OS shell is booted up. - -Configuring the Operating System -=================================================== -When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. - -Logging In to the Server --------------------------------- -You can log in to the server using the server's IP address and password for the **root** user. The server's IP address and **root** user were created while installing the operating system above. - -Automatically Creating a SQream User ------------------------------------- - -**To automatically create a SQream user:** - -#. If a SQream user was created during installation, verify that the same ID is used on every server: - - .. code-block:: console - - $ sudo id sqream - -The ID **1000** is used on each server in the following example: - - .. code-block:: console - - $ uid=1000(sqream) gid=1000(sqream) groups=1000(sqream) - -2. If the ID's are different, delete the SQream user and SQream group from both servers: - - .. code-block:: console - - $ sudo userdel sqream - -3. Recreate it using the same ID: - - .. code-block:: console - - $ sudo rm /var/spool/mail/sqream - -Manually Creating a SQream User --------------------------------- - -**To manually create a SQream user:** - -SQream enables you to manually create users. This section shows you how to manually create a user with the UID **1111**. You cannot manually create during the operating system installation procedure. - -1. Add a user with an identical UID on all cluster nodes: - - .. code-block:: console - - $ useradd -u 1111 sqream - -2. Add the user **sqream** to the **wheel** group. - - .. code-block:: console - - $ sudo usermod -aG wheel sqream - -You can remove the SQream user from the **wheel** group when the installation and configuration are complete: - - .. code-block:: console - - $ passwd sqream - -3. Log out and log back in as **sqream**. - -**Note:** If you deleted the **sqream** user and recreated it with different ID, to avoid permission errors, you must change its ownership to /home/sqream. - -4. Change the **sqream** user's ownership to /home/sqream: - - .. code-block:: console - - $ sudo chown -R sqream:sqream /home/sqream - -Setting Up A Locale --------------------------------- - -SQream enables you to set up a locale. In this example, the locale used is your own location. - -**To set up a locale:** - -1. Set the language of the locale: - - .. code-block:: console - - $ sudo localectl set-locale LANG=en_US.UTF-8 - -2. Set the time stamp (time and date) of the locale: - - .. code-block:: console - - $ sudo timedatectl set-timezone Asia/Jerusalem - -If needed, you can run the **timedatectl list-timezones** command to see your current time-zone. - - -Installing the Required Packages --------------------------------- -You can install the required packages by running the following command: - -.. code-block:: console - - $ sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq - - -Installing the Recommended Tools --------------------------------- -You can install the recommended tools by running the following command: - -.. code-block:: console - - $ sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix - - -Installing Python 3.6.7 --------------------------------- -1. Download the Python 3.6.7 source code tarball file from the following URL into the **/home/sqream** directory: - - .. code-block:: console - - $ wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz - -2. Extract the Python 3.6.7 source code into your current directory: - - .. code-block:: console - - $ tar -xf Python-3.6.7.tar.xz - -3. Navigate to the Python 3.6.7 directory: - - .. code-block:: console - - $ cd Python-3.6.7/Python-3 - -4. Run the **./configure** script: - - .. code-block:: console - - $ ./configure - -5. Build the software: - - .. code-block:: console - - $ make -j30 - -6. Install the software: - - .. code-block:: console - - $ sudo make install - -7. Verify that Python 3.6.7 has been installed: - - .. code-block:: console - - $ python3.6.7 - -Installing NodeJS on CentOS --------------------------------- -**To install the node.js on CentOS:** - -1. Download the `setup_12.x file `__ as a root user logged in shell: - - .. code-block:: console - - $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - - -2. Clear the YUM cache and update the local metadata: - - .. code-block:: console - - $ sudo yum clean all && sudo yum makecache fast - -3. Install the **node.js**) file: - - .. code-block:: console - - $ sudo yum install -y nodejs - -Installing NodeJS on Ubuntu --------------------------------- -**To install the node.js file on Ubuntu:** - -1. Download the `setup_12.x file `__ as a root user logged in shell: - - .. code-block:: console - - $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - - -2. Install the node.js file: - - .. code-block:: console - - $ sudo apt-get install -y nodejs - -3. Verify the node version: - -.. - **Comment: - is this step relevant only for installing on Ubuntu, or on CentOS as well?** - - .. code-block:: console - - $ node -v - -Configuring the Network Time Protocol (NTP) -------------------------------------------- -This section describes how to configure your NTP. - -If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server `__. - -.. - **Comment: - Is this the correct procedure on the linked URL: Configure NTP Client to Synchronize with NTP Server?* - -**To configure your NTP:** - -1. Install the NTP file. - - .. code-block:: console - - $ sudo yum install ntp - -2. Enable the **ntpd** program. - - .. code-block:: console - - $ sudo systemctl enable ntpd - -3. Start the **ntdp** program. - - .. code-block:: console - - $ sudo systemctl start ntpd - -4. Print a list of peers known to the server and a summary of their states. - - .. code-block:: console - - $ sudo ntpq -p - -Configuring the Network Time Protocol Server --------------------------------------------- -If your organization has an NTP server, you can configure it. - -**To configure your NTP server:** - -1. Output your NTP server address and append ``/etc/ntpd.conf`` to the outuput. - - .. code-block:: console - - $ echo -e "\nserver \n" | sudo tee -a /etc/ntp.conf - -2. Restart the service. - - .. code-block:: console - - $ sudo systemctl restart ntpd - -3. Check that synchronization is enabled: - - .. code-block:: console - - $ sudo timedatectl - -Checking that synchronization is enabled generates the following output: - - .. code-block:: console - - $ Local time: Sat 2019-10-12 17:26:13 EDT - Universal time: Sat 2019-10-12 21:26:13 UTC - RTC time: Sat 2019-10-12 21:26:13 - Time zone: America/New_York (EDT, -0400) - NTP enabled: yes - NTP synchronized: yes - RTC in local TZ: no - DST active: yes - Last DST change: DST began at - Sun 2019-03-10 01:59:59 EST - Sun 2019-03-10 03:00:00 EDT - Next DST change: DST ends (the clock jumps one hour backwards) at - Sun 2019-11-03 01:59:59 EDT - Sun 2019-11-03 01:00:00 EST - - - -Configuring the Server to Boot Without the UI ---------------------------------------------- -You can configure your server to boot without a UI in cases when it is not required (recommended) by running the following command: - -.. code-block:: console - - $ sudo systemctl set-default multi-user.target - -Running this command activates the **NO-UI** server mode. - -Configuring the Security Limits --------------------------------- -The security limits refers to the number of open files, processes, etc. - -You can configure the security limits by running the **echo -e** command as a root user logged in shell: - -.. code-block:: console - - $ sudo bash - -.. code-block:: console - - $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf - -Configuring the Kernel Parameters ---------------------------------- -**To configure the kernel parameters:** - -1. Insert a new line after each kernel parameter: - - .. code-block:: console - - $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf - -**Notice:** In the past, the **vm.zone_reclaim_mode** parameter was set to **7.** In the latest Sqream version, the vm.zone_reclaim_mode parameter must be set to **0**. If it is not set to **0**, when a numa node runs out of memory, the system will get stuck and will be unable to pull memory from other numa nodes. - -2. Check the maximum value of the **fs.file**. - - .. code-block:: console - - $ sysctl -n fs.file-max - -3. *Optional* - If the maximum value of the **fs.file** is smaller than **2097152**, run the following command: - - .. code-block:: console - - $ echo "fs.file-max=2097152" >> /etc/sysctl.conf - -**IP4 forward** must be enabled for Docker and K8s installation only. - -Configuring the Firewall --------------------------------- -The example in this section shows the open ports for four sqreamd sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. - -**To configure the firewall:** - -1. Start the service and enable FirewallID on boot: - - .. code-block:: console - - $ systemctl start firewalld - -2. Add the following ports to the permanent firewall: - - .. code-block:: console - - $ firewall-cmd --zone=public --permanent --add-port=8080/tcp - $ firewallfirewall-cmd --zone=public --permanent --add-port=3105/tcp - $ firewall-cmd --zone=public --permanent --add-port=3108/tcp - $ firewall-cmd --zone=public --permanent --add-port=5000-5003/tcp - $ firewall-cmd --zone=public --permanent --add-port=5100-5103/tcp - $ firewall-cmd --permanent --list-all - - -.. - **Comment: - does *--list-all* add the entire list of ports to the permanent firewall?** - -3. Reload the firewall: - - .. code-block:: console - - $ firewall-cmd --reload - -4. Start the service and enable FirewallID on boot: - - .. code-block:: console - - $ systemctl start firewalld - - If you do not need the firewall, you can disable it: - - .. code-block:: console - - $ sudo systemctl disable firewalld - - -Disabling selinux --------------------------------- -**To disable selinux:** - -1. Show the status of **selinux**: - - .. code-block:: console - - $ sudo sestatus - -2. If the output is not **disabled**, edit the **/etc/selinux/config** file: - - .. code-block:: console - - $ sudo vim /etc/selinux/config - -3. Change **SELINUX=enforcing** to **SELINUX=disabled**. - -The above changes will only take effect after rebooting the server. - -You can disable selinux immediately after rebooting the server by running the following command: - -.. code-block:: console - - $ sudo setenforce 0 - -Configuring the /etc/hosts File --------------------------------- -**To configure the /etc/hosts file:** - -1. Edit the **/etc/hosts** file: - - .. code-block:: console - - $ sudo vim /etc/hosts - -2. Call your local host: - - .. code-block:: console - - $ 127.0.0.1 localhost - $ - -.. - **Comment: - Is the above an output or a step?** - -Configuring the DNS --------------------------------- -**To configure the DNS:** - -1. Run the **ifconfig** commasnd to check your NIC name. In the following example, **eth0** is the NIC name: - - .. code-block:: console - - $ sudo vim /etc/sysconfig/network-scripts/ifcfg-eth0 - -2. Replace the DNS lines from the example above with your own DNS addresses : - - .. code-block:: console - - $ sudo vim /etc/sysconfig/network-scripts/ifcfg-4.4.4.4 - $ sudo vim /etc/sysconfig/network-scripts/ifcfg-8.8.8.8 - - -.. - **Comment: - is the above input correct?** - -Installing the Nvidia CUDA Driver -=================================================== - - -**Warning:** If your UI runs on the server, the server must be stopped before installing the CUDA drivers. - -CUDA Driver Prerequisites --------------------------------- -1. Verify that the NVIDIA card has been installed and is detected by the system: - - .. code-block:: console - - $ lspci | grep -i nvidia - -2. Check which version of gcc has been installed: - - .. code-block:: console - - $ gcc --version - -3. If gcc has not been installed, install it for one of the following operating systems: - - * On RHEL/CentOS: - - .. code-block:: console - - $ sudo yum install -y gcc - - * On Ubuntu: - - .. code-block:: console - - $ sudo apt-get install gcc - - -Updating the Kernel Headers --------------------------------- -**To update the kernel headers:** - -1. Update the kernel headers on one of the following operating systems: - - * On RHEL/CentOS: - - .. code-block:: console - - $ sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) - - * On Ubuntu: - - .. code-block:: console - - $ sudo apt-get install linux-headers-$(uname -r) - -2. Install **wget** one of the following operating systems: - - * On RHEL/CentOS: - - .. code-block:: console - - $ sudo yum install wget - - * On Ubuntu: - - .. code-block:: console - - $ sudo apt-get install wget - -Disabling Nouveau --------------------------------- -You can disable Nouveau, which is the default driver. - -**To disable Nouveau:** - -1. Check if the Nouveau driver has been loaded: - - .. code-block:: console - - $ lsmod | grep nouveau - -If the Nouveau driver has been loaded, the command above generates output. - -2. Blacklist the Nouveau drivers to disable them: - - .. code-block:: console - - $ cat <`__ for the additional set-up requirements. - - - c. **For K80**: - - .. code-block:: console - - $ nvidia-persistenced - $ nvidia-smi -pm 1 - $ nvidia-smi -acp 0 - $ nvidia-smi --auto-boost-permission=0 - $ nvidia-smi --auto-boost-default=0 - -4. Reboot the server and run the **NVIDIA System Management Interface (NVIDIA SMI)**: - - .. code-block:: console - - $ nvidia-smi - - -Disabling Automatic Bug Reporting Tools -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -**To disable automatic bug reporting tools:** - -1. Run the following **abort** commands: - - .. code-block:: console - - $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done - - -The server is ready for the SQream software installation. - - -2. Run the following checks: - - a. Check the OS release: - - .. code-block:: console - - $ cat /etc/os-release - - b. Verify that a SQream user exists and has the same ID on all cluster member services: - - .. code-block:: console - - $ id sqream - - c. Verify that the storage is mounted: - - .. code-block:: console - - $ mount - - d. Verify that the driver has been installed correctly: - - .. code-block:: console - - $ nvidia-smi - - e. Check the maximum value of the **fs.file**: - - .. code-block:: console - - $ sysctl -n fs.file-max - - The desired output when checking the maximum value of the **fs.file** is greater or equal to **2097152**. - - f. Run the following command as a SQream user: - -.. - **Comment: - **Question - what do the following command parameter do? -c?** - - .. code-block:: console - - $ ulimit -c -u -n - -.. - **Comment: - See https://ss64.com/bash/ulimit.html** - - The following shows the desired output when ****: - - .. code-block:: console - - $ core file size (blocks, -c) unlimited - $ max user processes (-u) 1000000 - $ open files (-n) 1000000 - -3. Configure the security limits by running the **echo -e** command as a root user logged in shell: - - .. code-block:: console - - $ sudo bash - $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf - -Enabling Core Dumps -=================================================== - -Enabling core dumps is recommended, but optional. - -**To enable core dumps:** - -1. Check the **abrtd** Status - -2. Set the limits - -3. Create the core dumps directory. - - -Checking the abrtd Status ---------------------------------------------------- - -**To check the abrtd status:** - -1. Check if **abrtd** is running: - - .. code-block:: console - - $ sudo ps -ef |grep abrt - -2. If **abrtd** is running, stop it: - - .. code-block:: console - - $ sudo service abrtd stop - $ sudo chkconfig abrt-ccpp off - $ sudo chkconfig abrt-oops off - $ sudo chkconfig abrt-vmcore off - $ sudo chkconfig abrt-xorg off - $ sudo chkconfig abrtd off - - -Setting the Limits ---------------------------------------------------- - -**To set the limits:** - -1. Set the limits: - - .. code-block:: console - - $ ulimit -c - -2. If the output is **0**, add the following lines to the **limits.conf** file (/etc/security): - - .. code-block:: console - - $ * soft core unlimited - $ * hard core unlimited - -3. Log out and log in to apply the limit changes. - -Creating the Core Dumps Directory ---------------------------------------------------- - -**To set the core dumps directory:** - -1. Make the **/tmp/core_dumps** directory: - - .. code-block:: console - - $ mkdir /tmp/core_dumps - -2. Set the ownership of the **/tmp/core_dumps** directory: - - .. code-block:: console - - $ sudo chown sqream.sqream /tmp/core_dumps - -3. Grant read, write, and execute permissions to all users: - - .. code-block:: console - - $ sudo chmod -R 777 /tmp/core_dumps - -Setting the Output Directory of the /etc/sysctl.conf File ------------------------------------------------------------------ - -**To set the output directory of the /etc/sysctl.conf file:** - -1. Edit the **/etc/sysctl.conf** file: - - .. code-block:: console - - $ sudo vim /etc/sysctl.conf - -2. Add the following to the bottom of the file: - - .. code-block:: console - - $ kernel.core_uses_pid = 1 - $ kernel.core_pattern = //core-%e-%s-%u-%g-%p-%t - $ fs.suid_dumpable = 2 - -.. - **Comment: - leave a note that the user can choose his correct location of the folder.** - -3. To apply the changes without rebooting the server, run: - - .. code-block:: console - - $ sudo sysctl -p - -4. Check that the core output directory points to the following: - - .. code-block:: console - - $ sudo cat /proc/sys/kernel/core_pattern - - The following shows the correct generated output: - - .. code-block:: console - - $ /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t - -5. Verify that the core dumping works: - - .. code-block:: console - - $ select abort_server(); - - -Verifying that the Core Dumps Work ---------------------------------------------------- -You can verify that the core dumps work only after installing and running SQream. This causes the server to crash and a new core.xxx file to be included in the folder that is written in **/etc/sysctl.conf** - -**To verify that the core dumps work:** - -1. Stop and restart all SQream services. - -2. Connect to SQream with ClientCmd and run the following command: - - .. code-block:: console - - $ select abort_server(); - - -.. - **Comment: - what did the author mean by "Stage 3"?** - -Troubleshooting Core Dumping ---------------------------------------------------- -This section describes the troubleshooting procedure to be followed if all parameters have been configured correctly, but the cores have not been created. - -**To troubleshoot core dumping:** - -1. Reboot the server. - -2. Verify that you have folder permissions: - - .. code-block:: console - - $ sudo chmod -R 777 /tmp/core_dumps - -3. Verify that the limits have been set correctly: - - .. code-block:: console - - $ ulimit -c - - If all parameters have been configured correctly, the correct output is: - - .. code-block:: console - - $ unlimited - -4. If all parameters have been configured correctly, but running **ulimit -c** outputs **0**, run the following: - - .. code-block:: console - - $ sudo vim /etc/profile - -5. Search for line and tag it with the **hash** symbol: - - .. code-block:: console - - $ ulimit -S -c 0 > /dev/null 2>&1 - - -6. If the line is not found in **/etc/profile** directory, do the following: - - a. Run the following command: - - .. code-block:: console - - $ sudo vim /etc/init.d/functions - - b. Search for the following: - - .. code-block:: console - - $ ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 - - c. If the line is found, tag it with the **hash** symbol and reboot the server. From 18f5b6bd108e640f907b784d238e3b06dd2ea2d9 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 13:58:57 +0200 Subject: [PATCH 098/300] Create installing_sqream_with_binary.rst Created installing_sqream_with_binary.rst file. --- .../installing_sqream_with_binary.rst | 277 ++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 guides/operations/installing_sqream_with_binary.rst diff --git a/guides/operations/installing_sqream_with_binary.rst b/guides/operations/installing_sqream_with_binary.rst new file mode 100644 index 000000000..fd549bdff --- /dev/null +++ b/guides/operations/installing_sqream_with_binary.rst @@ -0,0 +1,277 @@ +.. _installing_sqream_with_binary: + +********************************************* +Installing SQream Using Binary Packages +********************************************* +This procedure describes how to install SQream using Binary packages and must be done on all servers. + +**To install SQream using Binary packages:** + +1. Copy the SQream package to the **/home/sqream** directory for the current version: + + .. code-block:: console + + $ tar -xf sqream-db-v<2020.2>.tar.gz + +2. Append the version number to the name of the SQream folder. The version number in the following example is **v2020.2**: + + .. code-block:: console + + $ mv sqream sqream-db-v<2020.2> + +3. Move the new version of the SQream folder to the **/usr/local/** directory: + + .. code-block:: console + + $ sudo mv sqream-db-v<2020.2> /usr/local/ + +4. Change the ownership of the folder to **sqream folder**: + + .. code-block:: console + + $ sudo chown -R sqream:sqream /usr/local/sqream-db-v<2020.2> + +5. Navigate to the **/usr/local/** directory and create a symbolic link to SQream: + + .. code-block:: console + + $ cd /usr/local + $ sudo ln -s sqream-db-v<2020.2> sqream + +6. Verify that the symbolic link that you created points to the folder that you created: + + .. code-block:: console + + $ ls -l + +7. Verify that the symbolic link that you created points to the folder that you created: + + .. code-block:: console + + $ sqream -> sqream-db-v<2020.2> + +8. Create the SQream configuration file destination folders and set their ownership to **sqream**: + + .. code-block:: console + + $ sudo mkdir /etc/sqream + $ sudo chown -R sqream:sqream /etc/sqream + +9. Create the SQream service log destination folders and set their ownership to **sqream**: + + .. code-block:: console + + $ sudo mkdir /var/log/sqream + $ sudo chown -R sqream:sqream /var/log/sqream + +10. Navigate to the **/usr/local/** directory and copy the SQream configuration files from them: + + .. code-block:: console + + $ cd /usr/local/sqream/etc/ + $ cp * /etc/sqream + +The configuration files are **service configuration files**, and the JSON files are **SQream configuration files**, for a total of four files. The number of SQream configuration files and JSON files must be identical. + +**NOTICE** - Verify that the JSON files have been configured correctly and that all required flags have been set to the correct values. + +In each JSON file, the following parameters **must be updated**: + +* instanceId +* machineIP +* metadataServerIp +* spoolMemoryGB +* limitQueryMemoryGB +* gpu +* port +* ssl_port + +Note the following: + +* The value of the **metadataServerIp** parameter must point to the IP that the metadata is running on. +* The value of the **machineIP** parameter must point to the IP of your local machine. + +It would be same on server running metadataserver and different on other server nodes. + +11. **Optional** - To run additional SQream services, copy the required configuration files and create additional JSON files: + + .. code-block:: console + + $ cp sqream2_config.json sqream3_config.json + $ vim sqream3_config.json + +**NOTICE:** A unique **instanceID** must be used in each JSON file. IN the example above, the instanceID **sqream_2** is changed to **sqream_3**. + +12. **Optional** - If you created additional services in **Step 11**, verify that you have also created their additional configuration files: + + .. code-block:: console + + $ cp sqream2-service.conf sqream3-service.conf + $ vim sqream3-service.conf + +13. For each SQream service configuration file, do the following: + + 1. Change the **SERVICE_NAME=sqream2** value to **SERVICE_NAME=sqream3**. + + 2. Change **LOGFILE=/var/log/sqream/sqream2.log** to **LOGFILE=/var/log/sqream/sqream3.log**. + +**NOTE:** If you are running SQream on more than one server, you must configure the ``serverpicker`` and ``metadatserver`` services to start on only one of the servers. If **metadataserver** is running on the first server, the ``metadataServerIP`` value in the second server's /etc/sqream/sqream1_config.json file must point to the IP of the server on which the ``metadataserver`` service is running. + +14. Set up **servicepicker**: + + 1. Do the following: + + .. code-block:: console + + $ vim /etc/sqream/server_picker.conf + + 2. Change the IP **127.0.0.1** to the IP of the server that the **metadataserver** service is running on. + + 3. Change the **CLUSTER** to the value of the cluster path. + +15. Set up your service files: + + .. code-block:: console + + $ cd /usr/local/sqream/service/ + $ cp sqream2.service sqream3.service + $ vim sqream3.service + +16. Increment each **EnvironmentFile=/etc/sqream/sqream2-service.conf** configuration file for each SQream service file, as shown below: + + .. code-block:: console + + $ EnvironmentFile=/etc/sqream/sqream<3>-service.conf + +17. Copy and register your service files into systemd: + + .. code-block:: console + + $ sudo cp metadataserver.service /usr/lib/systemd/system/ + $ sudo cp serverpicker.service /usr/lib/systemd/system/ + $ sudo cp sqream*.service /usr/lib/systemd/system/ + +18. Verify that your service files have been copied into systemd: + + .. code-block:: console + + $ ls -l /usr/lib/systemd/system/sqream* + $ ls -l /usr/lib/systemd/system/metadataserver.service + $ ls -l /usr/lib/systemd/system/serverpicker.service + $ sudo systemctl daemon-reload + +19. Copy the license into the **/etc/license** directory: + + .. code-block:: console + + $ cp license.enc /etc/sqream/ + + +If you have an HDFS environment, see :ref:`Configuring an HDFS Environment for the User sqream `. + + + + + + +Upgrading SQream Version +------------------------- +Upgrading your SQream version requires stopping all running services while you manually upgrade SQream. + +**To upgrade your version of SQream:** + +1. Stop all actively running SQream services. + +**Notice-** All SQream services must remain stopped while the upgrade is in process. Ensuring that SQream services remain stopped depends on the tool being used. + +For an example of stopping actively running SQream services, see :ref:`Launching SQream with Monit `. + + + +2. Verify that SQream has stopped listening on ports **500X**, **510X**, and **310X**: + + .. code-block:: console + + $ sudo netstat -nltp #to make sure sqream stopped listening on 500X, 510X and 310X ports. + +3. Replace the old version ``sqream-db-v2020.2``, with the new version ``sqream-db-v2021.1``: + + .. code-block:: console + + $ cd /home/sqream + $ mkdir tempfolder + $ mv sqream-db-v2021.1.tar.gz tempfolder/ + $ tar -xf sqream-db-v2021.1.tar.gz + $ sudo mv sqream /usr/local/sqream-db-v2021.1 + $ cd /usr/local + $ sudo chown -R sqream:sqream sqream-db-v2021.1 + +4. Remove the symbolic link: + + .. code-block:: console + + $ sudo rm sqream + +5. Create a new symbolic link named "sqream" pointing to the new version: + + .. code-block:: console + + $ sudo ln -s sqream-db-v2021.1 sqream + +6. Verify that the symbolic SQream link points to the real folder: + + .. code-block:: console + + $ ls -l + + The following is an example of the correct output: + + .. code-block:: console + + $ sqream -> sqream-db-v2021.1 + +7. **Optional-** (for major versions) Upgrade your version of SQream storage cluster, as shown in the following example: + + .. code-block:: console + + $ cat /etc/sqream/sqream1_config.json |grep cluster + $ ./upgrade_storage + + The following is an example of the correct output: + + .. code-block:: console + + get_leveldb_version path{} + current storage version 23 + upgrade_v24 + upgrade_storage to 24 + upgrade_storage to 24 - Done + upgrade_v25 + upgrade_storage to 25 + upgrade_storage to 25 - Done + upgrade_v26 + upgrade_storage to 26 + upgrade_storage to 26 - Done + validate_leveldb + ... + upgrade_v37 + upgrade_storage to 37 + upgrade_storage to 37 - Done + validate_leveldb + storage has been upgraded successfully to version 37 + +8. Verify that the latest version has been installed: + + .. code-block:: console + + $ ./sqream sql --username sqream --password sqream --host localhost --databasename master -c "SELECT SHOW_VERSION();" + + The following is an example of the correct output: + + .. code-block:: console + + v2021.1 + 1 row + time: 0.050603s + +For more information, see the `upgrade_storage `_ command line program. From ccb872fcdc826ed3b0e1d6062e4aec69cb819fa5 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 14:07:30 +0200 Subject: [PATCH 099/300] Create installing_sqream_with_binary.rst --- .../installing_sqream_with_binary.rst | 278 ++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 guides/operations/installing_sqream_with_binary.rst diff --git a/guides/operations/installing_sqream_with_binary.rst b/guides/operations/installing_sqream_with_binary.rst new file mode 100644 index 000000000..b7dcf54c5 --- /dev/null +++ b/guides/operations/installing_sqream_with_binary.rst @@ -0,0 +1,278 @@ +.. _installing_sqream_with_binary: + +********************************************* +Installing SQream Using Binary Packages +********************************************* +This procedure describes how to install SQream using Binary packages and must be done on all servers. + +**To install SQream using Binary packages:** + +1. Copy the SQream package to the **/home/sqream** directory for the current version: + + .. code-block:: console + + $ tar -xf sqream-db-v<2020.2>.tar.gz + +2. Append the version number to the name of the SQream folder. The version number in the following example is **v2020.2**: + + .. code-block:: console + + $ mv sqream sqream-db-v<2020.2> + +3. Move the new version of the SQream folder to the **/usr/local/** directory: + + .. code-block:: console + + $ sudo mv sqream-db-v<2020.2> /usr/local/ + +4. Change the ownership of the folder to **sqream folder**: + + .. code-block:: console + + $ sudo chown -R sqream:sqream /usr/local/sqream-db-v<2020.2> + +5. Navigate to the **/usr/local/** directory and create a symbolic link to SQream: + + .. code-block:: console + + $ cd /usr/local + $ sudo ln -s sqream-db-v<2020.2> sqream + +6. Verify that the symbolic link that you created points to the folder that you created: + + .. code-block:: console + + $ ls -l + +7. Verify that the symbolic link that you created points to the folder that you created: + + .. code-block:: console + + $ sqream -> sqream-db-v<2020.2> + +8. Create the SQream configuration file destination folders and set their ownership to **sqream**: + + .. code-block:: console + + $ sudo mkdir /etc/sqream + $ sudo chown -R sqream:sqream /etc/sqream + +9. Create the SQream service log destination folders and set their ownership to **sqream**: + + .. code-block:: console + + $ sudo mkdir /var/log/sqream + $ sudo chown -R sqream:sqream /var/log/sqream + +10. Navigate to the **/usr/local/** directory and copy the SQream configuration files from them: + + .. code-block:: console + + $ cd /usr/local/sqream/etc/ + $ cp * /etc/sqream + +The configuration files are **service configuration files**, and the JSON files are **SQream configuration files**, for a total of four files. The number of SQream configuration files and JSON files must be identical. + +**NOTICE** - Verify that the JSON files have been configured correctly and that all required flags have been set to the correct values. + +In each JSON file, the following parameters **must be updated**: + +* instanceId +* machineIP +* metadataServerIp +* spoolMemoryGB +* limitQueryMemoryGB +* gpu +* port +* ssl_port + +Note the following: + +* The value of the **metadataServerIp** parameter must point to the IP that the metadata is running on. +* The value of the **machineIP** parameter must point to the IP of your local machine. + +It would be same on server running metadataserver and different on other server nodes. + +11. **Optional** - To run additional SQream services, copy the required configuration files and create additional JSON files: + + .. code-block:: console + + $ cp sqream2_config.json sqream3_config.json + $ vim sqream3_config.json + +**NOTICE:** A unique **instanceID** must be used in each JSON file. IN the example above, the instanceID **sqream_2** is changed to **sqream_3**. + +12. **Optional** - If you created additional services in **Step 11**, verify that you have also created their additional configuration files: + + .. code-block:: console + + $ cp sqream2-service.conf sqream3-service.conf + $ vim sqream3-service.conf + +13. For each SQream service configuration file, do the following: + + 1. Change the **SERVICE_NAME=sqream2** value to **SERVICE_NAME=sqream3**. + + 2. Change **LOGFILE=/var/log/sqream/sqream2.log** to **LOGFILE=/var/log/sqream/sqream3.log**. + +**NOTE:** If you are running SQream on more than one server, you must configure the ``serverpicker`` and ``metadatserver`` services to start on only one of the servers. If **metadataserver** is running on the first server, the ``metadataServerIP`` value in the second server's /etc/sqream/sqream1_config.json file must point to the IP of the server on which the ``metadataserver`` service is running. + +14. Set up **servicepicker**: + + 1. Do the following: + + .. code-block:: console + + $ vim /etc/sqream/server_picker.conf + + 2. Change the IP **127.0.0.1** to the IP of the server that the **metadataserver** service is running on. + + 3. Change the **CLUSTER** to the value of the cluster path. + +15. Set up your service files: + + .. code-block:: console + + $ cd /usr/local/sqream/service/ + $ cp sqream2.service sqream3.service + $ vim sqream3.service + +16. Increment each **EnvironmentFile=/etc/sqream/sqream2-service.conf** configuration file for each SQream service file, as shown below: + + .. code-block:: console + + $ EnvironmentFile=/etc/sqream/sqream<3>-service.conf + +17. Copy and register your service files into systemd: + + .. code-block:: console + + $ sudo cp metadataserver.service /usr/lib/systemd/system/ + $ sudo cp serverpicker.service /usr/lib/systemd/system/ + $ sudo cp sqream*.service /usr/lib/systemd/system/ + +18. Verify that your service files have been copied into systemd: + + .. code-block:: console + + $ ls -l /usr/lib/systemd/system/sqream* + $ ls -l /usr/lib/systemd/system/metadataserver.service + $ ls -l /usr/lib/systemd/system/serverpicker.service + $ sudo systemctl daemon-reload + +19. Copy the license into the **/etc/license** directory: + + .. code-block:: console + + $ cp license.enc /etc/sqream/ + + +If you have an HDFS environment, see :ref:`Configuring an HDFS Environment for the User sqream `. + + + + + + +Upgrading SQream Version +------------------------- +Upgrading your SQream version requires stopping all running services while you manually upgrade SQream. + +**To upgrade your version of SQream:** + +1. Stop all actively running SQream services. + +**Notice-** All SQream services must remain stopped while the upgrade is in process. Ensuring that SQream services remain stopped depends on the tool being used. + +For an example of stopping actively running SQream services, see :ref:`Launching SQream with Monit `. + + + +2. Verify that SQream has stopped listening on ports **500X**, **510X**, and **310X**: + + .. code-block:: console + + $ sudo netstat -nltp #to make sure sqream stopped listening on 500X, 510X and 310X ports. + +3. Replace the old version ``sqream-db-v2020.2``, with the new version ``sqream-db-v2021.1``: + + .. code-block:: console + + $ cd /home/sqream + $ mkdir tempfolder + $ mv sqream-db-v2021.1.tar.gz tempfolder/ + $ tar -xf sqream-db-v2021.1.tar.gz + $ sudo mv sqream /usr/local/sqream-db-v2021.1 + $ cd /usr/local + $ sudo chown -R sqream:sqream sqream-db-v2021.1 + +4. Remove the symbolic link: + + .. code-block:: console + + $ sudo rm sqream + +5. Create a new symbolic link named "sqream" pointing to the new version: + + .. code-block:: console + + $ sudo ln -s sqream-db-v2021.1 sqream + +6. Verify that the symbolic SQream link points to the real folder: + + .. code-block:: console + + $ ls -l + + The following is an example of the correct output: + + .. code-block:: console + + $ sqream -> sqream-db-v2021.1 + +7. **Optional-** (for major versions) Upgrade your version of SQream storage cluster, as shown in the following example: + + .. code-block:: console + + $ cat /etc/sqream/sqream1_config.json |grep cluster + $ ./upgrade_storage + + The following is an example of the correct output: + + .. code-block:: console + + get_leveldb_version path{} + current storage version 23 + upgrade_v24 + upgrade_storage to 24 + upgrade_storage to 24 - Done + upgrade_v25 + upgrade_storage to 25 + upgrade_storage to 25 - Done + upgrade_v26 + upgrade_storage to 26 + upgrade_storage to 26 - Done + validate_leveldb + ... + upgrade_v37 + upgrade_storage to 37 + upgrade_storage to 37 - Done + validate_leveldb + storage has been upgraded successfully to version 37 + +8. Verify that the latest version has been installed: + + .. code-block:: console + + $ ./sqream sql --username sqream --password sqream --host localhost --databasename master -c "SELECT SHOW_VERSION();" + + The following is an example of the correct output: + + .. code-block:: console + + v2021.1 + 1 row + time: 0.050603s + +For more information, see the `upgrade_storage `_ command line program. + From 9529dd3bd15569d7c03c1bea53d42c38c2ccf427 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 14:09:13 +0200 Subject: [PATCH 100/300] Create installing_sqream_with_kubernetes.rst Created installing_sqream_with_kubernetes.rst. --- .../installing_sqream_with_kubernetes.rst | 1805 +++++++++++++++++ 1 file changed, 1805 insertions(+) create mode 100644 guides/operations/installing_sqream_with_kubernetes.rst diff --git a/guides/operations/installing_sqream_with_kubernetes.rst b/guides/operations/installing_sqream_with_kubernetes.rst new file mode 100644 index 000000000..0269b1204 --- /dev/null +++ b/guides/operations/installing_sqream_with_kubernetes.rst @@ -0,0 +1,1805 @@ +.. _installing_sqream_with_kubernetes: + +********************************************* +Installing SQream with Kubernetes +********************************************* +**Kubernetes**, also known as **k8s**, is a portable open source platform that automates Linux container operations. Kubernetes supports outsourcing data centers to public cloud service providers or can be scaled for web hosting. SQream uses Kubernetes as an orchestration and recovery solution. + +The **Installing SQream with Kubernetes** guide describes the following: + +.. contents:: + :local: + :depth: 1 + +.. _preparing_sqream_environment: + +Preparing the SQream Environment to Launch SQream Using Kubernetes +=============== + +The **Preparing the SQream environment to Launch SQream Using Kubernetes** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +-------------- + +A minimum of three servers is required for preparing the SQream environment using Kubernetes. + +Kubernetes uses clusters, which are sets of nodes running containterized applications. A cluster consists of at least two GPU nodes and one additional server without GPU to act as the quorum manager. + +Each server must have the following IP addresses: + +* An IP address located in the management network. +* An additional IP address from the same subnet to function as a floating IP. + +All servers must be mounted in the same shared storage folder. + +The following list shows the server host name format requirements: + +* A maximum of 253 characters. +* Only lowercase alphanumeric characters, such as ``-`` or ``.``. +* Starts and ends with alphanumeric characters. + +Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes` + + +Operating System Requirements +------------------------------ +The required operating system is a version of x86 CentOS/RHEL between 7.6 and 7.9. Regarding PPC64le, the required version is RHEL 7.6. + +Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes` + + +Compute Server Specifications +------------------------------ +Installing SQream with Kubernetes includes the following compute server specifications: + +* **CPU:** 4 cores +* **RAM:** 16GB +* **HD:** 500GB + +Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes` + +.. _set_up_your_hosts: + +Setting Up Your Hosts +=============================== +SQream requires you to set up your hosts. Setting up your hosts requires the following: + +.. contents:: + :local: + :depth: 1 + +Configuring the Hosts File +-------------------------------- +**To configure the /etc/hosts file:** + +1. Edit the **/etc/hosts** file: + + .. code-block:: console + + $ sudo vim /etc/hosts + +2. Call your local host: + + .. code-block:: console + + $ 127.0.0.1 localhost + $ + + +Installing the Required Packages +---------------------------------- +The first step in setting up your hosts is to install the required packages. + +**To install the required packages:** + +1. Run the following command based on your operating system: + + * RHEL: + + .. code-block:: postgres + + $ sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + + * CentOS: + + .. code-block:: postgres + + $ sudo yum install epel-release + $ sudo yum install pciutils openssl-devel python36 python36-pip kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc jq net-tools ntp + +2. Verify that that the required packages were successfully installed. The following is the correct output: + + .. code-block:: postgres + + ntpq --version + jq --version + python3 --version + pip3 --version + rpm -qa |grep kernel-devel-$(uname -r) + rpm -qa |grep kernel-headers-$(uname -r) + gcc --version + +3. Enable the **ntpd (Network Time Protocol daemon)** program on all servers: + + .. code-block:: postgres + + $ sudo systemctl start ntpd + $ sudo systemctl enable ntpd + $ sudo systemctl status ntpd + $ sudo ntpq -p + +Go back to :ref:`Setting Up Your Hosts` + + +Disabling the Linux UI +---------------------------------- +After installing the required packages, you must disable the Linux UI if it has been installed. + +You can disable Linux by running the following command: + + .. code-block:: postgres + + $ sudo systemctl set-default multi-user.target + +Go back to :ref:`Setting Up Your Hosts` + + +Disabling SELinux +---------------------------------- +After disabling the Linux UI you must disable SELinux. + +**To disable SELinux:** + + 1. Run the following command: + + .. code-block:: postgres + + $ sed -i -e s/enforcing/disabled/g /etc/selinux/config + $ sudo reboot + + 2. Reboot the system as a root user: + + .. code-block:: postgres + + $ sudo reboot + +Go back to :ref:`Setting Up Your Hosts` + +Disabling Your Firewall +---------------------------------- +After disabling SELinux, you must disable your firewall by running the following commands: + + .. code-block:: postgres + + $ sudo systemctl stop firewalld + $ sudo systemctl disable firewalld + +Go back to :ref:`Setting Up Your Hosts` + + +Checking the CUDA Version +---------------------------------- +After completing all of the steps above, you must check the CUDA version. + +**To check the CUDA version:** + +1. Check the CUDA version: + + .. code-block:: postgres + + $ nvidia-smi + + The following is an example of the correct output: + + .. code-block:: postgres + + $ +-----------------------------------------------------------------------------+ + $ | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + $ |-------------------------------+----------------------+----------------------+ + $ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + $ | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + $ |===============================+======================+======================| + $ | 0 GeForce GTX 105... Off | 00000000:01:00.0 Off | N/A | + $ | 32% 38C P0 N/A / 75W | 0MiB / 4039MiB | 0% Default | + $ +-------------------------------+----------------------+----------------------+ + $ + $ +-----------------------------------------------------------------------------+ + $ | Processes: GPU Memory | + $ | GPU PID Type Process name Usage | + $ |=============================================================================| + $ | No running processes found | + $ +-----------------------------------------------------------------------------+ + +In the above output, the CUDA version is **10.1**. + +If the above output is not generated, CUDA has not been installed. To install CUDA, see `Installing the CUDA driver `_. + + +Go back to :ref:`Setting Up Your Hosts` + +.. _install_kubernetes_cluster: + +Installing Your Kubernetes Cluster +=================================== +After setting up your hosts, you must install your Kubernetes cluster. The Kubernetes and SQream software must be installed from the management host, and can be installed on any server in the cluster. + +Installing your Kubernetes cluster requires the following: + +.. contents:: + :local: + :depth: 1 + +Generating and Sharing SSH Keypairs Across All Existing Nodes +------------------------------------ +You can generate and share SSH keypairs across all existing nodes. Sharing SSH keypairs across all nodes enables passwordless access from the management server to all nodes in the cluster. All nodes in the cluster require passwordless access. + +.. note:: You must generate and share an SSH keypair across all nodes even if you are installing the Kubernetes cluster on a single host. + +**To generate and share an SSH keypair:** + +1. Switch to root user access: + + .. code-block:: postgres + + $ sudo su - + +2. Generate an RSA key pair: + + .. code-block:: postgres + + $ ssh-keygen + +The following is an example of the correct output: + + .. code-block:: postgres + + $ ssh-keygen + $ Generating public/private rsa key pair. + $ Enter file in which to save the key (/root/.ssh/id_rsa): + $ Created directory '/root/.ssh'. + $ Enter passphrase (empty for no passphrase): + $ Enter same passphrase again: + $ Your identification has been saved in /root/.ssh/id_rsa. + $ Your public key has been saved in /root/.ssh/id_rsa.pub. + $ The key fingerprint is: + $ SHA256:xxxxxxxxxxxxxxdsdsdffggtt66gfgfg root@localhost.localdomain + $ The key's randomart image is: + $ +---[RSA 2048]----+ + $ | =*. | + $ | .o | + $ | ..o o| + $ | . .oo +.| + $ | = S =...o o| + $ | B + *..o+.| + $ | o * *..o .+| + $ | o * oo.E.o| + $ | . ..+..B.+o| + $ +----[SHA256]-----+ + +The generated file is ``/root/.ssh/id_rsa.pub``. + +3. Copy the public key to all servers in the cluster, including the one that you are running on. + + .. code-block:: postgres + + $ ssh-copy-id -i ~/.ssh/id_rsa.pub root@remote-host + +4. Replace the ``remote host`` with your host IP address. + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Installing and Deploying a Kubernetes Cluster Using Kubespray +------------------------------------ +SQream uses the Kubespray software package to install and deploy Kubernetes clusters. + +**To install and deploy a Kubernetes cluster using Kubespray:** + + +1. Clone Kubernetes: + + 1. Clone the **kubespray.git** repository: + + .. code-block:: postgres + + $ git clone https://github.com/kubernetes-incubator/kubespray.git + + 2. Nagivate to the **kubespray** directory: + + .. code-block:: postgres + + $ cd kubespray + + 3. Install the **requirements.txt** configuration file: + + .. code-block:: postgres + + $ pip3 install -r requirements.txt + +2. Create your SQream inventory directory: + + 1. Run the following command: + + .. code-block:: postgres + + $ cp -rp inventory/sample inventory/sqream + + 2. Replace the **** with the defined cluster node IP address(es). + + .. code-block:: postgres + + $ declare -a IPS=(, ) + + For example, the following replaces ``192.168.0.93`` with ``192.168.0.92``: + + .. code-block:: postgres + + $ declare -a IPS=(host-93,192.168.0.93 host-92,192.168.0.92) + +Note the following: + * Running a declare requires defining a pair (host name and cluster node IP address), as shown in the above example. + * You can define more than one pair. + +3. When the reboot is complete, switch back to the root user: + + .. code-block:: postgres + + $ sudo su - + +4. Navigate to **root/kubespray**: + + .. code-block:: postgres + + $ cd /root/kubespray + +5. Copy ``inventory/sample`` as ``inventory/sqream``: + + .. code-block:: postgres + + $ cp -rfp inventory/sample inventory/sqream + +6. Update the Ansible inventory file with the inventory builder: + + .. code-block:: postgres + + $ declare -a IPS=(, , ,) + +7. In the **kubespray hosts.yml** file, set the node IP's: + + .. code-block:: postgres + + $ CONFIG_FILE=inventory/sqream/hosts.yml python3 contrib/inventory_builder/inventory.py ${IPS[@]} + + If you do not set a specific hostname in declare, the server hostnames will change to ``node1``, ``node2``, etc. To maintain specific hostnames, run declare as in the following example: + + .. code-block:: postgres + + $ declare -a IPS=(eks-rhl-1,192.168.5.81 eks-rhl-2,192.168.5.82 eks-rhl-3,192.168.5.83) + + Note that the declare must contain pairs (hostname,ip). + +:: + +8. Verify that the following have been done: + + * That the **hosts.yml** file is configured correctly. + * That all children are included with their relevant nodes. + +You can save your current server hostname by replacing with your server hostname. + +9. Generate the content output of the **hosts.yml** file. Make sure to include the file's directory: + + .. code-block:: postgres + + $ cat inventory/sqream/hosts.yml + +The hostname can be lowercase and contain ``-`` or ``.`` only, and must be aligned with the server's hostname. + +The following is an example of the correct output. Each host and IP address that you provided in Step 2 should be displayed once: + + .. code-block:: postgres + + $ all: + $ hosts: + $ node1: + $ ansible_host: 192.168.5.81 + $ ip: 192.168.5.81 + $ access_ip: 192.168.5.81 + $ node2: + $ ansible_host: 192.168.5.82 + $ ip: 192.168.5.82 + $ access_ip: 192.168.5.82 + $ node3: + $ ansible_host: 192.168.5.83 + $ ip: 192.168.5.83 + $ access_ip: 192.168.5.83 + $ children: + $ kube-master: + $ hosts: + $ node1: + $ node2: + $ node3: + $ kube-node: + $ hosts: + $ node1: + $ node2: + $ node3: + $ etcd: + $ hosts: + $ node1: + $ node2: + $ node3: + $ k8s-cluster: + $ children: + $ kube-master: + $ kube-node: + $ calico-rr: + $ hosts: {} + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Adjusting Kubespray Deployment Values +------------------------------------- +After downloading and configuring Kubespray, you can adjust your Kubespray deployment values. A script is used to modify how the Kubernetes cluster is deployed, and you must set the cluster name variable before running this script. + +.. note:: The script must be run from the **kubespray** folder. + +**To adjust Kubespray deployment values:** + +1. Add the following export to the local user’s **~/.bashrc** file by replacing the with the user's Virtual IP address: + + .. code-block:: postgres + + $ export VIP_IP= + +2. Logout, log back in, and verify the following: + + .. code-block:: postgres + + $ echo $VIP_IP + +3. Make the following replacements to the **kubespray.settings.sh** file: + + .. code-block:: postgres + + $ cat < kubespray_settings.sh + $ sed -i "/cluster_name: cluster.local/c \cluster_name: cluster.local.$cluster_name" inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ sed -i "/dashboard_enabled/c \dashboard_enabled\: "false"" inventory/sqream/group_vars/k8s-cluster/addons.yml + $ sed -i "/kube_version/c \kube_version\: "v1.18.3"" inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ sed -i "/metrics_server_enabled/c \metrics_server_enabled\: "true"" inventory/sample/group_vars/k8s-cluster/addons.yml + $ echo 'kube_apiserver_node_port_range: "3000-6000"' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'kube_controller_node_monitor_grace_period: 20s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'kube_controller_node_monitor_period: 2s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'kube_controller_pod_eviction_timeout: 30s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'kubelet_status_update_frequency: 4s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'ansible ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers + $ EOF + +.. note:: In most cases, the Docker data resides on the system disk. Because Docker requires a high volume of data (images, containers, volumes, etc.), you can change the default Docker data location to prevent the system disk from running out of space. + +4. *Optional* - Change the default Docker data location: + + .. code-block:: postgres + + $ sed -i "/docker_daemon_graph/c \docker_daemon_graph\: """ inventory/sqream/group_vars/all/docker.yml + +5. Make the **kubespray_settings.sh** file executable for your user: + + .. code-block:: postgres + + $ chmod u+x kubespray_settings.sh && ./kubespray_settings.sh + +6. Run the following script: + + .. code-block:: postgres + + $ ./kubespray_settings.sh + +7. Run a playbook on the **inventory/sqream/hosts.yml cluster.yml** file: + + .. code-block:: postgres + + $ ansible-playbook -i inventory/sqream/hosts.yml cluster.yml -v + +The Kubespray installation takes approximately 10 - 15 minutes. + +The following is an example of the correct output: + + .. code-block:: postgres + + $ PLAY RECAP + $ ********************************************************************************************* + $ node-1             : ok=680  changed=133  unreachable=0    failed=0 + $ node-2             : ok=583  changed=113  unreachable=0    failed=0 + $ node-3             : ok=586  changed=115  unreachable=0    failed=0 + $ localhost          : ok=1    changed=0    unreachable=0    failed=0 + +In the event that the output is incorrect, or a failure occurred during the installation, please contact a SQream customer support representative. + +Go back to :ref:`Installing Your Kubernetes Cluster`. + +Checking Your Kubernetes Status +------------------------------- +After adjusting your Kubespray deployment values, you must check your Kubernetes status. + +**To check your Kuberetes status:** + +1. Check the status of the node: + + .. code-block:: postgres + + $ kubectl get nodes + +The following is an example of the correct output: + + .. code-block:: postgres + + $ NAME STATUS ROLES AGE VERSION + $ eks-rhl-1 Ready control-plane,master 29m v1.21.1 + $ eks-rhl-2 Ready control-plane,master 29m v1.21.1 + $ eks-rhl-3 Ready 28m v1.21.1 + +2. Check the status of the pod: + + .. code-block:: postgres + + $ kubectl get pods --all-namespaces + + The following is an example of the correct output: + + .. code-block:: postgres + + $ NAMESPACE NAME READY STATUS RESTARTS AGE + $ kube-system calico-kube-controllers-68dc8bf4d5-n9pbp 1/1 Running 0 160m + $ kube-system calico-node-26cn9 1/1 Running 1 160m + $ kube-system calico-node-kjsgw 1/1 Running 1 160m + $ kube-system calico-node-vqvc5 1/1 Running 1 160m + $ kube-system coredns-58687784f9-54xsp 1/1 Running 0 160m + $ kube-system coredns-58687784f9-g94xb 1/1 Running 0 159m + $ kube-system dns-autoscaler-79599df498-hlw8k 1/1 Running 0 159m + $ kube-system kube-apiserver-k8s-host-1-134 1/1 Running 0 162m + $ kube-system kube-apiserver-k8s-host-194 1/1 Running 0 161m + $ kube-system kube-apiserver-k8s-host-68 1/1 Running 0 161m + $ kube-system kube-controller-manager-k8s-host-1-134 1/1 Running 0 162m + $ kube-system kube-controller-manager-k8s-host-194 1/1 Running 0 161m + $ kube-system kube-controller-manager-k8s-host-68 1/1 Running 0 161m + $ kube-system kube-proxy-5f42q 1/1 Running 0 161m + $ kube-system kube-proxy-bbwvk 1/1 Running 0 161m + $ kube-system kube-proxy-fgcfb 1/1 Running 0 161m + $ kube-system kube-scheduler-k8s-host-1-134 1/1 Running 0 161m + $ kube-system kube-scheduler-k8s-host-194 1/1 Running 0 161m + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Adding a SQream Label to Your Kubernetes Cluster Nodes +------------------------------------------------- +After checking your Kubernetes status, you must add a SQream label on your Kubernetes cluster nodes. + +**To add a SQream label on your Kubernetes cluster nodes:** + +1. Get the cluster node list: + + .. code-block:: postgres + + $ kubectl get nodes + + The following is an example of the correct output: + + .. code-block:: postgres + + $ NAME        STATUS   ROLES    AGE   VERSION + $ eks-rhl-1 Ready control-plane,master 29m v1.21.1 + $ eks-rhl-2 Ready control-plane,master 29m v1.21.1 + $ eks-rhl-3 Ready 28m v1.21.1 + +2. Set the node label, change the ``node-name`` to the node NAME(s) in the above example: + + .. code-block:: postgres + + $ kubectl label nodes cluster=sqream + + The following is an example of the correct output: + + .. code-block:: postgres + + $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-1 cluster=sqream + $ node/eks-rhl-1 labeled + $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-2 cluster=sqream + $ node/eks-rhl-2 labeled + $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-3 cluster=sqream + $ node/eks-rhl-3 labeled + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Copying Your Kubernetes Configuration API File to the Master Cluster Nodes +------------------------------------------------- +After adding a SQream label on your Kubernetes cluster nodes, you must copy your Kubernetes configuration API file to your Master cluster nodes. + +When the Kubernetes cluster installation is complete, an API configuration file is automatically created in the **.kube** folder of the root user. This file enables the **kubectl** command access Kubernetes' internal API service. Following this step lets you run **kubectl** commands from any node in the cluster. + + +.. warning:: You must perform this on the management server only! + +**To copy your Kubernetes configuration API file to your Master cluster nodes:** + +1. Create the **.kube** folder in the **local user** directory: + + .. code-block:: postgres + + $ mkdir /home//.kube + +2. Copy the configuration file from the root user directory to the directory: + + .. code-block:: postgres + + $ sudo cp /root/.kube/config /home//.kube + +3. Change the file owner from **root user** to the : + + .. code-block:: postgres + + $ sudo chown . /home//.kube/config + +4. Create the **.kube** folder in the other nodes located in the directory: + + .. code-block:: postgres + + $ ssh @ mkdir .kube + +5. Copy the configuration file from the management node to the other nodes: + + .. code-block:: postgres + + $ scp /home//.kube/config @:/home//.kube/ + +6. Under local user on each server you copied **.kube** to, run the following command: + + .. code-block:: postgres + + $ sudo usermod -aG docker $USER + +This grants the local user the necessary permissions to run Docker commands. + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Creating an env_file in Your Home Directory +------------------------------------------------- +After copying your Kubernetes configuration API file to your Master cluster nodes, you must create an **env_file** in your home directory, and must set the VIP address as a variable. + +.. warning:: You must perform this on the management server only! + + + +**To create an env_file for local users in the user's home directory:** + +1. Set a variable that includes the VIP IP address: + + .. code-block:: postgres + + $ export VIP_IP= + +.. note:: If you use Kerberos, replace the ``KRB5_SERVER`` value with the IP address of your Kerberos server. + +2. Do one of the following: + + * For local users: + + .. code-block:: postgres + + $ mkdir /home/$USER/.sqream + +3. Make the following replacements to the **kubespray.settings.sh** file, verifying that the ``KRB5_SERVER`` parameter is set to your server IP: + + + .. code-block:: postgres + + $ cat < /home/$USER/.sqream/env_file + SQREAM_K8S_VIP=$VIP_IP + SQREAM_ADMIN_UI_PORT=8080 + SQREAM_DASHBOARD_DATA_COLLECTOR_PORT=8100 + SQREAM_DATABASE_NAME=master + SQREAM_K8S_ADMIN_UI=sqream-admin-ui + SQREAM_K8S_DASHBOARD_DATA_COLLECTOR=dashboard-data-collector + SQREAM_K8S_METADATA=sqream-metadata + SQREAM_K8S_NAMESPACE=sqream + SQREAM_K8S_PICKER=sqream-picker + SQREAM_K8S_PROMETHEUS=prometheus + SQREAM_K8S_REGISTRY_PORT=6000 + SQREAM_METADATA_PORT=3105 + SQREAM_PICKER_PORT=3108 + SQREAM_PROMETHEUS_PORT=9090 + SQREAM_SPOOL_MEMORY_RATIO=0.25 + SQREAM_WORKER_0_PORT=5000 + KRB5CCNAME=FILE:/tmp/tgt + KRB5_SERVER=kdc.sq.com:1 + KRB5_CONFIG_DIR=${ $ SQREAM_MOUNT_DIR}/krb5 + KRB5_CONFIG_FILE=${KRB5_CONFIG_DIR}/krb5.conf + HADOOP_CONFIG_DIR=${ $ SQREAM_MOUNT_DIR}/hadoop + HADOOP_CORE_XML=${HADOOP_CONFIG_DIR}/core-site.xml + HADOOP_HDFS_XML=${HADOOP_CONFIG_DIR}/hdfs-site.xml + EOF + +Go back to :ref:`Installing Your Kubernetes Cluster` + + + + + +Creating a Base Kubernetes Namespace +------------------------------------ +After creating an env_file in the user's home directory, you must create a base Kubernetes namespace. + +You can create a Kubernetes namespace by running the following command: + +.. code-block:: postgres + + $ kubectl create namespace sqream-init + +The following is an example of the correct output: + +.. code-block:: postgres + + $ namespace/sqream-init created + +Go back to :ref:`Installing Your Kubernetes Cluster` + + +Pushing the **env_file** File to the Kubernetes Configmap +-------------------------------------- +After creating a base Kubernetes namespace, you must push the **env_file** to the Kubernetes configmap. You must push the **env_file** file to the Kubernetes **configmap** in the **sqream-init** namespace. + +This is done by running the following command: + +.. code-block:: postgres + + $ kubectl create configmap sqream-init -n sqream-init --from-env-file=/home/$USER/.sqream/env_file + +The following is an example of the correct output: + +.. code-block:: postgres + + $ configmap/sqream-init created + + +Go back to :ref:`Installing Your Kubernetes Cluster` + + +Installing the NVIDIA Docker2 Toolkit +------------------------------------- +After pushing the **env_file** file to the Kubernetes configmap, you must install the NVIDIA Docker2 Toolkit. The **NVIDIA Docker2 Toolkit** lets users build and run GPU-accelerated Docker containers, and must be run only on GPU servers. The NVIDIA Docker2 Toolkit includes a container runtime library and utilities that automatically configure containers to leverage NVIDIA GPUs. + + +Installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on CentOS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +**To install the NVIDIA Docker2 Toolkit on an x86_64 bit processor on CentOS:** + +1. Add the repository for your distribution: + + .. code-block:: postgres + + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ + $ sudo tee /etc/yum.repos.d/nvidia-docker.repo + +2. Install the **nvidia-docker2** package and reload the Docker daemon configuration: + + .. code-block:: postgres + + $ sudo yum install nvidia-docker2 + $ sudo pkill -SIGHUP dockerd + +3. Verify that the **nvidia-docker2** package has been installed correctly: + + .. code-block:: postgres + + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + + The following is an example of the correct output: + + .. code-block:: postgres + + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + $ Unable to find image 'nvidia/cuda:10.1-base' locally + $ 10.1-base: Pulling from nvidia/cuda + $ d519e2592276: Pull complete + $ d22d2dfcfa9c: Pull complete + $ b3afe92c540b: Pull complete + $ 13a10df09dc1: Pull complete + $ 4f0bc36a7e1d: Pull complete + $ cd710321007d: Pull complete + $ Digest: sha256:635629544b2a2be3781246fdddc55cc1a7d8b352e2ef205ba6122b8404a52123 + $ Status: Downloaded newer image for nvidia/cuda:10.1-base + $ Sun Feb 14 13:27:58 2021 + $ +-----------------------------------------------------------------------------+ + $ | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + $ |-------------------------------+----------------------+----------------------+ + $ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + $ | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + $ |===============================+======================+======================| + $ | 0 GeForce GTX 105... Off | 00000000:01:00.0 Off | N/A | + $ | 32% 37C P0 N/A / 75W | 0MiB / 4039MiB | 0% Default | + $ +-------------------------------+----------------------+----------------------+ + $ + $ +-----------------------------------------------------------------------------+ + $ | Processes: GPU Memory | + $ | GPU PID Type Process name Usage | + $ |=============================================================================| + $ | No running processes found | + $ +-----------------------------------------------------------------------------+ + +For more information on installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on CentOS, see `NVIDIA Docker Installation - CentOS distributions `_ + +Installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on Ubuntu +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +**To install the NVIDIA Docker2 Toolkit on an x86_64 bit processor on Ubuntu:** + +1. Add the repository for your distribution: + + .. code-block:: postgres + + $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \ + $ sudo apt-key add - + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \ + $ sudo tee /etc/apt/sources.list.d/nvidia-docker.list + $ sudo apt-get update + +2. Install the **nvidia-docker2** package and reload the Docker daemon configuration: + + .. code-block:: postgres + + $ sudo apt-get install nvidia-docker2 + $ sudo pkill -SIGHUP dockerd + +3. Verify that the nvidia-docker2 package has been installed correctly: + + .. code-block:: postgres + + $ docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi + +For more information on installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on Ubuntu, see `NVIDIA Docker Installation - Ubuntu distributions `_ + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Modifying the Docker Daemon JSON File for GPU and Compute Nodes +------------------------------------- +After installing the NVIDIA Docker2 toolkit, you must modify the Docker daemon JSON file for GPU and Compute nodes. + +Modifying the Docker Daemon JSON File for GPU Nodes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**To modify the Docker daemon JSON file for GPU nodes:** + +1. Enable GPU and set HTTP access to the local Kubernetes Docker registry. + +.. note:: The Docker daemon JSON file must be modified on all GPU nodes. + +.. note:: Contact your IT department for a virtual IP. + +2. Replace the ``VIP address`` with your assigned VIP address. + +:: + +3. Connect as a root user: + + .. code-block:: postgres + + $ sudo -i + +4. Set a variable that includes the VIP address: + + .. code-block:: postgres + + $ export VIP_IP= + +5. Replace the with the VIP address:  + + .. code-block:: postgres + + $ cat < /etc/docker/daemon.json + $ { + $ "insecure-registries": ["$VIP_IP:6000"], + $ "default-runtime": "nvidia", + $ "runtimes": { + $ "nvidia": { + $ "path": "nvidia-container-runtime", + $ "runtimeArgs": [] + $ } + $ } + $ } + $ EOF + +6. Apply the changes and restart Docker: + + .. code-block:: postgres + + $ systemctl daemon-reload && systemctl restart docker + +7. Exit the root user: + + .. code-block:: postgres + + $ exit + +Go back to :ref:`Installing Your Kubernetes Cluster` + + +Modifying the Docker Daemon JSON File for Compute Nodes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You must follow this procedure only if you have a Compute node. + +**To modify the Docker daemon JSON file for Compute nodes:** + +1. Switch to a root user: + + .. code-block:: postgres + + $ sudo -i + +2. Set a variable that includes a VIP address. + +.. note:: Contact your IT department for a virtual IP. + +3. Replace the ``VIP address`` with your assigned VIP address. + + .. code-block:: postgres + + $ cat < /etc/docker/daemon.json + $ { + $ "insecure-registries": ["$VIP_IP:6000"] + $ } + $ EOF + +4. Restart the services: + + .. code-block:: postgres + + $ systemctl daemon-reload && systemctl restart docker + +5. Exit the root user: + + + .. code-block:: postgres + + $ exit + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Installing the Nvidia-device-plugin Daemonset +---------------------------------------------- +After modifying the Docker daemon JSON file for GPU or Compute Nodes, you must installing the Nvidia-device-plugin daemonset. The Nvidia-device-plugin daemonset is only relevant to GPU nodes. + +**To install the Nvidia-device-plugin daemonset:** + +1. Set ``nvidia.com/gpu`` to ``true`` on all GPU nodes: + +.. code-block:: postgres + + $ kubectl label nodes nvidia.com/gpu=true + +2. Replace the ** with your GPU node name: + + For a complete list of GPU node names, run the ``kubectl get nodes`` command. + + The following is an example of the correct output: + + .. code-block:: postgres + + $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-1 nvidia.com/gpu=true + $ node/eks-rhl-1 labeled + $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-2 nvidia.com/gpu=true + $ node/eks-rhl-2 labeled + $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-3 nvidia.com/gpu=true + $ node/eks-rhl-3 labeled + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Creating an Nvidia Device Plugin +---------------------------------------------- +After installing the Nvidia-device-plugin daemonset, you must create an Nvidia-device-plugin. You can create an Nvidia-device-plugin by running the following command + +.. code-block:: postgres + + $ kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/1.0.0-beta6/nvidia-device-plugin.yml + +If needed, you can check the status of the Nvidia-device-plugin-daemonset pod status: + +.. code-block:: postgres + + $ kubectl get pods -n kube-system -o wide | grep nvidia-device-plugin + +The following is an example of the correct output: + +.. code-block:: postgres + + $ NAME READY STATUS RESTARTS AGE + $ nvidia-device-plugin-daemonset-fxfct 1/1 Running 0 6h1m + $ nvidia-device-plugin-daemonset-jdvxs 1/1 Running 0 6h1m + $ nvidia-device-plugin-daemonset-xpmsv 1/1 Running 0 6h1m + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Checking GPU Resources Allocatable to GPU Nodes +------------------------------------- +After creating an Nvidia Device Plugin, you must check the GPU resources alloctable to the GPU nodes. Each GPU node has records, such as ``nvidia.com/gpu: <#>``. The ``#`` indicates the number of allocatable, or available, GPUs in each node. + +You can output a description of allocatable resources by running the following command: + +.. code-block:: postgres + + $ kubectl describe node | grep -i -A 7 -B 2 allocatable: + +The following is an example of the correct output: + +.. code-block:: postgres + + $ Allocatable: + $ cpu: 3800m + $ ephemeral-storage: 94999346224 + $ hugepages-1Gi: 0 + $ hugepages-2Mi: 0 + $ memory: 15605496Ki + $ nvidia.com/gpu: 1 + $ pods: 110 + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Preparing the WatchDog Monitor +------------------------------ +SQream's deployment includes installing two watchdog services. These services monitor Kuberenetes management and the server's storage network. + +You can enable the storage watchdogs by adding entries in the **/etc/hosts** file on each server: + +.. code-block:: postgres + + $
k8s-node1.storage + $
k8s-node2.storage + $
k8s-node3.storage + +The following is an example of the correct syntax: + +.. code-block:: postgres + + $ 10.0.0.1 k8s-node1.storage + $ 10.0.0.2 k8s-node2.storage + $ 10.0.0.3 k8s-node3.storage + +Go back to :ref:`Installing Your Kubernetes Cluster` + +.. _installing_sqream_software: + +Installing the SQream Software +================================= +Once you've prepared the SQream environment for launching it using Kubernetes, you can begin installing the SQream software. + +The **Installing the SQream Software** section describes the following: + +.. contents:: + :local: + :depth: 1 + + +.. _getting_sqream_package: + +Getting the SQream Package +-------------------------------- +The first step in installing the SQream software is getting the SQream package. Please contact the SQream Support team to get the **sqream_k8s-nnn-DBnnn-COnnn-SDnnn-.tar.gz** tarball file. + +This file includes the following values: + +* **sqream_k8s-** - the SQream installer version. +* **DB** - the SQreamDB version. +* **CO** - the SQream console version. +* **SD** - the SQream Acceleration Studio version. +* **arch** - the server architecture. + +You can extract the contents of the tarball by running the following command: + +.. code-block:: postgres + + $ tar -xvf sqream_k8s-1.0.15-DB2020.1.0.2-SD0.7.3-x86_64.tar.gz + $ cd sqream_k8s-1.0.15-DB2020.1.0.2-SD0.7.3-x86_64 + $ ls + +Extracting the contents of the tarball file generates a new folder with the same name as the tarball file. + +The following shows the output of the extracted file: + +.. code-block:: postgres + + drwxrwxr-x. 2 sqream sqream 22 Jan 27 11:39 license + lrwxrwxrwx. 1 sqream sqream 49 Jan 27 11:39 sqream -> .sqream/sqream-sql-v2020.3.1_stable.x86_64/sqream + -rwxrwxr-x. 1 sqream sqream 9465 Jan 27 11:39 sqream-install + -rwxrwxr-x. 1 sqream sqream 12444 Jan 27 11:39 sqream-start + +Go back to :ref:`Installing Your SQream Software` + +Setting Up and Configuring Hadoop +-------------------------------- +After getting the SQream package, you can set up and configure Hadoop by configuring the **keytab** and **krb5.conf** files. + +.. note:: You only need to configure the **keytab** and **krb5.conf** files if you use Hadoop with Kerberos authentication. + + +**To set up and configure Hadoop:** + +1. Contact IT for the **keytab** and **krb5.conf** files. + +:: + +2. Copy both files into the respective empty **.hadoop/** and **.krb5/** directories: + +.. code-block:: postgres + + $ cp hdfs.keytab krb5.conf .krb5/ + $ cp core-site.xml hdfs-site.xml .hadoop/ + +The SQream installer automatically copies the above files during the installation process. + +Go back to :ref:`Installing Your SQream Software` + +Starting a Local Docker Image Registry +-------------------------------- +After getting the SQream package, or (optionally) setting up and configuring Hadoop, you must start a local Docker image registry. Because Kubernetes is based on Docker, you must start the local Docker image registry on the host's shared folder. This allows all hosts to pull the SQream Docker images. + +**To start a local Docker image registry:** + +1. Create a Docker registry folder: + + .. code-block:: postgres + + $ mkdir /docker-registry/ + +2. Set the ``docker_path`` for the Docker registry folder: + + .. code-block:: postgres + + $ export docker_path= + +3. Apply the **docker-registry** service to the cluster: + + .. code-block:: postgres + + $ cat .k8s/admin/docker_registry.yaml | envsubst | kubectl create -f - + + The following is an example of the correct output: + + .. code-block:: postgres + + namespace/sqream-docker-registry created + configmap/sqream-docker-registry-config created + deployment.apps/sqream-docker-registry created + service/sqream-docker-registry created + +4. Check the pod status of the **docker-registry** service: + + .. code-block:: postgres + + $ kubectl get pods -n sqream-docker-registry + +The following is an example of the correct output: + + .. code-block:: postgres + + NAME READY STATUS RESTARTS AGE + sqream-docker-registry-655889fc57-hmg7h 1/1 Running 0 6h40m + +Go back to :ref:`Installing Your SQream Software` + +Installing the Kubernetes Dashboard +-------------------------------- +After starting a local Docker image registry, you must install the Kubernetes dashboard. The Kubernetes dashboard lets you see the Kubernetes cluster, nodes, services, and pod status. + +**To install the Kubernetes dashboard:** + +1. Apply the **k8s-dashboard** service to the cluster: + + .. code-block:: postgres + + $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml + + The following is an example of the correct output: + + .. code-block:: postgres + + namespace/kubernetes-dashboard created + serviceaccount/kubernetes-dashboard created + service/kubernetes-dashboard created + secret/kubernetes-dashboard-certs created + secret/kubernetes-dashboard-csrf created + secret/kubernetes-dashboard-key-holder created + configmap/kubernetes-dashboard-settings created + role.rbac.authorization.k8s.io/kubernetes-dashboard created + clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created + rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created + clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created + deployment.apps/kubernetes-dashboard created + service/dashboard-metrics-scraper created + deployment.apps/dashboard-metrics-scraper created + +2. Grant the user external access to the Kubernetes dashboard: + + .. code-block:: postgres + + $ cat .k8s/admin/kubernetes-dashboard-svc-metallb.yaml | envsubst | kubectl create -f - + + The following is an example of the correct output: + + .. code-block:: postgres + + service/kubernetes-dashboard-nodeport created + +3. Create the ``cluster-admin-sa.yaml`` file: + + .. code-block:: postgres + + $ kubectl create -f .k8s/admin/cluster-admin-sa.yaml + + The following is an example of the correct output: + + .. code-block:: postgres + + clusterrolebinding.rbac.authorization.k8s.io/cluster-admin-sa-cluster-admin created + +4. Check the pod status of the **K8s-dashboard** service: + + .. code-block:: postgres + + $ kubectl get pods -n kubernetes-dashboard + + The following is an example of the correct output: + + .. code-block:: postgres + + NAME READY STATUS RESTARTS AGE + dashboard-metrics-scraper-6b4884c9d5-n8p57 1/1 Running 0 4m32s + kubernetes-dashboard-7b544877d5-qc8b4 1/1 Running 0 4m32s + +5. Obtain the **k8s-dashboard** access token: + + .. code-block:: postgres + + $ kubectl -n kube-system describe secrets cluster-admin-sa-token + + The following is an example of the correct output: + + .. code-block:: postgres + + Name: cluster-admin-sa-token-rbl9p + Namespace: kube-system + Labels: + Annotations: kubernetes.io/service-account.name: cluster-admin-sa + kubernetes.io/service-account.uid: 81866d6d-8ef3-4805-840d-58618235f68d + + Type: kubernetes.io/service-account-token + + Data + ==== + ca.crt: 1025 bytes + namespace: 11 bytes + token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjRMV09qVzFabjhId09oamQzZGFFNmZBeEFzOHp3SlJOZWdtVm5lVTdtSW8ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJjbHVzdGVyLWFkbWluLXNhLXRva2VuLXJibDlwIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImNsdXN0ZXItYWRtaW4tc2EiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI4MTg2NmQ2ZC04ZWYzLTQ4MDUtODQwZC01ODYxODIzNWY2OGQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06Y2x1c3Rlci1hZG1pbi1zYSJ9.mNhp8JMr5y3hQ44QrvRDCMueyjSHSrmqZcoV00ZC7iBzNUqh3n-fB99CvC_GR15ys43jnfsz0tdsTy7VtSc9hm5ENBI-tQ_mwT1Zc7zJrEtgFiA0o_eyfYZOARdhdyFEJg84bzkIxJFPKkBWb4iPWU1Xb7RibuMCjNTarZMZbqzKYfQEcMZWJ5UmfUqp-HahZZR4BNbjSWybs7t6RWdcQZt6sO_rRCDrOeEJlqKKjx4-5jFZB8Du_0kKmnw2YJmmSCEOXrpQCyXIiZJpX08HyDDYfFp8IGzm61arB8HDA9dN_xoWvuz4Cj8klUtTzL9effJJPjHJlZXcEqQc9hE3jw + +6. Navigate to ``https://:5999``. + +:: + +7. Select the **Token** radio button, paste the token from the previous command output, and click **Sign in**. + +The Kubernetes dashboard is displayed. + +Go back to :ref:`Installing Your SQream Software` + +Installing the SQream Prometheus Package +-------------------------------- +After installing the Kubernetes dashboard, you must install the SQream Prometheus package. To properly monitor the host and GPU statistics the **exporter service** must be installed on each Kubernetes cluster node. + +This section describes how to install the following: + +* **node_exporter** - collects host data, such as CPU memory usage. +* **nvidia_exporter** - collects GPU utilization data. + + +.. note:: The steps in this section must be done on **all** cluster nodes. + +To install the **sqream-prometheus** package, you must do the following: + +1. :ref:`Install the exporter service ` + +:: + +2. :ref:`Check the exporter service ` + +Go back to :ref:`Installing Your SQream Software` + + +.. _install_exporter_service: + +Installing the Exporter Service +~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the exporter service:** + +1. Create a user and group that will be used to run the exporter services: + + .. code-block:: console + + $ sudo groupadd --system prometheus && sudo useradd -s /sbin/nologin --system -g prometheus prometheus + +2. Extract the **sqream_exporters_prometheus.0.1.tar.gz** file: + + .. code-block:: console + + $ cd .prometheus + $ tar -xf sqream_exporters_prometheus.0.1.tar.gz + +3. Copy the exporter software files to the **/usr/bin** directory: + + .. code-block:: console + + $ cd sqream_exporters_prometheus.0.1 + $ sudo cp node_exporter/node_exporter /usr/bin/ + $ sudo cp nvidia_exporter/nvidia_exporter /usr/bin/ + +4. Copy the exporters service file to the **/etc/systemd/system/** directory: + + .. code-block:: console + + $ sudo cp services/node_exporter.service /etc/systemd/system/ + $ sudo cp services/nvidia_exporter.service /etc/systemd/system/ + +5. Set the permission and group of the service files: + + .. code-block:: console + + $ sudo chown prometheus:prometheus /usr/bin/node_exporter + $ sudo chmod u+x /usr/bin/node_exporter + $ sudo chown prometheus:prometheus /usr/bin/nvidia_exporter + $ sudo chmod u+x /usr/bin/nvidia_exporter + +6. Reload the services: + + .. code-block:: console + + $ sudo systemctl daemon-reload + +7. Start both services and set them to start when the server is booted up: + + * Node_exporter: + + .. code-block:: console + + $ sudo systemctl start node_exporter && sudo systemctl enable node_exporter + + * Nvidia_exporter: + + .. code-block:: console + + $ sudo systemctl start nvidia_exporter && sudo systemctl enable nvidia_exporter + + + +.. _check_exporter_status: + +Checking the Exporter Status +~~~~~~~~~~~~~~~~~~~~~~~~ +After installing the **exporter** service, you must check its status. + +You can check the exporter status by running the following command: + +.. code-block:: console + + $ sudo systemctl status node_exporter && sudo systemctl status nvidia_exporter + +Go back to :ref:`Installing Your SQream Software` + + +.. _running_sqream_install_service: + +Running the Sqream-install Service +================================ +The **Running the Sqream-install Service** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Installing Your License +-------------------------------- +After install the SQream Prometheus package, you must install your license. + +**To install your license:** + +1. Copy your license package to the sqream **/license** folder. + +.. note:: You do not need to untar the license package after copying it to the **/license** folder because the installer script does it automatically. + +The following flags are **mandatory** during your first run: + +.. code-block:: console + + $ sudo ./sqream-install -i -k -m + +.. note:: If you cannot run the script with **sudo**, verify that you have the right permission (**rwx** for the user) on the relevant directories (config, log, volume, and data-in directories). + +Go back to :ref:`Running the SQream_install Service`. + +Changing Your Data Ingest Folder +-------------------------------- +After installing your license, you must change your data ingest folder. + +You can change your data ingest folder by running the following command: + +.. code-block:: console + + $ sudo ./sqream-install -d /media/nfs/sqream/data_in + +Go back to :ref:`Running the SQream_install Service`. + +Checking Your System Settings +-------------------------------- +After changing your data ingest folder, you must check your system settings. + +The following command shows you all the variables that your SQream system is running with: + +.. code-block:: console + + $ ./sqream-install -s + +After optionally checking your system settings, you can use the **sqream-start** application to control your Kubernetes cluster. + +Go back to :ref:`Running the SQream_install Service`. + +SQream Installation Command Reference +-------------------------------- +If needed, you can use the **sqream-install** flag reference for any needed flags by typing: + +.. code-block:: console + + $ ./sqream-install --help + +The following shows the **sqream--install** flag descriptions: + +.. list-table:: + :widths: 22 59 25 + :header-rows: 1 + + * - Flag + - Function + - Note + * - **-i** + - Loads all the software from the hidden **.docker** folder. + - Mandatory + * - **-k** + - Loads the license package from the **/license** directory. + - Mandatory + * - **-m** + - Sets the relative path for all SQream folders under the shared filesystem available from all nodes (sqreamdb, config, logs and data_in). No other flags are required if you use this flag (such as c, v, l or d). + - Mandatory + * - **-c** + - Sets the path where to write/read SQream configuration files from. The default is **/etc/sqream/**. + - Optional + * - **-v** + - Shows the location of the SQream cluster. ``v`` creates a cluster if none exist, and mounts it if does. + - Optional + * - **-l** + - Shows the location of the SQream system startup logs. The logs contain startup and Docker logs. The default is **/var/log/sqream/**. + - Optional + * - **-d** + - Shows the folder containing data that you want to import into or copy from SQream. + - Optional + * - **-n** + - Sets the Kubernetes namespace. The default is **sqream**. + - Optional + * - **-N** + - Deletes a specific Kubernetes namespace and sets the factory default namespace (sqream). + - Optional + * - **-f** + - Overwrite existing folders and all files located in mounted directories. + - Optional + * - **-r** + - Resets the system configuration. This flag is run without any other variables. + - Optional + * - **-s** + - Shows the system settings. + - Optional + * - **-e** + - Sets the Kubernetes cluster's virtual IP address. + - Optional + * - **-h** + - Help, shows all available flags. + - Optional + +Go back to :ref:`Running the SQream_install Service`. + +Controlling Your Kubernetes Cluster Using SQream Flags +-------------------------------- +You can control your Kubernetes cluster using SQream flags. + +The following command shows you the available Kubernetes cluster control options: + +.. code-block:: console + + $ ./sqream-start -h + +The following describes the **sqream-start** flags: + +.. list-table:: + :widths: 22 59 25 + :header-rows: 1 + + * - Flag + - Function + - Note + * - **-s** + - Starts the sqream services, starting metadata, server picker, and workers. The number of workers started is based on the number of available GPU’s. + - Mandatory + * - **-p** + - Sets specific ports to the workers services. You must enter the starting port for the sqream-start application to allocate it based on the number of workers. + - + * - **-j** + - Uses an external .json configuration file. The file must be located in the **configuration** directory. + - The workers must each be started individually. + * - **-m** + - Allocates worker spool memory. + - The workers must each be started individually. + * - **-a** + - Starts the SQream Administration dashboard and specifies the listening port. + - + * - **-d** + - Deletes all running SQream services. + - + * - **-h** + - Shows all available flags. + - Help + +Go back to :ref:`Running the SQream_install Service`. + +.. _using_sqream_start_commands: + +Using the sqream-start Commands +======================= +In addition to controlling your Kubernetes cluster using SQream flags, you can control it using **sqream-start** commands. + +The **Using the sqream-start Commands** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Starting Your SQream Services +------------------------ +You can run the **sqream-start** command with the **-s** flag to start SQream services on all available GPU's: + +.. code-block:: console + + $ sudo ./sqream-start -s + +This command starts the SQream metadata, server picker, and sqream workers on all available GPU’s in the cluster. + +The following is an example of the correct output: + +.. code-block:: console + + ./sqream-start -s + Initializing network watchdogs on 3 hosts... + Network watchdogs are up and running + + Initializing 3 worker data collectors ... + Worker data collectors are up and running + + Starting Prometheus ... + Prometheus is available at 192.168.5.100:9090 + + Starting SQream master ... + SQream master is up and running + + Starting up 3 SQream workers ... + All SQream workers are up and running, SQream-DB is available at 192.168.5.100:3108 + All SQream workers are up and running, SQream-DB is available at 192.168.5.100:3108 + + +Go back to :ref:`Using the SQream-start Commands`. + +Starting Your SQream Services in Split Mode +------------------------ +Starting SQream services in split mode refers to running multiple SQream workers on a single GPU. You can do this by running the **sqream-start** command with the **-s** and **-z** flags. In addition, you can define the amount of hosts to run the multiple workers on. In the example below, the command defines to run the multiple workers on three hosts. + +**To start SQream services in split mode:** + +1. Run the following command: + +.. code-block:: console + + $ ./sqream-start -s -z 3 + +This command starts the SQream metadata, server picker, and sqream workers on a single GPU for three hosts: + +The following is an example of the correct output: + +.. code-block:: console + + Initializing network watchdogs on 3 hosts... + Network watchdogs are up and running + + Initializing 3 worker data collectors ... + Worker data collectors are up and running + + Starting Prometheus ... + Prometheus is available at 192.168.5.101:9090 + + Starting SQream master ... + SQream master is up and running + + Starting up 9 SQream workers over <#> available GPUs ... + All SQream workers are up and running, SQream-DB is available at 192.168.5.101:3108 + +2. Verify all pods are properly running in k8s cluster (**STATUS** column): + +.. code-block:: console + + kubectl -n sqream get pods + + NAME READY STATUS RESTARTS AGE + prometheus-bcf877867-kxhld 1/1 Running 0 106s + sqream-metadata-fbcbc989f-6zlkx 1/1 Running 0 103s + sqream-picker-64b8c57ff5-ndfr9 1/1 Running 2 102s + sqream-split-workers-0-1-2-6bdbfbbb86-ml7kn 1/1 Running 0 57s + sqream-split-workers-3-4-5-5cb49d49d7-596n4 1/1 Running 0 57s + sqream-split-workers-6-7-8-6d598f4b68-2n9z5 1/1 Running 0 56s + sqream-workers-start-xj75g 1/1 Running 0 58s + watchdog-network-management-6dnfh 1/1 Running 0 115s + watchdog-network-management-tfd46 1/1 Running 0 115s + watchdog-network-management-xct4d 1/1 Running 0 115s + watchdog-network-storage-lr6v4 1/1 Running 0 116s + watchdog-network-storage-s29h7 1/1 Running 0 116s + watchdog-network-storage-sx9mw 1/1 Running 0 116s + worker-data-collector-62rxs 0/1 Init:0/1 0 54s + worker-data-collector-n8jsv 0/1 Init:0/1 0 55s + worker-data-collector-zp8vf 0/1 Init:0/1 0 54s + +Go back to :ref:`Using the SQream-start Commands`. + +Starting the Sqream Studio UI +-------------------------------- +You can run the following command the to start the SQream Studio UI (Editor and Dashboard): + +.. code-block:: console + + $ ./sqream-start -a + +The following is an example of the correct output: + +.. code-block:: console + + $ ./sqream-start -a + Please enter USERNAME: + sqream + Please enter PASSWORD: + ****** + Please enter port value or press ENTER to keep 8080: + + Starting up SQream Admin UI... + SQream admin ui is available at 192.168.5.100:8080 + +Go back to :ref:`Using the SQream-start Commands`. + +Stopping the SQream Services +-------------------------------- +You can run the following command to stop all SQream services: + +.. code-block:: console + + $ ./sqream-start -d + +The following is an example of the correct output: + +.. code-block:: console + + $ ./sqream-start -d + $ Cleaning all SQream services in sqream namespace ... + $ All SQream service removed from sqream namespace + +Go back to :ref:`Using the SQream-start Commands`. + +Advanced sqream-start Commands +-------------------------------- +Controlling Your SQream Spool Size +~~~~~~~~~~~~~~~~~~~~~~~~ +If you do not specify the SQream spool size, the console automatically distributes the available RAM between all running workers. + +You can define a specific spool size by running the following command: + +.. code-block:: console + + $ ./sqream-start -s -m 4 + +Using a Custom .json File +~~~~~~~~~~~~~~~~~~~~~~~~ +You have the option of using your own .json file for your own custom configurations. Your .json file must be placed within the path mounted in the installation. SQream recommends placing your .json file in the **configuration** folder. + +The SQream console does not validate the integrity of external .json files. + +You can use the following command (using the ``j`` flag) to set the full path of your .json file to the configuration file: + +.. code-block:: console + + $ ./sqream-start -s -f .json + +This command starts one worker with an external configuration file. + +.. note:: The configuration file must be available in the shared configuration folder. + + +Checking the Status of the SQream Services +~~~~~~~~~~~~~~~~~~~~~~~~ +You can show all running SQream services by running the following command: + +.. code-block:: console + + $ kubectl get pods -n -o wide + +This command shows all running services in the cluster and which nodes they are running in. + +Go back to :ref:`Using the SQream-start Commands`. + +Upgrading Your SQream Version +================================ +The **Upgrading Your SQream Version** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Before Upgrading Your System +---------------------------- +Before upgrading your system you must do the following: + +1. Contact SQream support for a new SQream package tarball file. + +:: + +2. Set a maintenance window. + + +.. note:: You must stop the system while upgrading it. + + +Upgrading Your System +---------------------------- +After completing the steps in **Before Upgrading Your System** above, you can upgrade your system. + +**To upgrade your system:** + +1. Extract the contents of the tarball file that you received from SQream support. Make sure to extract the contents to the same directory as in :ref:`getting_sqream_package` and for the same user: + + .. code-block:: console + + $ tar -xvf sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ + $ cd sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ + +2. Start the upgrade process run the following command: + + .. code-block:: console + + $ ./sqream-install -i + +The upgrade process checks if the SQream services are running and will prompt you to stop them. + +3. Do one of the following: + + * Stop the upgrade by writing ``No``. + * Continue the upgrade by writing ``Yes``. + +If you continue upgrading, all running SQream workers (master and editor) are stopped. When all services have been stopped, the new version is loaded. + + +.. note:: SQream periodically upgrades its metadata structure. If an upgrade version includes an upgraded metadata service, an approval request message is displayed. This approval is required to finish the upgrade process. Because SQream supports only specific metadata versions, all SQream services must be upgraded at the same time. + + +4. When SQream has successfully upgraded, load the SQream console and restart your services. + +For questions, contact SQream Support. From 985ffb35a2e669fdb43f9c24ba3e1a953eefefa1 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 14:11:52 +0200 Subject: [PATCH 101/300] Create installing_sqream_with_kubernetes.rst Created installing_sqream_with_kubernetes.rst. --- .../installing_sqream_with_kubernetes.rst | 1805 +++++++++++++++++ 1 file changed, 1805 insertions(+) create mode 100644 guides/operations/installing_sqream_with_kubernetes.rst diff --git a/guides/operations/installing_sqream_with_kubernetes.rst b/guides/operations/installing_sqream_with_kubernetes.rst new file mode 100644 index 000000000..0269b1204 --- /dev/null +++ b/guides/operations/installing_sqream_with_kubernetes.rst @@ -0,0 +1,1805 @@ +.. _installing_sqream_with_kubernetes: + +********************************************* +Installing SQream with Kubernetes +********************************************* +**Kubernetes**, also known as **k8s**, is a portable open source platform that automates Linux container operations. Kubernetes supports outsourcing data centers to public cloud service providers or can be scaled for web hosting. SQream uses Kubernetes as an orchestration and recovery solution. + +The **Installing SQream with Kubernetes** guide describes the following: + +.. contents:: + :local: + :depth: 1 + +.. _preparing_sqream_environment: + +Preparing the SQream Environment to Launch SQream Using Kubernetes +=============== + +The **Preparing the SQream environment to Launch SQream Using Kubernetes** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +-------------- + +A minimum of three servers is required for preparing the SQream environment using Kubernetes. + +Kubernetes uses clusters, which are sets of nodes running containterized applications. A cluster consists of at least two GPU nodes and one additional server without GPU to act as the quorum manager. + +Each server must have the following IP addresses: + +* An IP address located in the management network. +* An additional IP address from the same subnet to function as a floating IP. + +All servers must be mounted in the same shared storage folder. + +The following list shows the server host name format requirements: + +* A maximum of 253 characters. +* Only lowercase alphanumeric characters, such as ``-`` or ``.``. +* Starts and ends with alphanumeric characters. + +Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes` + + +Operating System Requirements +------------------------------ +The required operating system is a version of x86 CentOS/RHEL between 7.6 and 7.9. Regarding PPC64le, the required version is RHEL 7.6. + +Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes` + + +Compute Server Specifications +------------------------------ +Installing SQream with Kubernetes includes the following compute server specifications: + +* **CPU:** 4 cores +* **RAM:** 16GB +* **HD:** 500GB + +Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes` + +.. _set_up_your_hosts: + +Setting Up Your Hosts +=============================== +SQream requires you to set up your hosts. Setting up your hosts requires the following: + +.. contents:: + :local: + :depth: 1 + +Configuring the Hosts File +-------------------------------- +**To configure the /etc/hosts file:** + +1. Edit the **/etc/hosts** file: + + .. code-block:: console + + $ sudo vim /etc/hosts + +2. Call your local host: + + .. code-block:: console + + $ 127.0.0.1 localhost + $ + + +Installing the Required Packages +---------------------------------- +The first step in setting up your hosts is to install the required packages. + +**To install the required packages:** + +1. Run the following command based on your operating system: + + * RHEL: + + .. code-block:: postgres + + $ sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + + * CentOS: + + .. code-block:: postgres + + $ sudo yum install epel-release + $ sudo yum install pciutils openssl-devel python36 python36-pip kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc jq net-tools ntp + +2. Verify that that the required packages were successfully installed. The following is the correct output: + + .. code-block:: postgres + + ntpq --version + jq --version + python3 --version + pip3 --version + rpm -qa |grep kernel-devel-$(uname -r) + rpm -qa |grep kernel-headers-$(uname -r) + gcc --version + +3. Enable the **ntpd (Network Time Protocol daemon)** program on all servers: + + .. code-block:: postgres + + $ sudo systemctl start ntpd + $ sudo systemctl enable ntpd + $ sudo systemctl status ntpd + $ sudo ntpq -p + +Go back to :ref:`Setting Up Your Hosts` + + +Disabling the Linux UI +---------------------------------- +After installing the required packages, you must disable the Linux UI if it has been installed. + +You can disable Linux by running the following command: + + .. code-block:: postgres + + $ sudo systemctl set-default multi-user.target + +Go back to :ref:`Setting Up Your Hosts` + + +Disabling SELinux +---------------------------------- +After disabling the Linux UI you must disable SELinux. + +**To disable SELinux:** + + 1. Run the following command: + + .. code-block:: postgres + + $ sed -i -e s/enforcing/disabled/g /etc/selinux/config + $ sudo reboot + + 2. Reboot the system as a root user: + + .. code-block:: postgres + + $ sudo reboot + +Go back to :ref:`Setting Up Your Hosts` + +Disabling Your Firewall +---------------------------------- +After disabling SELinux, you must disable your firewall by running the following commands: + + .. code-block:: postgres + + $ sudo systemctl stop firewalld + $ sudo systemctl disable firewalld + +Go back to :ref:`Setting Up Your Hosts` + + +Checking the CUDA Version +---------------------------------- +After completing all of the steps above, you must check the CUDA version. + +**To check the CUDA version:** + +1. Check the CUDA version: + + .. code-block:: postgres + + $ nvidia-smi + + The following is an example of the correct output: + + .. code-block:: postgres + + $ +-----------------------------------------------------------------------------+ + $ | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + $ |-------------------------------+----------------------+----------------------+ + $ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + $ | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + $ |===============================+======================+======================| + $ | 0 GeForce GTX 105... Off | 00000000:01:00.0 Off | N/A | + $ | 32% 38C P0 N/A / 75W | 0MiB / 4039MiB | 0% Default | + $ +-------------------------------+----------------------+----------------------+ + $ + $ +-----------------------------------------------------------------------------+ + $ | Processes: GPU Memory | + $ | GPU PID Type Process name Usage | + $ |=============================================================================| + $ | No running processes found | + $ +-----------------------------------------------------------------------------+ + +In the above output, the CUDA version is **10.1**. + +If the above output is not generated, CUDA has not been installed. To install CUDA, see `Installing the CUDA driver `_. + + +Go back to :ref:`Setting Up Your Hosts` + +.. _install_kubernetes_cluster: + +Installing Your Kubernetes Cluster +=================================== +After setting up your hosts, you must install your Kubernetes cluster. The Kubernetes and SQream software must be installed from the management host, and can be installed on any server in the cluster. + +Installing your Kubernetes cluster requires the following: + +.. contents:: + :local: + :depth: 1 + +Generating and Sharing SSH Keypairs Across All Existing Nodes +------------------------------------ +You can generate and share SSH keypairs across all existing nodes. Sharing SSH keypairs across all nodes enables passwordless access from the management server to all nodes in the cluster. All nodes in the cluster require passwordless access. + +.. note:: You must generate and share an SSH keypair across all nodes even if you are installing the Kubernetes cluster on a single host. + +**To generate and share an SSH keypair:** + +1. Switch to root user access: + + .. code-block:: postgres + + $ sudo su - + +2. Generate an RSA key pair: + + .. code-block:: postgres + + $ ssh-keygen + +The following is an example of the correct output: + + .. code-block:: postgres + + $ ssh-keygen + $ Generating public/private rsa key pair. + $ Enter file in which to save the key (/root/.ssh/id_rsa): + $ Created directory '/root/.ssh'. + $ Enter passphrase (empty for no passphrase): + $ Enter same passphrase again: + $ Your identification has been saved in /root/.ssh/id_rsa. + $ Your public key has been saved in /root/.ssh/id_rsa.pub. + $ The key fingerprint is: + $ SHA256:xxxxxxxxxxxxxxdsdsdffggtt66gfgfg root@localhost.localdomain + $ The key's randomart image is: + $ +---[RSA 2048]----+ + $ | =*. | + $ | .o | + $ | ..o o| + $ | . .oo +.| + $ | = S =...o o| + $ | B + *..o+.| + $ | o * *..o .+| + $ | o * oo.E.o| + $ | . ..+..B.+o| + $ +----[SHA256]-----+ + +The generated file is ``/root/.ssh/id_rsa.pub``. + +3. Copy the public key to all servers in the cluster, including the one that you are running on. + + .. code-block:: postgres + + $ ssh-copy-id -i ~/.ssh/id_rsa.pub root@remote-host + +4. Replace the ``remote host`` with your host IP address. + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Installing and Deploying a Kubernetes Cluster Using Kubespray +------------------------------------ +SQream uses the Kubespray software package to install and deploy Kubernetes clusters. + +**To install and deploy a Kubernetes cluster using Kubespray:** + + +1. Clone Kubernetes: + + 1. Clone the **kubespray.git** repository: + + .. code-block:: postgres + + $ git clone https://github.com/kubernetes-incubator/kubespray.git + + 2. Nagivate to the **kubespray** directory: + + .. code-block:: postgres + + $ cd kubespray + + 3. Install the **requirements.txt** configuration file: + + .. code-block:: postgres + + $ pip3 install -r requirements.txt + +2. Create your SQream inventory directory: + + 1. Run the following command: + + .. code-block:: postgres + + $ cp -rp inventory/sample inventory/sqream + + 2. Replace the **** with the defined cluster node IP address(es). + + .. code-block:: postgres + + $ declare -a IPS=(, ) + + For example, the following replaces ``192.168.0.93`` with ``192.168.0.92``: + + .. code-block:: postgres + + $ declare -a IPS=(host-93,192.168.0.93 host-92,192.168.0.92) + +Note the following: + * Running a declare requires defining a pair (host name and cluster node IP address), as shown in the above example. + * You can define more than one pair. + +3. When the reboot is complete, switch back to the root user: + + .. code-block:: postgres + + $ sudo su - + +4. Navigate to **root/kubespray**: + + .. code-block:: postgres + + $ cd /root/kubespray + +5. Copy ``inventory/sample`` as ``inventory/sqream``: + + .. code-block:: postgres + + $ cp -rfp inventory/sample inventory/sqream + +6. Update the Ansible inventory file with the inventory builder: + + .. code-block:: postgres + + $ declare -a IPS=(, , ,) + +7. In the **kubespray hosts.yml** file, set the node IP's: + + .. code-block:: postgres + + $ CONFIG_FILE=inventory/sqream/hosts.yml python3 contrib/inventory_builder/inventory.py ${IPS[@]} + + If you do not set a specific hostname in declare, the server hostnames will change to ``node1``, ``node2``, etc. To maintain specific hostnames, run declare as in the following example: + + .. code-block:: postgres + + $ declare -a IPS=(eks-rhl-1,192.168.5.81 eks-rhl-2,192.168.5.82 eks-rhl-3,192.168.5.83) + + Note that the declare must contain pairs (hostname,ip). + +:: + +8. Verify that the following have been done: + + * That the **hosts.yml** file is configured correctly. + * That all children are included with their relevant nodes. + +You can save your current server hostname by replacing with your server hostname. + +9. Generate the content output of the **hosts.yml** file. Make sure to include the file's directory: + + .. code-block:: postgres + + $ cat inventory/sqream/hosts.yml + +The hostname can be lowercase and contain ``-`` or ``.`` only, and must be aligned with the server's hostname. + +The following is an example of the correct output. Each host and IP address that you provided in Step 2 should be displayed once: + + .. code-block:: postgres + + $ all: + $ hosts: + $ node1: + $ ansible_host: 192.168.5.81 + $ ip: 192.168.5.81 + $ access_ip: 192.168.5.81 + $ node2: + $ ansible_host: 192.168.5.82 + $ ip: 192.168.5.82 + $ access_ip: 192.168.5.82 + $ node3: + $ ansible_host: 192.168.5.83 + $ ip: 192.168.5.83 + $ access_ip: 192.168.5.83 + $ children: + $ kube-master: + $ hosts: + $ node1: + $ node2: + $ node3: + $ kube-node: + $ hosts: + $ node1: + $ node2: + $ node3: + $ etcd: + $ hosts: + $ node1: + $ node2: + $ node3: + $ k8s-cluster: + $ children: + $ kube-master: + $ kube-node: + $ calico-rr: + $ hosts: {} + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Adjusting Kubespray Deployment Values +------------------------------------- +After downloading and configuring Kubespray, you can adjust your Kubespray deployment values. A script is used to modify how the Kubernetes cluster is deployed, and you must set the cluster name variable before running this script. + +.. note:: The script must be run from the **kubespray** folder. + +**To adjust Kubespray deployment values:** + +1. Add the following export to the local user’s **~/.bashrc** file by replacing the with the user's Virtual IP address: + + .. code-block:: postgres + + $ export VIP_IP= + +2. Logout, log back in, and verify the following: + + .. code-block:: postgres + + $ echo $VIP_IP + +3. Make the following replacements to the **kubespray.settings.sh** file: + + .. code-block:: postgres + + $ cat < kubespray_settings.sh + $ sed -i "/cluster_name: cluster.local/c \cluster_name: cluster.local.$cluster_name" inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ sed -i "/dashboard_enabled/c \dashboard_enabled\: "false"" inventory/sqream/group_vars/k8s-cluster/addons.yml + $ sed -i "/kube_version/c \kube_version\: "v1.18.3"" inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ sed -i "/metrics_server_enabled/c \metrics_server_enabled\: "true"" inventory/sample/group_vars/k8s-cluster/addons.yml + $ echo 'kube_apiserver_node_port_range: "3000-6000"' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'kube_controller_node_monitor_grace_period: 20s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'kube_controller_node_monitor_period: 2s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'kube_controller_pod_eviction_timeout: 30s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'kubelet_status_update_frequency: 4s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'ansible ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers + $ EOF + +.. note:: In most cases, the Docker data resides on the system disk. Because Docker requires a high volume of data (images, containers, volumes, etc.), you can change the default Docker data location to prevent the system disk from running out of space. + +4. *Optional* - Change the default Docker data location: + + .. code-block:: postgres + + $ sed -i "/docker_daemon_graph/c \docker_daemon_graph\: """ inventory/sqream/group_vars/all/docker.yml + +5. Make the **kubespray_settings.sh** file executable for your user: + + .. code-block:: postgres + + $ chmod u+x kubespray_settings.sh && ./kubespray_settings.sh + +6. Run the following script: + + .. code-block:: postgres + + $ ./kubespray_settings.sh + +7. Run a playbook on the **inventory/sqream/hosts.yml cluster.yml** file: + + .. code-block:: postgres + + $ ansible-playbook -i inventory/sqream/hosts.yml cluster.yml -v + +The Kubespray installation takes approximately 10 - 15 minutes. + +The following is an example of the correct output: + + .. code-block:: postgres + + $ PLAY RECAP + $ ********************************************************************************************* + $ node-1             : ok=680  changed=133  unreachable=0    failed=0 + $ node-2             : ok=583  changed=113  unreachable=0    failed=0 + $ node-3             : ok=586  changed=115  unreachable=0    failed=0 + $ localhost          : ok=1    changed=0    unreachable=0    failed=0 + +In the event that the output is incorrect, or a failure occurred during the installation, please contact a SQream customer support representative. + +Go back to :ref:`Installing Your Kubernetes Cluster`. + +Checking Your Kubernetes Status +------------------------------- +After adjusting your Kubespray deployment values, you must check your Kubernetes status. + +**To check your Kuberetes status:** + +1. Check the status of the node: + + .. code-block:: postgres + + $ kubectl get nodes + +The following is an example of the correct output: + + .. code-block:: postgres + + $ NAME STATUS ROLES AGE VERSION + $ eks-rhl-1 Ready control-plane,master 29m v1.21.1 + $ eks-rhl-2 Ready control-plane,master 29m v1.21.1 + $ eks-rhl-3 Ready 28m v1.21.1 + +2. Check the status of the pod: + + .. code-block:: postgres + + $ kubectl get pods --all-namespaces + + The following is an example of the correct output: + + .. code-block:: postgres + + $ NAMESPACE NAME READY STATUS RESTARTS AGE + $ kube-system calico-kube-controllers-68dc8bf4d5-n9pbp 1/1 Running 0 160m + $ kube-system calico-node-26cn9 1/1 Running 1 160m + $ kube-system calico-node-kjsgw 1/1 Running 1 160m + $ kube-system calico-node-vqvc5 1/1 Running 1 160m + $ kube-system coredns-58687784f9-54xsp 1/1 Running 0 160m + $ kube-system coredns-58687784f9-g94xb 1/1 Running 0 159m + $ kube-system dns-autoscaler-79599df498-hlw8k 1/1 Running 0 159m + $ kube-system kube-apiserver-k8s-host-1-134 1/1 Running 0 162m + $ kube-system kube-apiserver-k8s-host-194 1/1 Running 0 161m + $ kube-system kube-apiserver-k8s-host-68 1/1 Running 0 161m + $ kube-system kube-controller-manager-k8s-host-1-134 1/1 Running 0 162m + $ kube-system kube-controller-manager-k8s-host-194 1/1 Running 0 161m + $ kube-system kube-controller-manager-k8s-host-68 1/1 Running 0 161m + $ kube-system kube-proxy-5f42q 1/1 Running 0 161m + $ kube-system kube-proxy-bbwvk 1/1 Running 0 161m + $ kube-system kube-proxy-fgcfb 1/1 Running 0 161m + $ kube-system kube-scheduler-k8s-host-1-134 1/1 Running 0 161m + $ kube-system kube-scheduler-k8s-host-194 1/1 Running 0 161m + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Adding a SQream Label to Your Kubernetes Cluster Nodes +------------------------------------------------- +After checking your Kubernetes status, you must add a SQream label on your Kubernetes cluster nodes. + +**To add a SQream label on your Kubernetes cluster nodes:** + +1. Get the cluster node list: + + .. code-block:: postgres + + $ kubectl get nodes + + The following is an example of the correct output: + + .. code-block:: postgres + + $ NAME        STATUS   ROLES    AGE   VERSION + $ eks-rhl-1 Ready control-plane,master 29m v1.21.1 + $ eks-rhl-2 Ready control-plane,master 29m v1.21.1 + $ eks-rhl-3 Ready 28m v1.21.1 + +2. Set the node label, change the ``node-name`` to the node NAME(s) in the above example: + + .. code-block:: postgres + + $ kubectl label nodes cluster=sqream + + The following is an example of the correct output: + + .. code-block:: postgres + + $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-1 cluster=sqream + $ node/eks-rhl-1 labeled + $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-2 cluster=sqream + $ node/eks-rhl-2 labeled + $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-3 cluster=sqream + $ node/eks-rhl-3 labeled + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Copying Your Kubernetes Configuration API File to the Master Cluster Nodes +------------------------------------------------- +After adding a SQream label on your Kubernetes cluster nodes, you must copy your Kubernetes configuration API file to your Master cluster nodes. + +When the Kubernetes cluster installation is complete, an API configuration file is automatically created in the **.kube** folder of the root user. This file enables the **kubectl** command access Kubernetes' internal API service. Following this step lets you run **kubectl** commands from any node in the cluster. + + +.. warning:: You must perform this on the management server only! + +**To copy your Kubernetes configuration API file to your Master cluster nodes:** + +1. Create the **.kube** folder in the **local user** directory: + + .. code-block:: postgres + + $ mkdir /home//.kube + +2. Copy the configuration file from the root user directory to the directory: + + .. code-block:: postgres + + $ sudo cp /root/.kube/config /home//.kube + +3. Change the file owner from **root user** to the : + + .. code-block:: postgres + + $ sudo chown . /home//.kube/config + +4. Create the **.kube** folder in the other nodes located in the directory: + + .. code-block:: postgres + + $ ssh @ mkdir .kube + +5. Copy the configuration file from the management node to the other nodes: + + .. code-block:: postgres + + $ scp /home//.kube/config @:/home//.kube/ + +6. Under local user on each server you copied **.kube** to, run the following command: + + .. code-block:: postgres + + $ sudo usermod -aG docker $USER + +This grants the local user the necessary permissions to run Docker commands. + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Creating an env_file in Your Home Directory +------------------------------------------------- +After copying your Kubernetes configuration API file to your Master cluster nodes, you must create an **env_file** in your home directory, and must set the VIP address as a variable. + +.. warning:: You must perform this on the management server only! + + + +**To create an env_file for local users in the user's home directory:** + +1. Set a variable that includes the VIP IP address: + + .. code-block:: postgres + + $ export VIP_IP= + +.. note:: If you use Kerberos, replace the ``KRB5_SERVER`` value with the IP address of your Kerberos server. + +2. Do one of the following: + + * For local users: + + .. code-block:: postgres + + $ mkdir /home/$USER/.sqream + +3. Make the following replacements to the **kubespray.settings.sh** file, verifying that the ``KRB5_SERVER`` parameter is set to your server IP: + + + .. code-block:: postgres + + $ cat < /home/$USER/.sqream/env_file + SQREAM_K8S_VIP=$VIP_IP + SQREAM_ADMIN_UI_PORT=8080 + SQREAM_DASHBOARD_DATA_COLLECTOR_PORT=8100 + SQREAM_DATABASE_NAME=master + SQREAM_K8S_ADMIN_UI=sqream-admin-ui + SQREAM_K8S_DASHBOARD_DATA_COLLECTOR=dashboard-data-collector + SQREAM_K8S_METADATA=sqream-metadata + SQREAM_K8S_NAMESPACE=sqream + SQREAM_K8S_PICKER=sqream-picker + SQREAM_K8S_PROMETHEUS=prometheus + SQREAM_K8S_REGISTRY_PORT=6000 + SQREAM_METADATA_PORT=3105 + SQREAM_PICKER_PORT=3108 + SQREAM_PROMETHEUS_PORT=9090 + SQREAM_SPOOL_MEMORY_RATIO=0.25 + SQREAM_WORKER_0_PORT=5000 + KRB5CCNAME=FILE:/tmp/tgt + KRB5_SERVER=kdc.sq.com:1 + KRB5_CONFIG_DIR=${ $ SQREAM_MOUNT_DIR}/krb5 + KRB5_CONFIG_FILE=${KRB5_CONFIG_DIR}/krb5.conf + HADOOP_CONFIG_DIR=${ $ SQREAM_MOUNT_DIR}/hadoop + HADOOP_CORE_XML=${HADOOP_CONFIG_DIR}/core-site.xml + HADOOP_HDFS_XML=${HADOOP_CONFIG_DIR}/hdfs-site.xml + EOF + +Go back to :ref:`Installing Your Kubernetes Cluster` + + + + + +Creating a Base Kubernetes Namespace +------------------------------------ +After creating an env_file in the user's home directory, you must create a base Kubernetes namespace. + +You can create a Kubernetes namespace by running the following command: + +.. code-block:: postgres + + $ kubectl create namespace sqream-init + +The following is an example of the correct output: + +.. code-block:: postgres + + $ namespace/sqream-init created + +Go back to :ref:`Installing Your Kubernetes Cluster` + + +Pushing the **env_file** File to the Kubernetes Configmap +-------------------------------------- +After creating a base Kubernetes namespace, you must push the **env_file** to the Kubernetes configmap. You must push the **env_file** file to the Kubernetes **configmap** in the **sqream-init** namespace. + +This is done by running the following command: + +.. code-block:: postgres + + $ kubectl create configmap sqream-init -n sqream-init --from-env-file=/home/$USER/.sqream/env_file + +The following is an example of the correct output: + +.. code-block:: postgres + + $ configmap/sqream-init created + + +Go back to :ref:`Installing Your Kubernetes Cluster` + + +Installing the NVIDIA Docker2 Toolkit +------------------------------------- +After pushing the **env_file** file to the Kubernetes configmap, you must install the NVIDIA Docker2 Toolkit. The **NVIDIA Docker2 Toolkit** lets users build and run GPU-accelerated Docker containers, and must be run only on GPU servers. The NVIDIA Docker2 Toolkit includes a container runtime library and utilities that automatically configure containers to leverage NVIDIA GPUs. + + +Installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on CentOS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +**To install the NVIDIA Docker2 Toolkit on an x86_64 bit processor on CentOS:** + +1. Add the repository for your distribution: + + .. code-block:: postgres + + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ + $ sudo tee /etc/yum.repos.d/nvidia-docker.repo + +2. Install the **nvidia-docker2** package and reload the Docker daemon configuration: + + .. code-block:: postgres + + $ sudo yum install nvidia-docker2 + $ sudo pkill -SIGHUP dockerd + +3. Verify that the **nvidia-docker2** package has been installed correctly: + + .. code-block:: postgres + + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + + The following is an example of the correct output: + + .. code-block:: postgres + + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + $ Unable to find image 'nvidia/cuda:10.1-base' locally + $ 10.1-base: Pulling from nvidia/cuda + $ d519e2592276: Pull complete + $ d22d2dfcfa9c: Pull complete + $ b3afe92c540b: Pull complete + $ 13a10df09dc1: Pull complete + $ 4f0bc36a7e1d: Pull complete + $ cd710321007d: Pull complete + $ Digest: sha256:635629544b2a2be3781246fdddc55cc1a7d8b352e2ef205ba6122b8404a52123 + $ Status: Downloaded newer image for nvidia/cuda:10.1-base + $ Sun Feb 14 13:27:58 2021 + $ +-----------------------------------------------------------------------------+ + $ | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + $ |-------------------------------+----------------------+----------------------+ + $ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + $ | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + $ |===============================+======================+======================| + $ | 0 GeForce GTX 105... Off | 00000000:01:00.0 Off | N/A | + $ | 32% 37C P0 N/A / 75W | 0MiB / 4039MiB | 0% Default | + $ +-------------------------------+----------------------+----------------------+ + $ + $ +-----------------------------------------------------------------------------+ + $ | Processes: GPU Memory | + $ | GPU PID Type Process name Usage | + $ |=============================================================================| + $ | No running processes found | + $ +-----------------------------------------------------------------------------+ + +For more information on installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on CentOS, see `NVIDIA Docker Installation - CentOS distributions `_ + +Installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on Ubuntu +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +**To install the NVIDIA Docker2 Toolkit on an x86_64 bit processor on Ubuntu:** + +1. Add the repository for your distribution: + + .. code-block:: postgres + + $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \ + $ sudo apt-key add - + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \ + $ sudo tee /etc/apt/sources.list.d/nvidia-docker.list + $ sudo apt-get update + +2. Install the **nvidia-docker2** package and reload the Docker daemon configuration: + + .. code-block:: postgres + + $ sudo apt-get install nvidia-docker2 + $ sudo pkill -SIGHUP dockerd + +3. Verify that the nvidia-docker2 package has been installed correctly: + + .. code-block:: postgres + + $ docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi + +For more information on installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on Ubuntu, see `NVIDIA Docker Installation - Ubuntu distributions `_ + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Modifying the Docker Daemon JSON File for GPU and Compute Nodes +------------------------------------- +After installing the NVIDIA Docker2 toolkit, you must modify the Docker daemon JSON file for GPU and Compute nodes. + +Modifying the Docker Daemon JSON File for GPU Nodes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**To modify the Docker daemon JSON file for GPU nodes:** + +1. Enable GPU and set HTTP access to the local Kubernetes Docker registry. + +.. note:: The Docker daemon JSON file must be modified on all GPU nodes. + +.. note:: Contact your IT department for a virtual IP. + +2. Replace the ``VIP address`` with your assigned VIP address. + +:: + +3. Connect as a root user: + + .. code-block:: postgres + + $ sudo -i + +4. Set a variable that includes the VIP address: + + .. code-block:: postgres + + $ export VIP_IP= + +5. Replace the with the VIP address:  + + .. code-block:: postgres + + $ cat < /etc/docker/daemon.json + $ { + $ "insecure-registries": ["$VIP_IP:6000"], + $ "default-runtime": "nvidia", + $ "runtimes": { + $ "nvidia": { + $ "path": "nvidia-container-runtime", + $ "runtimeArgs": [] + $ } + $ } + $ } + $ EOF + +6. Apply the changes and restart Docker: + + .. code-block:: postgres + + $ systemctl daemon-reload && systemctl restart docker + +7. Exit the root user: + + .. code-block:: postgres + + $ exit + +Go back to :ref:`Installing Your Kubernetes Cluster` + + +Modifying the Docker Daemon JSON File for Compute Nodes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You must follow this procedure only if you have a Compute node. + +**To modify the Docker daemon JSON file for Compute nodes:** + +1. Switch to a root user: + + .. code-block:: postgres + + $ sudo -i + +2. Set a variable that includes a VIP address. + +.. note:: Contact your IT department for a virtual IP. + +3. Replace the ``VIP address`` with your assigned VIP address. + + .. code-block:: postgres + + $ cat < /etc/docker/daemon.json + $ { + $ "insecure-registries": ["$VIP_IP:6000"] + $ } + $ EOF + +4. Restart the services: + + .. code-block:: postgres + + $ systemctl daemon-reload && systemctl restart docker + +5. Exit the root user: + + + .. code-block:: postgres + + $ exit + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Installing the Nvidia-device-plugin Daemonset +---------------------------------------------- +After modifying the Docker daemon JSON file for GPU or Compute Nodes, you must installing the Nvidia-device-plugin daemonset. The Nvidia-device-plugin daemonset is only relevant to GPU nodes. + +**To install the Nvidia-device-plugin daemonset:** + +1. Set ``nvidia.com/gpu`` to ``true`` on all GPU nodes: + +.. code-block:: postgres + + $ kubectl label nodes nvidia.com/gpu=true + +2. Replace the ** with your GPU node name: + + For a complete list of GPU node names, run the ``kubectl get nodes`` command. + + The following is an example of the correct output: + + .. code-block:: postgres + + $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-1 nvidia.com/gpu=true + $ node/eks-rhl-1 labeled + $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-2 nvidia.com/gpu=true + $ node/eks-rhl-2 labeled + $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-3 nvidia.com/gpu=true + $ node/eks-rhl-3 labeled + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Creating an Nvidia Device Plugin +---------------------------------------------- +After installing the Nvidia-device-plugin daemonset, you must create an Nvidia-device-plugin. You can create an Nvidia-device-plugin by running the following command + +.. code-block:: postgres + + $ kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/1.0.0-beta6/nvidia-device-plugin.yml + +If needed, you can check the status of the Nvidia-device-plugin-daemonset pod status: + +.. code-block:: postgres + + $ kubectl get pods -n kube-system -o wide | grep nvidia-device-plugin + +The following is an example of the correct output: + +.. code-block:: postgres + + $ NAME READY STATUS RESTARTS AGE + $ nvidia-device-plugin-daemonset-fxfct 1/1 Running 0 6h1m + $ nvidia-device-plugin-daemonset-jdvxs 1/1 Running 0 6h1m + $ nvidia-device-plugin-daemonset-xpmsv 1/1 Running 0 6h1m + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Checking GPU Resources Allocatable to GPU Nodes +------------------------------------- +After creating an Nvidia Device Plugin, you must check the GPU resources alloctable to the GPU nodes. Each GPU node has records, such as ``nvidia.com/gpu: <#>``. The ``#`` indicates the number of allocatable, or available, GPUs in each node. + +You can output a description of allocatable resources by running the following command: + +.. code-block:: postgres + + $ kubectl describe node | grep -i -A 7 -B 2 allocatable: + +The following is an example of the correct output: + +.. code-block:: postgres + + $ Allocatable: + $ cpu: 3800m + $ ephemeral-storage: 94999346224 + $ hugepages-1Gi: 0 + $ hugepages-2Mi: 0 + $ memory: 15605496Ki + $ nvidia.com/gpu: 1 + $ pods: 110 + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Preparing the WatchDog Monitor +------------------------------ +SQream's deployment includes installing two watchdog services. These services monitor Kuberenetes management and the server's storage network. + +You can enable the storage watchdogs by adding entries in the **/etc/hosts** file on each server: + +.. code-block:: postgres + + $
k8s-node1.storage + $
k8s-node2.storage + $
k8s-node3.storage + +The following is an example of the correct syntax: + +.. code-block:: postgres + + $ 10.0.0.1 k8s-node1.storage + $ 10.0.0.2 k8s-node2.storage + $ 10.0.0.3 k8s-node3.storage + +Go back to :ref:`Installing Your Kubernetes Cluster` + +.. _installing_sqream_software: + +Installing the SQream Software +================================= +Once you've prepared the SQream environment for launching it using Kubernetes, you can begin installing the SQream software. + +The **Installing the SQream Software** section describes the following: + +.. contents:: + :local: + :depth: 1 + + +.. _getting_sqream_package: + +Getting the SQream Package +-------------------------------- +The first step in installing the SQream software is getting the SQream package. Please contact the SQream Support team to get the **sqream_k8s-nnn-DBnnn-COnnn-SDnnn-.tar.gz** tarball file. + +This file includes the following values: + +* **sqream_k8s-** - the SQream installer version. +* **DB** - the SQreamDB version. +* **CO** - the SQream console version. +* **SD** - the SQream Acceleration Studio version. +* **arch** - the server architecture. + +You can extract the contents of the tarball by running the following command: + +.. code-block:: postgres + + $ tar -xvf sqream_k8s-1.0.15-DB2020.1.0.2-SD0.7.3-x86_64.tar.gz + $ cd sqream_k8s-1.0.15-DB2020.1.0.2-SD0.7.3-x86_64 + $ ls + +Extracting the contents of the tarball file generates a new folder with the same name as the tarball file. + +The following shows the output of the extracted file: + +.. code-block:: postgres + + drwxrwxr-x. 2 sqream sqream 22 Jan 27 11:39 license + lrwxrwxrwx. 1 sqream sqream 49 Jan 27 11:39 sqream -> .sqream/sqream-sql-v2020.3.1_stable.x86_64/sqream + -rwxrwxr-x. 1 sqream sqream 9465 Jan 27 11:39 sqream-install + -rwxrwxr-x. 1 sqream sqream 12444 Jan 27 11:39 sqream-start + +Go back to :ref:`Installing Your SQream Software` + +Setting Up and Configuring Hadoop +-------------------------------- +After getting the SQream package, you can set up and configure Hadoop by configuring the **keytab** and **krb5.conf** files. + +.. note:: You only need to configure the **keytab** and **krb5.conf** files if you use Hadoop with Kerberos authentication. + + +**To set up and configure Hadoop:** + +1. Contact IT for the **keytab** and **krb5.conf** files. + +:: + +2. Copy both files into the respective empty **.hadoop/** and **.krb5/** directories: + +.. code-block:: postgres + + $ cp hdfs.keytab krb5.conf .krb5/ + $ cp core-site.xml hdfs-site.xml .hadoop/ + +The SQream installer automatically copies the above files during the installation process. + +Go back to :ref:`Installing Your SQream Software` + +Starting a Local Docker Image Registry +-------------------------------- +After getting the SQream package, or (optionally) setting up and configuring Hadoop, you must start a local Docker image registry. Because Kubernetes is based on Docker, you must start the local Docker image registry on the host's shared folder. This allows all hosts to pull the SQream Docker images. + +**To start a local Docker image registry:** + +1. Create a Docker registry folder: + + .. code-block:: postgres + + $ mkdir /docker-registry/ + +2. Set the ``docker_path`` for the Docker registry folder: + + .. code-block:: postgres + + $ export docker_path= + +3. Apply the **docker-registry** service to the cluster: + + .. code-block:: postgres + + $ cat .k8s/admin/docker_registry.yaml | envsubst | kubectl create -f - + + The following is an example of the correct output: + + .. code-block:: postgres + + namespace/sqream-docker-registry created + configmap/sqream-docker-registry-config created + deployment.apps/sqream-docker-registry created + service/sqream-docker-registry created + +4. Check the pod status of the **docker-registry** service: + + .. code-block:: postgres + + $ kubectl get pods -n sqream-docker-registry + +The following is an example of the correct output: + + .. code-block:: postgres + + NAME READY STATUS RESTARTS AGE + sqream-docker-registry-655889fc57-hmg7h 1/1 Running 0 6h40m + +Go back to :ref:`Installing Your SQream Software` + +Installing the Kubernetes Dashboard +-------------------------------- +After starting a local Docker image registry, you must install the Kubernetes dashboard. The Kubernetes dashboard lets you see the Kubernetes cluster, nodes, services, and pod status. + +**To install the Kubernetes dashboard:** + +1. Apply the **k8s-dashboard** service to the cluster: + + .. code-block:: postgres + + $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml + + The following is an example of the correct output: + + .. code-block:: postgres + + namespace/kubernetes-dashboard created + serviceaccount/kubernetes-dashboard created + service/kubernetes-dashboard created + secret/kubernetes-dashboard-certs created + secret/kubernetes-dashboard-csrf created + secret/kubernetes-dashboard-key-holder created + configmap/kubernetes-dashboard-settings created + role.rbac.authorization.k8s.io/kubernetes-dashboard created + clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created + rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created + clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created + deployment.apps/kubernetes-dashboard created + service/dashboard-metrics-scraper created + deployment.apps/dashboard-metrics-scraper created + +2. Grant the user external access to the Kubernetes dashboard: + + .. code-block:: postgres + + $ cat .k8s/admin/kubernetes-dashboard-svc-metallb.yaml | envsubst | kubectl create -f - + + The following is an example of the correct output: + + .. code-block:: postgres + + service/kubernetes-dashboard-nodeport created + +3. Create the ``cluster-admin-sa.yaml`` file: + + .. code-block:: postgres + + $ kubectl create -f .k8s/admin/cluster-admin-sa.yaml + + The following is an example of the correct output: + + .. code-block:: postgres + + clusterrolebinding.rbac.authorization.k8s.io/cluster-admin-sa-cluster-admin created + +4. Check the pod status of the **K8s-dashboard** service: + + .. code-block:: postgres + + $ kubectl get pods -n kubernetes-dashboard + + The following is an example of the correct output: + + .. code-block:: postgres + + NAME READY STATUS RESTARTS AGE + dashboard-metrics-scraper-6b4884c9d5-n8p57 1/1 Running 0 4m32s + kubernetes-dashboard-7b544877d5-qc8b4 1/1 Running 0 4m32s + +5. Obtain the **k8s-dashboard** access token: + + .. code-block:: postgres + + $ kubectl -n kube-system describe secrets cluster-admin-sa-token + + The following is an example of the correct output: + + .. code-block:: postgres + + Name: cluster-admin-sa-token-rbl9p + Namespace: kube-system + Labels: + Annotations: kubernetes.io/service-account.name: cluster-admin-sa + kubernetes.io/service-account.uid: 81866d6d-8ef3-4805-840d-58618235f68d + + Type: kubernetes.io/service-account-token + + Data + ==== + ca.crt: 1025 bytes + namespace: 11 bytes + token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjRMV09qVzFabjhId09oamQzZGFFNmZBeEFzOHp3SlJOZWdtVm5lVTdtSW8ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJjbHVzdGVyLWFkbWluLXNhLXRva2VuLXJibDlwIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImNsdXN0ZXItYWRtaW4tc2EiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI4MTg2NmQ2ZC04ZWYzLTQ4MDUtODQwZC01ODYxODIzNWY2OGQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06Y2x1c3Rlci1hZG1pbi1zYSJ9.mNhp8JMr5y3hQ44QrvRDCMueyjSHSrmqZcoV00ZC7iBzNUqh3n-fB99CvC_GR15ys43jnfsz0tdsTy7VtSc9hm5ENBI-tQ_mwT1Zc7zJrEtgFiA0o_eyfYZOARdhdyFEJg84bzkIxJFPKkBWb4iPWU1Xb7RibuMCjNTarZMZbqzKYfQEcMZWJ5UmfUqp-HahZZR4BNbjSWybs7t6RWdcQZt6sO_rRCDrOeEJlqKKjx4-5jFZB8Du_0kKmnw2YJmmSCEOXrpQCyXIiZJpX08HyDDYfFp8IGzm61arB8HDA9dN_xoWvuz4Cj8klUtTzL9effJJPjHJlZXcEqQc9hE3jw + +6. Navigate to ``https://:5999``. + +:: + +7. Select the **Token** radio button, paste the token from the previous command output, and click **Sign in**. + +The Kubernetes dashboard is displayed. + +Go back to :ref:`Installing Your SQream Software` + +Installing the SQream Prometheus Package +-------------------------------- +After installing the Kubernetes dashboard, you must install the SQream Prometheus package. To properly monitor the host and GPU statistics the **exporter service** must be installed on each Kubernetes cluster node. + +This section describes how to install the following: + +* **node_exporter** - collects host data, such as CPU memory usage. +* **nvidia_exporter** - collects GPU utilization data. + + +.. note:: The steps in this section must be done on **all** cluster nodes. + +To install the **sqream-prometheus** package, you must do the following: + +1. :ref:`Install the exporter service ` + +:: + +2. :ref:`Check the exporter service ` + +Go back to :ref:`Installing Your SQream Software` + + +.. _install_exporter_service: + +Installing the Exporter Service +~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the exporter service:** + +1. Create a user and group that will be used to run the exporter services: + + .. code-block:: console + + $ sudo groupadd --system prometheus && sudo useradd -s /sbin/nologin --system -g prometheus prometheus + +2. Extract the **sqream_exporters_prometheus.0.1.tar.gz** file: + + .. code-block:: console + + $ cd .prometheus + $ tar -xf sqream_exporters_prometheus.0.1.tar.gz + +3. Copy the exporter software files to the **/usr/bin** directory: + + .. code-block:: console + + $ cd sqream_exporters_prometheus.0.1 + $ sudo cp node_exporter/node_exporter /usr/bin/ + $ sudo cp nvidia_exporter/nvidia_exporter /usr/bin/ + +4. Copy the exporters service file to the **/etc/systemd/system/** directory: + + .. code-block:: console + + $ sudo cp services/node_exporter.service /etc/systemd/system/ + $ sudo cp services/nvidia_exporter.service /etc/systemd/system/ + +5. Set the permission and group of the service files: + + .. code-block:: console + + $ sudo chown prometheus:prometheus /usr/bin/node_exporter + $ sudo chmod u+x /usr/bin/node_exporter + $ sudo chown prometheus:prometheus /usr/bin/nvidia_exporter + $ sudo chmod u+x /usr/bin/nvidia_exporter + +6. Reload the services: + + .. code-block:: console + + $ sudo systemctl daemon-reload + +7. Start both services and set them to start when the server is booted up: + + * Node_exporter: + + .. code-block:: console + + $ sudo systemctl start node_exporter && sudo systemctl enable node_exporter + + * Nvidia_exporter: + + .. code-block:: console + + $ sudo systemctl start nvidia_exporter && sudo systemctl enable nvidia_exporter + + + +.. _check_exporter_status: + +Checking the Exporter Status +~~~~~~~~~~~~~~~~~~~~~~~~ +After installing the **exporter** service, you must check its status. + +You can check the exporter status by running the following command: + +.. code-block:: console + + $ sudo systemctl status node_exporter && sudo systemctl status nvidia_exporter + +Go back to :ref:`Installing Your SQream Software` + + +.. _running_sqream_install_service: + +Running the Sqream-install Service +================================ +The **Running the Sqream-install Service** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Installing Your License +-------------------------------- +After install the SQream Prometheus package, you must install your license. + +**To install your license:** + +1. Copy your license package to the sqream **/license** folder. + +.. note:: You do not need to untar the license package after copying it to the **/license** folder because the installer script does it automatically. + +The following flags are **mandatory** during your first run: + +.. code-block:: console + + $ sudo ./sqream-install -i -k -m + +.. note:: If you cannot run the script with **sudo**, verify that you have the right permission (**rwx** for the user) on the relevant directories (config, log, volume, and data-in directories). + +Go back to :ref:`Running the SQream_install Service`. + +Changing Your Data Ingest Folder +-------------------------------- +After installing your license, you must change your data ingest folder. + +You can change your data ingest folder by running the following command: + +.. code-block:: console + + $ sudo ./sqream-install -d /media/nfs/sqream/data_in + +Go back to :ref:`Running the SQream_install Service`. + +Checking Your System Settings +-------------------------------- +After changing your data ingest folder, you must check your system settings. + +The following command shows you all the variables that your SQream system is running with: + +.. code-block:: console + + $ ./sqream-install -s + +After optionally checking your system settings, you can use the **sqream-start** application to control your Kubernetes cluster. + +Go back to :ref:`Running the SQream_install Service`. + +SQream Installation Command Reference +-------------------------------- +If needed, you can use the **sqream-install** flag reference for any needed flags by typing: + +.. code-block:: console + + $ ./sqream-install --help + +The following shows the **sqream--install** flag descriptions: + +.. list-table:: + :widths: 22 59 25 + :header-rows: 1 + + * - Flag + - Function + - Note + * - **-i** + - Loads all the software from the hidden **.docker** folder. + - Mandatory + * - **-k** + - Loads the license package from the **/license** directory. + - Mandatory + * - **-m** + - Sets the relative path for all SQream folders under the shared filesystem available from all nodes (sqreamdb, config, logs and data_in). No other flags are required if you use this flag (such as c, v, l or d). + - Mandatory + * - **-c** + - Sets the path where to write/read SQream configuration files from. The default is **/etc/sqream/**. + - Optional + * - **-v** + - Shows the location of the SQream cluster. ``v`` creates a cluster if none exist, and mounts it if does. + - Optional + * - **-l** + - Shows the location of the SQream system startup logs. The logs contain startup and Docker logs. The default is **/var/log/sqream/**. + - Optional + * - **-d** + - Shows the folder containing data that you want to import into or copy from SQream. + - Optional + * - **-n** + - Sets the Kubernetes namespace. The default is **sqream**. + - Optional + * - **-N** + - Deletes a specific Kubernetes namespace and sets the factory default namespace (sqream). + - Optional + * - **-f** + - Overwrite existing folders and all files located in mounted directories. + - Optional + * - **-r** + - Resets the system configuration. This flag is run without any other variables. + - Optional + * - **-s** + - Shows the system settings. + - Optional + * - **-e** + - Sets the Kubernetes cluster's virtual IP address. + - Optional + * - **-h** + - Help, shows all available flags. + - Optional + +Go back to :ref:`Running the SQream_install Service`. + +Controlling Your Kubernetes Cluster Using SQream Flags +-------------------------------- +You can control your Kubernetes cluster using SQream flags. + +The following command shows you the available Kubernetes cluster control options: + +.. code-block:: console + + $ ./sqream-start -h + +The following describes the **sqream-start** flags: + +.. list-table:: + :widths: 22 59 25 + :header-rows: 1 + + * - Flag + - Function + - Note + * - **-s** + - Starts the sqream services, starting metadata, server picker, and workers. The number of workers started is based on the number of available GPU’s. + - Mandatory + * - **-p** + - Sets specific ports to the workers services. You must enter the starting port for the sqream-start application to allocate it based on the number of workers. + - + * - **-j** + - Uses an external .json configuration file. The file must be located in the **configuration** directory. + - The workers must each be started individually. + * - **-m** + - Allocates worker spool memory. + - The workers must each be started individually. + * - **-a** + - Starts the SQream Administration dashboard and specifies the listening port. + - + * - **-d** + - Deletes all running SQream services. + - + * - **-h** + - Shows all available flags. + - Help + +Go back to :ref:`Running the SQream_install Service`. + +.. _using_sqream_start_commands: + +Using the sqream-start Commands +======================= +In addition to controlling your Kubernetes cluster using SQream flags, you can control it using **sqream-start** commands. + +The **Using the sqream-start Commands** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Starting Your SQream Services +------------------------ +You can run the **sqream-start** command with the **-s** flag to start SQream services on all available GPU's: + +.. code-block:: console + + $ sudo ./sqream-start -s + +This command starts the SQream metadata, server picker, and sqream workers on all available GPU’s in the cluster. + +The following is an example of the correct output: + +.. code-block:: console + + ./sqream-start -s + Initializing network watchdogs on 3 hosts... + Network watchdogs are up and running + + Initializing 3 worker data collectors ... + Worker data collectors are up and running + + Starting Prometheus ... + Prometheus is available at 192.168.5.100:9090 + + Starting SQream master ... + SQream master is up and running + + Starting up 3 SQream workers ... + All SQream workers are up and running, SQream-DB is available at 192.168.5.100:3108 + All SQream workers are up and running, SQream-DB is available at 192.168.5.100:3108 + + +Go back to :ref:`Using the SQream-start Commands`. + +Starting Your SQream Services in Split Mode +------------------------ +Starting SQream services in split mode refers to running multiple SQream workers on a single GPU. You can do this by running the **sqream-start** command with the **-s** and **-z** flags. In addition, you can define the amount of hosts to run the multiple workers on. In the example below, the command defines to run the multiple workers on three hosts. + +**To start SQream services in split mode:** + +1. Run the following command: + +.. code-block:: console + + $ ./sqream-start -s -z 3 + +This command starts the SQream metadata, server picker, and sqream workers on a single GPU for three hosts: + +The following is an example of the correct output: + +.. code-block:: console + + Initializing network watchdogs on 3 hosts... + Network watchdogs are up and running + + Initializing 3 worker data collectors ... + Worker data collectors are up and running + + Starting Prometheus ... + Prometheus is available at 192.168.5.101:9090 + + Starting SQream master ... + SQream master is up and running + + Starting up 9 SQream workers over <#> available GPUs ... + All SQream workers are up and running, SQream-DB is available at 192.168.5.101:3108 + +2. Verify all pods are properly running in k8s cluster (**STATUS** column): + +.. code-block:: console + + kubectl -n sqream get pods + + NAME READY STATUS RESTARTS AGE + prometheus-bcf877867-kxhld 1/1 Running 0 106s + sqream-metadata-fbcbc989f-6zlkx 1/1 Running 0 103s + sqream-picker-64b8c57ff5-ndfr9 1/1 Running 2 102s + sqream-split-workers-0-1-2-6bdbfbbb86-ml7kn 1/1 Running 0 57s + sqream-split-workers-3-4-5-5cb49d49d7-596n4 1/1 Running 0 57s + sqream-split-workers-6-7-8-6d598f4b68-2n9z5 1/1 Running 0 56s + sqream-workers-start-xj75g 1/1 Running 0 58s + watchdog-network-management-6dnfh 1/1 Running 0 115s + watchdog-network-management-tfd46 1/1 Running 0 115s + watchdog-network-management-xct4d 1/1 Running 0 115s + watchdog-network-storage-lr6v4 1/1 Running 0 116s + watchdog-network-storage-s29h7 1/1 Running 0 116s + watchdog-network-storage-sx9mw 1/1 Running 0 116s + worker-data-collector-62rxs 0/1 Init:0/1 0 54s + worker-data-collector-n8jsv 0/1 Init:0/1 0 55s + worker-data-collector-zp8vf 0/1 Init:0/1 0 54s + +Go back to :ref:`Using the SQream-start Commands`. + +Starting the Sqream Studio UI +-------------------------------- +You can run the following command the to start the SQream Studio UI (Editor and Dashboard): + +.. code-block:: console + + $ ./sqream-start -a + +The following is an example of the correct output: + +.. code-block:: console + + $ ./sqream-start -a + Please enter USERNAME: + sqream + Please enter PASSWORD: + ****** + Please enter port value or press ENTER to keep 8080: + + Starting up SQream Admin UI... + SQream admin ui is available at 192.168.5.100:8080 + +Go back to :ref:`Using the SQream-start Commands`. + +Stopping the SQream Services +-------------------------------- +You can run the following command to stop all SQream services: + +.. code-block:: console + + $ ./sqream-start -d + +The following is an example of the correct output: + +.. code-block:: console + + $ ./sqream-start -d + $ Cleaning all SQream services in sqream namespace ... + $ All SQream service removed from sqream namespace + +Go back to :ref:`Using the SQream-start Commands`. + +Advanced sqream-start Commands +-------------------------------- +Controlling Your SQream Spool Size +~~~~~~~~~~~~~~~~~~~~~~~~ +If you do not specify the SQream spool size, the console automatically distributes the available RAM between all running workers. + +You can define a specific spool size by running the following command: + +.. code-block:: console + + $ ./sqream-start -s -m 4 + +Using a Custom .json File +~~~~~~~~~~~~~~~~~~~~~~~~ +You have the option of using your own .json file for your own custom configurations. Your .json file must be placed within the path mounted in the installation. SQream recommends placing your .json file in the **configuration** folder. + +The SQream console does not validate the integrity of external .json files. + +You can use the following command (using the ``j`` flag) to set the full path of your .json file to the configuration file: + +.. code-block:: console + + $ ./sqream-start -s -f .json + +This command starts one worker with an external configuration file. + +.. note:: The configuration file must be available in the shared configuration folder. + + +Checking the Status of the SQream Services +~~~~~~~~~~~~~~~~~~~~~~~~ +You can show all running SQream services by running the following command: + +.. code-block:: console + + $ kubectl get pods -n -o wide + +This command shows all running services in the cluster and which nodes they are running in. + +Go back to :ref:`Using the SQream-start Commands`. + +Upgrading Your SQream Version +================================ +The **Upgrading Your SQream Version** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Before Upgrading Your System +---------------------------- +Before upgrading your system you must do the following: + +1. Contact SQream support for a new SQream package tarball file. + +:: + +2. Set a maintenance window. + + +.. note:: You must stop the system while upgrading it. + + +Upgrading Your System +---------------------------- +After completing the steps in **Before Upgrading Your System** above, you can upgrade your system. + +**To upgrade your system:** + +1. Extract the contents of the tarball file that you received from SQream support. Make sure to extract the contents to the same directory as in :ref:`getting_sqream_package` and for the same user: + + .. code-block:: console + + $ tar -xvf sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ + $ cd sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ + +2. Start the upgrade process run the following command: + + .. code-block:: console + + $ ./sqream-install -i + +The upgrade process checks if the SQream services are running and will prompt you to stop them. + +3. Do one of the following: + + * Stop the upgrade by writing ``No``. + * Continue the upgrade by writing ``Yes``. + +If you continue upgrading, all running SQream workers (master and editor) are stopped. When all services have been stopped, the new version is loaded. + + +.. note:: SQream periodically upgrades its metadata structure. If an upgrade version includes an upgraded metadata service, an approval request message is displayed. This approval is required to finish the upgrade process. Because SQream supports only specific metadata versions, all SQream services must be upgraded at the same time. + + +4. When SQream has successfully upgraded, load the SQream console and restart your services. + +For questions, contact SQream Support. From c65b8e3c74739587a331c078e3935f71833c498b Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 14:16:46 +0200 Subject: [PATCH 102/300] Create installing_monit.rst Created installing_monit.rst. --- guides/operations/installing_monit.rst | 319 +++++++++++++++++++++++++ 1 file changed, 319 insertions(+) create mode 100644 guides/operations/installing_monit.rst diff --git a/guides/operations/installing_monit.rst b/guides/operations/installing_monit.rst new file mode 100644 index 000000000..85faae964 --- /dev/null +++ b/guides/operations/installing_monit.rst @@ -0,0 +1,319 @@ +.. _installing_monit: + +********************************************* +Installing Monit +********************************************* + +Getting Started +============================== + +Before installing SQream with Monit, verify that you have followed the required :ref:`recommended pre-installation configurations `. + +The procedures in the **Installing Monit** guide must be performed on each SQream cluster node. + + + + + +.. _back_to_top: + +Overview +============================== + + +Monit is a free open source supervision utility for managing and monitoring Unix and Linux. Monit lets you view system status directly from the command line or from a native HTTP web server. Monit can be used to conduct automatic maintenance and repair, such as executing meaningful causal actions in error situations. + +SQream uses Monit as a watchdog utility, but you can use any other utility that provides the same or similar functionality. + +The **Installing Monit** procedures describes how to install, configure, and start Monit. + +You can install Monit in one of the following ways: + +* :ref:`Installing Monit on CentOS ` +* :ref:`Installing Monit on CentOS offline ` +* :ref:`Installing Monit on Ubuntu ` +* :ref:`Installing Monit on Ubuntu offline ` + + + + + + + +.. _installing-monit-on-centos: + +Installing Monit on CentOS: +------------------------------------ + + + +**To install Monit on CentOS:** + +1. Install Monit as a superuser on CentOS: + + .. code-block:: console + + $ sudo yum install monit + + +.. _installing-monit-on-centos-offline: + + + +Installing Monit on CentOS Offline: +------------------------------------ + + +Installing Monit on CentOS offline can be done in either of the following ways: + +* :ref:`Building Monit from Source Code ` +* :ref:`Building Monit from Pre-Built Binaries ` + + + + +.. _building_monit_from_source_code: + +Building Monit from Source Code +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +**To build Monit from source code:** + +1. Copy the Monit package for the current version: + + .. code-block:: console + + $ tar zxvf monit-.tar.gz + + The value ``x.y.z`` denotes the version numbers. + +2. Navigate to the directory where you want to store the package: + + .. code-block:: console + + $ cd monit-x.y.z + +3. Configure the files in the package: + + .. code-block:: console + + $ ./configure (use ./configure --help to view available options) + +4. Build and install the package: + + .. code-block:: console + + $ make && make install + +The following are the default storage directories: + +* The Monit package: **/usr/local/bin/** +* The **monit.1 man-file**: **/usr/local/man/man1/** + +5. **Optional** - To change the above default location(s), use the **--prefix** option to ./configure. + +.. + _**Comment - I took this line directly from the external online documentation. Is the "prefix option" referrin gto the "--help" in Step 3? URL: https://mmonit.com/wiki/Monit/Installation** + +6. **Optional** - Create an RPM package for CentOS directly from the source code: + + .. code-block:: console + + $ rpmbuild -tb monit-x.y.z.tar.gz + +.. + _**Comment - Is this an optional or mandatory step?** + + + + +.. _building_monit_from_pre_built_binaries: + +Building Monit from Pre-Built Binaries +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To build Monit from pre-built binaries:** + +1. Copy the Monit package for the current version: + + .. code-block:: console + + $ tar zxvf monit-x.y.z-linux-x64.tar.gz + + The value ``x.y.z`` denotes the version numbers. + +2. Navigate to the directory where you want to store the package: + + .. code-block:: console$ cd monit-x.y.z + +3. Copy the **bin/monit** and **/usr/local/bin/** directories: + + .. code-block:: console + + $ cp bin/monit /usr/local/bin/ + +4. Copy the **conf/monitrc** and **/etc/** directories: + + .. code-block:: console + + $ cp conf/monitrc /etc/ + +.. + _**Comment - please review this procedure.** + +For examples of pre-built Monit binarties, see :ref:`Download Precompiled Binaries`. + +:ref:`Back to top ` + + + +.. _installing-monit-on-ubuntu: + + + +Installing Monit on Ubuntu: +------------------------------------ + + +**To install Monit on Ubuntu:** + +1. Install Monit as a superuser on Ubuntu: + + .. code-block:: console + + $ sudo apt-get install monit + +:ref:`Back to top ` + + + +.. _installing-monit-on-ubuntu-offline: + + +Installing Monit on Ubuntu Offline: +------------------------------------- + + +You can install Monit on Ubuntu when you do not have an internet connection. + +**To install Monit on Ubuntu offline:** + +1. Compress the required file: + + .. code-block:: console + + $ tar zxvf monit--linux-x64.tar.gz + + **NOTICE:** ** denotes the version number. + +2. Navigate to the directory where you want to save the file: + + .. code-block:: console + + $ cd monit-x.y.z + +3. Copy the **bin/monit** directory into the **/usr/local/bin/** directory: + + .. code-block:: console + + $ cp bin/monit /usr/local/bin/ + +4. Copy the **conf/monitrc** directory into the **/etc/** directory: + + .. code-block:: console + + $ cp conf/monitrc /etc/ + +:ref:`Back to top ` + + +Configuring Monit +==================================== + +When the installation is complete, you can configure Monit. You configure Monit by modifying the Monit configuration file, called **monitrc**. This file contains blocks for each service that you want to monitor. + +The following is an example of a service block: + + .. code-block:: console + + $ #SQREAM1-START + $ check process sqream1 with pidfile /var/run/sqream1.pid + $ start program = "/usr/bin/systemctl start sqream1" + $ stop program = "/usr/bin/systemctl stop sqream1" + $ #SQREAM1-END + +For example, if you have 16 services, you can configure this block by copying the entire block 15 times and modifying all service names as required, as shown below: + + .. code-block:: console + + $ #SQREAM2-START + $ check process sqream2 with pidfile /var/run/sqream2.pid + $ start program = "/usr/bin/systemctl start sqream2" + $ stop program = "/usr/bin/systemctl stop sqream2" + $ #SQREAM2-END + +For servers that don't run the **metadataserver** and **serverpicker** commands, you can use the block example above, but comment out the related commands, as shown below: + + .. code-block:: console + + $ #METADATASERVER-START + $ #check process metadataserver with pidfile /var/run/metadataserver.pid + $ #start program = "/usr/bin/systemctl start metadataserver" + $ #stop program = "/usr/bin/systemctl stop metadataserver" + $ #METADATASERVER-END + +**To configure Monit:** + +1. Copy the required block for each required service. +2. Modify all service names in the block. +3. Copy the configured **monitrc** file to the **/etc/monit.d/** directory: + + .. code-block:: console + + $ cp monitrc /etc/monit.d/ + +4. Set file permissions to **600** (full read and write access): + + .. code-block:: console + + $ sudo chmod 600 /etc/monit.d/monitrc + +5. Reload the system to activate the current configurations: + + .. code-block:: console + + $ sudo systemctl daemon-reload + +6. **Optional** - Navigate to the **/etc/sqream** directory and create a symbolic link to the **monitrc** file: + + .. code-block:: console + + $ cd /etc/sqream + $ sudo ln -s /etc/monit.d/monitrc monitrc + +Starting Monit +==================================== + +After configuring Monit, you can start it. + +**To start Monit:** + +1. Start Monit as a super user: + + .. code-block:: console + + $ sudo systemctl start monit + +2. View Monit's service status: + + .. code-block:: console + + $ sudo systemctl status monit + +3. If Monit is functioning correctly, enable the Monit service to start on boot: + + .. code-block:: console + + $ sudo systemctl enable monit From abcc7729e489ee6a03dad9718ad1845ee07ac557 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 14:20:18 +0200 Subject: [PATCH 103/300] Create installing_monit.rst Created installing_monit.rst. --- guides/operations/installing_monit.rst | 319 +++++++++++++++++++++++++ 1 file changed, 319 insertions(+) create mode 100644 guides/operations/installing_monit.rst diff --git a/guides/operations/installing_monit.rst b/guides/operations/installing_monit.rst new file mode 100644 index 000000000..85faae964 --- /dev/null +++ b/guides/operations/installing_monit.rst @@ -0,0 +1,319 @@ +.. _installing_monit: + +********************************************* +Installing Monit +********************************************* + +Getting Started +============================== + +Before installing SQream with Monit, verify that you have followed the required :ref:`recommended pre-installation configurations `. + +The procedures in the **Installing Monit** guide must be performed on each SQream cluster node. + + + + + +.. _back_to_top: + +Overview +============================== + + +Monit is a free open source supervision utility for managing and monitoring Unix and Linux. Monit lets you view system status directly from the command line or from a native HTTP web server. Monit can be used to conduct automatic maintenance and repair, such as executing meaningful causal actions in error situations. + +SQream uses Monit as a watchdog utility, but you can use any other utility that provides the same or similar functionality. + +The **Installing Monit** procedures describes how to install, configure, and start Monit. + +You can install Monit in one of the following ways: + +* :ref:`Installing Monit on CentOS ` +* :ref:`Installing Monit on CentOS offline ` +* :ref:`Installing Monit on Ubuntu ` +* :ref:`Installing Monit on Ubuntu offline ` + + + + + + + +.. _installing-monit-on-centos: + +Installing Monit on CentOS: +------------------------------------ + + + +**To install Monit on CentOS:** + +1. Install Monit as a superuser on CentOS: + + .. code-block:: console + + $ sudo yum install monit + + +.. _installing-monit-on-centos-offline: + + + +Installing Monit on CentOS Offline: +------------------------------------ + + +Installing Monit on CentOS offline can be done in either of the following ways: + +* :ref:`Building Monit from Source Code ` +* :ref:`Building Monit from Pre-Built Binaries ` + + + + +.. _building_monit_from_source_code: + +Building Monit from Source Code +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +**To build Monit from source code:** + +1. Copy the Monit package for the current version: + + .. code-block:: console + + $ tar zxvf monit-.tar.gz + + The value ``x.y.z`` denotes the version numbers. + +2. Navigate to the directory where you want to store the package: + + .. code-block:: console + + $ cd monit-x.y.z + +3. Configure the files in the package: + + .. code-block:: console + + $ ./configure (use ./configure --help to view available options) + +4. Build and install the package: + + .. code-block:: console + + $ make && make install + +The following are the default storage directories: + +* The Monit package: **/usr/local/bin/** +* The **monit.1 man-file**: **/usr/local/man/man1/** + +5. **Optional** - To change the above default location(s), use the **--prefix** option to ./configure. + +.. + _**Comment - I took this line directly from the external online documentation. Is the "prefix option" referrin gto the "--help" in Step 3? URL: https://mmonit.com/wiki/Monit/Installation** + +6. **Optional** - Create an RPM package for CentOS directly from the source code: + + .. code-block:: console + + $ rpmbuild -tb monit-x.y.z.tar.gz + +.. + _**Comment - Is this an optional or mandatory step?** + + + + +.. _building_monit_from_pre_built_binaries: + +Building Monit from Pre-Built Binaries +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To build Monit from pre-built binaries:** + +1. Copy the Monit package for the current version: + + .. code-block:: console + + $ tar zxvf monit-x.y.z-linux-x64.tar.gz + + The value ``x.y.z`` denotes the version numbers. + +2. Navigate to the directory where you want to store the package: + + .. code-block:: console$ cd monit-x.y.z + +3. Copy the **bin/monit** and **/usr/local/bin/** directories: + + .. code-block:: console + + $ cp bin/monit /usr/local/bin/ + +4. Copy the **conf/monitrc** and **/etc/** directories: + + .. code-block:: console + + $ cp conf/monitrc /etc/ + +.. + _**Comment - please review this procedure.** + +For examples of pre-built Monit binarties, see :ref:`Download Precompiled Binaries`. + +:ref:`Back to top ` + + + +.. _installing-monit-on-ubuntu: + + + +Installing Monit on Ubuntu: +------------------------------------ + + +**To install Monit on Ubuntu:** + +1. Install Monit as a superuser on Ubuntu: + + .. code-block:: console + + $ sudo apt-get install monit + +:ref:`Back to top ` + + + +.. _installing-monit-on-ubuntu-offline: + + +Installing Monit on Ubuntu Offline: +------------------------------------- + + +You can install Monit on Ubuntu when you do not have an internet connection. + +**To install Monit on Ubuntu offline:** + +1. Compress the required file: + + .. code-block:: console + + $ tar zxvf monit--linux-x64.tar.gz + + **NOTICE:** ** denotes the version number. + +2. Navigate to the directory where you want to save the file: + + .. code-block:: console + + $ cd monit-x.y.z + +3. Copy the **bin/monit** directory into the **/usr/local/bin/** directory: + + .. code-block:: console + + $ cp bin/monit /usr/local/bin/ + +4. Copy the **conf/monitrc** directory into the **/etc/** directory: + + .. code-block:: console + + $ cp conf/monitrc /etc/ + +:ref:`Back to top ` + + +Configuring Monit +==================================== + +When the installation is complete, you can configure Monit. You configure Monit by modifying the Monit configuration file, called **monitrc**. This file contains blocks for each service that you want to monitor. + +The following is an example of a service block: + + .. code-block:: console + + $ #SQREAM1-START + $ check process sqream1 with pidfile /var/run/sqream1.pid + $ start program = "/usr/bin/systemctl start sqream1" + $ stop program = "/usr/bin/systemctl stop sqream1" + $ #SQREAM1-END + +For example, if you have 16 services, you can configure this block by copying the entire block 15 times and modifying all service names as required, as shown below: + + .. code-block:: console + + $ #SQREAM2-START + $ check process sqream2 with pidfile /var/run/sqream2.pid + $ start program = "/usr/bin/systemctl start sqream2" + $ stop program = "/usr/bin/systemctl stop sqream2" + $ #SQREAM2-END + +For servers that don't run the **metadataserver** and **serverpicker** commands, you can use the block example above, but comment out the related commands, as shown below: + + .. code-block:: console + + $ #METADATASERVER-START + $ #check process metadataserver with pidfile /var/run/metadataserver.pid + $ #start program = "/usr/bin/systemctl start metadataserver" + $ #stop program = "/usr/bin/systemctl stop metadataserver" + $ #METADATASERVER-END + +**To configure Monit:** + +1. Copy the required block for each required service. +2. Modify all service names in the block. +3. Copy the configured **monitrc** file to the **/etc/monit.d/** directory: + + .. code-block:: console + + $ cp monitrc /etc/monit.d/ + +4. Set file permissions to **600** (full read and write access): + + .. code-block:: console + + $ sudo chmod 600 /etc/monit.d/monitrc + +5. Reload the system to activate the current configurations: + + .. code-block:: console + + $ sudo systemctl daemon-reload + +6. **Optional** - Navigate to the **/etc/sqream** directory and create a symbolic link to the **monitrc** file: + + .. code-block:: console + + $ cd /etc/sqream + $ sudo ln -s /etc/monit.d/monitrc monitrc + +Starting Monit +==================================== + +After configuring Monit, you can start it. + +**To start Monit:** + +1. Start Monit as a super user: + + .. code-block:: console + + $ sudo systemctl start monit + +2. View Monit's service status: + + .. code-block:: console + + $ sudo systemctl status monit + +3. If Monit is functioning correctly, enable the Monit service to start on boot: + + .. code-block:: console + + $ sudo systemctl enable monit From af5ce550f963ac48926a46b8ecf0077f5673852e Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 14:22:00 +0200 Subject: [PATCH 104/300] Create launching_sqream_with_monit.rst Created launching_sqream_with_monit.rst. --- .../launching_sqream_with_monit.rst | 290 ++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 guides/operations/launching_sqream_with_monit.rst diff --git a/guides/operations/launching_sqream_with_monit.rst b/guides/operations/launching_sqream_with_monit.rst new file mode 100644 index 000000000..7a26d5c91 --- /dev/null +++ b/guides/operations/launching_sqream_with_monit.rst @@ -0,0 +1,290 @@ +.. _launching_sqream_with_monit: + +********************************************* +Launching SQream with Monit +********************************************* +This procedure describes how to launch SQream using Monit. + +Launching SQream +==================================== + +After doing the following, you can launch SQream according to the instructions on this page. + + + +1. :ref:`Installing Monit ` +2. :ref:`Installing SQream with Binary ` + + + + +The following is an example of a working monitrc file configured to monitor the ***metadataserver** and **serverpicker** commands, and **four sqreamd services**. The **monitrc** configuration file is located in the **conf/monitrc** directory. + +Note that the **monitrc** in the following example is configured for eight ``sqreamd`` services, but that only the first four are enabled: + +.. code-block:: console + + $ set daemon 5 # check services at 30 seconds intervals + $ set logfile syslog + $ + $ set httpd port 2812 and + $ use address localhost # only accept connection from localhost + $ allow localhost # allow localhost to connect to the server and + $ allow admin:monit # require user 'admin' with password 'monit' + $ + $ ##set mailserver smtp.gmail.com port 587 + $ ## using tlsv12 + $ #METADATASERVER-START + $ check process metadataserver with pidfile /var/run/metadataserver.pid + $ start program = "/usr/bin/systemctl start metadataserver" + $ stop program = "/usr/bin/systemctl stop metadataserver" + $ #METADATASERVER-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: metadataserver $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ #SERVERPICKER-START + $ check process serverpicker with pidfile /var/run/serverpicker.pid + $ start program = "/usr/bin/systemctl start serverpicker" + $ stop program = "/usr/bin/systemctl stop serverpicker" + $ #SERVERPICKER-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: serverpicker $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # + $ # + $ #SQREAM1-START + $ check process sqream1 with pidfile /var/run/sqream1.pid + $ start program = "/usr/bin/systemctl start sqream1" + $ stop program = "/usr/bin/systemctl stop sqream1" + $ #SQREAM1-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream1 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ #SQREAM2-START + $ check process sqream2 with pidfile /var/run/sqream2.pid + $ start program = "/usr/bin/systemctl start sqream2" + $ #SQREAM2-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream1 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ #SQREAM3-START + $ check process sqream3 with pidfile /var/run/sqream3.pid + $ start program = "/usr/bin/systemctl start sqream3" + $ stop program = "/usr/bin/systemctl stop sqream3" + $ #SQREAM3-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ #SQREAM4-START + $ check process sqream4 with pidfile /var/run/sqream4.pid + $ start program = "/usr/bin/systemctl start sqream4" + $ stop program = "/usr/bin/systemctl stop sqream4" + $ #SQREAM4-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ # + $ #SQREAM5-START + $ #check process sqream5 with pidfile /var/run/sqream5.pid + $ #start program = "/usr/bin/systemctl start sqream5" + $ #stop program = "/usr/bin/systemctl stop sqream5" + $ #SQREAM5-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ # + $ #SQREAM6-START + $ #check process sqream6 with pidfile /var/run/sqream6.pid + $ #start program = "/usr/bin/systemctl start sqream6" + $ #stop program = "/usr/bin/systemctl stop sqream6" + $ #SQREAM6-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ # + $ #SQREAM7-START + $ #check process sqream7 with pidfile /var/run/sqream7.pid + $ #start program = "/usr/bin/systemctl start sqream7" + $ #stop program = "/usr/bin/systemctl stop sqream7" + $ #SQREAM7-END + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ # + $ #SQREAM8-START + $ #check process sqream8 with pidfile /var/run/sqream8.pid + $ #start program = "/usr/bin/systemctl start sqream8" + $ #stop program = "/usr/bin/systemctl stop sqream8" + $ #SQREAM8-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + +Monit Usage Examples +==================================== + +This section shows examples of two methods for stopping the **sqream3** service use Monit's command syntax: + + + +* :ref:`Stopping Monit and SQream separately ` +* :ref:`Stopping SQream using a Monit command ` + +.. _stopping_monit_and_sqream_separately: + +Stopping Monit and SQream Separately +------------------------------------- + +You can stop the Monit service and SQream separately as follows: + +.. code-block:: console + + $ sudo systemctl stop monit + $ sudo systemctl stop sqream3 + +You can restart Monit as follows: + +.. code-block:: console + + $ sudo systemctl start monit + +Restarting Monit automatically restarts the SQream services. + +.. _stopping_sqream_using_a_monit_command: + +Stopping SQream Using a Monit Command +------------------------------------- + +You can stop SQream using a Monit command as follows: + +.. code-block:: console + + $ sudo monit stop sqream3 + +This command stops SQream only (and not Monit). + +You can restart SQream as follows: + +.. code-block:: console + + $ sudo monit start sqream3 + +Monit Command Line Options +------------------------------------- +The **Monit Command Line Options** section describes some of the most commonly used Monit command options. + +You can show the command line options by running: + +.. code-block:: console + + $ monit --help + +.. code-block:: console + + $ start all - Start all services + $ start - Only start the named service + $ stop all - Stop all services + $ stop - Stop the named service + $ restart all - Stop and start all services + $ restart - Only restart the named service + $ monitor all - Enable monitoring of all services + $ monitor - Only enable monitoring of the named service + $ unmonitor all - Disable monitoring of all services + $ unmonitor - Only disable monitoring of the named service + $ reload - Reinitialize monit + $ status [name] - Print full status information for service(s) + $ summary [name] - Print short status information for service(s) + $ report [up|down|..] - Report state of services. See manual for options + $ quit - Kill the monit daemon process + $ validate - Check all services and start if not running + $ procmatch - Test process matching pattern + +Using Monit While Upgrading Your Version of SQream +================================================== + +While upgrading your version of SQream, you can use Monit to avoid conflicts (such as service start). This is done by pausing or stopping all running services while you manually upgrade SQream. When you finish successfully upgrading SQream, you can use Monit to restart all SQream services + +**To use Monit while upgrading your version of SQream:** + +1. Stop all actively running SQream services: + + .. code-block:: console + + $ sudo monit stop all + +2. Verify that SQream has stopped listening on ports **500X**, **510X**, and **310X**: + + .. code-block:: console + + $ sudo netstat -nltp #to make sure sqream stopped listening on 500X, 510X and 310X ports. + + The example below shows the old version ``sqream-db-v2020.2`` being replaced with the new version ``sqream-db-v2025.200``. + + .. code-block:: console + + $ cd /home/sqream + $ mkdir tempfolder + $ mv sqream-db-v2025.200.tar.gz tempfolder/ + $ tar -xf sqream-db-v2025.200.tar.gz + $ sudo mv sqream /usr/local/sqream-db-v2025.200 + $ cd /usr/local + $ sudo chown -R sqream:sqream sqream-db-v2025.200 + $ sudo rm sqream #This only should remove symlink + $ sudo ln -s sqream-db-v2025.200 sqream #this will create new symlink named "sqream" pointing to new version + $ ls -l + + The symbolic SQream link should point to the real folder: + + .. code-block:: console + + $ sqream -> sqream-db-v2025.200 + +4. Restart the SQream services: + + .. code-block:: console + + $ sudo monit start all + +5. Verify that the latest version has been installed: + + .. code-block:: console + + $ SELECT SHOW_VERSION(); + + The correct version is output. + + :: + +6. Restart the UI: + + .. code-block:: console + + $ pm2 start all From 916b89c9d23e9c05a16a81170eaf92015c89950a Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 14:24:09 +0200 Subject: [PATCH 105/300] Create launching_sqream_with_monit.rst Created launching_sqream_with_monit.rst. --- .../launching_sqream_with_monit.rst | 290 ++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 guides/operations/launching_sqream_with_monit.rst diff --git a/guides/operations/launching_sqream_with_monit.rst b/guides/operations/launching_sqream_with_monit.rst new file mode 100644 index 000000000..7a26d5c91 --- /dev/null +++ b/guides/operations/launching_sqream_with_monit.rst @@ -0,0 +1,290 @@ +.. _launching_sqream_with_monit: + +********************************************* +Launching SQream with Monit +********************************************* +This procedure describes how to launch SQream using Monit. + +Launching SQream +==================================== + +After doing the following, you can launch SQream according to the instructions on this page. + + + +1. :ref:`Installing Monit ` +2. :ref:`Installing SQream with Binary ` + + + + +The following is an example of a working monitrc file configured to monitor the ***metadataserver** and **serverpicker** commands, and **four sqreamd services**. The **monitrc** configuration file is located in the **conf/monitrc** directory. + +Note that the **monitrc** in the following example is configured for eight ``sqreamd`` services, but that only the first four are enabled: + +.. code-block:: console + + $ set daemon 5 # check services at 30 seconds intervals + $ set logfile syslog + $ + $ set httpd port 2812 and + $ use address localhost # only accept connection from localhost + $ allow localhost # allow localhost to connect to the server and + $ allow admin:monit # require user 'admin' with password 'monit' + $ + $ ##set mailserver smtp.gmail.com port 587 + $ ## using tlsv12 + $ #METADATASERVER-START + $ check process metadataserver with pidfile /var/run/metadataserver.pid + $ start program = "/usr/bin/systemctl start metadataserver" + $ stop program = "/usr/bin/systemctl stop metadataserver" + $ #METADATASERVER-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: metadataserver $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ #SERVERPICKER-START + $ check process serverpicker with pidfile /var/run/serverpicker.pid + $ start program = "/usr/bin/systemctl start serverpicker" + $ stop program = "/usr/bin/systemctl stop serverpicker" + $ #SERVERPICKER-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: serverpicker $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # + $ # + $ #SQREAM1-START + $ check process sqream1 with pidfile /var/run/sqream1.pid + $ start program = "/usr/bin/systemctl start sqream1" + $ stop program = "/usr/bin/systemctl stop sqream1" + $ #SQREAM1-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream1 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ #SQREAM2-START + $ check process sqream2 with pidfile /var/run/sqream2.pid + $ start program = "/usr/bin/systemctl start sqream2" + $ #SQREAM2-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream1 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ #SQREAM3-START + $ check process sqream3 with pidfile /var/run/sqream3.pid + $ start program = "/usr/bin/systemctl start sqream3" + $ stop program = "/usr/bin/systemctl stop sqream3" + $ #SQREAM3-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ #SQREAM4-START + $ check process sqream4 with pidfile /var/run/sqream4.pid + $ start program = "/usr/bin/systemctl start sqream4" + $ stop program = "/usr/bin/systemctl stop sqream4" + $ #SQREAM4-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ # + $ #SQREAM5-START + $ #check process sqream5 with pidfile /var/run/sqream5.pid + $ #start program = "/usr/bin/systemctl start sqream5" + $ #stop program = "/usr/bin/systemctl stop sqream5" + $ #SQREAM5-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ # + $ #SQREAM6-START + $ #check process sqream6 with pidfile /var/run/sqream6.pid + $ #start program = "/usr/bin/systemctl start sqream6" + $ #stop program = "/usr/bin/systemctl stop sqream6" + $ #SQREAM6-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ # + $ #SQREAM7-START + $ #check process sqream7 with pidfile /var/run/sqream7.pid + $ #start program = "/usr/bin/systemctl start sqream7" + $ #stop program = "/usr/bin/systemctl stop sqream7" + $ #SQREAM7-END + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ # + $ #SQREAM8-START + $ #check process sqream8 with pidfile /var/run/sqream8.pid + $ #start program = "/usr/bin/systemctl start sqream8" + $ #stop program = "/usr/bin/systemctl stop sqream8" + $ #SQREAM8-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + +Monit Usage Examples +==================================== + +This section shows examples of two methods for stopping the **sqream3** service use Monit's command syntax: + + + +* :ref:`Stopping Monit and SQream separately ` +* :ref:`Stopping SQream using a Monit command ` + +.. _stopping_monit_and_sqream_separately: + +Stopping Monit and SQream Separately +------------------------------------- + +You can stop the Monit service and SQream separately as follows: + +.. code-block:: console + + $ sudo systemctl stop monit + $ sudo systemctl stop sqream3 + +You can restart Monit as follows: + +.. code-block:: console + + $ sudo systemctl start monit + +Restarting Monit automatically restarts the SQream services. + +.. _stopping_sqream_using_a_monit_command: + +Stopping SQream Using a Monit Command +------------------------------------- + +You can stop SQream using a Monit command as follows: + +.. code-block:: console + + $ sudo monit stop sqream3 + +This command stops SQream only (and not Monit). + +You can restart SQream as follows: + +.. code-block:: console + + $ sudo monit start sqream3 + +Monit Command Line Options +------------------------------------- +The **Monit Command Line Options** section describes some of the most commonly used Monit command options. + +You can show the command line options by running: + +.. code-block:: console + + $ monit --help + +.. code-block:: console + + $ start all - Start all services + $ start - Only start the named service + $ stop all - Stop all services + $ stop - Stop the named service + $ restart all - Stop and start all services + $ restart - Only restart the named service + $ monitor all - Enable monitoring of all services + $ monitor - Only enable monitoring of the named service + $ unmonitor all - Disable monitoring of all services + $ unmonitor - Only disable monitoring of the named service + $ reload - Reinitialize monit + $ status [name] - Print full status information for service(s) + $ summary [name] - Print short status information for service(s) + $ report [up|down|..] - Report state of services. See manual for options + $ quit - Kill the monit daemon process + $ validate - Check all services and start if not running + $ procmatch - Test process matching pattern + +Using Monit While Upgrading Your Version of SQream +================================================== + +While upgrading your version of SQream, you can use Monit to avoid conflicts (such as service start). This is done by pausing or stopping all running services while you manually upgrade SQream. When you finish successfully upgrading SQream, you can use Monit to restart all SQream services + +**To use Monit while upgrading your version of SQream:** + +1. Stop all actively running SQream services: + + .. code-block:: console + + $ sudo monit stop all + +2. Verify that SQream has stopped listening on ports **500X**, **510X**, and **310X**: + + .. code-block:: console + + $ sudo netstat -nltp #to make sure sqream stopped listening on 500X, 510X and 310X ports. + + The example below shows the old version ``sqream-db-v2020.2`` being replaced with the new version ``sqream-db-v2025.200``. + + .. code-block:: console + + $ cd /home/sqream + $ mkdir tempfolder + $ mv sqream-db-v2025.200.tar.gz tempfolder/ + $ tar -xf sqream-db-v2025.200.tar.gz + $ sudo mv sqream /usr/local/sqream-db-v2025.200 + $ cd /usr/local + $ sudo chown -R sqream:sqream sqream-db-v2025.200 + $ sudo rm sqream #This only should remove symlink + $ sudo ln -s sqream-db-v2025.200 sqream #this will create new symlink named "sqream" pointing to new version + $ ls -l + + The symbolic SQream link should point to the real folder: + + .. code-block:: console + + $ sqream -> sqream-db-v2025.200 + +4. Restart the SQream services: + + .. code-block:: console + + $ sudo monit start all + +5. Verify that the latest version has been installed: + + .. code-block:: console + + $ SELECT SHOW_VERSION(); + + The correct version is output. + + :: + +6. Restart the UI: + + .. code-block:: console + + $ pm2 start all From 0f624f3f16f389bff90b43d25158f799b33ae923 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 14:34:53 +0200 Subject: [PATCH 106/300] Update index.rst Added items: installing_monit launching_sqream_with_monit --- guides/operations/index.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/guides/operations/index.rst b/guides/operations/index.rst index 4df9c0314..b8efaea25 100644 --- a/guides/operations/index.rst +++ b/guides/operations/index.rst @@ -13,9 +13,10 @@ The guides in this section include information about best practices, monitoring, optimization_best_practices recommended_pre-installation_configurations + installing_monit + launching_sqream_with_monit xxmonitoring monitoring_query_performance - launching_sqream_with_monit running_sqream_in_a_docker_container logging configuration From 40f44ab3e1979bec71816d4ee234a0d70fa7919f Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 14:38:15 +0200 Subject: [PATCH 107/300] Update index.rst Updated index. --- guides/operations/index.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/guides/operations/index.rst b/guides/operations/index.rst index 5c21a2f71..46719da3a 100644 --- a/guides/operations/index.rst +++ b/guides/operations/index.rst @@ -14,6 +14,10 @@ The guides in this section include information about best practices, monitoring, optimization_best_practices recommended_pre-installation_configurations xxmonitoring + installing_monit + launching_sqream_with_monit + installing_sqream_with_binary + installing_sqream_with_kubernetes running_sqream_in_a_docker_container logging configuration From 261b0ab8d72f9bc18c0c271d1e1b7d8d463997de Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 14:41:58 +0200 Subject: [PATCH 108/300] Update index.rst Updated index. --- guides/operations/index.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/guides/operations/index.rst b/guides/operations/index.rst index b8efaea25..25a624ad3 100644 --- a/guides/operations/index.rst +++ b/guides/operations/index.rst @@ -15,9 +15,11 @@ The guides in this section include information about best practices, monitoring, recommended_pre-installation_configurations installing_monit launching_sqream_with_monit + installing_sqream_with_binary + installing_sqream_with_kubernetes + running_sqream_in_a_docker_container xxmonitoring monitoring_query_performance - running_sqream_in_a_docker_container logging configuration troubleshooting From 1aa213c747f94ba15087600561a6378674e6afbe Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 15:45:21 +0200 Subject: [PATCH 109/300] Update running_sqream_in_a_docker_container.rst Added note: You must install the SQream software under a *sqream* and not a *root* user. --- .../operations/running_sqream_in_a_docker_container.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/guides/operations/running_sqream_in_a_docker_container.rst b/guides/operations/running_sqream_in_a_docker_container.rst index 7750db570..cd2b5294e 100644 --- a/guides/operations/running_sqream_in_a_docker_container.rst +++ b/guides/operations/running_sqream_in_a_docker_container.rst @@ -37,19 +37,19 @@ To run SQream in a Docker container you must create a local user. .. code-block:: console - $ useradd -m -U sqream + $ useradd -m -U 2. Set the local user's password: .. code-block:: console - $ passwd sqream + $ passwd 3. Add the local user to the ``wheel`` group: .. code-block:: console - $ usermod -aG wheel sqream + $ usermod -aG wheel You can remove the local user from the ``wheel`` group when you have completed the installation. @@ -808,6 +808,8 @@ Preparing Your Local Environment ------------------------- After installing the Nvidia Docker2 toolKit you must prepare your local environment. +.. note:: You must install the SQream software under a *sqream* and not a *root* user. + The Linux user preparing the local environment must have **read/write** access to the following directories for the SQream software to correctly read and write the required resources: * **Log directory** - default: /var/log/sqream/ From f3a3fac18169120540b2b74dcbba782dbe3231c2 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 7 Nov 2021 15:46:50 +0200 Subject: [PATCH 110/300] Update running_sqream_in_a_docker_container.rst Added note: You must install the SQream software under a *sqream* and not a *root* user. --- .../operations/running_sqream_in_a_docker_container.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/guides/operations/running_sqream_in_a_docker_container.rst b/guides/operations/running_sqream_in_a_docker_container.rst index 7750db570..cd2b5294e 100644 --- a/guides/operations/running_sqream_in_a_docker_container.rst +++ b/guides/operations/running_sqream_in_a_docker_container.rst @@ -37,19 +37,19 @@ To run SQream in a Docker container you must create a local user. .. code-block:: console - $ useradd -m -U sqream + $ useradd -m -U 2. Set the local user's password: .. code-block:: console - $ passwd sqream + $ passwd 3. Add the local user to the ``wheel`` group: .. code-block:: console - $ usermod -aG wheel sqream + $ usermod -aG wheel You can remove the local user from the ``wheel`` group when you have completed the installation. @@ -808,6 +808,8 @@ Preparing Your Local Environment ------------------------- After installing the Nvidia Docker2 toolKit you must prepare your local environment. +.. note:: You must install the SQream software under a *sqream* and not a *root* user. + The Linux user preparing the local environment must have **read/write** access to the following directories for the SQream software to correctly read and write the required resources: * **Log directory** - default: /var/log/sqream/ From 88bc81504e53a812c88f1242cb3db8fd2328606c Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 8 Nov 2021 11:36:31 +0200 Subject: [PATCH 111/300] Update 2020.3.rst Updated according to Master. Editing and wording. --- releases/2020.3.rst | 94 ++++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 43 deletions(-) diff --git a/releases/2020.3.rst b/releases/2020.3.rst index 691ba5adf..08f39f776 100644 --- a/releases/2020.3.rst +++ b/releases/2020.3.rst @@ -7,12 +7,14 @@ What's New in 2020.3 SQream DB v2020.3 contains new features, improved performance, and bug fixes. -New features -============ +New Features +---------- +The following list describes the new features: + * Parquet and ORC files can now be exported to local storage, S3, and HDFS with :ref:`copy_to` and foreign data wrappers. -* We've introduced new error tolerance features when loading data with foreign data wrappers +* New error tolerance features when loading data with foreign data wrappers. * ``TEXT`` is ramping up with new features (previously only available with VARCHARs): @@ -24,50 +26,56 @@ New features * :ref:`sqream_studio` v5.1 - * New log viewer helps you track and debug what's going on in SQream DB + * New log viewer helps you track and debug what's going on in SQream DB. - * Dashboard now also available for non-k8s deployments + * Dashboard now also available for non-k8s deployments. - * The editor contains a new query concurrency tool for date and numeric ranges + * The editor contains a new query concurrency tool for date and numeric ranges. -Enhancements -============ - -* Error handling for CSV FDW -* Enable logging errors - ORC, Parquet, CSV -* Add limit and offset options to csv_fdw import -* Enable logging errors to an external file when skipping CSV, Parquet, and ORC errors -* Option to specify date format to the CSV FDW -* Support all existing Varchar functions with Text on GPU -* Support INSERT INTO + ORDER BY optimization for non-clustered tables -* Performance improvements with I/O - -Bug fixes -============ - -* Better error message when passing the max errors limit -* showFullExceptionInfo is no longer restricted to developer mode -* StreamAggregateA reduction error when performing aggregation on a null column -* Insert into query fails with ""Error at Sql phase during Stages ""rewriteSqlQuery"" -* Cast from varchar to nvarchar doesn't remove the spaces -* Internal Runtime Error t1.size() == t2.size() when querying sqream_catalog.delete_predicates -* spoolMemoryGB and limitQueryMemoryGB show incorrectly in the runtime global section of show_conf -* Casting empty text to int causes illegal memory access -* Copy from TEXT field is 1.5x slower than the VARCHAR equivalent -* TPCDS 10TB - Internal runtime error (std::bad_alloc: out of memory) on 2020.1.0.2 -* Not equal join on not existing TEXT crashes the system -* Internal runtime time error when using TEXT (tpcds) -* Copying CSV with a quote in the middle of a field to TEXT field does not produce an error -* Can't monitor long network insert loads with SQream -* Upper & like performance on Nvarchar -* Insert into from 4 instances get stuck (hanging) -* An invalid formatted CSV can cause an insufficient memory error on a COPY FROM statement if a quote isn’t closed and the file is much larger than system memory. -* TEXT columns can’t be used with an outer join together with an inequality check (!= , <>) - -Known Issues & Limitations -================================ +Performance Enhancements +---------- +The following list describes the performance enhancements: + + +* Error handling for CSV FDW. +* Enable logging errors - ORC, Parquet, CSV. +* Add limit and offset options to ``csv_fdw`` import. +* Enable logging errors to an external file when skipping CSV, Parquet, and ORC errors. +* Option to specify date format to the CSV FDW. +* Support all existing ``VARCHAR`` functions with ``TEXT`` on GPU. +* Support ``INSERT INTO`` + ``ORDER BY`` optimization for non-clustered tables. +* Performance improvements with I/O. + +Resolved Issues +--------------- +The following list describes the resolved issues: + + +* Better error message when passing the max errors limit. This was fixed. +* ``showFullExceptionInfo`` is no longer restricted to Developer Mode. This was fixed. +* An ``StreamAggregateA`` reduction error occured when performing aggregation on a ``NULL`` column. This was fixed. +* Insert into query fails with ""Error at Sql phase during Stages ""rewriteSqlQuery"". This was fixed. +* Casting from ``VARCHAR`` to ``NVARCHAR` does not remove the spaces. This was fixed. +* An ``Internal Runtime Error t1.size() == t2.size()`` occurs when querying the ``sqream_catalog.delete_predicates``. This was fixed. +* ``spoolMemoryGB`` and ``limitQueryMemoryGB`` show incorrectly in the **runtime global** section of ``show_conf.`` This was fixed. +* Casting empty text to ``int`` causes illegal memory access. This was fixed. +* Copying from the ``TEXT`` field is 1.5x slower than the ``VARCHAR`` equivalent. This was fixed. +* ``TPCDS 10TB - Internal runtime error (std::bad_alloc: out of memory)`` occurs on 2020.1.0.2. This was fixed. +* An unequal join on non-existing ``TEXT`` caused a system crash. This was fixed. +* An ``Internal runtime time error`` occured when using ``TEXT (tpcds)``. This was fixed. +* Copying CSV with a quote in the middle of a field to a ``TEXT`` field does not produce the required error. This was fixed. +* Cannot monitor long network insert loads with SQream. This was fixed. +* Upper and like performance on ``NVARCHAR``. This was fixed. +* Insert into from 4 instances would get stuck (hanging). This was fixed. +* An invalid formatted CSV would cause an insufficient memory error on a ``COPY FROM`` statement if a quote was not closed and the file was much larger than system memory. This was fixed. +* ``TEXT`` columns cannot be used with an outer join together with an inequality check (!= , <>). This was fixed. + +Known Issues and Limitations +---------- +The following list describes the known issues and limitations: + * Cast from ``TEXT`` to a ``DATE`` or ``DATETIME`` errors when the ``TEXT`` column contains ``NULL`` @@ -79,7 +87,7 @@ Known Issues & Limitations Upgrading to v2020.3 -======================== +---------- Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. From 5b19fe085638583412c9adbc6946883d3ee4f401 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 8 Nov 2021 13:37:43 +0200 Subject: [PATCH 112/300] Update running_sqream_in_a_docker_container.rst Joined lines 995 and 996 into one command per Slavi's request. --- guides/operations/running_sqream_in_a_docker_container.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/guides/operations/running_sqream_in_a_docker_container.rst b/guides/operations/running_sqream_in_a_docker_container.rst index cd2b5294e..11aac5374 100644 --- a/guides/operations/running_sqream_in_a_docker_container.rst +++ b/guides/operations/running_sqream_in_a_docker_container.rst @@ -992,8 +992,7 @@ The following is an example of the correct command syntax: .. code-block:: console - $ sudo ./sqream-install -i -k -c /etc/sqream -v /home/sqream/sqreamdb -l - $ /var/log/sqream -d /home/sqream/data_ingest + $ sudo ./sqream-install -i -k -c /etc/sqream -v /home/sqream/sqreamdb -l /var/log/sqream -d /home/sqream/data_ingest .. _setting_hadoop_kubernetes_connectivity_parameters: From a81dbf16d4e987eab7db550f55606011805a713e Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 8 Nov 2021 13:39:15 +0200 Subject: [PATCH 113/300] Update running_sqream_in_a_docker_container.rst Joined lines 995 and 996 into one command per Slavi's request. --- guides/operations/running_sqream_in_a_docker_container.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/guides/operations/running_sqream_in_a_docker_container.rst b/guides/operations/running_sqream_in_a_docker_container.rst index cd2b5294e..11aac5374 100644 --- a/guides/operations/running_sqream_in_a_docker_container.rst +++ b/guides/operations/running_sqream_in_a_docker_container.rst @@ -992,8 +992,7 @@ The following is an example of the correct command syntax: .. code-block:: console - $ sudo ./sqream-install -i -k -c /etc/sqream -v /home/sqream/sqreamdb -l - $ /var/log/sqream -d /home/sqream/data_ingest + $ sudo ./sqream-install -i -k -c /etc/sqream -v /home/sqream/sqreamdb -l /var/log/sqream -d /home/sqream/data_ingest .. _setting_hadoop_kubernetes_connectivity_parameters: From edc572398c1b6339fce955790ba7cf0f3aa39ccc Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 14 Nov 2021 10:24:54 +0200 Subject: [PATCH 114/300] Update window_functions.rst Removed the first two bullets in the Limitations section and added one according to TPD-65. --- reference/sql/sql_syntax/window_functions.rst | 83 ++++++++++++------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/reference/sql/sql_syntax/window_functions.rst b/reference/sql/sql_syntax/window_functions.rst index 4c07f5a5d..cb87e085e 100644 --- a/reference/sql/sql_syntax/window_functions.rst +++ b/reference/sql/sql_syntax/window_functions.rst @@ -1,7 +1,7 @@ .. _window_functions: ******************** -Window functions +Window Functions ******************** Window functions are functions applied over a subset (known as a window) of the rows returned by a :ref:`select` query. @@ -30,6 +30,13 @@ Syntax | RANK | ROW_NUMBER | SUM + | FIRST_VALUE + | LAST_VALUE + | NTH_VALUE + | DENSE_RANK + | PERCENT_RANK + | CUME_DIST + | NTILE frame_clause ::= @@ -68,38 +75,62 @@ Arguments - An expression or column reference to order by -Supported window functions +Supported Window Functions =========================== -.. list-table:: Window function aggregations - :widths: auto +.. list-table:: Window Aggregation Functions + :widths: 16 200 :header-rows: 1 * - Function + - Description * - :ref:`avg` + - Returns the average of numeric values. * - :ref:`count` + - Returns the count of numeric values, or only the distinct values. * - :ref:`max` + - Returns the maximum values. * - :ref:`min` + - Returns the minimum values. * - :ref:`sum` + - Returns the sum of numeric values, or only the distinct values. + + -.. versionchanged:: 2020.1 - :ref:`count` and :ref:`avg` are supported in window functions from v2020.1. -.. list-table:: Ranking functions - :widths: auto +.. list-table:: Ranking Functions + :widths: 15 200 :header-rows: 1 - + * - Function + - Description * - :ref:`lag` + - Returns a value from a previous row within the partition of a result set. * - :ref:`lead` - * - :ref:`rank` + - Returns a value from a subsequent row within the partition of a result set. * - :ref:`row_number` - -.. versionchanged:: 2020.2 - :ref:`lag` and :ref:`lead` are supported from v2020.2. - - -How window functions work + - Returns the row number of each row within the partition of a result set. + * - :ref:`rank` + - Returns the rank of each row within the partition of a result set. + * - :ref:`first_value` + - Returns the value in the first row of a window. + * - :ref:`last_value` + - Returns the value in the last row of a window. + * - :ref:`nth_value` + - Returns the value in a specified (``n``) row of a window. + * - :ref:`dense_rank` + - Returns the rank of the current row with no gaps. + * - :ref:`percent_rank` + - Returns the relative rank of the current row. + * - :ref:`cume_dist` + - Returns the cumulative distribution of rows. + * - :ref:`ntile` + - Returns an integer ranging between ``1`` and the argument value, dividing the partitions as equally as possible. + + + + +How Window Functions Work ============================ A window function operates on a subset ("window") of rows. @@ -137,8 +168,7 @@ Without ``ORDER BY``, rows are processed in an unspecified order. Frames ------- -.. versionchanged:: 2020.1 - Frames are supported from v2020.1. + .. note:: Frames and frame exclusions have been tested extensively, but are a complex feature. They are released as a preview in v2020.1 pending longer-term testing. @@ -171,17 +201,14 @@ Restrictions For example ``RANGE BETWEEN CURRENT ROW AND 7 PRECEDING`` is not allowed. However, while ``ROWS BETWEEN 7 PRECEDING AND 8 PRECEDING`` is allowed, it would never select any rows. -Frame exclusion +Frame Exclusion ----------------- The ``frame_exclusion`` option allows rows around the current row to be excluded from the frame, even if they would be included according to the frame start and frame end options. ``EXCLUDE CURRENT ROW`` excludes the current row from the frame. ``EXCLUDE GROUP`` excludes the current row and its ordering peers from the frame. ``EXCLUDE TIES`` excludes any peers of the current row from the frame, but not the current row itself. ``EXCLUDE NO OTHERS`` simply specifies explicitly the default behavior of not excluding the current row or its peers. Limitations ================== - -* At this phase, text columns are not supported in window function expressions. - -* Window function calls are permitted only in the :ref:`select` list. +Window functions do not support the Numeric data type. @@ -213,7 +240,7 @@ Here's a peek at the table contents (:download:`Download nba.csv Date: Sun, 14 Nov 2021 10:26:16 +0200 Subject: [PATCH 115/300] Update window_functions.rst Removed the first two bullets in the Limitations section and added one according to TPD-65. --- reference/sql/sql_syntax/window_functions.rst | 113 ++++++++++++++---- 1 file changed, 90 insertions(+), 23 deletions(-) diff --git a/reference/sql/sql_syntax/window_functions.rst b/reference/sql/sql_syntax/window_functions.rst index 7c71db6d9..cb87e085e 100644 --- a/reference/sql/sql_syntax/window_functions.rst +++ b/reference/sql/sql_syntax/window_functions.rst @@ -1,7 +1,7 @@ .. _window_functions: ******************** -Window functions +Window Functions ******************** Window functions are functions applied over a subset (known as a window) of the rows returned by a :ref:`select` query. @@ -23,11 +23,20 @@ Syntax window_fn ::= | AVG | COUNT + | LAG + | LEAD | MAX | MIN | RANK | ROW_NUMBER | SUM + | FIRST_VALUE + | LAST_VALUE + | NTH_VALUE + | DENSE_RANK + | PERCENT_RANK + | CUME_DIST + | NTILE frame_clause ::= @@ -66,33 +75,62 @@ Arguments - An expression or column reference to order by -Supported window functions +Supported Window Functions =========================== -.. list-table:: Window function aggregations - :widths: auto +.. list-table:: Window Aggregation Functions + :widths: 16 200 :header-rows: 1 * - Function + - Description * - :ref:`avg` + - Returns the average of numeric values. * - :ref:`count` + - Returns the count of numeric values, or only the distinct values. * - :ref:`max` + - Returns the maximum values. * - :ref:`min` + - Returns the minimum values. * - :ref:`sum` + - Returns the sum of numeric values, or only the distinct values. + + -.. versionchanged:: 2020.1 - :ref:`count` and :ref:`avg` are supported in window functions from v2020.1. -.. list-table:: Ranking functions - :widths: auto +.. list-table:: Ranking Functions + :widths: 15 200 :header-rows: 1 - + * - Function - * - :ref:`rank` + - Description + * - :ref:`lag` + - Returns a value from a previous row within the partition of a result set. + * - :ref:`lead` + - Returns a value from a subsequent row within the partition of a result set. * - :ref:`row_number` - - -How window functions work + - Returns the row number of each row within the partition of a result set. + * - :ref:`rank` + - Returns the rank of each row within the partition of a result set. + * - :ref:`first_value` + - Returns the value in the first row of a window. + * - :ref:`last_value` + - Returns the value in the last row of a window. + * - :ref:`nth_value` + - Returns the value in a specified (``n``) row of a window. + * - :ref:`dense_rank` + - Returns the rank of the current row with no gaps. + * - :ref:`percent_rank` + - Returns the relative rank of the current row. + * - :ref:`cume_dist` + - Returns the cumulative distribution of rows. + * - :ref:`ntile` + - Returns an integer ranging between ``1`` and the argument value, dividing the partitions as equally as possible. + + + + +How Window Functions Work ============================ A window function operates on a subset ("window") of rows. @@ -130,8 +168,7 @@ Without ``ORDER BY``, rows are processed in an unspecified order. Frames ------- -.. versionchanged:: 2020.1 - Frames are supported from v2020.1. + .. note:: Frames and frame exclusions have been tested extensively, but are a complex feature. They are released as a preview in v2020.1 pending longer-term testing. @@ -164,17 +201,14 @@ Restrictions For example ``RANGE BETWEEN CURRENT ROW AND 7 PRECEDING`` is not allowed. However, while ``ROWS BETWEEN 7 PRECEDING AND 8 PRECEDING`` is allowed, it would never select any rows. -Frame exclusion +Frame Exclusion ----------------- The ``frame_exclusion`` option allows rows around the current row to be excluded from the frame, even if they would be included according to the frame start and frame end options. ``EXCLUDE CURRENT ROW`` excludes the current row from the frame. ``EXCLUDE GROUP`` excludes the current row and its ordering peers from the frame. ``EXCLUDE TIES`` excludes any peers of the current row from the frame, but not the current row itself. ``EXCLUDE NO OTHERS`` simply specifies explicitly the default behavior of not excluding the current row or its peers. Limitations ================== - -* At this phase, text columns are not supported in window function expressions. - -* Window function calls are permitted only in the :ref:`select` list. +Window functions do not support the Numeric data type. @@ -206,7 +240,7 @@ Here's a peek at the table contents (:download:`Download nba.csv SELECT "Name", + . "Salary", + . LEAD("Salary", 1) OVER (ORDER BY "Salary" DESC) AS "Salary - next", + . ABS(LEAD("Salary", 1) OVER (ORDER BY "Salary" DESC) - "Salary") AS "Salary - diff" + . FROM nba + . LIMIT 11 ; + Name | Salary | Salary - next | Salary - diff + ----------------+----------+---------------+-------------- + Kobe Bryant | 25000000 | 22970500 | 2029500 + LeBron James | 22970500 | 22875000 | 95500 + Carmelo Anthony | 22875000 | 22359364 | 515636 + Dwight Howard | 22359364 | 22192730 | 166634 + Chris Bosh | 22192730 | 21468695 | 724035 + Chris Paul | 21468695 | 20158622 | 1310073 + Kevin Durant | 20158622 | 20093064 | 65558 + Derrick Rose | 20093064 | 20000000 | 93064 + Dwyane Wade | 20000000 | 19689000 | 311000 + Brook Lopez | 19689000 | 19689000 | 0 + DeAndre Jordan | 19689000 | 19689000 | 0 From 32c8f26dc2b4df6223399b7d38b980dc6a95e215 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 14 Nov 2021 16:40:50 +0200 Subject: [PATCH 116/300] Update joins.rst Cleaned up page. --- reference/sql/sql_syntax/joins.rst | 168 +++++++++++++++++++++-------- 1 file changed, 123 insertions(+), 45 deletions(-) diff --git a/reference/sql/sql_syntax/joins.rst b/reference/sql/sql_syntax/joins.rst index 2527cec69..2563e7a5d 100644 --- a/reference/sql/sql_syntax/joins.rst +++ b/reference/sql/sql_syntax/joins.rst @@ -4,14 +4,14 @@ Joins *************************** -Joins combine results from two or more table expressions (tables, external tables, views) to form a new result set. +The ``JOIN`` clause combines results from two or more table expressions (tables, external tables, views) based on a related column or other condition. Performing a join outputs a new result set. For example, two tables containing one or more columns in common can be joined to match or correlate with rows from another table. -The combination of these table expressions ca nbe based on a set of conditions, such as equality of columns. + -Joins are useful when data in tables are related. For example, when two tables contain one or more columns in common, so that rows can be matched or correlated with rows from the other table. Syntax ========== +The following shows the correct syntax for creating a **join**: .. code-block:: postgres @@ -29,11 +29,20 @@ Syntax join_hint ::= MERGE | LOOP -Join types +Join Types ------------- +The **Join Types** section describes the following join types: + +* :ref:`Inner joins` +* :ref:`Left outer joins` +* :ref:`Right outer joins` +* :ref:`Cross joins` + +.. _inner_joins: -Inner join +Inner Joins ^^^^^^^^^^^^ +The following shows the correct syntax for creating an **inner join**: .. code-block:: postgres @@ -41,64 +50,125 @@ Inner join left_side [ INNER ] JOIN right_side USING ( join_column [, ... ] ) -This is the default join type. -Rows from the ``left_side`` and ``right_side`` that match the condition are returned. +Inner joins are the default join type and return rows from the ``left_side`` and ``right_side`` based on a matching condition. + +An inner join can also be specified by listing several tables in the ``FROM`` clause, as shown below: + +.. code-block:: postgres + + FROM table1, table2 + [ { INNER JOIN + | LEFT [OUTER] JOIN + | RIGHT [OUTER] JOIN + | FULL [OUTER] JOIN } table2 + ON table1.column1 = table2.column1 ] -An inner join can also be specified by listing several tables in the ``FROM`` clause. -Omitting the ``ON`` or ``WHERE`` will result in a ``CROSS JOIN``, where every row of ``left_side`` is matched with every row on ``right_side``. +Omitting the ``ON`` or ``WHERE`` clause creates a ``CROSS JOIN``, where every ``left_side`` row is matched with every ``right_side`` row. -Left outer join +For more information about cross joins, see :ref:`cross joins` below. + +For an inner join example, see :ref:`Inner Join Example`. + +.. _left_outer_joins: + +Left Outer Joins ^^^^^^^^^^^^^^^^^^ +The following shows the correct syntax for creating an **left outer join**: .. code-block:: postgres left_side LEFT [ OUTER ] JOIN right_side ON value_expr left_side LEFT [ OUTER ] JOIN right_side USING ( join_column [, ... ] ) -Similar to the inner join - but for every row of ``left_side`` that does not match, ``NULL`` values are returned for columns on ``right_side`` +Left outer joins are similar to inner joins, except that for every ``left_side`` row without a matching condition, a ``NULL`` value is returned for the corresponding ``right_side`` column. + +For a left inner join example, see :ref:`Left Join Example`. + +.. _right_outer_joins: -Right outer join +Right Outer Joins ^^^^^^^^^^^^^^^^^^^ +The following shows the correct syntax for creating an **right outer join**: .. code-block:: postgres left_side RIGHT [ OUTER ] JOIN right_side ON value_expr left_side RIGHT [ OUTER ] JOIN right_side USING ( join_column [, ... ] ) -Similar to the inner join - but for every row of ``right_side`` that does not match, ``NULL`` values are returned for columns on ``left_side`` +Right outer joins are similar to inner joins, except that for every ``right_side`` row without a matching condition, a ``NULL`` value is returned for the corresponding ``left_side`` column. -Cross join +For a right outer join example, see :ref:`Right Join Example`. + + +.. _cross_joins: + +Cross Joins ^^^^^^^^^^^^^ +The following shows the correct syntax for creating an **cross join**: .. code-block:: postgres left_side CROSS JOIN right_side -A cartesian product - all rows match on all sides. For every row from ``left_side`` and ``right_side``, the result set will contain a row with all columns from ``left_side`` and all columns from ``right_side``. +Cross joins return all rows in all tables listed in a query, pairing each row in the first table with each row in the second table. A cross join is also known as a **Cartesian product**, and occurs when no relationship is defined between the two tables. + +The ``CROSS JOIN`` clause cannot have an ``ON`` clause, but the ``WHERE`` clause can be used to limit the result set. + +The following is an example of two tables that will be used as the basis for a cross join: + +.. image:: /_static/images/joins/color_table.png -The ``CROSS JOIN`` can't have an ``ON`` clause, but ``WHERE`` can be used to limit the result set. +The following is the output result of the cross join: -Join conditions --------------------------------------------------------- ++-----------+-------------+ +| **Color** | **Size** | ++===========+=============+ +| Red | Small | ++-----------+-------------+ +| Blue | Small | ++-----------+-------------+ +| Red | Medium | ++-----------+-------------+ +| Blue | Medium | ++-----------+-------------+ +| Red | Large | ++-----------+-------------+ +| Blue | Large | ++-----------+-------------+ +| Red | Extra Large | ++-----------+-------------+ +| Blue | Extra Large | ++-----------+-------------+ -``ON value_expr`` -^^^^^^^^^^^^^^^^^^^^^^ -The ``ON`` condition is an expression that evaluates to a boolean to identify whether the rows match. +For a cross join example, see :ref:`Cross Join Example`. -For example, ``ON left_side.name = right_side.name`` matches when both name columns match. -For ``LEFT`` and ``RIGHT`` joins, the ``ON`` clause is optional. However, if it is not specified, the result is a computationally intensive ``CROSS JOIN``. + + + +The ON Condition +------------- + +The ``ON`` condition is a value expression that generates a Boolean output to identify whether rows match. + +For example, the following is displayed when two name columns match: + + +.. code-block:: postgres + + ON left_side.name = right_side.name + +The ``ON`` clause is optional for ``LEFT`` and ``RIGHT`` joins. However, excluding it results in a computationally intensive cross join. .. tip:: SQream DB does not support the ``USING`` syntax. However, queries can be easily rewritten. ``left_side JOIN right_side using (name)`` is equivalent to ``ON left_side.name = right_side.name`` -Examples +Join Type Examples ============= - -Assume a pair of tables with the following structure and content: +The examples in this section are based on a pair of tables with the following structure and content: .. code-block:: postgres @@ -108,10 +178,11 @@ Assume a pair of tables with the following structure and content: CREATE TABLE right_side (x INT); INSERT INTO right_side VALUES (2), (3), (4), (5), (6); -Inner join ------------- +.. _inner_join_example: -In inner joins, values that are not matched do not appear in the result set. +Inner Join Example +------------ +The following is an example of an inner join. .. code-block:: psql @@ -123,10 +194,13 @@ In inner joins, values that are not matched do not appear in the result set. 4 | 4 5 | 5 -Left join ------------- +Notice in the example above that values with no matching conditions do not appear in the result output. -.. note:: Note the null values for ``1`` which were not matched. SQream DB outputs nulls last. +.. _left_join_example: + +Left Join Example +------------ +The following is an example of a left join: .. code-block:: psql @@ -139,14 +213,17 @@ Left join 5 | 5 1 | \N -Right join ------------- +.. note:: Note the unmatched``NULL`` (``\N``) values for ``1``. SQream outputs ``NULL`` values last. -.. note:: Note the null values for ``3``, ``6`` which were not matched. SQream DB outputs nulls last. +.. _right_join_example: + +Right Join Example +------------ +The following is an example of a right join: .. code-block:: psql - t=> SELECT * FROM left_side AS l LEFT JOIN right_side AS r + t=> SELECT * FROM left_side AS l RIGHT JOIN right_side AS r . ON l.x = r.x; x | x0 ---+--- @@ -156,8 +233,13 @@ Right join \N | 3 \N | 6 -Cross join +.. note:: Note the unmatched ``NULL`` values for ``3`` and ``6``. SQream outputs ``NULL`` values last. + +.. _cross_join_example: + +Cross Join Example ------------- +The following is an example of a cross join: .. code-block:: psql @@ -185,7 +267,7 @@ Cross join 5 | 5 5 | 6 -Specifying multiple comma-separated tables is equivalent to a cross join, that can then be filtered with a ``WHERE`` clause.. +Specifying multiple comma-separated tables is equivalent to a cross join, which can be filtered with a ``WHERE`` clause as shown in the following example: .. code-block:: psql @@ -220,14 +302,12 @@ Specifying multiple comma-separated tables is equivalent to a cross join, that c 4 | 4 5 | 5 -Join hints +Join Hints ------------- -Join hints can be used to override the query compiler and choose a particular join algorithm. - -The available algorithms are ``LOOP`` (corresponding to non-indexed nested loop join algorithm), and ``MERGE`` (corresponding to sort merge join algorithm). +**Join hints** can be used to override the query compiler and choose a particular join algorithm. The available algorithms are ``LOOP`` (corresponding to non-indexed nested loop join algorithm), and ``MERGE`` (corresponding to sort merge join algorithm). If no algorithm is specified, a loop join is performed by default. -If no algorithm is specified, a loop join is performed by default. +The following is an example of using a join hint: .. code-block:: psql @@ -244,5 +324,3 @@ If no algorithm is specified, a loop join is performed by default. 2 | 2 4 | 4 5 | 5 - - From 743d7de2dc93b5dfce897f060519493064adeace Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 14 Nov 2021 16:42:09 +0200 Subject: [PATCH 117/300] Update joins.rst Cleaned up page. --- reference/sql/sql_syntax/joins.rst | 168 +++++++++++++++++++++-------- 1 file changed, 123 insertions(+), 45 deletions(-) diff --git a/reference/sql/sql_syntax/joins.rst b/reference/sql/sql_syntax/joins.rst index 2527cec69..2563e7a5d 100644 --- a/reference/sql/sql_syntax/joins.rst +++ b/reference/sql/sql_syntax/joins.rst @@ -4,14 +4,14 @@ Joins *************************** -Joins combine results from two or more table expressions (tables, external tables, views) to form a new result set. +The ``JOIN`` clause combines results from two or more table expressions (tables, external tables, views) based on a related column or other condition. Performing a join outputs a new result set. For example, two tables containing one or more columns in common can be joined to match or correlate with rows from another table. -The combination of these table expressions ca nbe based on a set of conditions, such as equality of columns. + -Joins are useful when data in tables are related. For example, when two tables contain one or more columns in common, so that rows can be matched or correlated with rows from the other table. Syntax ========== +The following shows the correct syntax for creating a **join**: .. code-block:: postgres @@ -29,11 +29,20 @@ Syntax join_hint ::= MERGE | LOOP -Join types +Join Types ------------- +The **Join Types** section describes the following join types: + +* :ref:`Inner joins` +* :ref:`Left outer joins` +* :ref:`Right outer joins` +* :ref:`Cross joins` + +.. _inner_joins: -Inner join +Inner Joins ^^^^^^^^^^^^ +The following shows the correct syntax for creating an **inner join**: .. code-block:: postgres @@ -41,64 +50,125 @@ Inner join left_side [ INNER ] JOIN right_side USING ( join_column [, ... ] ) -This is the default join type. -Rows from the ``left_side`` and ``right_side`` that match the condition are returned. +Inner joins are the default join type and return rows from the ``left_side`` and ``right_side`` based on a matching condition. + +An inner join can also be specified by listing several tables in the ``FROM`` clause, as shown below: + +.. code-block:: postgres + + FROM table1, table2 + [ { INNER JOIN + | LEFT [OUTER] JOIN + | RIGHT [OUTER] JOIN + | FULL [OUTER] JOIN } table2 + ON table1.column1 = table2.column1 ] -An inner join can also be specified by listing several tables in the ``FROM`` clause. -Omitting the ``ON`` or ``WHERE`` will result in a ``CROSS JOIN``, where every row of ``left_side`` is matched with every row on ``right_side``. +Omitting the ``ON`` or ``WHERE`` clause creates a ``CROSS JOIN``, where every ``left_side`` row is matched with every ``right_side`` row. -Left outer join +For more information about cross joins, see :ref:`cross joins` below. + +For an inner join example, see :ref:`Inner Join Example`. + +.. _left_outer_joins: + +Left Outer Joins ^^^^^^^^^^^^^^^^^^ +The following shows the correct syntax for creating an **left outer join**: .. code-block:: postgres left_side LEFT [ OUTER ] JOIN right_side ON value_expr left_side LEFT [ OUTER ] JOIN right_side USING ( join_column [, ... ] ) -Similar to the inner join - but for every row of ``left_side`` that does not match, ``NULL`` values are returned for columns on ``right_side`` +Left outer joins are similar to inner joins, except that for every ``left_side`` row without a matching condition, a ``NULL`` value is returned for the corresponding ``right_side`` column. + +For a left inner join example, see :ref:`Left Join Example`. + +.. _right_outer_joins: -Right outer join +Right Outer Joins ^^^^^^^^^^^^^^^^^^^ +The following shows the correct syntax for creating an **right outer join**: .. code-block:: postgres left_side RIGHT [ OUTER ] JOIN right_side ON value_expr left_side RIGHT [ OUTER ] JOIN right_side USING ( join_column [, ... ] ) -Similar to the inner join - but for every row of ``right_side`` that does not match, ``NULL`` values are returned for columns on ``left_side`` +Right outer joins are similar to inner joins, except that for every ``right_side`` row without a matching condition, a ``NULL`` value is returned for the corresponding ``left_side`` column. -Cross join +For a right outer join example, see :ref:`Right Join Example`. + + +.. _cross_joins: + +Cross Joins ^^^^^^^^^^^^^ +The following shows the correct syntax for creating an **cross join**: .. code-block:: postgres left_side CROSS JOIN right_side -A cartesian product - all rows match on all sides. For every row from ``left_side`` and ``right_side``, the result set will contain a row with all columns from ``left_side`` and all columns from ``right_side``. +Cross joins return all rows in all tables listed in a query, pairing each row in the first table with each row in the second table. A cross join is also known as a **Cartesian product**, and occurs when no relationship is defined between the two tables. + +The ``CROSS JOIN`` clause cannot have an ``ON`` clause, but the ``WHERE`` clause can be used to limit the result set. + +The following is an example of two tables that will be used as the basis for a cross join: + +.. image:: /_static/images/joins/color_table.png -The ``CROSS JOIN`` can't have an ``ON`` clause, but ``WHERE`` can be used to limit the result set. +The following is the output result of the cross join: -Join conditions --------------------------------------------------------- ++-----------+-------------+ +| **Color** | **Size** | ++===========+=============+ +| Red | Small | ++-----------+-------------+ +| Blue | Small | ++-----------+-------------+ +| Red | Medium | ++-----------+-------------+ +| Blue | Medium | ++-----------+-------------+ +| Red | Large | ++-----------+-------------+ +| Blue | Large | ++-----------+-------------+ +| Red | Extra Large | ++-----------+-------------+ +| Blue | Extra Large | ++-----------+-------------+ -``ON value_expr`` -^^^^^^^^^^^^^^^^^^^^^^ -The ``ON`` condition is an expression that evaluates to a boolean to identify whether the rows match. +For a cross join example, see :ref:`Cross Join Example`. -For example, ``ON left_side.name = right_side.name`` matches when both name columns match. -For ``LEFT`` and ``RIGHT`` joins, the ``ON`` clause is optional. However, if it is not specified, the result is a computationally intensive ``CROSS JOIN``. + + + +The ON Condition +------------- + +The ``ON`` condition is a value expression that generates a Boolean output to identify whether rows match. + +For example, the following is displayed when two name columns match: + + +.. code-block:: postgres + + ON left_side.name = right_side.name + +The ``ON`` clause is optional for ``LEFT`` and ``RIGHT`` joins. However, excluding it results in a computationally intensive cross join. .. tip:: SQream DB does not support the ``USING`` syntax. However, queries can be easily rewritten. ``left_side JOIN right_side using (name)`` is equivalent to ``ON left_side.name = right_side.name`` -Examples +Join Type Examples ============= - -Assume a pair of tables with the following structure and content: +The examples in this section are based on a pair of tables with the following structure and content: .. code-block:: postgres @@ -108,10 +178,11 @@ Assume a pair of tables with the following structure and content: CREATE TABLE right_side (x INT); INSERT INTO right_side VALUES (2), (3), (4), (5), (6); -Inner join ------------- +.. _inner_join_example: -In inner joins, values that are not matched do not appear in the result set. +Inner Join Example +------------ +The following is an example of an inner join. .. code-block:: psql @@ -123,10 +194,13 @@ In inner joins, values that are not matched do not appear in the result set. 4 | 4 5 | 5 -Left join ------------- +Notice in the example above that values with no matching conditions do not appear in the result output. -.. note:: Note the null values for ``1`` which were not matched. SQream DB outputs nulls last. +.. _left_join_example: + +Left Join Example +------------ +The following is an example of a left join: .. code-block:: psql @@ -139,14 +213,17 @@ Left join 5 | 5 1 | \N -Right join ------------- +.. note:: Note the unmatched``NULL`` (``\N``) values for ``1``. SQream outputs ``NULL`` values last. -.. note:: Note the null values for ``3``, ``6`` which were not matched. SQream DB outputs nulls last. +.. _right_join_example: + +Right Join Example +------------ +The following is an example of a right join: .. code-block:: psql - t=> SELECT * FROM left_side AS l LEFT JOIN right_side AS r + t=> SELECT * FROM left_side AS l RIGHT JOIN right_side AS r . ON l.x = r.x; x | x0 ---+--- @@ -156,8 +233,13 @@ Right join \N | 3 \N | 6 -Cross join +.. note:: Note the unmatched ``NULL`` values for ``3`` and ``6``. SQream outputs ``NULL`` values last. + +.. _cross_join_example: + +Cross Join Example ------------- +The following is an example of a cross join: .. code-block:: psql @@ -185,7 +267,7 @@ Cross join 5 | 5 5 | 6 -Specifying multiple comma-separated tables is equivalent to a cross join, that can then be filtered with a ``WHERE`` clause.. +Specifying multiple comma-separated tables is equivalent to a cross join, which can be filtered with a ``WHERE`` clause as shown in the following example: .. code-block:: psql @@ -220,14 +302,12 @@ Specifying multiple comma-separated tables is equivalent to a cross join, that c 4 | 4 5 | 5 -Join hints +Join Hints ------------- -Join hints can be used to override the query compiler and choose a particular join algorithm. - -The available algorithms are ``LOOP`` (corresponding to non-indexed nested loop join algorithm), and ``MERGE`` (corresponding to sort merge join algorithm). +**Join hints** can be used to override the query compiler and choose a particular join algorithm. The available algorithms are ``LOOP`` (corresponding to non-indexed nested loop join algorithm), and ``MERGE`` (corresponding to sort merge join algorithm). If no algorithm is specified, a loop join is performed by default. -If no algorithm is specified, a loop join is performed by default. +The following is an example of using a join hint: .. code-block:: psql @@ -244,5 +324,3 @@ If no algorithm is specified, a loop join is performed by default. 2 | 2 4 | 4 5 | 5 - - From 1f1d870fefc67fcf7a1634aabf4f9dd635661686 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 14 Nov 2021 18:12:31 +0200 Subject: [PATCH 118/300] Update create_table_as.rst Cleaned up page. --- .../ddl_commands/create_table_as.rst | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table_as.rst b/reference/sql/sql_statements/ddl_commands/create_table_as.rst index 19aaf8128..a7f9dd4d4 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table_as.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table_as.rst @@ -4,14 +4,13 @@ CREATE TABLE AS ***************** -``CREATE TABLE AS`` creates a new table from the result of a select query. +The ``CREATE TABLE AS`` commands creates a new table from the result of a select query. -Permissions -============= -The role must have the ``CREATE`` permission at the schema level, as well as ``SELECT`` permissions for any tables referenced by the statement. Syntax ========== +The following is the correct syntax for creating a table from the result of a select query: + .. CREATE [ OR REPLACE ] TABLE [schema_name].table_name ( .. { column_def [, ...] } @@ -32,6 +31,7 @@ Syntax Parameters ============ +The following parameters can be used when creating a table from the result of a select query: .. list-table:: :widths: auto @@ -51,15 +51,27 @@ Parameters .. * - ``column_def`` .. - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. +Permissions +============= +The role must have the ``CREATE`` permission at the schema level, as well as ``SELECT`` permissions for any tables referenced by the statement. + + Examples =========== +This section includes the following examples: -Create a copy of an :ref:`foreign table ` or view +.. contents:: + :local: + :depth: 1 + +Creating a Copy of a Foreign Table or View --------------------------------------------------------------------------- .. code-block:: postgres CREATE TABLE users AS SELECT * FROM users_source; + +For more information, see :ref:`CREATE FOREIGN TABLE `. Filtering ------------ @@ -68,14 +80,14 @@ Filtering CREATE TABLE users_uk AS SELECT * FROM users WHERE country = 'United Kingdom'; -Adding columns +Adding Columns ----------------------- .. code-block:: postgres CREATE TABLE users_uk_new AS SELECT GETDATE() as "Date",*,false as is_new FROM users_uk; -Creating a table from values +Creating a Table From Values ----------------------------------------- .. code-block:: postgres From 59f4594c5832853f0c02103be786e9f54889b10a Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 14 Nov 2021 18:13:58 +0200 Subject: [PATCH 119/300] Update create_table_as.rst Cleaned up page. --- .../ddl_commands/create_table_as.rst | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table_as.rst b/reference/sql/sql_statements/ddl_commands/create_table_as.rst index 7bcfe2752..a7f9dd4d4 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table_as.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table_as.rst @@ -4,14 +4,13 @@ CREATE TABLE AS ***************** -``CREATE TABLE AS`` creates a new table from the result of a select query. +The ``CREATE TABLE AS`` commands creates a new table from the result of a select query. -Permissions -============= -The role must have the ``CREATE`` permission at the schema level, as well as ``SELECT`` permissions for any tables referenced by the statement. Syntax ========== +The following is the correct syntax for creating a table from the result of a select query: + .. CREATE [ OR REPLACE ] TABLE [schema_name].table_name ( .. { column_def [, ...] } @@ -28,8 +27,11 @@ Syntax table_name ::= identifier +.. _ctas_params: + Parameters ============ +The following parameters can be used when creating a table from the result of a select query: .. list-table:: :widths: auto @@ -49,15 +51,27 @@ Parameters .. * - ``column_def`` .. - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. +Permissions +============= +The role must have the ``CREATE`` permission at the schema level, as well as ``SELECT`` permissions for any tables referenced by the statement. + + Examples =========== +This section includes the following examples: + +.. contents:: + :local: + :depth: 1 -Create a copy of an :ref:`external table ` or view +Creating a Copy of a Foreign Table or View --------------------------------------------------------------------------- .. code-block:: postgres CREATE TABLE users AS SELECT * FROM users_source; + +For more information, see :ref:`CREATE FOREIGN TABLE `. Filtering ------------ @@ -66,14 +80,14 @@ Filtering CREATE TABLE users_uk AS SELECT * FROM users WHERE country = 'United Kingdom'; -Adding columns +Adding Columns ----------------------- .. code-block:: postgres CREATE TABLE users_uk_new AS SELECT GETDATE() as "Date",*,false as is_new FROM users_uk; -Creating a table from values +Creating a Table From Values ----------------------------------------- .. code-block:: postgres From ab2670b4c900bb259a70f782ca79949c7c952867 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 14 Nov 2021 18:22:30 +0200 Subject: [PATCH 120/300] Update add_column.rst Cleaned up page. --- .../ddl_commands/add_column.rst | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/add_column.rst b/reference/sql/sql_statements/ddl_commands/add_column.rst index 790c29ee2..d532c956f 100644 --- a/reference/sql/sql_statements/ddl_commands/add_column.rst +++ b/reference/sql/sql_statements/ddl_commands/add_column.rst @@ -4,16 +4,13 @@ ADD COLUMN ********************** -``ADD COLUMN`` can be used to add columns to an existing table. +The ``ADD COLUMN`` command is used to add columns to an existing table. -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. Syntax ========== +The following is the correct syntax for adding a table: .. code-block:: postgres @@ -39,6 +36,7 @@ Syntax Parameters ============ +The following parameters can be used for adding a table: .. list-table:: :widths: auto @@ -58,12 +56,23 @@ Parameters .. note:: * When adding a new column to an existing table, a default (or null constraint) has to be specified, even if the table is empty. * A new column added to the table can not contain an IDENTITY or be of the TEXT type. + + +Permissions +============= +The role must have the ``DDL`` permission at the database or table level. Examples =========== +This section includes the following examples: -Adding a simple column with default value +.. contents:: + :local: + :depth: 1 + +Adding a Simple Column with a Default Value ----------------------------------------- +This example shows how to add a simple column with a default value: .. code-block:: postgres @@ -71,8 +80,9 @@ Adding a simple column with default value ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL; -Adding several columns in one command +Adding Several Columns in One Command ------------------------------------------- +This example shows how to add several columns in one command: .. code-block:: postgres From 00ea228526912961481e415a4d19ca9400d96dd6 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 14 Nov 2021 18:23:49 +0200 Subject: [PATCH 121/300] Update add_column.rst Cleaned up page. --- .../ddl_commands/add_column.rst | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/add_column.rst b/reference/sql/sql_statements/ddl_commands/add_column.rst index e54e1f945..d532c956f 100644 --- a/reference/sql/sql_statements/ddl_commands/add_column.rst +++ b/reference/sql/sql_statements/ddl_commands/add_column.rst @@ -4,16 +4,13 @@ ADD COLUMN ********************** -``ADD COLUMN`` can be used to add columns to an existing table. +The ``ADD COLUMN`` command is used to add columns to an existing table. -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. Syntax ========== +The following is the correct syntax for adding a table: .. code-block:: postgres @@ -39,6 +36,7 @@ Syntax Parameters ============ +The following parameters can be used for adding a table: .. list-table:: :widths: auto @@ -57,13 +55,24 @@ Parameters .. note:: * When adding a new column to an existing table, a default (or null constraint) has to be specified, even if the table is empty. - * A new column added to the table can not contain an IDENTITY or be of the NVARCHAR type. + * A new column added to the table can not contain an IDENTITY or be of the TEXT type. + + +Permissions +============= +The role must have the ``DDL`` permission at the database or table level. Examples =========== +This section includes the following examples: -Adding a simple column with default value +.. contents:: + :local: + :depth: 1 + +Adding a Simple Column with a Default Value ----------------------------------------- +This example shows how to add a simple column with a default value: .. code-block:: postgres @@ -71,8 +80,9 @@ Adding a simple column with default value ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL; -Adding several columns in one command +Adding Several Columns in One Command ------------------------------------------- +This example shows how to add several columns in one command: .. code-block:: postgres From ab5a5b9d714464d3e7a34a8e3eedfb157738a7e6 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 14 Nov 2021 18:47:12 +0200 Subject: [PATCH 122/300] Update alter_default_schema.rst Cleaned up page. --- .../ddl_commands/alter_default_schema.rst | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst b/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst index 1dbba7a42..e40a8af7c 100644 --- a/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst +++ b/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst @@ -4,19 +4,15 @@ ALTER DEFAULT SCHEMA ********************** -``ALTER DEFAULT SCHEMA`` can be used to change a role's default schema. +The ``ALTER DEFAULT SCHEMA`` command can be used to change a role's default schema. The default schema in SQream is ``public``. -The default schema in SQream DB is ``public``. +For more information, see :ref:`create_schema` and :ref:`drop_schema`. -See also: :ref:`create_schema`, :ref:`drop_schema`. -Permissions -============= - -No special permissions are required Syntax ========== +The following is the correct syntax for altering a default schema: .. code-block:: postgres @@ -32,6 +28,7 @@ Syntax Parameters ============ +The following parameters can be used when altering a default schema: .. list-table:: :widths: auto @@ -43,12 +40,14 @@ Parameters - The name of the role the change will apply to. * - ``schema_name`` - The new default schema name. + +Permissions +============= +No special permissions are required. Examples =========== - -Altering the default schema for a role ------------------------------------------ +This section includes an example of **altering the default schema for a role**: .. code-block:: postgres From 096613f6ad51effa2fb58458454664f3db244c9a Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 14 Nov 2021 18:48:30 +0200 Subject: [PATCH 123/300] Update alter_default_schema.rst Cleaned up page. --- .../ddl_commands/alter_default_schema.rst | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst b/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst index 1dbba7a42..e40a8af7c 100644 --- a/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst +++ b/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst @@ -4,19 +4,15 @@ ALTER DEFAULT SCHEMA ********************** -``ALTER DEFAULT SCHEMA`` can be used to change a role's default schema. +The ``ALTER DEFAULT SCHEMA`` command can be used to change a role's default schema. The default schema in SQream is ``public``. -The default schema in SQream DB is ``public``. +For more information, see :ref:`create_schema` and :ref:`drop_schema`. -See also: :ref:`create_schema`, :ref:`drop_schema`. -Permissions -============= - -No special permissions are required Syntax ========== +The following is the correct syntax for altering a default schema: .. code-block:: postgres @@ -32,6 +28,7 @@ Syntax Parameters ============ +The following parameters can be used when altering a default schema: .. list-table:: :widths: auto @@ -43,12 +40,14 @@ Parameters - The name of the role the change will apply to. * - ``schema_name`` - The new default schema name. + +Permissions +============= +No special permissions are required. Examples =========== - -Altering the default schema for a role ------------------------------------------ +This section includes an example of **altering the default schema for a role**: .. code-block:: postgres From 686994485f777038d95f17dff26ae16dd212f4bf Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 15 Nov 2021 13:00:04 +0200 Subject: [PATCH 124/300] Update hardware_guide.rst Changed Line 47 (request made by Slavi). --- guides/operations/hardware_guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/operations/hardware_guide.rst b/guides/operations/hardware_guide.rst index 99e0d9265..15ddd38a2 100644 --- a/guides/operations/hardware_guide.rst +++ b/guides/operations/hardware_guide.rst @@ -44,7 +44,7 @@ An average single-node cluster can be a rackmount server or workstation, contain * - Processor - 2x Intel Xeon Gold 6240 (18C/36HT) 2.6GHz * - RAM - - 512 GB + - 512 GB - 1 TB * - Onboard storage - * 2x 960GB SSD 2.5in Hot-plug for OS, RAID1 From 080877a8841a2cd0951adace57c5e74c1443b8f2 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 15 Nov 2021 13:01:32 +0200 Subject: [PATCH 125/300] Update hardware_guide.rst Changed Line 47 (request made by Slavi). --- guides/operations/hardware_guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/operations/hardware_guide.rst b/guides/operations/hardware_guide.rst index 99e0d9265..15ddd38a2 100644 --- a/guides/operations/hardware_guide.rst +++ b/guides/operations/hardware_guide.rst @@ -44,7 +44,7 @@ An average single-node cluster can be a rackmount server or workstation, contain * - Processor - 2x Intel Xeon Gold 6240 (18C/36HT) 2.6GHz * - RAM - - 512 GB + - 512 GB - 1 TB * - Onboard storage - * 2x 960GB SSD 2.5in Hot-plug for OS, RAID1 From c592681481731f111b244d04163dbac56e1920f1 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 21 Nov 2021 14:58:16 +0200 Subject: [PATCH 126/300] Minor Changes to two pages Testing Merge functionality. --- guides/index.rst | 2 +- index.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/guides/index.rst b/guides/index.rst index 515f4e5c4..7a43fb7c8 100644 --- a/guides/index.rst +++ b/guides/index.rst @@ -14,7 +14,7 @@ This section has concept and features guides, and task focused guides. * :ref:`Client drivers for SQream DB` -Full list of guides +Full List of Guides ========================= .. toctree:: diff --git a/index.rst b/index.rst index 71e6a4c0a..858106ae6 100644 --- a/index.rst +++ b/index.rst @@ -1,7 +1,7 @@ .. _index: *********************** -SQream DB documentation +SQream Documentation *********************** .. only:: html From 2ff3908a641d148f7991e9fdf1e7e29267c9a2ae Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 08:37:11 +0200 Subject: [PATCH 127/300] Update index.rst Removed dead link "setup". --- index.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/index.rst b/index.rst index 2ef59d284..6ad01b030 100644 --- a/index.rst +++ b/index.rst @@ -46,9 +46,7 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` :ref:`connect_to_tableau` From 0888d608f964b1835adbce05ac1c5f762e5093a3 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 08:39:22 +0200 Subject: [PATCH 128/300] Update octet_length.rst Replaced NVARCHAR with TEXT. --- .../scalar_functions/string/octet_length.rst | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/octet_length.rst b/reference/sql/sql_functions/scalar_functions/string/octet_length.rst index 61ac2fa85..8bb1e3daf 100644 --- a/reference/sql/sql_functions/scalar_functions/string/octet_length.rst +++ b/reference/sql/sql_functions/scalar_functions/string/octet_length.rst @@ -16,7 +16,7 @@ Calculates the number of bytes in a string. Syntax ========== - +The following is the correct syntax for the ``OCTET_LENGTH`` function: .. code-block:: postgres @@ -24,6 +24,7 @@ Syntax Arguments ============ +The following table describes the ``OCTET_LENGTH`` arguments: .. list-table:: :widths: auto @@ -36,33 +37,29 @@ Arguments Returns ============ - -Returns an integer containing the number of bytes in the string. +The ``OCTET_LENGTH`` function returns an integer containing the number of bytes in the string. Notes ======= +The following notes are applicable to the ``OCTET_LENGTH`` function: * To get the length in characters, see :ref:`char_length` * If the value is NULL, the result is NULL. -Examples +Length in Characters and Bytes of Strings =========== - -For these examples, consider the following table and contents: +The **Length in characters and bytes of strings** example is based on the following table and contents: .. code-block:: postgres - CREATE TABLE alphabets(line NVARCHAR(50)); + CREATE TABLE alphabets(line TEXT(50)); INSERT INTO alphabets VALUES ('abcdefghijklmnopqrstuvwxyz'), ('กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯ') , ('אבגדהוזחטיכלמנסעפצקרשת'); -Length in characters and bytes of strings --------------------------------------------------- - -ASCII characters take up 1 byte per character, while Thai takes up 3 bytes and Hebrew takes up 2 bytes. +ASCII characters take up 1 byte per character, while Thai takes up 3 bytes and Hebrew takes up 2 bytes, as shown below: .. code-block:: psql @@ -72,6 +69,3 @@ ASCII characters take up 1 byte per character, while Thai takes up 3 bytes and H 26 | 26 | 26 47 | 47 | 141 22 | 22 | 44 - - - From ebc380b7704cd38368270179afbe99df0775f8c7 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 08:40:22 +0200 Subject: [PATCH 129/300] Update 2019.2.1.rst Replaced NVARCHAR with TEXT. --- releases/2019.2.1.rst | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/releases/2019.2.1.rst b/releases/2019.2.1.rst index 238e18353..784ab5eff 100644 --- a/releases/2019.2.1.rst +++ b/releases/2019.2.1.rst @@ -1,7 +1,7 @@ .. _2019.2.1: ****************************** -What's New in 2019.2.1 +What's new in 2019.2.1 ****************************** * 250 bugs fixed. Thanks to all of our customers and an unprecedented number of deployments for helping us find and fix these! @@ -29,10 +29,10 @@ Improvements * SQream DB CLI’s history can be disabled, by passing ``./ClientCmd --no-history`` -Behaviour changes +Behaviour Changes ===================== -* SQream DB no longer applies an implicit cast from a long text column to a shorter text column (``VARCHAR``/``NVARCHAR``). This means some ``INSERT``/``COPY`` operations will now error instead of truncating the text. This is intended to prevent accidental truncation of text columns. If you want the old truncation behaviour, you can use the ``SUBSTRING`` function to truncate the text. +* SQream DB no longer applies an implicit cast from a long text column to a shorter text column (``VARCHAR``/``TEXT``). This means some ``INSERT``/``COPY`` operations will now error instead of truncating the text. This is intended to prevent accidental truncation of text columns. If you want the old truncation behaviour, you can use the ``SUBSTRING`` function to truncate the text. Operations @@ -45,20 +45,20 @@ Operations * When upgrading from SQream DB v3.2 or lower, the storage version must be upgraded using the :ref:`upgrade_storage_cli_reference` utility: ``./bin/upgrade_storage /path/to/storage/sqreamdb/`` -Known Issues & Limitations +Known Issues and Limitations =================================== -* NVARCHAR columns cannot be used as a ``GROUP BY`` key when there are multiple ``COUNT (DISTINCT …)`` operations in a query +* TEXT columns cannot be used as a ``GROUP BY`` key when there are multiple ``COUNT (DISTINCT …)`` operations in a query -* NVARCHAR columns cannot be used in a statement containing window functions +* TEXT columns cannot be used in a statement containing window functions -* NVARCHAR is not supported as a join key +* TEXT is not supported as a join key -* The following functions are not supported on ``NVARCHAR`` column types: ``chr``, ``min``, ``max``, ``patindex``, ``to_binary``, ``to_hex``, ``rlike``, ``regexp_count``, ``regexp_instr``, ``regexp_substr`` +* The following functions are not supported on ``TEXT`` column types: ``chr``, ``min``, ``max``, ``patindex``, ``to_binary``, ``to_hex``, ``rlike``, ``regexp_count``, ``regexp_instr``, ``regexp_substr`` -* SQream DB dashboard: Only works with a HA clustered installation +* SQream Dashboard: Only works with a HA clustered installation -* SQream DB editor: External tables and UDFs don’t appear in the DB Tree but do appear in the relevant sqream_catalog entries. +* SQream Editor: External tables and UDFs don’t appear in the DB Tree but do appear in the relevant sqream_catalog entries. Fixes @@ -68,7 +68,7 @@ Fixes * Variety of performance improvements: -* Improved performance of ``NVARCHAR`` by up to 315% for a variety of scenarios, including ``COPY FROM``, ``INNER JOIN``, ``LEFT JOIN``. +* Improved performance of ``TEXT`` by up to 315% for a variety of scenarios, including ``COPY FROM``, ``INNER JOIN``, ``LEFT JOIN``. * Improved load performance from previous versions From b65881dc2281704dc4d7dcc0dd7eabda187ea81d Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 08:42:09 +0200 Subject: [PATCH 130/300] Update 2020.3.rst Replaced VARCHAR with TEXT. --- releases/2020.3.rst | 112 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 5 deletions(-) diff --git a/releases/2020.3.rst b/releases/2020.3.rst index 08f39f776..1bb5ebe44 100644 --- a/releases/2020.3.rst +++ b/releases/2020.3.rst @@ -3,8 +3,110 @@ ************************** What's New in 2020.3 ************************** +SQream DB v2020.3 contains new features, performance enhancements, and resolved issues. -SQream DB v2020.3 contains new features, improved performance, and bug fixes. +The 2020.3 Release Notes describe the following: + +.. contents:: + :local: + :depth: 1 + + +:::: + +Release Notes Version 2020.3.2.1 +============== +SQream DB v2020.3.2.1 contains major performance improvements and some bug fixes. + +Performance Enhancements +------------- +* Metadata on Demand optimization resulting in reduced latency and improved overall performance. + + +Known Issues and Limitations +------------- +* Multiple count distinct operations is enabled for all data types. + +Upgrading to v2020.3.2.1 +------------- + +Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. + +Contact your account manager to get the latest release of SQream DB. + + + +:::: + + + +Release Notes Version 2020.3.1 +================= +New Features +------------- +The following list describes the new features: + + +* TEXT data type: + * Full support for ``MIN`` and ``MAX`` aggregate functions on ``TEXT`` columns in ``GROUP BY`` queries. + * Support Text-type as window partition keys (e.g., select distinct name, max(id) over (partition by name) from ``textTable;``). + * Support Text-type fields in windows order by keys. + * Support join on ``TEXT`` columns (such as ``t1.x = t2.y`` where ``x`` and ``y`` are columns of type ``TEXT``). + * Complete the implementation of ``LIKE`` on ``TEXT`` columns (previously limited to prefix and suffix). + * Support for cast fromm ``TEXT`` to ``REAL/FLOAT``. + * New string function - ``REPEAT`` for repeating a string value for a specified number of times. + +* Support mapping ``DECIMAL ORC`` columns to SQream's floating-point types. + +* Support ``LIKE`` on non-literal patterns (such as columns and complex expressions). + +* Catch OS signals and save the signal along with the stack trace in the SQream debug log. + +* Support equijoin conditions on columns with different types (such as ``tinyint``, ``smallint``, ``int`` and ``bigint``). + +* ``DUMP_DATABASE_DDL`` now includes foreign tables in the output. + +* New utility function - ``TRUNCATE_IF_EXISTS``. + + +Performance Enhancements +------------- +The following list describes the performance enhancements: + + +* Introduced the "MetaData on Demand" feature which results in signicant proformance improvements. + +* Implemented regex functions (``RLIKE``, ``REGEXP_COUNT``, ``REGEXP_INSTR``, ``REGEXP_SUBSTR``, ``PATINDEX``) for ``TEXT`` columns on GPU. + + +Resolved Issues +------------- +The following list describes the resolved issues: + + +* Multiple distinct aggregates no longer need to be used with developerMode flag. +* In some scenarios, the ``statement_id`` and ``connection_id values`` are incorrectly recorded as ``-1`` in the log. +* ``NOT RLIKE`` is not supported for ``TEXT`` in the compiler. +* Casting from ``TEXT`` to ``date/datetime`` returns an error when the ``TEXT`` column contains ``NULL``. + + +Known Issues and Limitations +------------- +No known issues and limitations. + + +Upgrading to v2020.3.1 +---------------- + +Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. + +Contact your account manager to get the latest release of SQream DB. + + +:::: + +Release Notes Version 2020.3 +================= New Features @@ -57,7 +159,7 @@ The following list describes the resolved issues: * ``showFullExceptionInfo`` is no longer restricted to Developer Mode. This was fixed. * An ``StreamAggregateA`` reduction error occured when performing aggregation on a ``NULL`` column. This was fixed. * Insert into query fails with ""Error at Sql phase during Stages ""rewriteSqlQuery"". This was fixed. -* Casting from ``VARCHAR`` to ``NVARCHAR` does not remove the spaces. This was fixed. +* Casting from ``VARCHAR`` to ``TEXT`` does not remove the spaces. This was fixed. * An ``Internal Runtime Error t1.size() == t2.size()`` occurs when querying the ``sqream_catalog.delete_predicates``. This was fixed. * ``spoolMemoryGB`` and ``limitQueryMemoryGB`` show incorrectly in the **runtime global** section of ``show_conf.`` This was fixed. * Casting empty text to ``int`` causes illegal memory access. This was fixed. @@ -67,12 +169,12 @@ The following list describes the resolved issues: * An ``Internal runtime time error`` occured when using ``TEXT (tpcds)``. This was fixed. * Copying CSV with a quote in the middle of a field to a ``TEXT`` field does not produce the required error. This was fixed. * Cannot monitor long network insert loads with SQream. This was fixed. -* Upper and like performance on ``NVARCHAR``. This was fixed. +* Upper and like performance on ``TEXT``. This was fixed. * Insert into from 4 instances would get stuck (hanging). This was fixed. * An invalid formatted CSV would cause an insufficient memory error on a ``COPY FROM`` statement if a quote was not closed and the file was much larger than system memory. This was fixed. * ``TEXT`` columns cannot be used with an outer join together with an inequality check (!= , <>). This was fixed. -Known Issues and Limitations +Known Issues And Limitations ---------- The following list describes the known issues and limitations: @@ -91,4 +193,4 @@ Upgrading to v2020.3 Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. -Contact your account manager to get the latest release of SQream DB. +Contact your account manager to get the latest release of SQream. From 006887d75286fe4002bc60ea45e4fdcea24a3b47 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 08:43:05 +0200 Subject: [PATCH 131/300] Update sql_feature_support.rst Replaced VARCHAR with TEXT. --- reference/sql_feature_support.rst | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/reference/sql_feature_support.rst b/reference/sql_feature_support.rst index 6e537bcdd..ba4ca39e4 100644 --- a/reference/sql_feature_support.rst +++ b/reference/sql_feature_support.rst @@ -11,12 +11,12 @@ To understand which ANSI SQL and other SQL features SQream DB supports, use the :local: -Data types and values +Data Types and Values ========================= Read more about :ref:`supported data types`. -.. list-table:: Value +.. list-table:: Data Types and Values :widths: auto :header-rows: 1 @@ -45,12 +45,12 @@ Read more about :ref:`supported data types`. - ✓ - 8 byte floating point * - ``DECIMAL``, ``NUMERIC`` - - Planned - - Fixed-point numbers. Use ``DOUBLE`` instead + - ✓ + - Fixed-point numbers. * - ``VARCHAR`` - ✓ - Variable length string - ASCII only - * - ``TEXT``, ``NVARCHAR`` + * - ``TEXT`` - ✓ - Variable length string - UTF-8 encoded * - ``DATE`` @@ -107,10 +107,10 @@ SQream DB does not support explicit indexing, but does support clustering keys. Read more about :ref:`clustering keys` and our :ref:`metadata system`. -Schema changes +Schema Changes ================ -.. list-table:: Schema changes +.. list-table:: Schema Changes :widths: auto :header-rows: 1 @@ -219,10 +219,10 @@ Clauses - ✓ - -Table expressions +Table Expressions ==================== -.. list-table:: Table expressions +.. list-table:: Table Expressions :widths: auto :header-rows: 1 @@ -246,12 +246,12 @@ Table expressions - -Scalar expressions +Scalar Expressions ==================== Read more about :ref:`scalar_expressions`. -.. list-table:: Scalar expressions +.. list-table:: Scalar Expressions :widths: auto :header-rows: 1 @@ -285,7 +285,7 @@ Read more about :ref:`scalar_expressions`. * - ``IN``, ``NOT IN`` - Partial - Literal values only - * - Bitwise arithemtic + * - Bitwise arithmetic - ✓ - ``&``, ``|``, ``XOR``, ``~``, ``>>``, ``<<`` @@ -318,10 +318,10 @@ Read more about :ref:`access_control` in SQream DB. -Extra functionality +Extra Functionality ====================== -.. list-table:: Extra functionality +.. list-table:: Extra Functionality :widths: auto :header-rows: 1 From 01d446bec806fc0aad64c1219c8ef09d7dafa3d7 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 08:43:46 +0200 Subject: [PATCH 132/300] Update optimization_best_practices.rst Replaced VARCHAR with TEXT. --- .../optimization_best_practices.rst | 130 ++++++++---------- 1 file changed, 58 insertions(+), 72 deletions(-) diff --git a/guides/operations/optimization_best_practices.rst b/guides/operations/optimization_best_practices.rst index e1abecd21..2ee93dbe0 100644 --- a/guides/operations/optimization_best_practices.rst +++ b/guides/operations/optimization_best_practices.rst @@ -1,10 +1,10 @@ .. _sql_best_practices: ********************************** -Optimization and best practices +Optimization and Best Practices ********************************** -This topic explains some best practices of working with SQream DB. +This topic explains some best practices of working with SQream. See also our :ref:`monitoring_query_performance` guide for more information. @@ -13,16 +13,16 @@ See also our :ref:`monitoring_query_performance` guide for more information. .. _table_design_best_practices: -Table design +Table Design ============== This section describes best practices and guidelines for designing tables. -Use date and datetime types for columns +Using Date and Datetime Types for Columns ----------------------------------------- -When creating tables with dates or timestamps, using the purpose-built ``DATE`` and ``DATETIME`` types over integer types or ``VARCHAR`` will bring performance and storage footprint improvements, and in many cases huge performance improvements (as well as data integrity benefits). SQream DB stores dates and datetimes very efficiently and can strongly optimize queries using these specific types. +When creating tables with dates or timestamps, using the purpose-built ``DATE`` and ``DATETIME`` types over integer types or ``VARCHAR`` will bring performance and storage footprint improvements, and in many cases huge performance improvements (as well as data integrity benefits). SQream stores dates and datetimes very efficiently and can strongly optimize queries using these specific types. -Reduce varchar length to a minimum +Shortening VARCHAR Length -------------------------------------- With the ``VARCHAR`` type, the length has a direct effect on query performance. @@ -31,23 +31,23 @@ If the size of your column is predictable, by defining an appropriate column len * Data loading issues can be identified more quickly -* SQream DB can reserve less memory for decompression operations +* SQream can reserve less memory for decompression operations * Third-party tools that expect a data size are less likely to over-allocate memory -Don't flatten or denormalize data +Avoiding Flattening or Denormalizing Data ----------------------------------- -SQream DB executes JOIN operations very effectively. It is almost always better to JOIN tables at query-time rather than flatten/denormalize your tables. +SQream executes JOIN operations very effectively. It is almost always better to JOIN tables at query-time rather than flatten/denormalize your tables. This will also reduce storage size and reduce row-lengths. We highly suggest using ``INT`` or ``BIGINT`` as join keys, rather than a text/string type. -Convert foreign tables to native tables +Converting Foreign Tables to Native Tables ------------------------------------------- -SQream DB's native storage is heavily optimized for analytic workloads. It is always faster for querying than other formats, even columnar ones such as Parquet. It also enables the use of additional metadata to help speed up queries, in some cases by many orders of magnitude. +SQream's native storage is heavily optimized for analytic workloads. It is always faster for querying than other formats, even columnar ones such as Parquet. It also enables the use of additional metadata to help speed up queries, in some cases by many orders of magnitude. You can improve the performance of all operations by converting :ref:`foreign tables` into native tables by using the :ref:`create_table_as` syntax. @@ -59,52 +59,46 @@ For example, The one situation when this wouldn't be as useful is when data will be only queried once. -Use information about the column data to your advantage +Leverating Column Data Information ------------------------------------------------------------- Knowing the data types and their ranges can help design a better table. -Set ``NULL`` or ``NOT NULL`` when relevant +Identifying Relevance of Setting NULL or NOT NULL Values ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For example, if a value can't be missing (or ``NULL``), specify a ``NOT NULL`` constraint on the columns. +For example, if a value cannot be omitted (or ``NULL``), you must specify a ``NOT NULL`` constraint on the columns. -Not only does specifying ``NOT NULL`` save on data storage, it lets the query compiler know that a column cannot have a ``NULL`` value, which can improve query performance. +In addition to saving data storage, specifying ``NOT NULL`` informs the query compiler that a column cannot have a ``NULL`` value, which can improve query performance. -Keep VARCHAR lengths to a minimum +Shortening VARCHAR Length ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Although long strings do not affect storage, they require a lot of memory while queries are being run. If a column's string length is less than 50 characters, specify ``VARCHAR(50)`` rather than an arbitrarily large number. -While it won't make a big difference in storage, large strings allocate a lot of memory at query time. -If a column's string length never exceeds 50 characters, specify ``VARCHAR(50)`` rather than an arbitrarily large number. - - -Sorting +Sorting Data ============== +Sorting data is an important factor in minimizing storage size and improving query performance for the following reasons: -Data sorting is an important factor in minimizing storage size and improving query performance. +* Minimizing storage saves on physical resources and increases performance by reducing overall disk I/O. Prioritize the sorting of low-cardinality columns. This reduces the number of chunks and extents that SQream reads during query execution. -* Minimizing storage saves on physical resources and increases performance by reducing overall disk I/O. Prioritize the sorting of low-cardinality columns. This reduces the number of chunks and extents that SQream DB reads during query execution. - -* Where possible, sort columns with the lowest cardinality first. Avoid sorting ``VARCHAR`` and ``TEXT/NVARCHAR`` columns with lengths exceeding 50 characters. +* Where possible, sort columns with the lowest cardinality first. Avoid sorting ``VARCHAR`` and ``TEXT`` columns with lengths exceeding 50 characters. * For longer-running queries that run on a regular basis, performance can be improved by sorting data based on the ``WHERE`` and ``GROUP BY`` parameters. Data can be sorted during insert by using :ref:`external_tables` or by using :ref:`create_table_as`. .. _query_best_practices: -Query best practices +Best Practices for Writing SQL Queries ===================== This section describes best practices for writing SQL queries. -Reduce data sets before joining tables +Reducing Data Sets Before Joining Tables ----------------------------------------- Reducing the input to a ``JOIN`` clause can increase performance. -Some queries benefit from retreiving a reduced dataset as a subquery prior to a join. - -For example, +Some queries benefit from retreiving a reduced dataset as a subquery prior to a join, as shown in the following example: .. code-block:: postgres @@ -113,7 +107,7 @@ For example, WHERE p_date BETWEEN '2018-07-01' AND '2018-07-31' GROUP BY 1; -Can be rewritten as +This can be rewritten as follows: .. code-block:: postgres @@ -125,13 +119,11 @@ Can be rewritten as group by 2) AS fact ON dim.store_id=fact.store_id; -Prefer the ANSI JOIN +Using an ANSI JOIN ---------------------------- -SQream DB prefers the ANSI JOIN syntax. -In some cases, the ANSI JOIN performs better than the non-ANSI variety. - -For example, this ANSI JOIN example will perform better: +SQream prefers the ANSI JOIN syntax. +In some cases ANSI JOINs performs better than the non-ANSI variety, as shown in the following example: .. code-block:: postgres :caption: ANSI JOIN will perform better @@ -143,7 +135,7 @@ For example, this ANSI JOIN example will perform better: JOIN "Customers" as c ON s.c_id = c.id AND c.id = 20301125; -This non-ANSI JOIN is supported, but not recommended: +SQream supports the following non-ANSI JOIN, but does not recommend using it: .. code-block:: postgres :caption: Non-ANSI JOIN may not perform well @@ -158,19 +150,16 @@ This non-ANSI JOIN is supported, but not recommended: .. _high_selectivity: -Use the high selectivity hint +Using a High Selectivity Hint -------------------------------- -Selectivity is the ratio of cardinality to the number of records of a chunk. We define selectivity as :math:`\frac{\text{Distinct values}}{\text{Total number of records in a chunk}}` +**Selectivity** is the ratio of cardinality to the number of records of a chunk. Selectivity is defined as ``:math:`\frac{\text{Distinct values}}{\text{Total number of records in a chunk}}```. -SQream DB has a hint function called ``HIGH_SELECTIVITY``, which is a function you can wrap a condition in. +SQream employees a hint function called ``HIGH_SELECTIVITY``, which is a function that can be used for wrapping a condition. The hint signals to SQream that the result of the condition is very sparse and to rechunk the results into fewer, fuller chunks. -The hint signals to SQream DB that the result of the condition will be very sparse, and that it should attempt to rechunk -the results into fewer, fuller chunks. +SQream recommends using the high selectivity hint when you expect a predicate to filter out most values, such as when data is dispersed over many chunks, indicating that the data has not been optimally clustered. -Use the high selectivity hint when you expect a predicate to filter out most values. For example, when the data is dispersed over lots of chunks (meaning that the data is :ref:`not well-clustered`). - -For example, +The following example shows data that is not clustered optimally: .. code-block:: postgres @@ -178,19 +167,19 @@ For example, WHERE HIGH_SELECTIVITY(p_date = '2018-07-01') GROUP BY 1; -This hint tells the query compiler that the ``WHERE`` condition is expected to filter out more than 60% of values. It never affects the query results, but when used correctly can improve query performance. +This hint tells the query compiler that the ``WHERE`` condition is expected to filter out more than 60% of values. While it does not affect query results, using it correctly can improve query performance. + +.. tip:: The ``HIGH_SELECTIVITY()`` hint function can only be used as part of the ``WHERE`` clause and cannot be used in equijoin conditions, cases, or in the select list. -.. tip:: The ``HIGH_SELECTIVITY()`` hint function can only be used as part of the ``WHERE`` clause. It can't be used in equijoin conditions, cases, or in the select list. +For more information about identifying scenarios for the high selectivity hint, see the :ref:`Monitoring Query Performance Guide`. -Read more about identifying the scenarios for the high selectivity hint in our :ref:`Monitoring query performance guide`. +For more information about optimal data clustering, see :ref:`not well-clustered`). -Cast smaller types to avoid overflow in aggregates +Casting Smaller Types to Avoid Aggregate Overflow ------------------------------------------------------ When using an ``INT`` or smaller type, the ``SUM`` and ``COUNT`` operations return a value of the same type. -To avoid overflow on large results, cast the column up to a larger type. - -For example +To avoid overflow on large results, cast the column up to a larger type, as shown in the following example: .. code-block:: postgres @@ -198,13 +187,13 @@ For example GROUP BY 1; -Prefer ``COUNT(*)`` and ``COUNT`` on non-nullable columns +Preferring ``COUNT(*)`` and ``COUNT`` on Non-Nullable Columns ------------------------------------------------------------ -SQream DB optimizes ``COUNT(*)`` queries very strongly. This also applies to ``COUNT(column_name)`` on non-nullable columns. Using ``COUNT(column_name)`` on a nullable column will operate quickly, but much slower than the previous variations. +SQream optimizes ``COUNT(*)`` queries very strongly. This also applies to ``COUNT(column_name)`` on non-nullable columns. Using ``COUNT(column_name)`` on a nullable column operate quickly, but much slower than the previous variations. -Return only required columns +Returning Only Required Columns ------------------------------- Returning only the columns you need to client programs can improve overall query performance. @@ -212,10 +201,10 @@ This also reduces the overall result set, which can improve performance in third SQream is able to optimize out unneeded columns very strongly due to its columnar storage. -Use saved queries to reduce recurring compilation time +Using Saved Queries to Reduce Recurring Compilation Duration ------------------------------------------------------- -:ref:`saved_queries` are compiled when they are created. The query plan is saved in SQream DB's metadata for later re-use. +:ref:`saved_queries` are compiled when they are created. The query plan is saved in SQream's metadata for later re-use. Because the query plan is saved, they can be used to reduce compilation overhead, especially with very complex queries, such as queries with lots of values in an :ref:`IN` predicate. @@ -223,10 +212,9 @@ When executed, the saved query plan is recalled and executed on the up-to-date d See how to use saved queries in the :ref:`saved queries guide`. -Pre-filter to reduce :ref:`JOIN` complexity +Pre-Filtering to Reduce JOIN Complexity -------------------------------------------------------- - -Filter and reduce table sizes prior to joining on them +The following is the correct syntax for pre-filtering to reduce JOIN complexity by filtering and reducing table sizes before joining them: .. code-block:: postgres @@ -237,7 +225,7 @@ Filter and reduce table sizes prior to joining on them WHERE p_date BETWEEN '2019-07-01' AND '2019-07-31' GROUP BY store_name; -Can be rewritten as: +The example above can be rewritten as follows: .. code-block:: postgres @@ -249,27 +237,25 @@ Can be rewritten as: FROM fact WHERE p_date BETWEEN '2019-07-01' AND '2019-07-31' GROUP BY store_id) AS fact ON dim.store_id = fact.store_id; + +For more information about reducing JOIN complexity, see :ref:`JOIN`. .. _data_loading_considerations: -Data loading considerations +Data Loading Considerations ================================= -Allow and use natural sorting on data +Enabling and Using Natural Data Sorting ---------------------------------------- -Very often, tabular data is already naturally ordered along a dimension such as a timestamp or area. - -This natural order is a major factor for query performance later on, as data that is naturally sorted can be more easily compressed and analyzed with SQream DB's metadata collection. +Tabular data is often naturally ordered along a dimension, such as a timestamp or area. This natural order is a major factor for query performance during later stages, as data that is naturally sorted can be more easily compressed and analyzed with SQream's metadata collection. -For example, when data is sorted by timestamp, filtering on this timestamp is more effective than filtering on an unordered column. +For example, when data is sorted by timestamp, filtering on this timestamp is more effective than filtering on an unordered column. Natural ordering can also be used for effective **DELETE** operations. -Natural ordering can also be used for effective :ref:`delete` operations. +For more information about Delete operations, see :ref:`delete operations`. -Further reading and monitoring query performance +Further Reading and Monitoring Query Performance ======================================================= - -Read our :ref:`monitoring_query_performance` guide to learn how to use the built in monitoring utilities. -The guide also gives concerete examples for improving query performance. +For more information about built-in monitoring utilities, see the :ref:`monitoring_query_performance` guide. The Monitoring Query Performance Guide also gives concerete examples for improving query performance. From 655eeecdd39624b4cb475d4562c9c995ae1a3f93 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 08:45:55 +0200 Subject: [PATCH 133/300] Update 2020.1.rst Capitalization. --- releases/2020.1.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/releases/2020.1.rst b/releases/2020.1.rst index 7915ac261..ecea0f29e 100644 --- a/releases/2020.1.rst +++ b/releases/2020.1.rst @@ -13,7 +13,7 @@ The latest release vastly improves reliability and performance, and makes gettin The core of SQream DB v2020.1 contains new integration features, more analytics capabilities, and better drivers and connectors. -New features +New Features ================ Integrations @@ -35,7 +35,7 @@ Integrations See :ref:`logging` for more information. -SQL support +SQL Support --------------- * @@ -53,7 +53,7 @@ SQL support * Added lots of new :ref:`aggregate functions`, including ``VAR_SAMP``, ``VAR_POP``, ``COVAR_POP``, etc. -Improvements and fixes +Improvements and Fixes ======================== SQream DB v2020.1 includes hundreds of small new features and tunable parameters that improve performance, reliability, and stability. Existing SQream DB users can expect to see a general speedup of around 10% on most statements and queries! @@ -94,7 +94,7 @@ SQream DB v2020.1 includes hundreds of small new features and tunable parameters * Additional CSV date formats (date parsers) added for compatibility -Behaviour changes +Behaviour Changes ======================== * ``ClientCmd`` is now known as :ref:`sqream sql` @@ -162,7 +162,7 @@ Operations -Known Issues & Limitations +Known Issues and Limitations ================================ * An invalid formatted CSV can cause an ``insufficient memory`` error on a :ref:`copy_from` statement if a quote isn't closed and the file is much larger than system memory. From 62d7de264db9b726990928e299ce25ba59907c5b Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 08:46:40 +0200 Subject: [PATCH 134/300] Update oracle.rst Replaced VARCHAR with TEXT. --- guides/migration/oracle.rst | 82 ++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/guides/migration/oracle.rst b/guides/migration/oracle.rst index 86be41517..6c7106741 100644 --- a/guides/migration/oracle.rst +++ b/guides/migration/oracle.rst @@ -10,7 +10,7 @@ This guide covers actions required for migrating from Oracle to SQream DB with C :local: -1. Preparing the tools and login information +1. Preparing Your Tools and Login Information ==================================================== * Migrating data from Oracle requires a username and password for your Oracle system. @@ -18,7 +18,7 @@ This guide covers actions required for migrating from Oracle to SQream DB with C * In this guide, we'll use the `Oracle Data Pump `_ , specifically the `Data Pump Export utility `_ . -2. Export the desired schema +2. Exporting Your Schema =================================== Use the Data Pump Export utility to export the database schema. @@ -33,16 +33,18 @@ The resulting Oracle-only schema is stored in a dump file. Examples ------------ -Dump all tables +Dump All Tables ^^^^^^^^^^^^^^^^^^^^^^ +The following shows the correct syntax for dumping all tables: .. code-block:: console $ expdp rhendricks/secretpassword DIRECTORY=dpumpdir DUMPFILE=tables.dmp CONTENT=metadata_only NOLOGFILE -Dump only specific tables +Dumping Specific Tables ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following shows the correct syntax for dumping specific tables: In this example, we specify two tables for dumping. @@ -50,12 +52,12 @@ In this example, we specify two tables for dumping. $ expdp rhendricks/secretpassword DIRECTORY=dpumpdir DUMPFILE=tables.dmp CONTENT=metadata_only TABLES=employees,jobs NOLOGFILE -3. Convert the Oracle dump to standard SQL +3. Converting the Oracle Dump to Standard SQL ======================================================= -Oracle's Data Pump Import utility will help us convert the dump from the previous step to standard SQL. +Oracle's Data Pump Import utility helps convert the dump from the previous step to standard SQL. -The format for using the Import utility is +The following is the correct Import utility format: ``impdp / DIRECTORY= DUMPFILE= SQLFILE= TRANSFORM=SEGMENT_ATTRIBUTES:N:table PARTITION_OPTIONS=MERGE`` @@ -65,33 +67,34 @@ The format for using the Import utility is Example ---------- +The following shows the correct syntax for converting the Oracle dump to standard SQL: .. code-block:: console $ impdp rhendricks/secretpassword DIRECTORY=dpumpdir DUMPFILE=tables.dmp SQLFILE=sql_export.sql TRANSFORM=SEGMENT_ATTRIBUTES:N:table PARTITION_OPTIONS=MERGE -4. Figure out the database structures +4. Identify Database Structures =============================================== -Using the SQL file created in the previous step, write CREATE TABLE statements to match the schemas of the tables. +Using the SQL file created in the previous step, write ``CREATE TABLE`` statements to match the schemas of the tables. -Remove unsupported attributes +Removing Unsupported Attributes ----------------------------------- Trim unsupported primary keys, indexes, constraints, and other unsupported Oracle attributes. -Match data types +Matching Data Types --------------------- -Refer to the table below to match the Oracle source data type to a new SQream DB type: +Refer to the table below to match the Oracle source data type to a new SQream type: -.. list-table:: Data types +.. list-table:: Data Types :widths: auto :header-rows: 1 - * - Oracle Data type + * - Oracle Data Type - Precision - - SQream DB data type + - SQream Data Type * - ``CHAR(n)``, ``CHARACTER(n)`` - Any ``n`` - ``VARCHAR(n)`` @@ -141,8 +144,9 @@ Refer to the table below to match the Oracle source data type to a new SQream DB Read more about :ref:`supported data types in SQream DB`. -Additional considerations +Additional Considerations ----------------------------- +Note the following when migrating from Oracle to SQream using CSV files: * Understand how :ref:`tables are created in SQream DB` @@ -150,16 +154,13 @@ Additional considerations * Oracle roles and user management commands need to be rewritten to SQream DB's format. SQream DB supports :ref:`full role-based access control (RBAC)` similar to Oracle. -5. Create the tables in SQream DB +5. Creating the Tables in SQream ====================================== - -After rewriting the table strucutres, create them in SQream DB. +After rewriting the table strucutres, you can create them in SQream. Example --------- - - -Consider Oracle's ``HR.EMPLOYEES`` sample table: +The following example of creating a table in SQream is based on Oracle's ``HR.EMPLOYEES`` sample table: .. code-block:: sql @@ -201,7 +202,7 @@ Consider Oracle's ``HR.EMPLOYEES`` sample table: REFERENCES employees ) ; -This table rewritten for SQream DB would be created like this: +This table is rewritten for SQream as follows: .. code-block:: postgres @@ -221,20 +222,18 @@ This table rewritten for SQream DB would be created like this: ); -6. Export tables to CSVs +6. Exporting Tables to CSV Files =============================== -Exporting CSVs from Oracle servers is not a trivial task. +The following options can be used for exporting tables to CSV files: -.. contents:: Options for exporting to CSVs +.. contents:: :local: -Using SQL*Plus to export data lists +Using SQL*Plus to Export Data Lists ------------------------------------------ -Here's a sample SQL*Plus script that will export PSVs in a format that SQream DB can read: - -:download:`Download to_csv.sql ` +The following is a :download:`sample SQL*Plus script ` for exporting PSVs in a SQream readable format: .. literalinclude:: to_csv.sql :language: sql @@ -254,14 +253,14 @@ Enter SQL*Plus and export tables one-by-one interactively: Each table is exported as a data list file (``.lst``). -Creating CSVs using stored procedures +Creating CSVs Using Stored Procedures ------------------------------------------- -You can use stored procedures if you have them set-up. +You can use stored procedures if they have been set-up. Examples of `stored procedures for generating CSVs `_` can be found in the Ask The Oracle Mentors forums. -CSV generation considerations +CSV Generation Considerations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Files should be a valid CSV. By default, SQream DB's CSV parser can handle `RFC 4180 standard CSVs `_ , but can also be modified to support non-standard CSVs (with multi-character delimiters, unquoted fields, etc). @@ -293,7 +292,7 @@ CSV generation considerations .. note:: If a text field is quoted but contains no content (``""``) it is considered an empty text field. It is not considered ``NULL``. -7. Place CSVs where SQream DB workers can access +7. Storing CSV Files in a SQream Worker Accessible Location ======================================================= During data load, the :ref:`copy_from` command can run on any worker (unless explicitly speficied with the :ref:`workload_manager`). @@ -305,7 +304,7 @@ It is important that every node has the same view of the storage being used - me * For S3, ensure network access to the S3 endpoint -8. Bulk load the CSVs +8. Bulk Load CSV Files ================================= Issue the :ref:`copy_from` commands to SQream DB to insert a table from the CSVs created. @@ -314,21 +313,18 @@ Repeat the ``COPY FROM`` command for each table exported from Oracle. Example ------------- - -For the ``employees`` table, run the following command: +The following shows the correct syntax of bulk loading CSV files based on the ``employees`` table: .. code-block:: postgres COPY employees FROM 'employees.lst' WITH DELIMITER '|'; -9. Rewrite Oracle queries +9. Rewriting Oracle Queries ===================================== -SQream DB supports a large subset of ANSI SQL. - -You will have to refactor much of Oracle's SQL and functions that often are not ANSI SQL. +SQream supports a large subset of ANSI SQL. You must refactor much of Oracle's SQL and functions that often are not ANSI SQL. -We recommend the following resources: +SQream recommends the following resources: * :ref:`sql_feature_support` - to understand SQream DB's SQL feature support. @@ -350,4 +346,4 @@ We recommend the following resources: * :ref:`Views` - SQream DB supports logical views, but does not support materialized views. -* :ref:`window_functions` - SQream DB supports a wide array of window functions. \ No newline at end of file +* :ref:`window_functions` - SQream DB supports a wide array of window functions. From c0f0dfc55b9da40340476df42ea3e7479b299e2f Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:06:33 +0200 Subject: [PATCH 135/300] Update orc.rst General clean-up. --- guides/migration/orc.rst | 63 +++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/guides/migration/orc.rst b/guides/migration/orc.rst index cd448bde0..cac4aadd8 100644 --- a/guides/migration/orc.rst +++ b/guides/migration/orc.rst @@ -4,10 +4,10 @@ Insert from ORC ********************** -This guide covers inserting data from ORC files into SQream DB using :ref:`EXTERNAL TABLE`. +This guide covers inserting data from ORC files into SQream DB using :ref:`FOREIGN TABLE`. -1. Prepare the files +1. Preparing Your Files ===================== Prepare the source ORC files, with the following requirements: @@ -145,7 +145,7 @@ Prepare the source ORC files, with the following requirements: .. rubric:: Footnotes -.. [#f0] Text values include ``TEXT``, ``VARCHAR``, and ``NVARCHAR`` +.. [#f0] Text values include ``TEXT`` and ``VARCHAR``. .. [#f5] Boolean values are cast to 0, 1 @@ -153,7 +153,7 @@ Prepare the source ORC files, with the following requirements: .. [#f7] Will succeed if all values fit the destination type -2. Place ORC files where SQream DB workers can access them +2. Storing CSV Files in a SQream Worker Accessible Location ================================================================ Any worker may try to access files (unless explicitly speficied with the :ref:`workload_manager`). @@ -161,11 +161,11 @@ It is important that every node has the same view of the storage being used - me * For files hosted on NFS, ensure that the mount is accessible from all servers. -* For HDFS, ensure that SQream DB servers can access the HDFS name node with the correct user-id +* For HDFS, ensure that SQream DB servers can access the HDFS name node with the correct user-id. See our :ref:`hdfs` guide for more information. -* For S3, ensure network access to the S3 endpoint +* For S3, ensure network access to the S3 endpoint. See our :ref:`s3` guide for more information. -3. Figure out the table structure +3. Determining Your Table Structure =============================================== Prior to loading data, you will need to write out the table structure, so that it matches the file structure. @@ -180,11 +180,11 @@ For example, to import the data from ``nba.orc``, we will first look at the sour * The file is stored on S3, at ``s3://sqream-demo-data/nba.orc``. -We will make note of the file structure to create a matching ``CREATE EXTERNAL TABLE`` statement. +We will make note of the file structure to create a matching ``CREATE FOREIGN TABLE`` statement. .. code-block:: postgres - CREATE EXTERNAL TABLE ext_nba + CREATE FOREIGN TABLE ext_nba ( Name VARCHAR(40), Team VARCHAR(40), @@ -196,8 +196,11 @@ We will make note of the file structure to create a matching ``CREATE EXTERNAL T College VARCHAR(40), Salary FLOAT ) - USING FORMAT ORC - WITH PATH 's3://sqream-demo-data/nba.orc'; + WRAPPER orc_fdw + OPTIONS + ( + LOCATION = 's3://sqream-demo-data/nba.orc' + ); .. tip:: @@ -206,7 +209,7 @@ We will make note of the file structure to create a matching ``CREATE EXTERNAL T If the column type isn't supported, a possible workaround is to set it to any arbitrary type and then exclude it from subsequent queries. -4. Verify table contents +4. Verify Your Table of Contents ==================================== External tables do not verify file integrity or structure, so verify that the table definition matches up and contains the correct data. @@ -229,7 +232,7 @@ External tables do not verify file integrity or structure, so verify that the ta If any errors show up at this stage, verify the structure of the ORC files and match them to the external table structure you created. -5. Copying data into SQream DB +5. Copying Your Data into SQream =================================== To load the data into SQream DB, use the :ref:`create_table_as` statement: @@ -239,7 +242,7 @@ To load the data into SQream DB, use the :ref:`create_table_as` statement: CREATE TABLE nba AS SELECT * FROM ext_nba; -Working around unsupported column types +Working Around Unsupported Column Types --------------------------------------------- Suppose you only want to load some of the columns - for example, if one of the columns isn't supported. @@ -256,7 +259,7 @@ For this example, assume that the ``Position`` column isn't supported because of -- We ommitted the unsupported column `Position` from this query, and replaced it with a default ``NULL`` value, to maintain the same table structure. -Modifying data during the copy process +Modifying Data During the Copy Process ------------------------------------------ One of the main reasons for staging data with ``EXTERNAL TABLE`` is to examine the contents and modify them before loading them. @@ -273,34 +276,40 @@ Similar to the previous example, we will also set the ``Position`` column as a d ORDER BY weight; -Further ORC loading examples +Additional ORC Loading Examples ======================================= -:ref:`create_external_table` contains several configuration options. See more in :ref:`the CREATE EXTERNAL TABLE parameters section`. +:ref:`create_foreign_table` contains several configuration options. See more in :ref:`the CREATE FOREIGN TABLE parameters section`. -Loading a table from a directory of ORC files on HDFS +Loading a Table from a Directory of ORC Files on HDFS ------------------------------------------------------------ .. code-block:: postgres - CREATE EXTERNAL TABLE ext_users + CREATE FOREIGN TABLE ext_users (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) - USING FORMAT ORC - WITH PATH 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.ORC'; + WRAPPER orc_fdw + OPTIONS + ( + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.ORC' + ); CREATE TABLE users AS SELECT * FROM ext_users; -Loading a table from a bucket of files on S3 +Loading a Table from a Bucket of Files on S3 ----------------------------------------------- .. code-block:: postgres - CREATE EXTERNAL TABLE ext_users + CREATE FOREIGN TABLE ext_users (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) - USING FORMAT ORC - WITH PATH 's3://pp-secret-bucket/users/*.ORC' - AWS_ID 'our_aws_id' - AWS_SECRET 'our_aws_secret'; + WRAPPER orc_fdw + OPTIONS + ( LOCATION = 's3://pp-secret-bucket/users/*.ORC', + AWS_ID = 'our_aws_id', + AWS_SECRET = 'our_aws_secret' + ) + ; CREATE TABLE users AS SELECT * FROM ext_users; From 12b606005025991ee703ff34b8b3783da827cb89 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:07:32 +0200 Subject: [PATCH 136/300] Update sql_feature_support.rst Replaced VARCHAR with TEXT. --- reference/sql_feature_support.rst | 87 ++++++++++++++++++------------- 1 file changed, 51 insertions(+), 36 deletions(-) diff --git a/reference/sql_feature_support.rst b/reference/sql_feature_support.rst index 9c75adde7..ba4ca39e4 100644 --- a/reference/sql_feature_support.rst +++ b/reference/sql_feature_support.rst @@ -11,10 +11,12 @@ To understand which ANSI SQL and other SQL features SQream DB supports, use the :local: -Data types and values +Data Types and Values ========================= -.. list-table:: Value +Read more about :ref:`supported data types`. + +.. list-table:: Data Types and Values :widths: auto :header-rows: 1 @@ -43,17 +45,14 @@ Data types and values - ✓ - 8 byte floating point * - ``DECIMAL``, ``NUMERIC`` - - Planned - - Fixed-point numbers. Use ``DOUBLE`` instead + - ✓ + - Fixed-point numbers. * - ``VARCHAR`` - ✓ - Variable length string - ASCII only - * - ``NVARCHAR`` + * - ``TEXT`` - ✓ - Variable length string - UTF-8 encoded - * - ``TEXT`` - - Planned - - Use ``VARCHAR``, ``NVARCHAR`` * - ``DATE`` - ✓ - Date @@ -96,19 +95,22 @@ SQream DB treats each statement as an auto-commit transaction. Each transaction If a statement fails, the entire transaction is cancelled and rolled back. The database is unchanged. +Read more about :ref:`transactions in SQream DB`. + Indexes ============ SQream DB has a range-index collected on all columns as part of the metadata collection process. -SQream DB does not support explicit indexing. +SQream DB does not support explicit indexing, but does support clustering keys. +Read more about :ref:`clustering keys` and our :ref:`metadata system`. -Schema changes +Schema Changes ================ -.. list-table:: Schema changes +.. list-table:: Schema Changes :widths: auto :header-rows: 1 @@ -117,25 +119,31 @@ Schema changes - Further information * - ``ALTER TABLE`` - ✓ - - Add column, alter column, drop column, rename column, rename table + - :ref:`alter_table` - Add column, alter column, drop column, rename column, rename table, modify clustering keys * - Rename database - ✗ - * - Rename table - ✓ - - + - :ref:`rename_table` * - Rename column - ✓ - - + - :ref:`rename_column` * - Add column - ✓ - - + - :ref:`add_column` * - Remove column - ✓ - - + - :ref:`drop_column` * - Alter column data type - ✗ - + * - Add / modify clustering keys + - ✓ + - :ref:`cluster_by` + * - Drop clustering keys + - ✓ + - :ref:`drop_clustering_key` * - Add / Remove constraints - ✗ - @@ -144,10 +152,10 @@ Schema changes - * - Drop schema - ✓ - - + - :ref:`drop_schema` * - Alter default schema per user - ✓ - - + - :ref:`alter_default_schema` Statements @@ -162,25 +170,28 @@ Statements - Further information * - SELECT - ✓ - - + - :ref:`select` * - CREATE TABLE - ✓ - - + - :ref:`create_table` + * - CREATE FOREIGN / EXTERNAL TABLE + - ✓ + - :ref:`create_foreign_table` * - DELETE - ✓ - - + - :ref:`delete_guide` * - INSERT - ✓ - - + - :ref:`insert`, :ref:`copy_from` * - TRUNCATE - ✓ - - + - :ref:`truncate` * - UPDATE - ✗ - * - VALUES - ✓ - - + - :ref:`values` Clauses =========== @@ -208,10 +219,10 @@ Clauses - ✓ - -Table expressions +Table Expressions ==================== -.. list-table:: Table expressions +.. list-table:: Table Expressions :widths: auto :header-rows: 1 @@ -235,10 +246,12 @@ Table expressions - -Scalar expressions +Scalar Expressions ==================== -.. list-table:: Scalar expressions +Read more about :ref:`scalar_expressions`. + +.. list-table:: Scalar Expressions :widths: auto :header-rows: 1 @@ -281,6 +294,8 @@ Scalar expressions Permissions =============== +Read more about :ref:`access_control` in SQream DB. + .. list-table:: Permissions :widths: auto :header-rows: 1 @@ -303,10 +318,10 @@ Permissions -Extra functionality +Extra Functionality ====================== -.. list-table:: Extra functionality +.. list-table:: Extra Functionality :widths: auto :header-rows: 1 @@ -315,19 +330,19 @@ Extra functionality - Further information * - Information schema - ✓ - - ``SQream Catalog`` + - :ref:`catalog_reference` * - Views - ✓ - - + - :ref:`create_view` * - Window functions - ✓ - - + - :ref:`window_functions` * - CTEs - ✓ - - + - :ref:`common_table_expressions` * - Saved queries, Saved queries with parameters - ✓ - - + - :ref:`saved_queries` * - Sequences - ✓ - - + - :ref:`identity` From f98ef1bcb4f7085f1c3ebb550ea025921cf4ca22 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:08:51 +0200 Subject: [PATCH 137/300] Update crc64.rst Replaced VARCHAR with TEXT. --- reference/sql/sql_functions/scalar_functions/numeric/crc64.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst b/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst index 46713e6c5..9173a1984 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst @@ -25,7 +25,7 @@ Arguments * - Parameter - Description * - ``expr`` - - Text expression (``VARCHAR``, ``NVARCHAR``) + - Text expression (``VARCHAR``, ``TEXT``) Returns ============ From 8bbbd4df63e7e8eaa5c5d143caa126dee152d62b Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:09:52 +0200 Subject: [PATCH 138/300] Update isprefixof.rst Replaced VARCHAR with TEXT. --- .../sql/sql_functions/scalar_functions/string/isprefixof.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst b/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst index e402404ea..4a978b1ff 100644 --- a/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst +++ b/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst @@ -39,7 +39,7 @@ Returns Notes ======= -* This function is supported on ``NVARCHAR`` strings only. +* This function is supported on ``TEXT`` strings only. * If the value is NULL, the result is NULL. @@ -69,4 +69,4 @@ Filtering using ``ISPREFIXOF`` ----------------------------------- And the mome raths outgrabe. -.. tip:: Use :ref:`trim` to avoid leading and trailing whitespace issues \ No newline at end of file +.. tip:: Use :ref:`trim` to avoid leading and trailing whitespace issues From b0cd46dca91e8e2169e3b7343efd6aa39b20e41a Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:11:17 +0200 Subject: [PATCH 139/300] Update char_length.rst Replaced VARCHAR with TEXT. --- .../sql_functions/scalar_functions/string/char_length.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/char_length.rst b/reference/sql/sql_functions/scalar_functions/string/char_length.rst index 1de9cce4b..2e940aabd 100644 --- a/reference/sql/sql_functions/scalar_functions/string/char_length.rst +++ b/reference/sql/sql_functions/scalar_functions/string/char_length.rst @@ -8,7 +8,7 @@ Calculates the number of characters in a string. .. note:: - * This function is supported on ``NVARCHAR`` only. + * This function is supported on ``TEXT`` only. * To get the length in bytes, see :ref:`octet_length`. @@ -30,8 +30,8 @@ Arguments * - Parameter - Description - * - ``nvarchar_expr`` - - ``NVARCHAR`` expression + * - ``text_expr`` + - ``TEXT`` expression Returns ============ @@ -52,7 +52,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE alphabets(line NVARCHAR(50)); + CREATE TABLE alphabets(line TEXT(50)); INSERT INTO alphabets VALUES ('abcdefghijklmnopqrstuvwxyz'), ('กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯ') From aa24b6123c8ba73d6779d06c7cc501b87b4abb64 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:11:52 +0200 Subject: [PATCH 140/300] Update octet_length.rst Replaced VARCHAR with TEXT. --- .../scalar_functions/string/octet_length.rst | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/octet_length.rst b/reference/sql/sql_functions/scalar_functions/string/octet_length.rst index db8e3839e..8bb1e3daf 100644 --- a/reference/sql/sql_functions/scalar_functions/string/octet_length.rst +++ b/reference/sql/sql_functions/scalar_functions/string/octet_length.rst @@ -8,7 +8,7 @@ Calculates the number of bytes in a string. .. note:: - * This function is supported on ``NVARCHAR`` strings only. + * This function is supported on ``TEXT`` strings only. * To get the length in characters, see :ref:`char_length`. @@ -16,14 +16,15 @@ Calculates the number of bytes in a string. Syntax ========== - +The following is the correct syntax for the ``OCTET_LENGTH`` function: .. code-block:: postgres - OCTET_LEN( nvarchar_expr ) --> INT + OCTET_LEN( text_expr ) --> INT Arguments ============ +The following table describes the ``OCTET_LENGTH`` arguments: .. list-table:: :widths: auto @@ -31,38 +32,34 @@ Arguments * - Parameter - Description - * - ``nvarchar_expr`` - - ``NVARCHAR`` expression + * - ``text_expr`` + - ``TEXT`` expression Returns ============ - -Returns an integer containing the number of bytes in the string. +The ``OCTET_LENGTH`` function returns an integer containing the number of bytes in the string. Notes ======= +The following notes are applicable to the ``OCTET_LENGTH`` function: * To get the length in characters, see :ref:`char_length` * If the value is NULL, the result is NULL. -Examples +Length in Characters and Bytes of Strings =========== - -For these examples, consider the following table and contents: +The **Length in characters and bytes of strings** example is based on the following table and contents: .. code-block:: postgres - CREATE TABLE alphabets(line NVARCHAR(50)); + CREATE TABLE alphabets(line TEXT(50)); INSERT INTO alphabets VALUES ('abcdefghijklmnopqrstuvwxyz'), ('กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯ') , ('אבגדהוזחטיכלמנסעפצקרשת'); -Length in characters and bytes of strings --------------------------------------------------- - -ASCII characters take up 1 byte per character, while Thai takes up 3 bytes and Hebrew takes up 2 bytes. +ASCII characters take up 1 byte per character, while Thai takes up 3 bytes and Hebrew takes up 2 bytes, as shown below: .. code-block:: psql @@ -72,6 +69,3 @@ ASCII characters take up 1 byte per character, while Thai takes up 3 bytes and H 26 | 26 | 26 47 | 47 | 141 22 | 22 | 44 - - - From 55fb2ce3152dbdac5742a3b8362160282b77dec0 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:13:22 +0200 Subject: [PATCH 141/300] Update literals.rst Replaced VARCHAR with TEXT. --- reference/sql/sql_syntax/literals.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_syntax/literals.rst b/reference/sql/sql_syntax/literals.rst index 7a5e8fa90..5ec0e6512 100644 --- a/reference/sql/sql_syntax/literals.rst +++ b/reference/sql/sql_syntax/literals.rst @@ -128,7 +128,7 @@ Syntax reference | DATE | DATETIME | VARCHAR ( digits ) - | NVARCHAR ( digits ) + | TEXT ( digits ) Examples ---------- From 2243807c9289835d7ee01fffa3e2b26119af0e7c Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:14:43 +0200 Subject: [PATCH 142/300] Update left.rst Replaced VARCHAR with TEXT. --- .../sql/sql_functions/scalar_functions/string/left.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/left.rst b/reference/sql/sql_functions/scalar_functions/string/left.rst index 089a873af..77c99b0f1 100644 --- a/reference/sql/sql_functions/scalar_functions/string/left.rst +++ b/reference/sql/sql_functions/scalar_functions/string/left.rst @@ -37,7 +37,7 @@ Returns the same type as the argument supplied. Notes ======= -* This function works on ``NVARCHAR`` strings only. +* This function works on ``TEXT`` strings only. * If the value is NULL, the result is NULL. @@ -48,7 +48,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line NVARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT(50)); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') @@ -72,4 +72,4 @@ Using ``LEFT`` "Beware th | , my son! The | at catch! Beware the | and shun - The | rsnatch!" \ No newline at end of file + The | rsnatch!" From 452b21ace8cdf4d9b22c09e21e6397b7bd0a1d15 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:15:15 +0200 Subject: [PATCH 143/300] Update right.rst Replaced VARCHAR with TEXT. --- .../sql/sql_functions/scalar_functions/string/right.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/right.rst b/reference/sql/sql_functions/scalar_functions/string/right.rst index 4d5e753b0..158de7da0 100644 --- a/reference/sql/sql_functions/scalar_functions/string/right.rst +++ b/reference/sql/sql_functions/scalar_functions/string/right.rst @@ -37,7 +37,7 @@ Returns the same type as the argument supplied. Notes ======= -* This function works on ``NVARCHAR`` strings only. +* This function works on ``TEXT`` strings only. * If the value is NULL, the result is NULL. @@ -48,7 +48,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line NVARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT(50)); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') @@ -72,4 +72,4 @@ Using ``RIGHT`` "Beware th | , my son! The | at catch! Beware the | and shun - The | rsnatch!" \ No newline at end of file + The | rsnatch!" From d1195b1e629e6e13525603c45dbdf11245a5d717 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:16:07 +0200 Subject: [PATCH 144/300] Update is_ascii.rst Replaced NVARCHAR with TEXT. --- .../sql_functions/scalar_functions/conditionals/is_ascii.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst b/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst index f19a13d86..bb9e3b2f9 100644 --- a/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst +++ b/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst @@ -45,7 +45,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE dictionary (id INT NOT NULL, fw NVARCHAR(30), en VARCHAR(30)); + CREATE TABLE dictionary (id INT NOT NULL, fw TEXT(30), en VARCHAR(30)); INSERT INTO dictionary VALUES (1, '行こう', 'Let''s go'), (2, '乾杯', 'Cheers'), (3, 'L''chaim', 'Cheers'); From 6c036ea8458fd3aa99ddde44da7b95d0ba9a5558 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:17:02 +0200 Subject: [PATCH 145/300] Update 2019.2.1.rst Replaced NVARCHAR with TEXT. --- releases/2019.2.1.rst | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/releases/2019.2.1.rst b/releases/2019.2.1.rst index 238e18353..784ab5eff 100644 --- a/releases/2019.2.1.rst +++ b/releases/2019.2.1.rst @@ -1,7 +1,7 @@ .. _2019.2.1: ****************************** -What's New in 2019.2.1 +What's new in 2019.2.1 ****************************** * 250 bugs fixed. Thanks to all of our customers and an unprecedented number of deployments for helping us find and fix these! @@ -29,10 +29,10 @@ Improvements * SQream DB CLI’s history can be disabled, by passing ``./ClientCmd --no-history`` -Behaviour changes +Behaviour Changes ===================== -* SQream DB no longer applies an implicit cast from a long text column to a shorter text column (``VARCHAR``/``NVARCHAR``). This means some ``INSERT``/``COPY`` operations will now error instead of truncating the text. This is intended to prevent accidental truncation of text columns. If you want the old truncation behaviour, you can use the ``SUBSTRING`` function to truncate the text. +* SQream DB no longer applies an implicit cast from a long text column to a shorter text column (``VARCHAR``/``TEXT``). This means some ``INSERT``/``COPY`` operations will now error instead of truncating the text. This is intended to prevent accidental truncation of text columns. If you want the old truncation behaviour, you can use the ``SUBSTRING`` function to truncate the text. Operations @@ -45,20 +45,20 @@ Operations * When upgrading from SQream DB v3.2 or lower, the storage version must be upgraded using the :ref:`upgrade_storage_cli_reference` utility: ``./bin/upgrade_storage /path/to/storage/sqreamdb/`` -Known Issues & Limitations +Known Issues and Limitations =================================== -* NVARCHAR columns cannot be used as a ``GROUP BY`` key when there are multiple ``COUNT (DISTINCT …)`` operations in a query +* TEXT columns cannot be used as a ``GROUP BY`` key when there are multiple ``COUNT (DISTINCT …)`` operations in a query -* NVARCHAR columns cannot be used in a statement containing window functions +* TEXT columns cannot be used in a statement containing window functions -* NVARCHAR is not supported as a join key +* TEXT is not supported as a join key -* The following functions are not supported on ``NVARCHAR`` column types: ``chr``, ``min``, ``max``, ``patindex``, ``to_binary``, ``to_hex``, ``rlike``, ``regexp_count``, ``regexp_instr``, ``regexp_substr`` +* The following functions are not supported on ``TEXT`` column types: ``chr``, ``min``, ``max``, ``patindex``, ``to_binary``, ``to_hex``, ``rlike``, ``regexp_count``, ``regexp_instr``, ``regexp_substr`` -* SQream DB dashboard: Only works with a HA clustered installation +* SQream Dashboard: Only works with a HA clustered installation -* SQream DB editor: External tables and UDFs don’t appear in the DB Tree but do appear in the relevant sqream_catalog entries. +* SQream Editor: External tables and UDFs don’t appear in the DB Tree but do appear in the relevant sqream_catalog entries. Fixes @@ -68,7 +68,7 @@ Fixes * Variety of performance improvements: -* Improved performance of ``NVARCHAR`` by up to 315% for a variety of scenarios, including ``COPY FROM``, ``INNER JOIN``, ``LEFT JOIN``. +* Improved performance of ``TEXT`` by up to 315% for a variety of scenarios, including ``COPY FROM``, ``INNER JOIN``, ``LEFT JOIN``. * Improved load performance from previous versions From 7d7806d22694d6f7a002e702c8228c97da4ce100 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:21:04 +0200 Subject: [PATCH 146/300] Update patindex.rst Replaced NVARCHAR with TEXT. --- .../sql/sql_functions/scalar_functions/string/patindex.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/patindex.rst b/reference/sql/sql_functions/scalar_functions/string/patindex.rst index 8f2d67665..f6c068241 100644 --- a/reference/sql/sql_functions/scalar_functions/string/patindex.rst +++ b/reference/sql/sql_functions/scalar_functions/string/patindex.rst @@ -75,7 +75,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line NVARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT(50)); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') From fea592fcdbdec8d641ae01ec7cccd4af3cea19ee Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:21:35 +0200 Subject: [PATCH 147/300] Update replace.rst Replaced NVARCHAR with TEXT. --- reference/sql/sql_functions/scalar_functions/string/replace.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/replace.rst b/reference/sql/sql_functions/scalar_functions/string/replace.rst index 688328cd5..230125a7e 100644 --- a/reference/sql/sql_functions/scalar_functions/string/replace.rst +++ b/reference/sql/sql_functions/scalar_functions/string/replace.rst @@ -50,7 +50,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line NVARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT(50)); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') From c53b6de40148e8aaae14eb3abb2bc737a1571e20 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:22:01 +0200 Subject: [PATCH 148/300] Update reverse.rst Replaced NVARCHAR with TEXT. --- .../sql/sql_functions/scalar_functions/string/reverse.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/reverse.rst b/reference/sql/sql_functions/scalar_functions/string/reverse.rst index 5e61dcaa3..bb3be626e 100644 --- a/reference/sql/sql_functions/scalar_functions/string/reverse.rst +++ b/reference/sql/sql_functions/scalar_functions/string/reverse.rst @@ -34,7 +34,7 @@ Returns the same type as the argument supplied. Notes ======= -.. * This function works on ``NVARCHAR`` strings only. +.. * This function works on ``TEXT`` strings only. * If the value is NULL, the result is NULL. @@ -45,7 +45,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line NVARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT(50)); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') From 8664c3c10c384a4e7535e5f5893bf80d8d6803b7 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:22:28 +0200 Subject: [PATCH 149/300] Update trim.rst Replaced NVARCHAR with TEXT. --- reference/sql/sql_functions/scalar_functions/string/trim.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/trim.rst b/reference/sql/sql_functions/scalar_functions/string/trim.rst index 35952c410..d6e90c2f8 100644 --- a/reference/sql/sql_functions/scalar_functions/string/trim.rst +++ b/reference/sql/sql_functions/scalar_functions/string/trim.rst @@ -48,7 +48,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line NVARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT(50)); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') From 016983cc12ad5b322fc8b3c438d3a99354712ef0 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:22:56 +0200 Subject: [PATCH 150/300] Update optimization_best_practices.rst Replaced NVARCHAR with TEXT. --- .../optimization_best_practices.rst | 154 ++++++++++-------- 1 file changed, 90 insertions(+), 64 deletions(-) diff --git a/guides/operations/optimization_best_practices.rst b/guides/operations/optimization_best_practices.rst index 7290f49ac..2ee93dbe0 100644 --- a/guides/operations/optimization_best_practices.rst +++ b/guides/operations/optimization_best_practices.rst @@ -1,26 +1,28 @@ .. _sql_best_practices: ********************************** -Optimization and best practices +Optimization and Best Practices ********************************** -This topic explains some best practices of working with SQream DB. +This topic explains some best practices of working with SQream. + +See also our :ref:`monitoring_query_performance` guide for more information. .. contents:: In this topic: :local: .. _table_design_best_practices: -Table design +Table Design ============== This section describes best practices and guidelines for designing tables. -Use date and datetime types for columns +Using Date and Datetime Types for Columns ----------------------------------------- -When creating tables with dates or timestamps, using the purpose-built ``DATE`` and ``DATETIME`` types over integer types or ``VARCHAR`` will bring performance and storage footprint improvements, and in many cases huge performance improvements (as well as data integrity benefits). SQream DB stores dates and datetimes very efficiently and can strongly optimize queries using these specific types. +When creating tables with dates or timestamps, using the purpose-built ``DATE`` and ``DATETIME`` types over integer types or ``VARCHAR`` will bring performance and storage footprint improvements, and in many cases huge performance improvements (as well as data integrity benefits). SQream stores dates and datetimes very efficiently and can strongly optimize queries using these specific types. -Reduce varchar length to a minimum +Shortening VARCHAR Length -------------------------------------- With the ``VARCHAR`` type, the length has a direct effect on query performance. @@ -29,25 +31,25 @@ If the size of your column is predictable, by defining an appropriate column len * Data loading issues can be identified more quickly -* SQream DB can reserve less memory for decompression operations +* SQream can reserve less memory for decompression operations * Third-party tools that expect a data size are less likely to over-allocate memory -Don't flatten or denormalize data +Avoiding Flattening or Denormalizing Data ----------------------------------- -SQream DB executes JOIN operations very effectively. It is almost always better to JOIN tables at query-time rather than flatten/denormalize your tables. +SQream executes JOIN operations very effectively. It is almost always better to JOIN tables at query-time rather than flatten/denormalize your tables. This will also reduce storage size and reduce row-lengths. We highly suggest using ``INT`` or ``BIGINT`` as join keys, rather than a text/string type. -Convert external tables to native tables +Converting Foreign Tables to Native Tables ------------------------------------------- -SQream DB's native storage is heavily optimized for analytic workloads. It is always faster for querying than other formats, even columnar ones such as Parquet. It also enables the use of additional metadata to help speed up queries, in some cases by many orders of magnitude. +SQream's native storage is heavily optimized for analytic workloads. It is always faster for querying than other formats, even columnar ones such as Parquet. It also enables the use of additional metadata to help speed up queries, in some cases by many orders of magnitude. -You can improve the performance of all operations by converting :ref:`external tables` into native tables by using the :ref:`create_table_as` syntax. +You can improve the performance of all operations by converting :ref:`foreign tables` into native tables by using the :ref:`create_table_as` syntax. For example, @@ -57,52 +59,46 @@ For example, The one situation when this wouldn't be as useful is when data will be only queried once. -Use information about the column data to your advantage +Leverating Column Data Information ------------------------------------------------------------- Knowing the data types and their ranges can help design a better table. -Set ``NULL`` or ``NOT NULL`` when relevant +Identifying Relevance of Setting NULL or NOT NULL Values ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For example, if a value can't be missing (or ``NULL``), specify a ``NOT NULL`` constraint on the columns. +For example, if a value cannot be omitted (or ``NULL``), you must specify a ``NOT NULL`` constraint on the columns. -Not only does specifying ``NOT NULL`` save on data storage, it lets the query compiler know that a column cannot have a ``NULL`` value, which can improve query performance. +In addition to saving data storage, specifying ``NOT NULL`` informs the query compiler that a column cannot have a ``NULL`` value, which can improve query performance. -Keep VARCHAR lengths to a minimum +Shortening VARCHAR Length ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Although long strings do not affect storage, they require a lot of memory while queries are being run. If a column's string length is less than 50 characters, specify ``VARCHAR(50)`` rather than an arbitrarily large number. -While it won't make a big difference in storage, large strings allocate a lot of memory at query time. - -If a column's string length never exceeds 50 characters, specify ``VARCHAR(50)`` rather than an arbitrarily large number. - -Sorting +Sorting Data ============== +Sorting data is an important factor in minimizing storage size and improving query performance for the following reasons: -Data sorting is an important factor in minimizing storage size and improving query performance. - -* Minimizing storage saves on physical resources and increases performance by reducing overall disk I/O. Prioritize the sorting of low-cardinality columns. This reduces the number of chunks and extents that SQream DB reads during query execution. +* Minimizing storage saves on physical resources and increases performance by reducing overall disk I/O. Prioritize the sorting of low-cardinality columns. This reduces the number of chunks and extents that SQream reads during query execution. -* Where possible, sort columns with the lowest cardinality first. Avoid sorting ``VARCHAR`` and ``TEXT/NVARCHAR`` columns with lengths exceeding 50 characters. +* Where possible, sort columns with the lowest cardinality first. Avoid sorting ``VARCHAR`` and ``TEXT`` columns with lengths exceeding 50 characters. -* For longer-running queries that run on a regular basis, performance can be improved by sorting data based on the ``WHERE`` and ``GROUP BY`` parameters. Data can be sorted during insert by using :ref:`external tables` or by using :ref:`create_table_as`. +* For longer-running queries that run on a regular basis, performance can be improved by sorting data based on the ``WHERE`` and ``GROUP BY`` parameters. Data can be sorted during insert by using :ref:`external_tables` or by using :ref:`create_table_as`. .. _query_best_practices: -Query best practices +Best Practices for Writing SQL Queries ===================== This section describes best practices for writing SQL queries. -Reduce data sets before joining tables +Reducing Data Sets Before Joining Tables ----------------------------------------- Reducing the input to a ``JOIN`` clause can increase performance. -Some queries benefit from retreiving a reduced dataset as a subquery prior to a join. - -For example, +Some queries benefit from retreiving a reduced dataset as a subquery prior to a join, as shown in the following example: .. code-block:: postgres @@ -111,7 +107,7 @@ For example, WHERE p_date BETWEEN '2018-07-01' AND '2018-07-31' GROUP BY 1; -Can be rewritten as +This can be rewritten as follows: .. code-block:: postgres @@ -123,15 +119,47 @@ Can be rewritten as group by 2) AS fact ON dim.store_id=fact.store_id; +Using an ANSI JOIN +---------------------------- + +SQream prefers the ANSI JOIN syntax. +In some cases ANSI JOINs performs better than the non-ANSI variety, as shown in the following example: + +.. code-block:: postgres + :caption: ANSI JOIN will perform better + + SELECT p.name, s.name, c.name + FROM "Products" AS p + JOIN "Sales" AS s + ON p.product_id = s.sale_id + JOIN "Customers" as c + ON s.c_id = c.id AND c.id = 20301125; + +SQream supports the following non-ANSI JOIN, but does not recommend using it: + +.. code-block:: postgres + :caption: Non-ANSI JOIN may not perform well + + SELECT p.name, s.name, c.name + FROM "Products" AS p, "Sales" AS s, "Customers" as c + WHERE p.product_id = s.sale_id + AND s.c_id = c.id + AND c.id = 20301125; + + .. _high_selectivity: -Use the high selectivity hint +Using a High Selectivity Hint -------------------------------- -Use the high selectivity hint when you expect a predicate to filter out most values. +**Selectivity** is the ratio of cardinality to the number of records of a chunk. Selectivity is defined as ``:math:`\frac{\text{Distinct values}}{\text{Total number of records in a chunk}}```. -For example, +SQream employees a hint function called ``HIGH_SELECTIVITY``, which is a function that can be used for wrapping a condition. The hint signals to SQream that the result of the condition is very sparse and to rechunk the results into fewer, fuller chunks. + +SQream recommends using the high selectivity hint when you expect a predicate to filter out most values, such as when data is dispersed over many chunks, indicating that the data has not been optimally clustered. + +The following example shows data that is not clustered optimally: .. code-block:: postgres @@ -139,16 +167,19 @@ For example, WHERE HIGH_SELECTIVITY(p_date = '2018-07-01') GROUP BY 1; -This hint tells the query compiler that the ``WHERE`` condition is expected to filter out more than 50% of values. It does not affect the query results, but when used correctly can improve query performance. +This hint tells the query compiler that the ``WHERE`` condition is expected to filter out more than 60% of values. While it does not affect query results, using it correctly can improve query performance. + +.. tip:: The ``HIGH_SELECTIVITY()`` hint function can only be used as part of the ``WHERE`` clause and cannot be used in equijoin conditions, cases, or in the select list. +For more information about identifying scenarios for the high selectivity hint, see the :ref:`Monitoring Query Performance Guide`. -Cast smaller types to avoid overflow in aggregates +For more information about optimal data clustering, see :ref:`not well-clustered`). + +Casting Smaller Types to Avoid Aggregate Overflow ------------------------------------------------------ When using an ``INT`` or smaller type, the ``SUM`` and ``COUNT`` operations return a value of the same type. -To avoid overflow on large results, cast the column up to a larger type. - -For example +To avoid overflow on large results, cast the column up to a larger type, as shown in the following example: .. code-block:: postgres @@ -156,13 +187,13 @@ For example GROUP BY 1; -Prefer ``COUNT(*)`` and ``COUNT`` on non-nullable columns +Preferring ``COUNT(*)`` and ``COUNT`` on Non-Nullable Columns ------------------------------------------------------------ -SQream DB optimizes ``COUNT(*)`` queries very strongly. This also applies to ``COUNT(column_name)`` on non-nullable columns. Using ``COUNT(column_name)`` on a nullable column will operate quickly, but much slower than the previous variations. +SQream optimizes ``COUNT(*)`` queries very strongly. This also applies to ``COUNT(column_name)`` on non-nullable columns. Using ``COUNT(column_name)`` on a nullable column operate quickly, but much slower than the previous variations. -Return only required columns +Returning Only Required Columns ------------------------------- Returning only the columns you need to client programs can improve overall query performance. @@ -170,10 +201,10 @@ This also reduces the overall result set, which can improve performance in third SQream is able to optimize out unneeded columns very strongly due to its columnar storage. -Use saved queries to reduce recurring compilation time +Using Saved Queries to Reduce Recurring Compilation Duration ------------------------------------------------------- -:ref:`saved_queries` are compiled when they are created. The query plan is saved in SQream DB's metadata for later re-use. +:ref:`saved_queries` are compiled when they are created. The query plan is saved in SQream's metadata for later re-use. Because the query plan is saved, they can be used to reduce compilation overhead, especially with very complex queries, such as queries with lots of values in an :ref:`IN` predicate. @@ -181,10 +212,9 @@ When executed, the saved query plan is recalled and executed on the up-to-date d See how to use saved queries in the :ref:`saved queries guide`. -Pre-filter to reduce :ref:`JOIN` complexity +Pre-Filtering to Reduce JOIN Complexity -------------------------------------------------------- - -Filter and reduce table sizes prior to joining on them +The following is the correct syntax for pre-filtering to reduce JOIN complexity by filtering and reducing table sizes before joining them: .. code-block:: postgres @@ -195,7 +225,7 @@ Filter and reduce table sizes prior to joining on them WHERE p_date BETWEEN '2019-07-01' AND '2019-07-31' GROUP BY store_name; -Can be rewritten as: +The example above can be rewritten as follows: .. code-block:: postgres @@ -207,29 +237,25 @@ Can be rewritten as: FROM fact WHERE p_date BETWEEN '2019-07-01' AND '2019-07-31' GROUP BY store_id) AS fact ON dim.store_id = fact.store_id; + +For more information about reducing JOIN complexity, see :ref:`JOIN`. .. _data_loading_considerations: -Data loading considerations +Data Loading Considerations ================================= -Allow and use natural sorting on data +Enabling and Using Natural Data Sorting ---------------------------------------- -Very often, tabular data is already naturally ordered along a dimension such as a timestamp or area. - -This natural order is a major factor for query performance later on, as data that is naturally sorted can be more easily compressed and analyzed with SQream DB's metadata collection. - -For example, when data is sorted by timestamp, filtering on this timestamp is more effective than filtering on an unordered column. - -Natural ordering can also be used for effective :ref:`delete` operations. +Tabular data is often naturally ordered along a dimension, such as a timestamp or area. This natural order is a major factor for query performance during later stages, as data that is naturally sorted can be more easily compressed and analyzed with SQream's metadata collection. +For example, when data is sorted by timestamp, filtering on this timestamp is more effective than filtering on an unordered column. Natural ordering can also be used for effective **DELETE** operations. -.. todo: show an execution plan +For more information about Delete operations, see :ref:`delete operations`. -.. reorder tables join- much more effective to join first the small tables (or those who have filters on them). -.. what else should be here, and what can we do right now -.. select report('/tmp',$$select a,b,c from tableA a join tableB b on a.id=b.id and a>4000 and b like '%this is a sample query%' $$); -.. discard_results +Further Reading and Monitoring Query Performance +======================================================= +For more information about built-in monitoring utilities, see the :ref:`monitoring_query_performance` guide. The Monitoring Query Performance Guide also gives concerete examples for improving query performance. From 6b7604f5f02956dbb86b84b689fb5a51b542c1e7 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:23:45 +0200 Subject: [PATCH 151/300] Update index.rst Replaced NVARCHAR with TEXT. --- guides/client_drivers/python/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/client_drivers/python/index.rst b/guides/client_drivers/python/index.rst index 1a7b323a3..887244f75 100644 --- a/guides/client_drivers/python/index.rst +++ b/guides/client_drivers/python/index.rst @@ -284,7 +284,7 @@ This example loads 10,000 rows of dummy data to a SQream DB instance , clustered=True) # Create a table for loading - create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s varchar(12), ss nvarchar(20), dt date, dtt datetime)' + create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s varchar(12), ss text(20), dt date, dtt datetime)' con.execute(create) # After creating the table, we can load data into it with the INSERT command From 22ebb8c89f90f3ac29d4850315873be171c99954 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 21:22:33 +0200 Subject: [PATCH 152/300] Update s3.rst Replaced "external table" with "foreign table." Ticket UI-393. General clean-up. --- guides/features/external_data/s3.rst | 78 ++++++++++++++++------------ 1 file changed, 45 insertions(+), 33 deletions(-) diff --git a/guides/features/external_data/s3.rst b/guides/features/external_data/s3.rst index 2a1d9f628..bba878830 100644 --- a/guides/features/external_data/s3.rst +++ b/guides/features/external_data/s3.rst @@ -1,62 +1,66 @@ .. _s3: *********************** -S3 +Amazon S3 *********************** -SQream DB has a native S3 connector for inserting data. The ``s3://`` URI specifies an external file path on an S3 bucket. +SQream uses a native S3 connector for inserting data. The ``s3://`` URI specifies an external file path on an S3 bucket. File names may contain wildcard characters, and the files can be in CSV or columnar format, such as Parquet and ORC. -File names may contain wildcard characters and the files can be a CSV or columnar format like Parquet and ORC. +The **Amazon S3** describes the following topics: - -.. contents:: In this topic: +.. contents:: :local: -S3 configuration +S3 Configuration ============================== -Any SQream DB host that has access to S3 endpoints can access S3 without any configuration. - -To read files from an S3 bucket, it must have listable files. +Any database host with access to S3 endpoints can access S3 without any configuration. To read files from an S3 bucket, the database must have listable files. -S3 URI format +S3 URI Format =============== With S3, specify a location for a file (or files) when using :ref:`copy_from` or :ref:`external_tables`. -The general S3 syntax is: -``s3://bucket_name/path`` +The following is an example of the general S3 syntax: + +.. code-block:: console + + s3://bucket_name/path Authentication ================= -SQream DB supports ``AWS ID`` and ``AWS SECRET`` authentication. -These should be specified when executing a statement. +SQream supports ``AWS ID`` and ``AWS SECRET`` authentication. These should be specified when executing a statement. Examples ========== -Use an external table to stage data from S3 before loading from CSV, Parquet or ORC files. +Use a foreign table to stage data from S3 before loading from CSV, Parquet, or ORC files. + +The **Examples** section includes the following examples: + +.. contents:: + :local: + :depth: 1 + + -Planning for data staging +Planning for Data Staging -------------------------------- -For the following examples, we will want to interact with a CSV file. Here's a peek at the table contents: +The examples in this section are based on a CSV file, as shown in the following table: .. csv-table:: nba.csv :file: ../nba-t10.csv :widths: auto :header-rows: 1 -The file is stored on :ref:`s3`, at ``s3://sqream-demo-data/nba_players.csv``. -This bucket is public and listable. - -We will make note of the file structure, to create a matching ``CREATE FOREIGN TABLE`` statement. +The file is stored on Amazon S3, and this bucket is public and listable. To create a matching ``CREATE FOREIGN TABLE`` statement you can make note of the file structure. -Creating the external table +Creating a Foreign Table ----------------------------- -Based on the source file structure, we we :ref:`create a foreign table` with the appropriate structure, and point it to the file. +Based on the source file's structure, you can create a foreign table with the appropriate structure, and point it to your file as shown in the following example: .. code-block:: postgres @@ -76,18 +80,21 @@ Based on the source file structure, we we :ref:`create a foreign table`. +* **Using SQream in an HDFS environment** - see :ref:`hdfs`. + +Querying Foreign Tables ------------------------------ -Let's peek at the data from the external table: +The following shows the data in the foreign table: .. code-block:: psql @@ -105,22 +112,27 @@ Let's peek at the data from the external table: Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 -Bulk loading a file from a public S3 bucket +Bulk Loading a File from a Public S3 Bucket ---------------------------------------------- -The :ref:`copy_from` command can also be used to load data without staging it first. +The ``COPY FROM`` command can also be used to load data without staging it first. + +.. note:: The bucket must be publicly available and objects can be listed. -.. note:: The bucket must be publicly available and objects can be listed +The following is an example of bulk loading a file from a public S3 bucket: .. code-block:: postgres COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n'; + +For more information on the ``COPY FROM`` command, see :ref:`copy_from`. -Loading files from an authenticated S3 bucket +Loading Files from an Authenticated S3 Bucket --------------------------------------------------- +The following is an example of loading fles from an authenticated S3 bucket: .. code-block:: postgres COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n' AWS_ID '12345678' - AWS_SECRET 'super_secretive_secret'; \ No newline at end of file + AWS_SECRET 'super_secretive_secret'; From 47d4273a3b8563095d08ec45d8e2c6bee2e67efc Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 21:23:56 +0200 Subject: [PATCH 153/300] Update s3.rst Replaced "external table" with "foreign table." Ticket UI-393. General clean-up. --- guides/features/external_data/s3.rst | 88 ++++++++++++++++------------ 1 file changed, 52 insertions(+), 36 deletions(-) diff --git a/guides/features/external_data/s3.rst b/guides/features/external_data/s3.rst index 3f2fc3dc8..bba878830 100644 --- a/guides/features/external_data/s3.rst +++ b/guides/features/external_data/s3.rst @@ -1,66 +1,70 @@ .. _s3: *********************** -S3 +Amazon S3 *********************** -SQream DB has a native S3 connector for inserting data. The ``s3://`` URI specifies an external file path on an S3 bucket. +SQream uses a native S3 connector for inserting data. The ``s3://`` URI specifies an external file path on an S3 bucket. File names may contain wildcard characters, and the files can be in CSV or columnar format, such as Parquet and ORC. -File names may contain wildcard characters and the files can be a CSV or columnar format like Parquet and ORC. +The **Amazon S3** describes the following topics: - -.. contents:: In this topic: +.. contents:: :local: -S3 configuration +S3 Configuration ============================== -Any SQream DB host that has access to S3 endpoints can access S3 without any configuration. - -To read files from an S3 bucket, it must have listable files. +Any database host with access to S3 endpoints can access S3 without any configuration. To read files from an S3 bucket, the database must have listable files. -S3 URI format +S3 URI Format =============== With S3, specify a location for a file (or files) when using :ref:`copy_from` or :ref:`external_tables`. -The general S3 syntax is: -``s3://bucket_name/path`` +The following is an example of the general S3 syntax: + +.. code-block:: console + + s3://bucket_name/path Authentication ================= -SQream DB supports ``AWS ID`` and ``AWS SECRET`` authentication. -These should be specified when executing a statement. +SQream supports ``AWS ID`` and ``AWS SECRET`` authentication. These should be specified when executing a statement. Examples ========== -Use an external table to stage data from S3 before loading from CSV, Parquet or ORC files. +Use a foreign table to stage data from S3 before loading from CSV, Parquet, or ORC files. + +The **Examples** section includes the following examples: + +.. contents:: + :local: + :depth: 1 + + -Planning for data staging +Planning for Data Staging -------------------------------- -For the following examples, we will want to interact with a CSV file. Here's a peek at the table contents: +The examples in this section are based on a CSV file, as shown in the following table: .. csv-table:: nba.csv :file: ../nba-t10.csv :widths: auto :header-rows: 1 -The file is stored on :ref:`s3`, at ``s3://sqream-demo-data/nba_players.csv``. -This bucket is public and listable. - -We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_TABLE`` statement. +The file is stored on Amazon S3, and this bucket is public and listable. To create a matching ``CREATE FOREIGN TABLE`` statement you can make note of the file structure. -Creating the external table +Creating a Foreign Table ----------------------------- -Based on the source file structure, we we :ref:`create an external table` with the appropriate structure, and point it to the file. +Based on the source file's structure, you can create a foreign table with the appropriate structure, and point it to your file as shown in the following example: .. code-block:: postgres - CREATE EXTERNAL TABLE nba + CREATE FOREIGN TABLE nba ( Name varchar(40), Team varchar(40), @@ -72,18 +76,25 @@ Based on the source file structure, we we :ref:`create an external table`. +* **Using SQream in an HDFS environment** - see :ref:`hdfs`. + +Querying Foreign Tables ------------------------------ -Let's peek at the data from the external table: +The following shows the data in the foreign table: .. code-block:: psql @@ -101,22 +112,27 @@ Let's peek at the data from the external table: Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 -Bulk loading a file from a public S3 bucket +Bulk Loading a File from a Public S3 Bucket ---------------------------------------------- -The :ref:`copy_from` command can also be used to load data without staging it first. +The ``COPY FROM`` command can also be used to load data without staging it first. + +.. note:: The bucket must be publicly available and objects can be listed. -.. note:: The bucket must be publicly available and objects can be listed +The following is an example of bulk loading a file from a public S3 bucket: .. code-block:: postgres COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n'; + +For more information on the ``COPY FROM`` command, see :ref:`copy_from`. -Loading files from an authenticated S3 bucket +Loading Files from an Authenticated S3 Bucket --------------------------------------------------- +The following is an example of loading fles from an authenticated S3 bucket: .. code-block:: postgres COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n' AWS_ID '12345678' - AWS_SECRET 'super_secretive_secret'; \ No newline at end of file + AWS_SECRET 'super_secretive_secret'; From 68e6941201ba15052f807c8c05b11d19c0d632a3 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 21:48:16 +0200 Subject: [PATCH 154/300] Update 2020.2.rst Replaced "external table" with "foreign table." Ticket UI-393. --- releases/2020.2.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/releases/2020.2.rst b/releases/2020.2.rst index 006708b9c..17d77383c 100644 --- a/releases/2020.2.rst +++ b/releases/2020.2.rst @@ -4,27 +4,27 @@ What's New in 2020.2 ************************** -SQream DB v2020.2 contains some new features, improved performance, and bug fixes. +SQream v2020.2 contains some new features, improved performance, and bug fixes. This version has new window ranking function and a new editor UI to empower data users to analyze more data with less friction. -As always, the latest release improves reliability and performance, and makes getting more data into SQream DB easier than ever. +As always, the latest release improves reliability and performance, and makes getting more data into SQream easier than ever. -New features +New Features ================ UI ---------- -* New :ref:`sqream_studio` replaces the previous Statement Editor. Try it out today! +* New :ref:`sqream_studio` replaces the previous Statement Editor. Integrations ----------------- -* Our :ref:`Python driver (pysqream)` now has an SQLAlchemy dialect. Customers can write high-performance Python applications that make full use of SQream DB - connect, query, delete, and insert data. Data scientists can use pysqream with Pandas, Numpy, and AI/ML frameworks like TensorFlow for direct queries of huge datasets. +* Our :ref:`Python driver (pysqream)` now has an SQLAlchemy dialect. Customers can write high-performance Python applications that make full use of SQream - connect, query, delete, and insert data. Data scientists can use pysqream with Pandas, Numpy, and AI/ML frameworks like TensorFlow for direct queries of huge datasets. -SQL support +SQL Support --------------- * Added :ref:`lag`/:ref:`lead` ranking functions to our :ref:`window_functions` support. We will have more features coming in the next version. @@ -32,7 +32,7 @@ SQL support * New syntax preview for :ref:`external_tables`. Foreign tables replace external tables, with improved functionality. - You can keep using the existing external table syntax for now, but it may be deprecated in the future. + You can keep using the existing foreign table syntax for now, but it may be deprecated in the future. .. code-block:: postgres @@ -47,10 +47,10 @@ SQL support ( LOCATION = 'hdfs://hadoop-nn.piedpiper.com:8020/demo-data/example.orc' ); -Improvements and fixes +Improvements and Fixes ======================== -SQream DB v2020.2 includes hundreds of small new features and tunable parameters that improve performance, reliability, and stability. +SQream v2020.2 includes hundreds of small new features and tunable parameters that improve performance, reliability, and stability. * ~100 bug fixes, including: @@ -67,7 +67,7 @@ SQream DB v2020.2 includes hundreds of small new features and tunable parameters Operations ======================== -* When upgrading from a previous version of SQream DB (for example, v2019.2), the storage version must be upgraded using the :ref:`upgrade_storage_cli_reference` utility: ``./bin/upgrade_storage /path/to/storage/sqreamdb/`` +* When upgrading from a previous version of SQream (for example, v2019.2), the storage version must be upgraded using the :ref:`upgrade_storage_cli_reference` utility: ``./bin/upgrade_storage /path/to/storage/sqreamdb/`` * A change in memory allocation behaviour in this version sees the introduction of a new setting, ``limitQueryMemoryGB``. This is an addition to the previous ``spoolMemoryGB`` setting. @@ -97,7 +97,7 @@ Operations -Known Issues & Limitations +Known Issues and Limitations ================================ * An invalid formatted CSV can cause an ``insufficient memory`` error on a :ref:`copy_from` statement if a quote isn't closed and the file is much larger than system memory. @@ -107,9 +107,9 @@ Known Issues & Limitations * ``TEXT`` columns can't be used with an outer join together with an inequality check (``!= , <>``) -Upgrading to v2020.2 +Upgrading to Version 2020.2 ======================== Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. -Contact your account manager to get the latest release of SQream DB. +Contact your account manager to get the latest release of SQream. From bfbae2795a1571d003f7312515b4ea1c719c1a30 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 22 Nov 2021 22:22:50 +0200 Subject: [PATCH 155/300] Update inserting_data.rst Replaced "external table" with "foreign table." Ticket UI-393. --- guides/inserting_data.rst | 82 +++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/guides/inserting_data.rst b/guides/inserting_data.rst index 2affcd795..5e6f1bcdb 100644 --- a/guides/inserting_data.rst +++ b/guides/inserting_data.rst @@ -1,19 +1,19 @@ .. _inserting_data: *************************** -Inserting data +Inserting Data *************************** -This guide covers inserting data into SQream DB, with subguides on inserting data from a variety of sources and locations. +This guide covers inserting data into SQream, with subguides on inserting data from a variety of sources and locations. .. contents:: In this topic: :local: -Data loading overview +Data Loading Overview ================================ -SQream DB supports importing data from the following sources: +SQream supports importing data from the following sources: * Using :ref:`insert` with :ref:`a client driver` * Using :ref:`copy_from`: @@ -29,19 +29,19 @@ SQream DB supports importing data from the following sources: - :ref:`hdfs` -SQream DB supports loading files in the following formats: +SQream supports loading files in the following formats: * Text - CSV, TSV, PSV * Parquet * ORC -Data loading considerations +Data Loading Considerations ================================ -Verify data and performance after load +Verifying Data and Performance When Load is Completed ----------------------------------------- -Like other RDBMSs, SQream DB has its own set of best practcies for table design and query optimization. +Like other RDBMSs, SQream has its own set of best practcies for table design and query optimization. SQream therefore recommends: @@ -55,17 +55,17 @@ SQream therefore recommends: * Data types were not over-provisioned (e.g. don't use VARCHAR(2000) to store a short string) -File source location for loading +File Source location for Loading -------------------------------- During loading using :ref:`copy_from`, the statement can run on any worker. If you are running multiple nodes, make sure that all nodes can see the source the same. If you load from a local file which is only on 1 node and not on shared storage, it will fail some of the time. (If you need to, you can also control which node a statement runs on using the :ref:`workload_manager`). -Supported load methods +Supported Load Methods ------------------------------- -SQream DB's :ref:`COPY FROM` syntax can be used to load CSV files, but can't be used for Parquet and ORC. +SQream's :ref:`COPY FROM` syntax can be used to load CSV files, but can't be used for Parquet and ORC. -:ref:`FOREIGN TABLE` can be used to load text files, Parquet, and ORC files, and can also transform the data prior to materialization as a full table. +The :ref:`FOREIGN TABLE` statement can be used to load text files, Parquet, and ORC files, and can also transform the data prior to materialization as a full table. .. list-table:: :widths: auto @@ -78,34 +78,34 @@ SQream DB's :ref:`COPY FROM` syntax can be used to load CSV files, bu - ORC - Streaming data * - :ref:`copy_from` - - ✓ - - ✗ - - ✗ - - ✗ + - Can be used + - Cannot be used + - Cannot be used + - Cannot be used * - :ref:`external_tables` - - ✓ - - ✓ - - ✓ - - ✗ + - Can be used + - Can be used + - Can be used + - Cannot be used * - :ref:`insert` - - ✗ - - ✗ - - ✗ - - ✓ (Python, JDBC, Node.JS) + - Cannot be used + - Cannot be used + - Cannot be used + - Can be used (Python, JDBC, Node.JS) -Unsupported data types +Unsupported Data Types ----------------------------- -SQream DB doesn't support the entire set of features that some other database systems may have, such as ``ARRAY``, ``BLOB``, ``ENUM``, ``SET``, etc. +SQream doesn't support the entire set of features that some other database systems may have, such as ``ARRAY``, ``BLOB``, ``ENUM``, ``SET``, etc. These data types will have to be converted before load. For example, ``ENUM`` can often be stored as a ``VARCHAR``. -Extended error handling +Extended Error Handling ---------------------------- -While :ref:`external tables` can be used to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options, as well as extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. +While :ref:`foreign tables` can be used to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options, as well as extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. -Best practices for CSV +Best Practices for CSV ------------------------------ Text files like CSV rarely conform to `RFC 4180 `_ , so alterations may be required: @@ -126,26 +126,26 @@ Text files like CSV rarely conform to `RFC 4180 Date: Mon, 22 Nov 2021 22:24:00 +0200 Subject: [PATCH 156/300] Update inserting_data.rst Replaced "external table" with "foreign table." Ticket UI-393. --- guides/inserting_data.rst | 93 +++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/guides/inserting_data.rst b/guides/inserting_data.rst index a2256eef8..5e6f1bcdb 100644 --- a/guides/inserting_data.rst +++ b/guides/inserting_data.rst @@ -1,19 +1,19 @@ .. _inserting_data: *************************** -Inserting data +Inserting Data *************************** -This guide covers inserting data into SQream DB, with subguides on inserting data from a variety of sources and locations. +This guide covers inserting data into SQream, with subguides on inserting data from a variety of sources and locations. .. contents:: In this topic: :local: -Data loading overview +Data Loading Overview ================================ -SQream DB supports importing data from the following sources: +SQream supports importing data from the following sources: * Using :ref:`insert` with :ref:`a client driver` * Using :ref:`copy_from`: @@ -29,19 +29,19 @@ SQream DB supports importing data from the following sources: - :ref:`hdfs` -SQream DB supports loading files in the following formats: +SQream supports loading files in the following formats: * Text - CSV, TSV, PSV * Parquet * ORC -Data loading considerations +Data Loading Considerations ================================ -Verify data and performance after load +Verifying Data and Performance When Load is Completed ----------------------------------------- -Like other RDBMSs, SQream DB has its own set of best practcies for table design and query optimization. +Like other RDBMSs, SQream has its own set of best practcies for table design and query optimization. SQream therefore recommends: @@ -55,17 +55,17 @@ SQream therefore recommends: * Data types were not over-provisioned (e.g. don't use VARCHAR(2000) to store a short string) -File source location for loading +File Source location for Loading -------------------------------- During loading using :ref:`copy_from`, the statement can run on any worker. If you are running multiple nodes, make sure that all nodes can see the source the same. If you load from a local file which is only on 1 node and not on shared storage, it will fail some of the time. (If you need to, you can also control which node a statement runs on using the :ref:`workload_manager`). -Supported load methods +Supported Load Methods ------------------------------- -SQream DB's :ref:`COPY FROM` syntax can be used to load CSV files, but can't be used for Parquet and ORC. +SQream's :ref:`COPY FROM` syntax can be used to load CSV files, but can't be used for Parquet and ORC. -:ref:`EXTERNAL TABLE` can be used to load text files, Parquet, and ORC files, and can also transform the data prior to materialization as a full table. +The :ref:`FOREIGN TABLE` statement can be used to load text files, Parquet, and ORC files, and can also transform the data prior to materialization as a full table. .. list-table:: :widths: auto @@ -78,34 +78,34 @@ SQream DB's :ref:`COPY FROM` syntax can be used to load CSV files, bu - ORC - Streaming data * - :ref:`copy_from` - - ✓ - - ✗ - - ✗ - - ✗ + - Can be used + - Cannot be used + - Cannot be used + - Cannot be used * - :ref:`external_tables` - - ✓ - - ✓ - - ✓ - - ✗ + - Can be used + - Can be used + - Can be used + - Cannot be used * - :ref:`insert` - - ✗ - - ✗ - - ✗ - - ✓ (Python, JDBC, Node.JS) + - Cannot be used + - Cannot be used + - Cannot be used + - Can be used (Python, JDBC, Node.JS) -Unsupported data types +Unsupported Data Types ----------------------------- -SQream DB doesn't support the entire set of features that some other database systems may have, such as ``ARRAY``, ``BLOB``, ``ENUM``, ``SET``, etc. +SQream doesn't support the entire set of features that some other database systems may have, such as ``ARRAY``, ``BLOB``, ``ENUM``, ``SET``, etc. These data types will have to be converted before load. For example, ``ENUM`` can often be stored as a ``VARCHAR``. -Extended error handling +Extended Error Handling ---------------------------- -While :ref:`external tables` can be used to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options, as well as extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. +While :ref:`foreign tables` can be used to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options, as well as extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. -Best practices for CSV +Best Practices for CSV ------------------------------ Text files like CSV rarely conform to `RFC 4180 `_ , so alterations may be required: @@ -126,26 +126,26 @@ Text files like CSV rarely conform to `RFC 4180 Date: Tue, 23 Nov 2021 09:41:21 +0200 Subject: [PATCH 157/300] Create avro_foreign_data_format.rst Created avro_foreign_data_format, adding to Index. Checking front-end. Not appearing in build file index, not sure why... --- guides/migration/avro_foreign_data_format.rst | 352 ++++++++++++++++++ 1 file changed, 352 insertions(+) create mode 100644 guides/migration/avro_foreign_data_format.rst diff --git a/guides/migration/avro_foreign_data_format.rst b/guides/migration/avro_foreign_data_format.rst new file mode 100644 index 000000000..88ad6bf2f --- /dev/null +++ b/guides/migration/avro_foreign_data_format.rst @@ -0,0 +1,352 @@ +.. _avro_foreign_data_format: + +************************** +Inserting Data from Avro +************************** +The **Inserting Data from Avro** page describes inserting data from Avro into SQream and includes the following: + +.. contents:: + :local: + :depth: 2 + +Overview +=========== +**Avro** is a well-known data serialization system that relies on schemas. Due to its flexibility and nesting as an efficient data storage method, SQream supports the Avro binary data format as an alternative to JSON. + +Avro Data Types +=========== + +Avro includes the following data types: + +.. contents:: + :local: + :depth: 1 + +Primitive Data Types +-------------- +The following table shows the supported **Primitive** data types: + ++-------------+-------------------------------------------+ +| Avro Type | SQream Type | +| +--------+---------------+--------+---------+ +| | Number | Date/Datetime | String | Boolean | ++=============+========+===============+========+=========+ +| ``null`` | ✓ | ✓ | ✓ | ✓ | ++-------------+--------+---------------+--------+---------+ +| ``boolean`` | | | ✓ | ✓ | ++-------------+--------+---------------+--------+---------+ +| ``int`` | ✓ | | ✓ | | ++-------------+--------+---------------+--------+---------+ +| ``long`` | ✓ | | ✓ | | ++-------------+--------+---------------+--------+---------+ +| ``float`` | ✓ | | ✓ | | ++-------------+--------+---------------+--------+---------+ +| ``double`` | ✓ | | ✓ | | ++-------------+--------+---------------+--------+---------+ +| ``bytes`` | | | | | ++-------------+--------+---------------+--------+---------+ +| ``string`` | | ✓ | ✓ | | ++-------------+--------+---------------+--------+---------+ + + + + + + +Complex Data Types +-------------- +The following table shows the supported **Complex** data types: + ++------------+-------------------------------------------+ +| | SQream Type | +| +--------+---------------+--------+---------+ +|Avro Type | Number | Date/Datetime | String | Boolean | ++============+========+===============+========+=========+ +| ``record`` | | | | | ++------------+--------+---------------+--------+---------+ +| ``enum`` | | | ✓ | | ++------------+--------+---------------+--------+---------+ +| ``array`` | | | | | ++------------+--------+---------------+--------+---------+ +| ``map`` | | | | | ++------------+--------+---------------+--------+---------+ +| ``union`` | ✓ | ✓ | ✓ | ✓ | ++------------+--------+---------------+--------+---------+ +| ``fixed`` | | | | | ++------------+--------+---------------+--------+---------+ + + +Logical Data Types +-------------- +The following table shows the supported **Logical** data types: + ++----------------------------+-------------------------------------------+ +| Avro Type | SQream Type | +| +--------+---------------+--------+---------+ +| | Number | Date/Datetime | String | Boolean | ++============================+========+===============+========+=========+ +| ``decimal`` | ✓ | | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``uuid`` | | | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``date`` | | ✓ | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``time-millis`` | | | | | ++----------------------------+--------+---------------+--------+---------+ +| ``time-micros`` | | | | | ++----------------------------+--------+---------------+--------+---------+ +| ``timestamp-millis`` | | ✓ | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``timestamp-micros`` | | ✓ | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``local-timestamp-millis`` | | | | | ++----------------------------+--------+---------------+--------+---------+ +| ``local-timestamp-micros`` | | | | | ++----------------------------+--------+---------------+--------+---------+ +| ``duration`` | | | | | ++----------------------------+--------+---------------+--------+---------+ + + +Mapping Objects to Rows +=============== +When mapping objects to rows, each Avro object or message must contain one ``record`` type object corresponding to a single row in SQream. The ``record`` fields are **Comment - Must be associated?** associated by name to their target table columns. + +Additional unmapped fields will be ignored. Note that using the JSONPath option overrides this. + +Ingesting Avro Files +==================== +This section describes how to ingest Avro files into SQream and covers the following: + + +.. contents:: + :local: + :depth: 1 + + +Preparing Your Avro Source File +---------- +Prepare your Avro source files according to the following requirements: + +* RFC 4180 standard CSV files, but can also be modified to support non-standard CSVs (with multi-character delimiters, unquoted fields, etc). + + :: + +* Files are encoded with UTF-8 or ASCII. + + :: + +* Field delimiter is an ASCII character or characters. + + :: + +* Record delimiter, also known as a new line separator, is a Unix-style newline (``\n``), DOS-style newline (``\r\n``), or Mac style newline (``\r``). + + :: + +* If a field is quoted, any double quote that appears must be double-quoted (similar to the :ref:`string literals quoting rules`. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. + + :: + +* Fields can be enclosed by double-quotes (optional), or mandatory quotes if they contain one of the following characters: + + * The record delimiter or field delimiter. + + :: + + * A double quote character. + + :: + + * A newline. + +SQream does not support other modes of escaping, such as ``1,"What are \"birds\"?"``. + +``NULL`` values can be marked in the following ways in Avro files: + + * An explicit null marker. For example, ``col1,\N,col3``. + + :: + + * An empty field delimited by the field delimiter. For example, ``col1,,col3``. + + .. note:: If a text field is quoted but contains no content (``""``) it is considered an empty text field and not ``NULL``. + +For more information about standard CSV files, see `RFC 4180 standard CSVs `_. + +Making Avro Files Accessible to Workers +--------------------- +To give workers access to files every node must have the same view of the storage being used. + +The following apply for Avro files to be accessible to workers: + +* For files hosted on NFS, ensure that the mount is accessible from all servers. + +* For HDFS, ensure that SQream servers have access to the HDFS name node with the correct **user-id**. For more information, see :ref:`hdfs`. + +* For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. + +For more information about restricted worker access, see :ref:`workload_manager`. + +Basing Your Table Structure on Inserted Tables +--------------------- +Before loading data, you must build the ``CREATE EXTERNAL TABLE`` to correspond with the file structure of the inserted table. + +The example in this section is based on the source ``nba.parquet`` table shown below: + +.. csv-table:: nba.parquet + :file: nba-t10.csv + :widths: auto + :header-rows: 1 + +The following example shows the correct file structure used to create the ``CREATE EXTERNAL TABLE`` statement based on the **nba.parquet** table: + +.. code-block:: postgres + + CREATE FOREIGN TABLE ext_nba + ( + Name VARCHAR(40), + Team VARCHAR(40), + Number BIGINT, + Position VARCHAR(2), + Age BIGINT, + Height VARCHAR(4), + Weight BIGINT, + College VARCHAR(40), + Salary FLOAT + ) + WRAPPER parquet_fdw + OPTIONS + ( + LOCATION = 's3://sqream-demo-data/nba.parquet' + ); + +.. tip:: + + An exact match must exist between the SQream and Avro types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. + +.. note:: The **nba.parquet** file is stored on S3 at ``s3://sqream-demo-data/nba.parquet``. + +Verifying Your Table Output +--------------------- +Because external tables do not automatically verify the file integrity or structure, you must manually verify that the table output is identical to the original inserted table. + +The following is an example of the output based on the **nba.parquet** table: + +.. code-block:: psql + + t=> SELECT * FROM ext_nba LIMIT 10; + Name | Team | Number | Position | Age | Height | Weight | College | Salary + --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- + Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 + Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 + John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | + R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 + Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 + Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 + Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 + Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 + Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 + Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 + +.. note:: If your table output has errors, verify that the structure of the Avro files correctly corresponds to the external table structure that you created. + +Loading Data into SQream +--------------------- + +Syntax +~~~~~~~~~~~~~~~~~~~~~ +The following is the correct syntax for loading data into SQream: + +.. code-block:: postgres + + CREATE TABLE AS + SELECT * FROM ; + +The following is an example of loading data into SQream: + +.. code-block:: postgres + + CREATE TABLE nba AS + SELECT * FROM ext_nba; + +For more information about the **CREATE TABLE AS** statement, see :ref:`create_table_as`. + +Examples +~~~~~~~~~~~~~~~~~~~~~ + +This section includes the following examples of loading data into SQream: + +.. contents:: + :local: + :depth: 1 + +Omitting Unsupported Column Types +********************** +When loading data, you can omit columns using the ``NULL as`` argument. You can use this argument to omit unsupported columns from queries that access external tables. By omitting them, these columns will not be called and will avoid generating a "type mismatch" error. + +**Comment - Is "type mismatch" the official name of this error, do the words "type mismatch" appear anywhere, or is this just a description of the error?** + +In the example below, the ``Position`` column is not supported due its type. + +.. code-block:: postgres + + CREATE TABLE nba AS + SELECT Name, Team, Number, NULL as Position, Age, Height, Weight, College, Salary FROM ext_nba; + + +Modifying Data Before Loading +********************** +One of the main reasons for staging data using the ``EXTERNAL TABLE`` argument is to examine and modify table contents before loading it into SQream. + +For example, we can replace **Comment - Convert?** pounds with kilograms using the :ref:`create_table_as` statement + +In the example below, the ``Position`` column is set to the default ``NULL``. + +.. code-block:: postgres + + CREATE TABLE nba AS + SELECT name, team, number, NULL as Position, age, height, (weight / 2.205) as weight, college, salary + FROM ext_nba + ORDER BY weight; + + +Loading a Table from a Directory of Avro Files on HDFS +********************** +The following is an example of loading a table from a directory of Avro files on HDFS: + +.. code-block:: postgres + + CREATE FOREIGN TABLE ext_users + (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + WRAPPER parquet_fdw + OPTIONS + ( + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet' + ); + + CREATE TABLE users AS SELECT * FROM ext_users; + +For more configuration option examples, see the `CREATE FOREIGN TABLE parameters `_. + +Loading a Table from a Directory of Avro Files on S3 +********************** +The following is an example of loading a table from a directory of Avro files on S3: + +.. code-block:: postgres + + CREATE FOREIGN TABLE ext_users + (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + WRAPPER parquet_fdw + OPTIONS + ( LOCATION = 's3://pp-secret-bucket/users/*.parquet', + AWS_ID = 'our_aws_id', + AWS_SECRET = 'our_aws_secret' + ); + + CREATE TABLE users AS SELECT * FROM ext_users; + + + + + + From 770cbe895c84c3db4efea79a8e59619d8aba5a05 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 25 Nov 2021 16:35:11 +0200 Subject: [PATCH 158/300] Update count.rst Updated according to SQ-9036. --- .../aggregate_functions/count.rst | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/reference/sql/sql_functions/aggregate_functions/count.rst b/reference/sql/sql_functions/aggregate_functions/count.rst index ab7f492e1..803e529c0 100644 --- a/reference/sql/sql_functions/aggregate_functions/count.rst +++ b/reference/sql/sql_functions/aggregate_functions/count.rst @@ -4,18 +4,20 @@ COUNT ************************** -Returns the count of numeric values, or only the distinct values. +The ``COUNT`` function returns the count of numeric values, or only the distinct values. Syntax ========== - +The following is the correct syntax for using the ``COUNT`` function as an **aggregate**: .. code-block:: postgres - -- As an aggregate COUNT( { [ DISTINCT ] expr | * } ) --> BIGINT - -- As a window function +The following is the correct syntax for using the ``COUNT`` function as a **window function**: + +.. code-block:: postgres + COUNT ( { [ DISTINCT ] expr | * } ) OVER ( [ PARTITION BY value_expression [, ...] ] [ ORDER BY value_expression [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] ] @@ -24,6 +26,7 @@ Syntax Arguments ============ +The following table describes the ``COUNT`` arguments: .. list-table:: :widths: auto @@ -40,22 +43,25 @@ Arguments Returns ============ - -* Count returns ``BIGINT``. +* The ``COUNT`` function returns ``BIGINT``. Notes ======= +The following notes apply to the ``COUNT`` function: + +* When all rows contain ``NULL`` values, the function returns ``NULL``. + +* ``COUNT(*)`` returns the number of items in a group, including duplicates and ``NULL`` values. -* ``NULL`` values are *not* ignored by ``COUNT`` +* ``COUNT(ALL expression)`` evaluates expressions for each row in a group, returning the number of non-null values. -* When all rows contain ``NULL`` values, the function returns the amount of rows in the table. +* ``COUNT(DISTINCT expression)`` evaluates expressions for each row in a group, returning the number of unique, non-null values. Examples =========== - -For these examples, assume a table named ``nba``, with the following structure: +The examples in this section are based on a table named ``nba``, structured as follows: .. code-block:: postgres @@ -72,16 +78,22 @@ For these examples, assume a table named ``nba``, with the following structure: "Salary" float ); - -Here's a peek at the table contents (:download:`Download nba.csv `): +The following table is a preview of the source :download:`nba.csv ` table shown below: .. csv-table:: nba.csv :file: nba-t10.csv :widths: auto :header-rows: 1 + +This section includes the following examples: + +.. contents:: + :local: + :depth: 1 -Count rows in a table +Counting Rows in a Table --------------------------- +This example shows how to count rows in a table: .. code-block:: psql @@ -90,10 +102,11 @@ Count rows in a table ----- 457 -Count distinct values in a table +Counting Distinct Values in a Table ---------------------------------- +This example shows how to count distinct values in a table: -These two forms are equivalent: +The following structures generate the same result: .. code-block:: psql @@ -102,14 +115,17 @@ These two forms are equivalent: ----- 22 +.. code-block:: psql + t=> SELECT COUNT(*) FROM (SELECT "Age" FROM nba GROUP BY 1); count ----- 22 -Combine COUNT with other aggregates +Combining COUNT with Other Aggregates ------------------------------------- +This example shows how to combine the ``COUNT`` function with other aggregates: .. code-block:: psql @@ -138,4 +154,3 @@ Combine COUNT with other aggregates 38 | 1840041 | 4 39 | 2517872 | 2 40 | 4666916 | 3 - From ae353b08766644d980d5d74c98937bf365350272 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 25 Nov 2021 16:36:17 +0200 Subject: [PATCH 159/300] Update count.rst Updated according to SQ-9036. --- .../aggregate_functions/count.rst | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/reference/sql/sql_functions/aggregate_functions/count.rst b/reference/sql/sql_functions/aggregate_functions/count.rst index ab7f492e1..803e529c0 100644 --- a/reference/sql/sql_functions/aggregate_functions/count.rst +++ b/reference/sql/sql_functions/aggregate_functions/count.rst @@ -4,18 +4,20 @@ COUNT ************************** -Returns the count of numeric values, or only the distinct values. +The ``COUNT`` function returns the count of numeric values, or only the distinct values. Syntax ========== - +The following is the correct syntax for using the ``COUNT`` function as an **aggregate**: .. code-block:: postgres - -- As an aggregate COUNT( { [ DISTINCT ] expr | * } ) --> BIGINT - -- As a window function +The following is the correct syntax for using the ``COUNT`` function as a **window function**: + +.. code-block:: postgres + COUNT ( { [ DISTINCT ] expr | * } ) OVER ( [ PARTITION BY value_expression [, ...] ] [ ORDER BY value_expression [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] ] @@ -24,6 +26,7 @@ Syntax Arguments ============ +The following table describes the ``COUNT`` arguments: .. list-table:: :widths: auto @@ -40,22 +43,25 @@ Arguments Returns ============ - -* Count returns ``BIGINT``. +* The ``COUNT`` function returns ``BIGINT``. Notes ======= +The following notes apply to the ``COUNT`` function: + +* When all rows contain ``NULL`` values, the function returns ``NULL``. + +* ``COUNT(*)`` returns the number of items in a group, including duplicates and ``NULL`` values. -* ``NULL`` values are *not* ignored by ``COUNT`` +* ``COUNT(ALL expression)`` evaluates expressions for each row in a group, returning the number of non-null values. -* When all rows contain ``NULL`` values, the function returns the amount of rows in the table. +* ``COUNT(DISTINCT expression)`` evaluates expressions for each row in a group, returning the number of unique, non-null values. Examples =========== - -For these examples, assume a table named ``nba``, with the following structure: +The examples in this section are based on a table named ``nba``, structured as follows: .. code-block:: postgres @@ -72,16 +78,22 @@ For these examples, assume a table named ``nba``, with the following structure: "Salary" float ); - -Here's a peek at the table contents (:download:`Download nba.csv `): +The following table is a preview of the source :download:`nba.csv ` table shown below: .. csv-table:: nba.csv :file: nba-t10.csv :widths: auto :header-rows: 1 + +This section includes the following examples: + +.. contents:: + :local: + :depth: 1 -Count rows in a table +Counting Rows in a Table --------------------------- +This example shows how to count rows in a table: .. code-block:: psql @@ -90,10 +102,11 @@ Count rows in a table ----- 457 -Count distinct values in a table +Counting Distinct Values in a Table ---------------------------------- +This example shows how to count distinct values in a table: -These two forms are equivalent: +The following structures generate the same result: .. code-block:: psql @@ -102,14 +115,17 @@ These two forms are equivalent: ----- 22 +.. code-block:: psql + t=> SELECT COUNT(*) FROM (SELECT "Age" FROM nba GROUP BY 1); count ----- 22 -Combine COUNT with other aggregates +Combining COUNT with Other Aggregates ------------------------------------- +This example shows how to combine the ``COUNT`` function with other aggregates: .. code-block:: psql @@ -138,4 +154,3 @@ Combine COUNT with other aggregates 38 | 1840041 | 4 39 | 2517872 | 2 40 | 4666916 | 3 - From 55646ff7540c158950c891bfb692da18f98d20f8 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 5 Dec 2021 15:12:27 +0200 Subject: [PATCH 160/300] Update configuration.rst Updated Configuration file based on meetings with Dor and Eilon. --- guides/operations/configuration.rst | 719 +++++++++++++++++++++++++++- 1 file changed, 698 insertions(+), 21 deletions(-) diff --git a/guides/operations/configuration.rst b/guides/operations/configuration.rst index feceb5e56..79d48493a 100644 --- a/guides/operations/configuration.rst +++ b/guides/operations/configuration.rst @@ -1,14 +1,703 @@ .. _configuration: -*********************** +************************** Configuration -*********************** +************************** + +The **Configuration** page describes SQream’s method for configuring your instance of SQream and includes the following topics: + +.. contents:: + :local: + :depth: 1 + +Current Configuration Method +=================== + + +Overview +----- + + + +Modifications that you make to your configurations are persistent based on whether they are made at the session or cluster level. Persistent configurations are modifications made to attributes that are retained after shutting down your system. + + +Modifying Your Configuration +---- +The **Modifying Your Configuration** section describes the following: + +.. contents:: + :local: + :depth: 1 + + + + + + + + + + +Modifying Your Configuration Using the Worker Configuration File +~~~~~~~~~~~ + +You can modify your configuration using the **worker configuration file (config.json)**. Changes that you make to worker configuration files are persistent. Note that you can only set the attributes in your worker configuration file **before** initializing your SQream worker, and while your worker is active these attributes are read-only. + +The following is an example of a worker configuration file: + +.. code-block:: postgres + + { + “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, + “gpu”: 0, + “licensePath”: “home/test_user/SQream/tests/license.enc”, + “machineIP”: “127.0.0.1”, + “metadataServerIp”: “127.0.0.1”, + “metadataServerPort”: “3105, + “port”: 5000, + “useConfigIP”” true, + “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” + } + +You can access the legacy configuration file from the ``legacyConfigFilePath`` parameter shown above. If all (or most) of your workers require the same flag settings, you can set the ``legacyConfigFilePath`` attribute to the same legacy file. + + + +Modifying Your Configuration Using a Legacy Configuration File +~~~~~~~~~~~ + +You can modify your configuration using a legacy configuration file. + +The Legacy configuration file provides access to the read/write flags used in SQream’s previous configuration method. A link to this file is provided in the **legacyConfigFilePath** parameter in the worker configuration file. + +The following is an example of the legacy configuration file: + + +.. code-block:: postgres + + { + “developerMode”: true, + “reextentUse”: false, + “useClientLog”: true, + “useMetadataServer”” false + } + + + +Session vs Cluster Based Configuration +============================== + +.. contents:: + :local: + :depth: 1 + + + + + +Cluster-Based Configuration +-------------- +SQream uses cluster-based configuration, enabling you to centralize configurations for all workers on the cluster. Only flags set to the regular or cluster flag type have access to cluster-based configuration. Configurations made on the cluster level are persistent and stored at the metadata level. The parameter settings in this file are applied globally to all workers connected to it. + +For more information, see the following: + +* `Using SQream SQL `_ - modifying flag attributes from the CLI. +* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. + +For more information on flag-based access to cluster-based configuration, see **Configuration Flag Types** below. + +Session-Based Configuration +---------------- +Session-based configurations are not persistent and are deleted when your session ends. This method enables you to modify all required configurations while avoiding conflicts between flag attributes modified on different devices at different points in time. + +The **SET flag_name** command is used to modify flag attributes. Any modifications you make with the **SET flag_name** command apply only to your open session, and are not saved when it ends + +For example, when the query below has completed executing, the values configured will be restored to its previous setting: + +.. code-block:: console + + set spoolMemoryGB=700; + select * from table a where date='2021-11-11' + +For more information, see the following: + +* `Using SQream SQL `_ - modifying flag attributes from the CLI. +* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. + +Configuration Flag Types +========== +The flag type attribute can be set for each flag and determines its write access as follows: + +* **Regular:** session-based read/write flags that can be stored in the metadata file +* **Cluster:** global cluster-based read/write flags that can be stored in the metadata file +* **Worker:** single worker-based read-only flags that can be stored in the worker configuration file + +The flag type determines which files can be accessed and which commands or commands sets users can run. + +The following table describes the file or command modification rights for each flag type: + +.. list-table:: + :widths: 20 20 20 20 + :header-rows: 1 + + * - **Flag Type** + - **Legacy Configuration File** + - **ALTER SYSTEM SET** + - **Worker Configuration File** + * - :ref:`Regular` + - Can modify + - Can modify + - Cannot modify + * - :ref:`Cluster` + - Cannot modify + - Can modify + - Cannot modify + * - :ref:`Worker` + - Cannot modify + - Cannot modify + - Can modify + +.. _regular_flag_types: + +Regular Flag Types +--------------------- +The following is an example of the correct syntax for running a **Regular** flag type command: + +.. code-block:: console + + SET spoolMemoryGB= 11; + executed + +The following table describes the Regular flag types: + +.. list-table:: + :widths: 2 5 10 + :header-rows: 1 + + * - **Command** + - **Description** + - **Example** + * - ``SET `` + - Used for modifying flag attributes. + - ``SET developerMode=true`` + * - ``SHOW / ALL`` + - Used to preset either a specific flag value or all flag values. + - ``SHOW `` + * - ``SHOW ALL LIKE`` + - Used as a wildcard character for flag names. + - ``SHOW `` + * - ``show_conf_UF`` + - Used to print all flags with the following attributes: + + * Flag name + * Default value + * Is developer mode (Boolean) + * Flag category + * Flag type + - ``rechunkThreshold,90,true,RND,regular`` + * - ``show_conf_extended UF`` + - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. + - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` + ``utility functions names,boolean,true,false`` + * - ``show_md_flag UF`` + - Used to show a specific flag/all flags stored in the metadata file. + - + * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` + * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` + * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` + +.. _cluster_flag_types: + +Cluster Flag Types +--------------------- +The following is an example of the correct syntax for running a **Cluster** flag type command: + +.. code-block:: console + + ALTER SYSTEM RESET useMetadataServer; + executed + +The following table describes the Cluster flag types: + +.. list-table:: + :widths: 1 5 10 + :header-rows: 1 + + * - **Command** + - **Description** + - **Example** + * - ``ALTER SYSTEM SET `` + - Used to storing or modifying flag attributes in the metadata file. + - ``ALTER SYSTEM SET `` + * - ``ALTER SYSTEM RESET `` + - Used to remove a flag or all flag attributes from the metadata file. + - ``ALTER SYSTEM RESET `` + * - ``SHOW / ALL`` + - Used to print the value of a specified value or all flag values. + - ``SHOW `` + * - ``SHOW ALL LIKE`` + - Used as a wildcard character for flag names. + - ``SHOW `` + * - ``show_conf_UF`` + - Used to print all flags with the following attributes: + + * Flag name + * Default value + * Is developer mode (Boolean) + * Flag category + * Flag type + - ``rechunkThreshold,90,true,RND,regular`` + * - ``show_conf_extended UF`` + - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. + - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` + ``utility functions names,boolean,true,false`` + * - ``show_md_flag UF`` + - Used to show a specific flag/all flags stored in the metadata file. + - + * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` + * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` + * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` + +.. _worker_flag_types: + +Worker Flag Types +--------------------- +The following is an example of the correct syntax for running a **Worker** flag type command: + +.. code-block:: console + + SHOW spoolMemoryGB; + +The following table describes the Worker flag types: + +.. list-table:: + :widths: 1 5 10 + :header-rows: 1 + + * - **Command** + - **Description** + - **Example** + * - ``ALTER SYSTEM SET `` + - Used to storing or modifying flag attributes in the metadata file. + - ``ALTER SYSTEM SET `` + * - ``ALTER SYSTEM RESET `` + - Used to remove a flag or all flag attributes from the metadata file. + - ``ALTER SYSTEM RESET `` + * - ``SHOW / ALL`` + - Used to print the value of a specified value or all flag values. + - ``SHOW `` + * - ``SHOW ALL LIKE`` + - Used as a wildcard character for flag names. + - ``SHOW `` + * - ``show_conf_UF`` + - Used to print all flags with the following attributes: + + * Flag name + * Default value + * Is developer mode (Boolean) + * Flag category + * Flag type + - ``rechunkThreshold,90,true,RND,regular`` + * - ``show_conf_extended UF`` + - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. + - + ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` + ``utility functions names,boolean,true,false`` + * - ``show_md_flag UF`` + - Used to show a specific flag/all flags stored in the metadata file. + - + * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` + * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` + * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` + +Configuration Commands +========== + + + +The configuration commands are associated with particular flag types based on permissions. + +The following table describes the commands or command sets that can be run based on their flag type. Note that the flag names described in the following table are described in the :ref:`Configuration Roles` section below. + +.. list-table:: + :header-rows: 1 + :widths: 1 2 10 17 + :class: my-class + :name: my-name + + * - Flag Type + - Command + - Description + - Example + * - Regular + - ``SET `` + - Used for modifying flag attributes. + - ``SET developerMode=true`` + * - Cluster + - ``ALTER SYSTEM SET `` + - Used to storing or modifying flag attributes in the metadata file. + - ``ALTER SYSTEM SET `` + * - Cluster + - ``ALTER SYSTEM RESET `` + - Used to remove a flag or all flag attributes from the metadata file. + - ``ALTER SYSTEM RESET `` + * - Regular, Cluster, Worker + - ``SHOW / ALL`` + - Used to print the value of a specified value or all flag values. + - ``SHOW `` + * - Regular, Cluster, Worker + - ``SHOW ALL LIKE`` + - Used as a wildcard character for flag names. + - ``SHOW `` + * - Regular, Cluster, Worker + - ``show_conf_UF`` + - Used to print all flags with the following attributes: + + * Flag name + * Default value + * Is developer mode (Boolean) + * Flag category + * Flag type + + + + - ``rechunkThreshold,90,true,RND,regular`` + * - Regular, Cluster, Worker + - ``show_conf_extended UF`` + - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. + - ``spoolMemoryGB,15,false,generic,regular,Amount of memory (GB)`` + ``the server can use for spooling,”Statement that perform “”group by””,`` + ``“”order by”” or “”join”” operation(s) on large set of data will run`` + ``much faster if given enough spool memory, otherwise disk spooling will`` + ``be used resulting in performance hit.”,uint,,0-5000`` + * - Regular, Cluster, Worker + - ``show_md_flag UF`` + - Used to show a specific flag/all flags stored in the metadata file. + - + * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` + * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` + * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` + + + + + + + +.. _configuration_roles: + +Configuration Roles +=========== +SQream divides flags into the following roles, each with their own set of permissions: + + - + * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` + * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` + * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` + +* **Generic** – Flags that can be modified by standard users on a session basis. +* **Admin** – Flags that can be modified by administrators on a session and cluster basis using the ALTER SYSTEM SET command. + + + +The following table describes the Generic and Admin configuration flags: + +.. list-table:: + :header-rows: 1 + :widths: 1 2 1 15 1 20 + :class: my-class + :name: my-name + + * - Flag Name + - Access Control + - Modification Type + - Description + - Data Type + - Default Value + + * - ``binSizes`` + - Admin + - Regular + - Sets the custom bin size in the cache to enable high granularity bin control. + - string + - + ``16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,`` + ``131072,262144,524288,1048576,2097152,4194304,8388608,16777216,`` + ``33554432,67108864,134217728,268435456,536870912,786432000,107374,`` + ``1824,1342177280,1610612736,1879048192,2147483648,2415919104,`` + ``2684354560,2952790016,3221225472`` + + * - ``checkCudaMemory`` + - Admin + - Regular + - Sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. + - boolean + - ``FALSE`` + + * - ``compilerGetsOnlyUFs`` + - Admin + - Regular + - Sets the runtime to pass only utility functions names to the compiler. + - boolean + - ``FALSE`` + + * - ``copyToRestrictUtf8`` + - Admin + - Regular + - Sets the custom bin size in the cache to enable high granularity bin control. + - boolean + - ``FALSE`` + + * - ``cpuReduceHashtableSize`` + - Admin + - Regular + - Sets the hash table size of the CpuReduce. + - uint + - ``10000`` + + * - ``csvLimitRowLength`` + - Admin + - Cluster + - Sets the maximum supported CSV row length. + - uint + - ``100000`` + + * - ``cudaMemcpyMaxSizeBytes`` + - Admin + - Regular + - Sets the chunk size for copying from CPU to GPU. If set to 0, do not divide. + - uint + - ``0`` + + * - ``CudaMemcpySynchronous`` + - Admin + - Regular + - Indicates if copying from/to GPU is synchronous. + - boolean + - ``FALSE`` + + * - ``cudaMemQuota`` + - Admin + - Worker + - Sets the percentage of total device memory to be used by the instance. + - uint + - ``90`` + + * - ``developerMode`` + - Admin + - Regular + - Enables modifying R&D flags. + - boolean + - ``FALSE`` + + * - ``enableDeviceDebugMessages`` + - Admin + - Regular + - Activates the Nvidia profiler (nvprof) markers. + - boolean + - ``FALSE`` + + * - ``enableLogDebug`` + - Admin + - Regular + - Enables creating and logging in the clientLogger_debug file. + - boolean + - ``TRUE`` + + * - ``enableNvprofMarkers`` + - Admin + - Regular + - Activates the Nvidia profiler (nvprof) markers. + - boolean + - ``FALSE`` + + * - ``endLogMessage`` + - Admin + - Regular + - Appends a string at the end of every log line. + - string + - ``EOM`` + + * - ``extentStorageFileSizeMB`` + - Admin + - Cluster + - Sets the minimum size in mebibytes of extents for table bulk data. + - uint + - ``20`` + + * - ``gatherMemStat`` + - Admin + - Regular + - Monitors all pinned allocations and all **memcopies** to/from device, and prints a report of pinned allocations that were not memcopied to/from the device using the **dump_pinned_misses** utility function. + - boolean + - ``FALSE`` + + * - ``increaseChunkSizeBeforeReduce`` + - Admin + - Regular + - Increases the chunk size to reduce query speed. + - boolean + - ``FALSE`` + + * - ``increaseMemFactors`` + - Admin + - Regular + - Adds rechunker before expensive chunk producer. + - boolean + - ``TRUE`` + + * - ``leveldbWriteBufferSize`` + - Admin + - Regular + - Sets the buffer size. + - uint + - ``524288`` + + * - ``machineIP`` + - Admin + - Worker + - Manual setting of reported IP. + - string + - ``127.0.0.1`` + + + + + * - ``memoryResetTriggerMB`` + - Admin + - Regular + - Sets the size of memory used during a query to trigger aborting the server. + - uint + - ``0`` + + * - ``metadataServerPort`` + - Admin + - Worker + - Sets the port used to connect to the metadata server. SQream recommends using port ranges above 1024† because ports below 1024 are usually reserved, although there are no strict limitations. Any positive number (1 - 65535) can be used. + - uint + - ``3105`` + + * - ``mtRead`` + - Admin + - Regular + - Splits large reads to multiple smaller ones and executes them concurrently. + - boolean + - ``FALSE`` + + * - ``mtReadWorkers`` + - Admin + - Regular + - Sets the number of workers to handle smaller concurrent reads. + - uint + - ``30`` + + * - ``orcImplicitCasts`` + - Admin + - Regular + - Sets the implicit cast in orc files, such as **int** to **tinyint** and vice versa. + - boolean + - ``TRUE`` + + * - ``statementLockTimeout`` + - Admin + - Regular + - Sets the timeout (seconds) for acquiring object locks before executing statements. + - uint + - ``3`` + + * - ``useConfigIP`` + - Admin + - Worker + - Activates the machineIP (true). Setting to false ignores the machineIP and automatically assigns a local network IP. This cannot be activated in a cloud scenario (on-premises only). + - boolean + - ``FALSE`` + + * - ``useLegacyDecimalLiterals`` + - Admin + - Regular + - Interprets decimal literals as **Double** instead of **Numeric**. Used to preserve legacy behavior in existing customers. + - boolean + - ``FALSE`` + + * - ``useLegacyStringLiterals`` + - Admin + - Regular + - Interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. Used to preserve legacy behavior in existing customers. + - boolean + - ``FALSE`` + + * - ``flipJoinOrder`` + - Generic + - Regular + - Reorders join to force equijoins and/or equijoins sorted by table size. + - boolean + - ``FALSE`` + + * - ``limitQueryMemoryGB`` + - Generic + - Worker + - Prevents a query from processing more memory than the flag’s value. + - uint + - ``100000`` + + * - ``logSysLevel`` + - Generic + - Regular + - + Determines the client log level: + 0 - L_SYSTEM, + 1 - L_FATAL, + 2 - L_ERROR, + 3 - L_WARN, + 4 - L_INFO, + 5 - L_DEBUG, + 6 - L_TRACE + - uint + - ``100000`` + + * - ``maxAvgBlobSizeToCompressOnGpu`` + - Generic + - Regular + - Sets the CPU to compress columns with size above (flag’s value) * (row count). + - uint + - ``120`` + + * - ``spoolMemoryGB`` + - Generic + - Regular + - Sets the amount of memory (GB) to be used by the server for spooling. + - uint + - ``8`` + +Showing All Flags in the Catalog Table +======= +SQream uses the **sqream_catalog.parameters** catalog table for showing all flags, providing the scope (default, cluster and session), description, default value and actual value. + +The following is the correct syntax for a catalog table query: + + +.. code-block:: console + + SELECT * FROM sqream_catalog.settings + +The following is an example of a catalog table query: + + +.. code-block:: console + + externalTableBlobEstimate, 100, 100, default, + varcharEncoding, ascii, ascii, default, Changes the expected encoding for Varchar columns + useCrcForTextJoinKeys, true, true, default, + hiveStyleImplicitStringCasts, false, false, default, This guide covers the configuration files and the ``SET`` statement. -Configuration files -========================== + + +Previous Configuration Method +=================== By default, configuration files are stored in ``/etc/sqream``. A very minimal configuration file looks like this: @@ -36,9 +725,8 @@ A very minimal configuration file looks like this: In the example above, the worker will start on port 5000, and will use GPU #0. -Frequently set parameters -============================ - +Frequently Set Parameters +------ .. todo list-table:: Compiler flags :widths: auto @@ -235,10 +923,10 @@ Frequently set parameters .. point to the best practices as well -.. warning:: JSON files can't contain any comments +.. warning:: JSON files can't contain any comments. -Recommended configuration file -===================================== +Recommended Configuration File +----- .. code-block:: json @@ -267,14 +955,3 @@ Recommended configuration file "licensePath":"/etc/sqream/license.enc" } } - -Changing settings temporarily -=================================== - -The ``SET`` statement can modify one of the configuration settings for the session or connection. - -For example, to set the query plan's logging interval to "every 3 seconds" for subsequent statements: - -.. code-block:: psql - - t=> SET nodeInfoLoggingSec=3; SELECT * FROM nba; From 67ad253d84482392704fc83224883439aa8be712 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 5 Dec 2021 15:13:56 +0200 Subject: [PATCH 161/300] Update configuration.rst Updated Configuration file based on meetings with Dor and Eilon. --- guides/operations/configuration.rst | 719 +++++++++++++++++++++++++++- 1 file changed, 698 insertions(+), 21 deletions(-) diff --git a/guides/operations/configuration.rst b/guides/operations/configuration.rst index feceb5e56..79d48493a 100644 --- a/guides/operations/configuration.rst +++ b/guides/operations/configuration.rst @@ -1,14 +1,703 @@ .. _configuration: -*********************** +************************** Configuration -*********************** +************************** + +The **Configuration** page describes SQream’s method for configuring your instance of SQream and includes the following topics: + +.. contents:: + :local: + :depth: 1 + +Current Configuration Method +=================== + + +Overview +----- + + + +Modifications that you make to your configurations are persistent based on whether they are made at the session or cluster level. Persistent configurations are modifications made to attributes that are retained after shutting down your system. + + +Modifying Your Configuration +---- +The **Modifying Your Configuration** section describes the following: + +.. contents:: + :local: + :depth: 1 + + + + + + + + + + +Modifying Your Configuration Using the Worker Configuration File +~~~~~~~~~~~ + +You can modify your configuration using the **worker configuration file (config.json)**. Changes that you make to worker configuration files are persistent. Note that you can only set the attributes in your worker configuration file **before** initializing your SQream worker, and while your worker is active these attributes are read-only. + +The following is an example of a worker configuration file: + +.. code-block:: postgres + + { + “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, + “gpu”: 0, + “licensePath”: “home/test_user/SQream/tests/license.enc”, + “machineIP”: “127.0.0.1”, + “metadataServerIp”: “127.0.0.1”, + “metadataServerPort”: “3105, + “port”: 5000, + “useConfigIP”” true, + “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” + } + +You can access the legacy configuration file from the ``legacyConfigFilePath`` parameter shown above. If all (or most) of your workers require the same flag settings, you can set the ``legacyConfigFilePath`` attribute to the same legacy file. + + + +Modifying Your Configuration Using a Legacy Configuration File +~~~~~~~~~~~ + +You can modify your configuration using a legacy configuration file. + +The Legacy configuration file provides access to the read/write flags used in SQream’s previous configuration method. A link to this file is provided in the **legacyConfigFilePath** parameter in the worker configuration file. + +The following is an example of the legacy configuration file: + + +.. code-block:: postgres + + { + “developerMode”: true, + “reextentUse”: false, + “useClientLog”: true, + “useMetadataServer”” false + } + + + +Session vs Cluster Based Configuration +============================== + +.. contents:: + :local: + :depth: 1 + + + + + +Cluster-Based Configuration +-------------- +SQream uses cluster-based configuration, enabling you to centralize configurations for all workers on the cluster. Only flags set to the regular or cluster flag type have access to cluster-based configuration. Configurations made on the cluster level are persistent and stored at the metadata level. The parameter settings in this file are applied globally to all workers connected to it. + +For more information, see the following: + +* `Using SQream SQL `_ - modifying flag attributes from the CLI. +* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. + +For more information on flag-based access to cluster-based configuration, see **Configuration Flag Types** below. + +Session-Based Configuration +---------------- +Session-based configurations are not persistent and are deleted when your session ends. This method enables you to modify all required configurations while avoiding conflicts between flag attributes modified on different devices at different points in time. + +The **SET flag_name** command is used to modify flag attributes. Any modifications you make with the **SET flag_name** command apply only to your open session, and are not saved when it ends + +For example, when the query below has completed executing, the values configured will be restored to its previous setting: + +.. code-block:: console + + set spoolMemoryGB=700; + select * from table a where date='2021-11-11' + +For more information, see the following: + +* `Using SQream SQL `_ - modifying flag attributes from the CLI. +* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. + +Configuration Flag Types +========== +The flag type attribute can be set for each flag and determines its write access as follows: + +* **Regular:** session-based read/write flags that can be stored in the metadata file +* **Cluster:** global cluster-based read/write flags that can be stored in the metadata file +* **Worker:** single worker-based read-only flags that can be stored in the worker configuration file + +The flag type determines which files can be accessed and which commands or commands sets users can run. + +The following table describes the file or command modification rights for each flag type: + +.. list-table:: + :widths: 20 20 20 20 + :header-rows: 1 + + * - **Flag Type** + - **Legacy Configuration File** + - **ALTER SYSTEM SET** + - **Worker Configuration File** + * - :ref:`Regular` + - Can modify + - Can modify + - Cannot modify + * - :ref:`Cluster` + - Cannot modify + - Can modify + - Cannot modify + * - :ref:`Worker` + - Cannot modify + - Cannot modify + - Can modify + +.. _regular_flag_types: + +Regular Flag Types +--------------------- +The following is an example of the correct syntax for running a **Regular** flag type command: + +.. code-block:: console + + SET spoolMemoryGB= 11; + executed + +The following table describes the Regular flag types: + +.. list-table:: + :widths: 2 5 10 + :header-rows: 1 + + * - **Command** + - **Description** + - **Example** + * - ``SET `` + - Used for modifying flag attributes. + - ``SET developerMode=true`` + * - ``SHOW / ALL`` + - Used to preset either a specific flag value or all flag values. + - ``SHOW `` + * - ``SHOW ALL LIKE`` + - Used as a wildcard character for flag names. + - ``SHOW `` + * - ``show_conf_UF`` + - Used to print all flags with the following attributes: + + * Flag name + * Default value + * Is developer mode (Boolean) + * Flag category + * Flag type + - ``rechunkThreshold,90,true,RND,regular`` + * - ``show_conf_extended UF`` + - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. + - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` + ``utility functions names,boolean,true,false`` + * - ``show_md_flag UF`` + - Used to show a specific flag/all flags stored in the metadata file. + - + * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` + * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` + * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` + +.. _cluster_flag_types: + +Cluster Flag Types +--------------------- +The following is an example of the correct syntax for running a **Cluster** flag type command: + +.. code-block:: console + + ALTER SYSTEM RESET useMetadataServer; + executed + +The following table describes the Cluster flag types: + +.. list-table:: + :widths: 1 5 10 + :header-rows: 1 + + * - **Command** + - **Description** + - **Example** + * - ``ALTER SYSTEM SET `` + - Used to storing or modifying flag attributes in the metadata file. + - ``ALTER SYSTEM SET `` + * - ``ALTER SYSTEM RESET `` + - Used to remove a flag or all flag attributes from the metadata file. + - ``ALTER SYSTEM RESET `` + * - ``SHOW / ALL`` + - Used to print the value of a specified value or all flag values. + - ``SHOW `` + * - ``SHOW ALL LIKE`` + - Used as a wildcard character for flag names. + - ``SHOW `` + * - ``show_conf_UF`` + - Used to print all flags with the following attributes: + + * Flag name + * Default value + * Is developer mode (Boolean) + * Flag category + * Flag type + - ``rechunkThreshold,90,true,RND,regular`` + * - ``show_conf_extended UF`` + - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. + - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` + ``utility functions names,boolean,true,false`` + * - ``show_md_flag UF`` + - Used to show a specific flag/all flags stored in the metadata file. + - + * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` + * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` + * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` + +.. _worker_flag_types: + +Worker Flag Types +--------------------- +The following is an example of the correct syntax for running a **Worker** flag type command: + +.. code-block:: console + + SHOW spoolMemoryGB; + +The following table describes the Worker flag types: + +.. list-table:: + :widths: 1 5 10 + :header-rows: 1 + + * - **Command** + - **Description** + - **Example** + * - ``ALTER SYSTEM SET `` + - Used to storing or modifying flag attributes in the metadata file. + - ``ALTER SYSTEM SET `` + * - ``ALTER SYSTEM RESET `` + - Used to remove a flag or all flag attributes from the metadata file. + - ``ALTER SYSTEM RESET `` + * - ``SHOW / ALL`` + - Used to print the value of a specified value or all flag values. + - ``SHOW `` + * - ``SHOW ALL LIKE`` + - Used as a wildcard character for flag names. + - ``SHOW `` + * - ``show_conf_UF`` + - Used to print all flags with the following attributes: + + * Flag name + * Default value + * Is developer mode (Boolean) + * Flag category + * Flag type + - ``rechunkThreshold,90,true,RND,regular`` + * - ``show_conf_extended UF`` + - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. + - + ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` + ``utility functions names,boolean,true,false`` + * - ``show_md_flag UF`` + - Used to show a specific flag/all flags stored in the metadata file. + - + * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` + * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` + * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` + +Configuration Commands +========== + + + +The configuration commands are associated with particular flag types based on permissions. + +The following table describes the commands or command sets that can be run based on their flag type. Note that the flag names described in the following table are described in the :ref:`Configuration Roles` section below. + +.. list-table:: + :header-rows: 1 + :widths: 1 2 10 17 + :class: my-class + :name: my-name + + * - Flag Type + - Command + - Description + - Example + * - Regular + - ``SET `` + - Used for modifying flag attributes. + - ``SET developerMode=true`` + * - Cluster + - ``ALTER SYSTEM SET `` + - Used to storing or modifying flag attributes in the metadata file. + - ``ALTER SYSTEM SET `` + * - Cluster + - ``ALTER SYSTEM RESET `` + - Used to remove a flag or all flag attributes from the metadata file. + - ``ALTER SYSTEM RESET `` + * - Regular, Cluster, Worker + - ``SHOW / ALL`` + - Used to print the value of a specified value or all flag values. + - ``SHOW `` + * - Regular, Cluster, Worker + - ``SHOW ALL LIKE`` + - Used as a wildcard character for flag names. + - ``SHOW `` + * - Regular, Cluster, Worker + - ``show_conf_UF`` + - Used to print all flags with the following attributes: + + * Flag name + * Default value + * Is developer mode (Boolean) + * Flag category + * Flag type + + + + - ``rechunkThreshold,90,true,RND,regular`` + * - Regular, Cluster, Worker + - ``show_conf_extended UF`` + - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. + - ``spoolMemoryGB,15,false,generic,regular,Amount of memory (GB)`` + ``the server can use for spooling,”Statement that perform “”group by””,`` + ``“”order by”” or “”join”” operation(s) on large set of data will run`` + ``much faster if given enough spool memory, otherwise disk spooling will`` + ``be used resulting in performance hit.”,uint,,0-5000`` + * - Regular, Cluster, Worker + - ``show_md_flag UF`` + - Used to show a specific flag/all flags stored in the metadata file. + - + * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` + * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` + * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` + + + + + + + +.. _configuration_roles: + +Configuration Roles +=========== +SQream divides flags into the following roles, each with their own set of permissions: + + - + * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` + * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` + * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` + +* **Generic** – Flags that can be modified by standard users on a session basis. +* **Admin** – Flags that can be modified by administrators on a session and cluster basis using the ALTER SYSTEM SET command. + + + +The following table describes the Generic and Admin configuration flags: + +.. list-table:: + :header-rows: 1 + :widths: 1 2 1 15 1 20 + :class: my-class + :name: my-name + + * - Flag Name + - Access Control + - Modification Type + - Description + - Data Type + - Default Value + + * - ``binSizes`` + - Admin + - Regular + - Sets the custom bin size in the cache to enable high granularity bin control. + - string + - + ``16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,`` + ``131072,262144,524288,1048576,2097152,4194304,8388608,16777216,`` + ``33554432,67108864,134217728,268435456,536870912,786432000,107374,`` + ``1824,1342177280,1610612736,1879048192,2147483648,2415919104,`` + ``2684354560,2952790016,3221225472`` + + * - ``checkCudaMemory`` + - Admin + - Regular + - Sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. + - boolean + - ``FALSE`` + + * - ``compilerGetsOnlyUFs`` + - Admin + - Regular + - Sets the runtime to pass only utility functions names to the compiler. + - boolean + - ``FALSE`` + + * - ``copyToRestrictUtf8`` + - Admin + - Regular + - Sets the custom bin size in the cache to enable high granularity bin control. + - boolean + - ``FALSE`` + + * - ``cpuReduceHashtableSize`` + - Admin + - Regular + - Sets the hash table size of the CpuReduce. + - uint + - ``10000`` + + * - ``csvLimitRowLength`` + - Admin + - Cluster + - Sets the maximum supported CSV row length. + - uint + - ``100000`` + + * - ``cudaMemcpyMaxSizeBytes`` + - Admin + - Regular + - Sets the chunk size for copying from CPU to GPU. If set to 0, do not divide. + - uint + - ``0`` + + * - ``CudaMemcpySynchronous`` + - Admin + - Regular + - Indicates if copying from/to GPU is synchronous. + - boolean + - ``FALSE`` + + * - ``cudaMemQuota`` + - Admin + - Worker + - Sets the percentage of total device memory to be used by the instance. + - uint + - ``90`` + + * - ``developerMode`` + - Admin + - Regular + - Enables modifying R&D flags. + - boolean + - ``FALSE`` + + * - ``enableDeviceDebugMessages`` + - Admin + - Regular + - Activates the Nvidia profiler (nvprof) markers. + - boolean + - ``FALSE`` + + * - ``enableLogDebug`` + - Admin + - Regular + - Enables creating and logging in the clientLogger_debug file. + - boolean + - ``TRUE`` + + * - ``enableNvprofMarkers`` + - Admin + - Regular + - Activates the Nvidia profiler (nvprof) markers. + - boolean + - ``FALSE`` + + * - ``endLogMessage`` + - Admin + - Regular + - Appends a string at the end of every log line. + - string + - ``EOM`` + + * - ``extentStorageFileSizeMB`` + - Admin + - Cluster + - Sets the minimum size in mebibytes of extents for table bulk data. + - uint + - ``20`` + + * - ``gatherMemStat`` + - Admin + - Regular + - Monitors all pinned allocations and all **memcopies** to/from device, and prints a report of pinned allocations that were not memcopied to/from the device using the **dump_pinned_misses** utility function. + - boolean + - ``FALSE`` + + * - ``increaseChunkSizeBeforeReduce`` + - Admin + - Regular + - Increases the chunk size to reduce query speed. + - boolean + - ``FALSE`` + + * - ``increaseMemFactors`` + - Admin + - Regular + - Adds rechunker before expensive chunk producer. + - boolean + - ``TRUE`` + + * - ``leveldbWriteBufferSize`` + - Admin + - Regular + - Sets the buffer size. + - uint + - ``524288`` + + * - ``machineIP`` + - Admin + - Worker + - Manual setting of reported IP. + - string + - ``127.0.0.1`` + + + + + * - ``memoryResetTriggerMB`` + - Admin + - Regular + - Sets the size of memory used during a query to trigger aborting the server. + - uint + - ``0`` + + * - ``metadataServerPort`` + - Admin + - Worker + - Sets the port used to connect to the metadata server. SQream recommends using port ranges above 1024† because ports below 1024 are usually reserved, although there are no strict limitations. Any positive number (1 - 65535) can be used. + - uint + - ``3105`` + + * - ``mtRead`` + - Admin + - Regular + - Splits large reads to multiple smaller ones and executes them concurrently. + - boolean + - ``FALSE`` + + * - ``mtReadWorkers`` + - Admin + - Regular + - Sets the number of workers to handle smaller concurrent reads. + - uint + - ``30`` + + * - ``orcImplicitCasts`` + - Admin + - Regular + - Sets the implicit cast in orc files, such as **int** to **tinyint** and vice versa. + - boolean + - ``TRUE`` + + * - ``statementLockTimeout`` + - Admin + - Regular + - Sets the timeout (seconds) for acquiring object locks before executing statements. + - uint + - ``3`` + + * - ``useConfigIP`` + - Admin + - Worker + - Activates the machineIP (true). Setting to false ignores the machineIP and automatically assigns a local network IP. This cannot be activated in a cloud scenario (on-premises only). + - boolean + - ``FALSE`` + + * - ``useLegacyDecimalLiterals`` + - Admin + - Regular + - Interprets decimal literals as **Double** instead of **Numeric**. Used to preserve legacy behavior in existing customers. + - boolean + - ``FALSE`` + + * - ``useLegacyStringLiterals`` + - Admin + - Regular + - Interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. Used to preserve legacy behavior in existing customers. + - boolean + - ``FALSE`` + + * - ``flipJoinOrder`` + - Generic + - Regular + - Reorders join to force equijoins and/or equijoins sorted by table size. + - boolean + - ``FALSE`` + + * - ``limitQueryMemoryGB`` + - Generic + - Worker + - Prevents a query from processing more memory than the flag’s value. + - uint + - ``100000`` + + * - ``logSysLevel`` + - Generic + - Regular + - + Determines the client log level: + 0 - L_SYSTEM, + 1 - L_FATAL, + 2 - L_ERROR, + 3 - L_WARN, + 4 - L_INFO, + 5 - L_DEBUG, + 6 - L_TRACE + - uint + - ``100000`` + + * - ``maxAvgBlobSizeToCompressOnGpu`` + - Generic + - Regular + - Sets the CPU to compress columns with size above (flag’s value) * (row count). + - uint + - ``120`` + + * - ``spoolMemoryGB`` + - Generic + - Regular + - Sets the amount of memory (GB) to be used by the server for spooling. + - uint + - ``8`` + +Showing All Flags in the Catalog Table +======= +SQream uses the **sqream_catalog.parameters** catalog table for showing all flags, providing the scope (default, cluster and session), description, default value and actual value. + +The following is the correct syntax for a catalog table query: + + +.. code-block:: console + + SELECT * FROM sqream_catalog.settings + +The following is an example of a catalog table query: + + +.. code-block:: console + + externalTableBlobEstimate, 100, 100, default, + varcharEncoding, ascii, ascii, default, Changes the expected encoding for Varchar columns + useCrcForTextJoinKeys, true, true, default, + hiveStyleImplicitStringCasts, false, false, default, This guide covers the configuration files and the ``SET`` statement. -Configuration files -========================== + + +Previous Configuration Method +=================== By default, configuration files are stored in ``/etc/sqream``. A very minimal configuration file looks like this: @@ -36,9 +725,8 @@ A very minimal configuration file looks like this: In the example above, the worker will start on port 5000, and will use GPU #0. -Frequently set parameters -============================ - +Frequently Set Parameters +------ .. todo list-table:: Compiler flags :widths: auto @@ -235,10 +923,10 @@ Frequently set parameters .. point to the best practices as well -.. warning:: JSON files can't contain any comments +.. warning:: JSON files can't contain any comments. -Recommended configuration file -===================================== +Recommended Configuration File +----- .. code-block:: json @@ -267,14 +955,3 @@ Recommended configuration file "licensePath":"/etc/sqream/license.enc" } } - -Changing settings temporarily -=================================== - -The ``SET`` statement can modify one of the configuration settings for the session or connection. - -For example, to set the query plan's logging interval to "every 3 seconds" for subsequent statements: - -.. code-block:: psql - - t=> SET nodeInfoLoggingSec=3; SELECT * FROM nba; From 4cbc0d01efacb1d177264bf310b008833d19820d Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 5 Dec 2021 15:23:40 +0200 Subject: [PATCH 162/300] Update configuration.rst Corrected line 392. --- guides/operations/configuration.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/guides/operations/configuration.rst b/guides/operations/configuration.rst index 79d48493a..b1e05d54f 100644 --- a/guides/operations/configuration.rst +++ b/guides/operations/configuration.rst @@ -391,11 +391,6 @@ Configuration Roles =========== SQream divides flags into the following roles, each with their own set of permissions: - - - * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` - * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` - * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` - * **Generic** – Flags that can be modified by standard users on a session basis. * **Admin** – Flags that can be modified by administrators on a session and cluster basis using the ALTER SYSTEM SET command. From f214b6a1000fb3cff508ddbebe19f19059f17560 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 5 Dec 2021 15:25:40 +0200 Subject: [PATCH 163/300] Update configuration.rst Corrected line 393-397. --- guides/operations/configuration.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/guides/operations/configuration.rst b/guides/operations/configuration.rst index 79d48493a..b1e05d54f 100644 --- a/guides/operations/configuration.rst +++ b/guides/operations/configuration.rst @@ -391,11 +391,6 @@ Configuration Roles =========== SQream divides flags into the following roles, each with their own set of permissions: - - - * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` - * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` - * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` - * **Generic** – Flags that can be modified by standard users on a session basis. * **Admin** – Flags that can be modified by administrators on a session and cluster basis using the ALTER SYSTEM SET command. From 4386d5ffe8a6cdc595436edfbac7ce315561dc74 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 5 Jan 2022 14:32:56 +0200 Subject: [PATCH 164/300] Update sql_data_types.rst Added Alias column to Supported Data types table. --- reference/sql_data_types.rst | 118 ++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 51 deletions(-) diff --git a/reference/sql_data_types.rst b/reference/sql_data_types.rst index 63aaab9bf..6714494f1 100644 --- a/reference/sql_data_types.rst +++ b/reference/sql_data_types.rst @@ -4,9 +4,11 @@ Data Types ************************* -This topic describes the data types that SQream DB supports, and how to convert between them. +This topic describes the data types that SQream supports, and how to convert between them. -.. contents:: In this topic: +This page describes the following: + +.. contents:: :local: :depth: 2 @@ -16,84 +18,101 @@ Supported Types The following table shows the supported data types. .. list-table:: - :widths: 20 15 20 55 + :widths: 20 15 20 30 20 :header-rows: 1 * - Name - Description - Data Size (Not Null, Uncompressed) - Example + - Alias * - ``BOOL`` - Boolean values (``true``, ``false``) - 1 byte - ``true`` + - ``BIT`` * - ``TINYINT`` - Unsigned integer (0 - 255) - 1 byte - ``5`` + - NA * - ``SMALLINT`` - Integer (-32,768 - 32,767) - 2 bytes - ``-155`` + - NA * - ``INT`` - Integer (-2,147,483,648 - 2,147,483,647) - 4 bytes - ``1648813`` + - ``INTEGER`` * - ``BIGINT`` - Integer (-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807) - 8 bytes - ``36124441255243`` + - ``NUMBER`` * - ``REAL`` - Floating point (inexact) - 4 bytes - ``3.141`` - * - ``DOUBLE`` (``FLOAT``) + - NA + * - ``DOUBLE`` - Floating point (inexact) - 8 bytes - ``0.000003`` + - ``FLOAT``/``DOUBLE PRECISION`` * - ``TEXT [(n)]``, ``NVARCHAR (n)`` - Variable length string - UTF-8 unicode - Up to ``4*n`` bytes - ``'キウイは楽しい鳥です'`` - * - ``NUMERIC``, ``DECIMAL`` + - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR``, ``NVARCHAR`` + * - ``NUMERIC`` - 38 digits - 16 bytes - ``0.123245678901234567890123456789012345678`` + - ``DECIMAL`` * - ``VARCHAR (n)`` - Variable length string - ASCII only - ``n`` bytes - ``'Kiwis have tiny wings, but cannot fly.'`` + - ``SQL VARIANT`` * - ``DATE`` - Date - 4 bytes - ``'1955-11-05'`` - * - ``DATETIME`` (``TIMESTAMP``) + - NA + * - ``DATETIME`` - Date and time pairing in UTC - 8 bytes - ``'1955-11-05 01:24:00.000'`` + - ``TIMESTAMP``, ``DATETIME2`` -.. note:: SQream DB compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. +.. note:: SQream compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. .. _cast: Converting and Casting Types ============================== - -SQream DB supports explicit and implicit casting and type conversion. -The system may automatically add implicit casts when combining different data types in the same expression. In many cases, while the details related to this are not important, they can affect the query results of a query. When necessary, an explicit cast can be used to override the automatic cast added by SQream DB. +SQream supports explicit and implicit casting and type conversion. The system may automatically add implicit casts when combining different data types in the same expression. In many cases, while the details related to this are not important, they can affect the query results of a query. When necessary, an explicit cast can be used to override the automatic cast added by SQream DB. For example, the ANSI standard defines a ``SUM()`` aggregation over an ``INT`` column as an ``INT``. However, when dealing with large amounts of data this could cause an overflow. -You can rectify this by casting the value to a larger data type: +You can rectify this by casting the value to a larger data type, as shown below: .. code-block:: postgres SUM(some_int_column :: BIGINT) -SQream DB supports the following three data conversion types: +SQream supports the following three data conversion types: -* ``CAST( AS )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' AS DATE)``, ``CAST(3.45 AS SMALLINT)``, ``CAST(some_column AS VARCHAR(30))``. +* ``CAST( TO )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO VARCHAR(30))``. + + :: + * `` :: ``, a shorthand for the ``CAST`` syntax. For example, ``'1997-01-01' :: DATE``, ``3.45 :: SMALLINT``, ``(3+5) :: BIGINT``. + + :: + * See the :ref:`SQL functions reference ` for additional functions that convert from a specific value which is not an SQL type, such as :ref:`from_unixts`, etc. The **Data Type Reference** section below provides more details about the supported casts for each type. @@ -103,7 +122,7 @@ Data Type Reference .. _numeric: -Numeric (``NUMERIC``, ``DECIMAL``) +Numeric ----------------------- The **Numeric** data type (also known as **Decimal**) is recommended for values that tend to occur as exact decimals, such as in Finance. While Numeric has a fixed precision of ``38``, higher than ``REAL`` (``9``) or ``DOUBLE`` (``17``), it runs calculations more slowly. For operations that require faster performance, using :ref:`Floating Point ` is recommended. @@ -141,7 +160,7 @@ Numeric supports the following operations: -Boolean (``BOOL``) +Boolean ------------------- The following table describes the Boolean data type. @@ -158,7 +177,6 @@ The following table describes the Boolean data type. Boolean Examples ^^^^^^^^^^ - The following is an example of the Boolean syntax: .. code-block:: postgres @@ -193,15 +211,7 @@ The following table shows the possible Boolean value conversions: * - ``REAL``, ``DOUBLE`` - ``true`` → ``1.0``, ``false`` → ``0.0`` - - - - - - - - -Integers (``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``) +Integers ------------------------------------------------------------ Integer data types are designed to store whole numbers. @@ -284,7 +294,7 @@ The following table shows the possible Integer value conversions: .. _floating_point: -Floating Point (``REAL``, ``DOUBLE``) +Floating Point ------------------------------------------------ The **Floating Point** data types (``REAL`` and ``DOUBLE``) store extremely close value approximations, and are therefore recommended for values that tend to be inexact, such as Scientific Notation. While Floating Point generally runs faster than Numeric, it has a lower precision of ``9`` (``REAL``) or ``17`` (``DOUBLE``) compared to Numeric's ``38``. For operations that require a higher level of precision, using :ref:`Numeric ` is recommended. @@ -326,6 +336,7 @@ The following table shows information relevant to the Floating Point data types. Floating Point Examples ^^^^^^^^^^ +The following are examples of the Floating Point syntax: .. code-block:: postgres @@ -359,19 +370,19 @@ The following table shows the possible Floating Point value conversions: * - ``VARCHAR(n)`` (n > 6 recommended) - ``1`` → ``'1.0000'``, ``3.14159265358979`` → ``'3.1416'`` -.. note:: As shown in the above examples, when casting ``real`` to ``int``, we round down. +.. note:: As shown in the above examples, casting ``real`` to ``int`` rounds down. -String (``TEXT``, ``VARCHAR``) +String ------------------------------------------------ ``TEXT`` and ``VARCHAR`` are types designed for storing text or strings of characters. -SQream DB separates ASCII (``VARCHAR``) and UTF-8 representations (``TEXT``). +SQream separates ASCII (``VARCHAR``) and UTF-8 representations (``TEXT``). .. note:: The data type ``NVARCHAR`` has been deprecated by ``TEXT`` as of version 2020.1. String Types ^^^^^^^^^^^^^^^^^^^^^^ -The following table describes the String types. +The following table describes the String types: .. list-table:: :widths: auto @@ -392,7 +403,6 @@ The following table describes the String types. Length ^^^^^^^^^ - When using ``TEXT``, specifying a size is optional. If not specified, the text field carries no constraints. To limit the size of the input, use ``VARCHAR(n)`` or ``TEXT(n)``, where ``n`` is the permitted number of characters. The following apply to setting the String type length: @@ -403,19 +413,12 @@ The following apply to setting the String type length: Syntax ^^^^^^^^ - String types can be written with standard SQL string literals, which are enclosed with single quotes, such as -``'Kiwi bird'``. - -To include a single quote in the string, use double quotations, such as ``'Kiwi bird''s wings are tiny'``. - -String literals can also be dollar-quoted with the dollar sign ``$``, such as ``$$Kiwi bird's wings are tiny$$`` is the same as ``'Kiwi bird''s wings are tiny'``. +``'Kiwi bird'``. To include a single quote in the string, use double quotations, such as ``'Kiwi bird''s wings are tiny'``. String literals can also be dollar-quoted with the dollar sign ``$``, such as ``$$Kiwi bird's wings are tiny$$`` is the same as ``'Kiwi bird''s wings are tiny'``. Size ^^^^^^ - -``VARCHAR(n)`` can occupy up to *n* bytes, whereas ``TEXT(n)`` can occupy up to *4*n* bytes. -However, the size of strings is variable and is compressed by SQream DB. +``VARCHAR(n)`` can occupy up to *n* bytes, whereas ``TEXT(n)`` can occupy up to *4*n* bytes. However, the size of strings is variable and is compressed by SQream. String Examples ^^^^^^^^^^ @@ -461,18 +464,16 @@ The following table shows the possible String value conversions: -Date (``DATE``, ``DATETIME``) +Date ------------------------------------------------ -``DATE`` is a type designed for storing year, month, and day. - -``DATETIME`` is a type designed for storing year, month, day, hour, minute, seconds, and milliseconds in UTC with 1 millisecond precision. +``DATE`` is a type designed for storing year, month, and day. ``DATETIME`` is a type designed for storing year, month, day, hour, minute, seconds, and milliseconds in UTC with 1 millisecond precision. Date Types ^^^^^^^^^^^^^^^^^^^^^^ -The following table describes the Date types. +The following table describes the Date types: -.. list-table:: Date types +.. list-table:: Date Types :widths: auto :header-rows: 1 @@ -492,21 +493,36 @@ The following table describes the Date types. Aliases ^^^^^^^^^^ -``DATETIME`` is also known as ``TIMESTAMP``. +``DATETIME`` is also known as ``TIMESTAMP`` or ``DATETIME2``. Syntax ^^^^^^^^ +``DATE`` values are formatted as string literals. -``DATE`` values are formatted as string literals. For example, ``'1955-11-05'`` or ``date '1955-11-05'``. +The following is an example of the DATETIME syntax: -``DATETIME`` values are formatted as string literals conforming to `ISO 8601 `_, for example ``'1955-11-05 01:26:00'``. +.. code-block:: console + + '1955-11-05' -SQream DB attempts to guess if the string literal is a date or datetime based on context, for example when used in date-specific functions. +.. code-block:: console + + date '1955-11-05' + +``DATETIME`` values are formatted as string literals conforming to `ISO 8601 `_. + +The following is an example of the DATETIME syntax: + + +.. code-block:: console + + '1955-11-05 01:26:00' + +SQream attempts to guess if the string literal is a date or datetime based on context, for example when used in date-specific functions. Size ^^^^^^ - A ``DATE`` column is 4 bytes in length, while a ``DATETIME`` column is 8 bytes in length. However, the size of these values is compressed by SQream DB. From 8919a52c296f349c433a8e3d5b803df89bee2b5b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 12 Jan 2022 10:53:17 +0200 Subject: [PATCH 165/300] Create index.rst --- installation_guides/index.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 installation_guides/index.rst diff --git a/installation_guides/index.rst b/installation_guides/index.rst new file mode 100644 index 000000000..7fd1014f3 --- /dev/null +++ b/installation_guides/index.rst @@ -0,0 +1,22 @@ +.. _installation_guides: + +************************* +Installation Guides +************************* + +The **Installation Guides** page incudes the following installation guides: + +.. toctree:: + :maxdepth: 1 + :glob: + + sqream_studio_installation + recommended_pre-installation_configurations + xxrunning_sqream_in_a_docker_container + installing_sqream_with_binary + installing_monit + installing_sqream_with_kubernetes + xxinstalling_prometheus_exporters + xxinstalling_studio_on_stand_alone_server + + From 3a3a3967690ecfbb59b7860fed206301910741c3 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 12 Jan 2022 11:00:48 +0200 Subject: [PATCH 166/300] Uploaded files from Branch: Reorganizing-Documentation I'm attempting to make a branch with updated Installation Guide topic modifications. I originally made those changes in Reorganizing-Documentation, and realized that they needed their own branch, especially in order to update all RN branches with those changes. I'm trying it on this branch first because it's the oldest and least visible. I made Branch: installation_guides_2021_1 because merging Reorganizing-Documentation into 2021-1 had too many conflicts. There were many conflicts because I use that branch to update ALL aspects of the documentation. Hopefully installation_guides_2021_1 will prevent/reduce merge conflicts when merging this branch into previous RN's. --- .../installing_dashboard_data_collector.rst | 163 ++ installation_guides/installing_monit.rst | 319 +++ .../installing_prometheus_exporters.rst | 196 ++ ...lling_prometheus_using_binary_packages.rst | 241 +++ .../installing_sqream_with_binary.rst | 279 +++ .../installing_sqream_with_kubernetes.rst | 1805 +++++++++++++++++ ...nstalling_studio_on_stand_alone_server.rst | 578 ++++++ ...mended_pre-installation_configurations.rst | 1158 +++++++++++ .../running_sqream_in_a_docker_container.rst | 1490 ++++++++++++++ .../sqream_studio_installation.rst | 20 + 10 files changed, 6249 insertions(+) create mode 100644 installation_guides/installing_dashboard_data_collector.rst create mode 100644 installation_guides/installing_monit.rst create mode 100644 installation_guides/installing_prometheus_exporters.rst create mode 100644 installation_guides/installing_prometheus_using_binary_packages.rst create mode 100644 installation_guides/installing_sqream_with_binary.rst create mode 100644 installation_guides/installing_sqream_with_kubernetes.rst create mode 100644 installation_guides/installing_studio_on_stand_alone_server.rst create mode 100644 installation_guides/recommended_pre-installation_configurations.rst create mode 100644 installation_guides/running_sqream_in_a_docker_container.rst create mode 100644 installation_guides/sqream_studio_installation.rst diff --git a/installation_guides/installing_dashboard_data_collector.rst b/installation_guides/installing_dashboard_data_collector.rst new file mode 100644 index 000000000..ba0475a6d --- /dev/null +++ b/installation_guides/installing_dashboard_data_collector.rst @@ -0,0 +1,163 @@ +.. _installing_dashboard_data_collector: + + + +*********************** +Installing the Dashboard Data Collector +*********************** + +Installing the Dashboard Data Collector +^^^^^^^^^^^^^^^ +After accessing the Prometheus user interface, you can install the **Dashboard Data Collector**. You must install the Dashboard Data Collector to enable the Dashboard in Studio. + +.. note:: Before installing the Dashboard Data collector, verify that Prometheus has been installed and configured for the cluster. + +How to install Prometheus from tarball - **Comment - this needs to be its own page.** + +**To install the Dashboard Data Collector:** + +1. Store the Data Collector Package obtained from `SQream Artifactory `_. + + :: + +2. Extract and rename the package: + + .. code-block:: console + + $ tar -xvf dashboard-data-collector-0.5.2.tar.gz + $ mv package dashboard-data-collector + +3. Change your directory to the location of the package folder: + + .. code-block:: console + + $ cd dashboard-data-collector + +4. Set up the data collection by modifying the SQream and Data Collector IPs, ports, user name, and password according to the cluster: + + .. code-block:: console + + $ npm run setup -- \ + $ --host=127.0.0.1 \ + $ --port=3108 \ + $ --database=master \ + $ --is-cluster=true \ + $ --service=sqream \ + $ --dashboard-user=sqream \ + $ --dashboard-password=sqream \ + $ --prometheus-url=http://127.0.0.1:9090/api/v1/query + +5. Debug the Data Collector: (**Comment** - *using the npm project manager*). + + .. code-block:: console + + $ npm start + + A json file is generated in the log, as shown below: + + .. code-block:: console + + $ { + $ "machines": [ + $ { + $ "machineId": "dd4af489615", + $ "name": "Server 0", + $ "location": "192.168.4.94", + $ "totalMemory": 31.19140625, + $ "gpus": [ + $ { + $ "gpuId": "GPU-b17575ec-eeba-3e0e-99cd-963967e5ee3f", + $ "machineId": "dd4af489615", + $ "name": "GPU 0", + $ "totalMemory": 3.9453125 + $ } + $ ], + $ "workers": [ + $ { + $ "workerId": "sqream_01", + $ "gpuId": "", + $ "name": "sqream_01" + $ } + $ ], + $ "storageWrite": 0, + $ "storageRead": 0, + $ "freeStorage": 0 + $ }, + $ { + $ "machineId": "704ec607174", + $ "name": "Server 1", + $ "location": "192.168.4.95", + $ "totalMemory": 31.19140625, + $ "gpus": [ + $ { + $ "gpuId": "GPU-8777c14f-7611-517a-e9c7-f42eeb21700b", + $ "machineId": "704ec607174", + $ "name": "GPU 0", + $ "totalMemory": 3.9453125 + $ } + $ ], + $ "workers": [ + $ { + $ "workerId": "sqream_02", + $ "gpuId": "", + $ "name": "sqream_02" + $ } + $ ], + $ "storageWrite": 0, + $ "storageRead": 0, + $ "freeStorage": 0 + $ } + $ ], + $ "clusterStatus": true, + $ "storageStatus": { + $ "dataStorage": 49.9755859375, + $ "totalDiskUsage": 52.49829018075231, + $ "storageDetails": { + $ "data": 0, + $ "freeData": 23.7392578125, + $ "tempData": 0, + $ "deletedData": 0, + $ "other": 26.236328125 + $ }, + $ "avgThroughput": { + $ "read": 0, + $ "write": 0 + $ }, + $ "location": "/" + $ }, + $ "queues": [ + $ { + $ "queueId": "sqream", + $ "name": "sqream", + $ "workerIds": [ + $ "sqream_01", + $ "sqream_02" + $ ] + $ } + $ ], + $ "queries": [], + $ "collected": true, + $ "lastCollect": "2021-11-17T12:46:31.601Z" + $ } + +.. note:: Verify that all machines and workers are correctly registered. + + +6. Press **CTRL + C** to stop ``npm start`` (**Comment** - *It may be better to refer to it as the npm project manager*). + + :: + + +7. Start the Data Collector with the ``pm2`` service: + + .. code-block:: console + + $ pm2 start ./index.js --name=dashboard-data-collector + +8. Add the following parameter to the SQream Studio setup defined in :ref:`Step 4` in **Installing Studio** below. + + .. code-block:: console + + --data-collector-url=http://127.0.0.1:8100/api/dashboard/data + +Back to :ref:`Installing Studio on a Stand-Alone Server` diff --git a/installation_guides/installing_monit.rst b/installation_guides/installing_monit.rst new file mode 100644 index 000000000..b27800cce --- /dev/null +++ b/installation_guides/installing_monit.rst @@ -0,0 +1,319 @@ +.. _installing_monit: + +********************************************* +Installing Monit +********************************************* + +Getting Started +============================== + +Before installing SQream with Monit, verify that you have followed the required :ref:`recommended pre-installation configurations `. + +The procedures in the **Installing Monit** guide must be performed on each SQream cluster node. + + + + + +.. _back_to_top: + +Overview +============================== + + +Monit is a free open source supervision utility for managing and monitoring Unix and Linux. Monit lets you view system status directly from the command line or from a native HTTP web server. Monit can be used to conduct automatic maintenance and repair, such as executing meaningful causal actions in error situations. + +SQream uses Monit as a watchdog utility, but you can use any other utility that provides the same or similar functionality. + +The **Installing Monit** procedures describes how to install, configure, and start Monit. + +You can install Monit in one of the following ways: + +* :ref:`Installing Monit on CentOS ` +* :ref:`Installing Monit on CentOS offline ` +* :ref:`Installing Monit on Ubuntu ` +* :ref:`Installing Monit on Ubuntu offline ` + + + + + + + +.. _installing-monit-on-centos: + +Installing Monit on CentOS: +------------------------------------ + + + +**To install Monit on CentOS:** + +1. Install Monit as a superuser on CentOS: + + .. code-block:: console + + $ sudo yum install monit + + +.. _installing-monit-on-centos-offline: + + + +Installing Monit on CentOS Offline: +------------------------------------ + + +Installing Monit on CentOS offline can be done in either of the following ways: + +* :ref:`Building Monit from Source Code ` +* :ref:`Building Monit from Pre-Built Binaries ` + + + + +.. _building_monit_from_source_code: + +Building Monit from Source Code +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +**To build Monit from source code:** + +1. Copy the Monit package for the current version: + + .. code-block:: console + + $ tar zxvf monit-.tar.gz + + The value ``x.y.z`` denotes the version numbers. + +2. Navigate to the directory where you want to store the package: + + .. code-block:: console + + $ cd monit-x.y.z + +3. Configure the files in the package: + + .. code-block:: console + + $ ./configure (use ./configure --help to view available options) + +4. Build and install the package: + + .. code-block:: console + + $ make && make install + +The following are the default storage directories: + +* The Monit package: **/usr/local/bin/** +* The **monit.1 man-file**: **/usr/local/man/man1/** + +5. **Optional** - To change the above default location(s), use the **--prefix** option to ./configure. + +.. + _**Comment - I took this line directly from the external online documentation. Is the "prefix option" referrin gto the "--help" in Step 3? URL: https://mmonit.com/wiki/Monit/Installation** + +6. **Optional** - Create an RPM package for CentOS directly from the source code: + + .. code-block:: console + + $ rpmbuild -tb monit-x.y.z.tar.gz + +.. + _**Comment - Is this an optional or mandatory step?** + + + + +.. _building_monit_from_pre_built_binaries: + +Building Monit from Pre-Built Binaries +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To build Monit from pre-built binaries:** + +1. Copy the Monit package for the current version: + + .. code-block:: console + + $ tar zxvf monit-x.y.z-linux-x64.tar.gz + + The value ``x.y.z`` denotes the version numbers. + +2. Navigate to the directory where you want to store the package: + + .. code-block:: console$ cd monit-x.y.z + +3. Copy the **bin/monit** and **/usr/local/bin/** directories: + + .. code-block:: console + + $ cp bin/monit /usr/local/bin/ + +4. Copy the **conf/monitrc** and **/etc/** directories: + + .. code-block:: console + + $ cp conf/monitrc /etc/ + +.. + _**Comment - please review this procedure.** + +For examples of pre-built Monit binarties, see :ref:`Download Precompiled Binaries`. + +:ref:`Back to top ` + + + +.. _installing-monit-on-ubuntu: + + + +Installing Monit on Ubuntu: +------------------------------------ + + +**To install Monit on Ubuntu:** + +1. Install Monit as a superuser on Ubuntu: + + .. code-block:: console + + $ sudo apt-get install monit + +:ref:`Back to top ` + + + +.. _installing-monit-on-ubuntu-offline: + + +Installing Monit on Ubuntu Offline: +------------------------------------- + + +You can install Monit on Ubuntu when you do not have an internet connection. + +**To install Monit on Ubuntu offline:** + +1. Compress the required file: + + .. code-block:: console + + $ tar zxvf monit--linux-x64.tar.gz + + **NOTICE:** ** denotes the version number. + +2. Navigate to the directory where you want to save the file: + + .. code-block:: console + + $ cd monit-x.y.z + +3. Copy the **bin/monit** directory into the **/usr/local/bin/** directory: + + .. code-block:: console + + $ cp bin/monit /usr/local/bin/ + +4. Copy the **conf/monitrc** directory into the **/etc/** directory: + + .. code-block:: console + + $ cp conf/monitrc /etc/ + +:ref:`Back to top ` + + +Configuring Monit +==================================== + +When the installation is complete, you can configure Monit. You configure Monit by modifying the Monit configuration file, called **monitrc**. This file contains blocks for each service that you want to monitor. + +The following is an example of a service block: + + .. code-block:: console + + $ #SQREAM1-START + $ check process sqream1 with pidfile /var/run/sqream1.pid + $ start program = "/usr/bin/systemctl start sqream1" + $ stop program = "/usr/bin/systemctl stop sqream1" + $ #SQREAM1-END + +For example, if you have 16 services, you can configure this block by copying the entire block 15 times and modifying all service names as required, as shown below: + + .. code-block:: console + + $ #SQREAM2-START + $ check process sqream2 with pidfile /var/run/sqream2.pid + $ start program = "/usr/bin/systemctl start sqream2" + $ stop program = "/usr/bin/systemctl stop sqream2" + $ #SQREAM2-END + +For servers that don't run the **metadataserver** and **serverpicker** commands, you can use the block example above, but comment out the related commands, as shown below: + + .. code-block:: console + + $ #METADATASERVER-START + $ #check process metadataserver with pidfile /var/run/metadataserver.pid + $ #start program = "/usr/bin/systemctl start metadataserver" + $ #stop program = "/usr/bin/systemctl stop metadataserver" + $ #METADATASERVER-END + +**To configure Monit:** + +1. Copy the required block for each required service. +2. Modify all service names in the block. +3. Copy the configured **monitrc** file to the **/etc/monit.d/** directory: + + .. code-block:: console + + $ cp monitrc /etc/monit.d/ + +4. Set file permissions to **600** (full read and write access): + + .. code-block:: console + + $ sudo chmod 600 /etc/monit.d/monitrc + +5. Reload the system to activate the current configurations: + + .. code-block:: console + + $ sudo systemctl daemon-reload + +6. **Optional** - Navigate to the **/etc/sqream** directory and create a symbolic link to the **monitrc** file: + + .. code-block:: console + + $ cd /etc/sqream + $ sudo ln -s /etc/monit.d/monitrc monitrc + +Starting Monit +==================================== + +After configuring Monit, you can start it. + +**To start Monit:** + +1. Start Monit as a super user: + + .. code-block:: console + + $ sudo systemctl start monit + +2. View Monit's service status: + + .. code-block:: console + + $ sudo systemctl status monit + +3. If Monit is functioning correctly, enable the Monit service to start on boot: + + .. code-block:: console + + $ sudo systemctl enable monit diff --git a/installation_guides/installing_prometheus_exporters.rst b/installation_guides/installing_prometheus_exporters.rst new file mode 100644 index 000000000..a1381fea3 --- /dev/null +++ b/installation_guides/installing_prometheus_exporters.rst @@ -0,0 +1,196 @@ +.. _installing_prometheus_exporters: + +********************************************* +Installing Prometheus Exporter +********************************************* + +The **Installing Prometheus Exporters** guide includes the following sections: + +.. contents:: + :local: + :depth: 1 + +Overview +============================== +The **Prometheus** exporter is an open-source systems monitoring and alerting toolkit. It is used for collecting metrics from an operating system and exporting them to a graphic user interface. + +The Installing Prometheus Exporters guide describes how to installing the following exporters: + +* The **Node_exporter** - the basic exporter used for displaying server metrics, such as CPU and memory. + +* The **Nvidia_exporter** - shows Nvidia GPU metrics. + +* The **process_exporter** - shows data belonging to the server's running processes. + +For information about more exporters, see `Exporters and Integration `_ + +Adding a User and Group +===================== +Adding a user and group determines who can run processes. + +You can add users with the following command: + +.. code-block:: console + + $ sudo groupadd --system prometheus + +You can add groups with the following command: + +.. code-block:: console + + $ sudo useradd -s /sbin/nologin --system -g prometheus prometheus + +Cloning the Prometheus GIT Project +===================== +After adding a user and group you must clone the Prometheus GIT project. + +You can clone the Prometheus GIT project with the following command: + +.. code-block:: console + + $ git clone http://gitlab.sq.l/IT/promethues.git prometheus + +.. note:: If you experience difficulties cloning the Prometheus GIT project or receive an error, contact your IT department. + +The following shows the result of cloning your Prometheus GIT project: + +.. code-block:: console + + $ prometheus/ + $ ├── node_exporter + $ │   └── node_exporter + $ ├── nvidia_exporter + $ │   └── nvidia_exporter + $ ├── process_exporter + $ │   └── process-exporter_0.5.0_linux_amd64.rpm + $ ├── README.md + $ └── services + $ ├── node_exporter.service + $ └── nvidia_exporter.service + +Installing the Node Exporter and NVIDIA Exporter +===================== +After cloning the Prometheus GIT project you must install the **node_exporter** and **NVIDIA_exporter**. + +**To install the node_exporter and NVIDIA_exporter:** + +1. Navigate to the cloned folder: + + .. code-block:: console + + $ cd prometheus + +2. Copy **node_exporter** and **nvidia_exporter** to **/usr/bin/**. + + .. code-block:: console + + $ sudo cp node_exporter/node_exporter /usr/bin/ + $ sudo cp nvidia_exporter/nvidia_exporter /usr/bin/ + +3. Copy the **services** files to the services folder: + + .. code-block:: console + + $ sudo cp services/node_exporter.service /etc/systemd/system/ + $ sudo cp services/nvidia_exporter.service /etc/systemd/system/ + +4. Reload the services so that they can be run: + + .. code-block:: console + + $ sudo systemctl daemon-reload + +5. Set the permissions and group for both service files: + + .. code-block:: console + + $ sudo chown prometheus:prometheus /usr/bin/node_exporter + $ sudo chmod u+x /usr/bin/node_exporter + $ sudo chown prometheus:prometheus /usr/bin/nvidia_exporter + $ sudo chmod u+x /usr/bin/nvidia_exporter + +6. Start both services: + + .. code-block:: console + + $ sudo systemctl start node_exporter && sudo systemctl enable node_exporter + +7. Set both services to start automatically when the server is booted up: + + .. code-block:: console + + $ sudo systemctl start nvidia_exporter && sudo systemctl enable nvidia_exporter + +8. Verify that the server's status is **active (running)**: + + .. code-block:: console + + $ sudo systemctl status node_exporter && sudo systemctl status nvidia_exporter + + The following is the correct output: + + .. code-block:: console + + $ ● node_exporter.service - Node Exporter + $ Loaded: loaded (/etc/systemd/system/node_exporter.service; enabled; vendor preset: disabled) + $ Active: active (running) since Wed 2019-12-11 12:28:31 IST; 1 months 5 days ago + $ Main PID: 28378 (node_exporter) + $ CGroup: /system.slice/node_exporter.service + $ + $ ● nvidia_exporter.service - Nvidia Exporter + $ Loaded: loaded (/etc/systemd/system/nvidia_exporter.service; enabled; vendor preset: disabled) + $ Active: active (running) since Wed 2020-01-22 13:40:11 IST; 31min ago + $ Main PID: 1886 (nvidia_exporter) + $ CGroup: /system.slice/nvidia_exporter.service + $ └─1886 /usr/bin/nvidia_exporter + +Installing the Process Exporter +===================== +After installing the **node_exporter** and **Nvidia_exporter** you must install the **process_exporter**. + +**To install the process_exporter:** + +1. Do one of the following: + + * For **CentOS**, run ``sudo rpm -i process_exporter/process-exporter_0.5.0_linux_amd64.rpm``. + * For **Ubuntu**, run ``sudo dpkg -i process_exporter/process-exporter_0.6.0_linux_amd64.deb``. + +2. Verify that the process_exporter is running: + + .. code-block:: console + + $ sudo systemctl status process-exporter + +3. Set the process_exporter to start automatically when the server is booted up: + + .. code-block:: console + + $ sudo systemctl enable process-exporter + +Opening the Firewall Ports +===================== +After installing the **process_exporter** you must open the firewall ports for the following services: + +* **node_exporter** - port: 9100 + +* **nvidia_exporter** - port: 9445 + +* **process-exporter** - port: 9256 + +.. note:: This procedure is only relevant if your firwall is running. + +**To open the firewall ports:** + +1. Run the following command: + + .. code-block:: console + + $ sudo firewall-cmd --zone=public --add-port=/tcp --permanent + +2. Reload the firewall: + + .. code-block:: console + + $ sudo firewall-cmd --reload + +3. Verify that the changes have taken effect. \ No newline at end of file diff --git a/installation_guides/installing_prometheus_using_binary_packages.rst b/installation_guides/installing_prometheus_using_binary_packages.rst new file mode 100644 index 000000000..6864dd793 --- /dev/null +++ b/installation_guides/installing_prometheus_using_binary_packages.rst @@ -0,0 +1,241 @@ +.. _installing_prometheus_using_binary_packages: + +.. _install_prometheus_binary_top: + +*********************** +Installing Prometheus Using Binary Packages +*********************** + + + +The **Installing Prometheus Using Binary Packages** guide includes the following sections: + +.. contents:: + :local: + :depth: 1 + +Overview +^^^^^^^^^^^^^^^ +Prometheus is an application used for event monitoring and alerting. + +Installing Prometheus +^^^^^^^^^^^^^^^ +You must install Prometheus before installing the Dashboard Data Collector. + +**To install Prometheus:** + +1. Verify the following: + + 1. That you have **sudo** access to your Linux server. + 2. That your server has access to the internet (for downloading the Prometheus binary package). + 3. That your firewall rules are opened (**Comment** *- does "open" mean "disabled"?*) for accessing Prometheus Port 9090. + +2. Navigate to the Prometheus `Download `_ page and download the **prometheus-2.32.0-rc.1.linux-amd64.tar.gz** package. + + :: + +3. Do the following: + + 1. Download the source using the ``curl`` command: + + .. code-block:: console + + $ curl -LO url -LO https://github.com/prometheus/prometheus/releases/download/v2.22.0/prometheus-2.22.0.linux-amd64.tar.gz + + 2. Extract the file contents: + + .. code-block:: console + + $ tar -xvf prometheus-2.22.0.linux-amd64.tar.gz + + 3. Rename the extracted folder **prometheus-files**: + + .. code-block:: console + + $ mv prometheus-2.22.0.linux-amd64 prometheus-files + +4. Create a Prometheus user: + + .. code-block:: console + + $ sudo useradd --no-create-home --shell /bin/false prometheus + +5. Create your required directories: (**Comment** - *Does the user have to make these exact directories, or can they be whatever he wants?*) + + .. code-block:: console + + $ sudo mkdir /etc/prometheus + $ sudo mkdir /var/lib/prometheus + +6. Set the Prometheus user as the owner of your required directories: + + .. code-block:: console + + $ sudo chown prometheus:prometheus /etc/prometheus + $ sudo chown prometheus:prometheus /var/lib/prometheus + +7. Copy the Prometheus and Promtool binary packages from the **prometheus-files** folder to **/usr/local/bin**: + + .. code-block:: console + + $ sudo cp prometheus-files/prometheus /usr/local/bin/ + $ sudo cp prometheus-files/promtool /usr/local/bin/ + +8. Change the ownership to the prometheus user: + + .. code-block:: console + + $ sudo chown prometheus:prometheus /usr/local/bin/prometheus + $ sudo chown prometheus:prometheus /usr/local/bin/promtool + +9. Move the **consoles** and **consoles_libraries** directories from **prometheus-files** folder to **/etc/prometheus** folder: + + .. code-block:: console + + $ sudo cp -r prometheus-files/consoles /etc/prometheus + $ sudo cp -r prometheus-files/console_libraries /etc/prometheus + +10. Change the ownership to the prometheus user: + + .. code-block:: console + + $ sudo chown -R prometheus:prometheus /etc/prometheus/consoles + $ sudo chown -R prometheus:prometheus /etc/prometheus/console_libraries + +For more information on installing the Dashboard Data Collector, see `Installing the Dashboard Data Collector `_. + +Back to :ref:`Installing Prometheus Using Binary Packages` + +Configuring Your Prometheus Settings +^^^^^^^^^^^^^^^ +After installing Prometheus you must configure your Prometheus settings. You must perform all Prometheus configurations in the **/etc/prometheus/prometheus.yml** file. + +**To configure your Prometheus settings:** + +1. Create your **prometheus.yml** file: + + .. code-block:: console + + $ sudo vi /etc/prometheus/prometheus.yml + +2. Copy the contents below into your prometheus.yml file: + + .. code-block:: console + + $ #node_exporter port : 9100 + $ #nvidia_exporter port: 9445 + $ #process-exporter port: 9256 + $ + $ global: + $ scrape_interval: 10s + $ + $ scrape_configs: + $ - job_name: 'prometheus' + $ scrape_interval: 5s + $ static_configs: + $ - targets: + $ - :9090 + $ - job_name: 'processes' + $ scrape_interval: 5s + $ static_configs: + $ - targets: + $ - :9256 + $ - :9256 + $ - job_name: 'nvidia' + $ scrape_interval: 5s + $ static_configs: + $ - targets: + $ - :9445 + $ - :9445 + $ - job_name: 'nodes' + $ scrape_interval: 5s + $ static_configs: + $ - targets: + $ - :9100 + $ - :9100 + +3. Change the ownership of the file to the prometheus user: + + .. code-block:: console + + $ sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml + +Back to :ref:`Installing Prometheus Using Binary Packages` + +Configuring Your Prometheus Service File +^^^^^^^^^^^^^^^ +After configuring your Prometheus settings you must configure your Prometheus service file. + +**To configure your Prometheus service file**: + +1. Create your **prometheus.yml** file: + + .. code-block:: console + + $ sudo vi /etc/systemd/system/prometheus.service + +2. Copy the contents below into your prometheus service file: + + .. code-block:: console + + $ [Unit] + $ Description=Prometheus + $ Wants=network-online.target + $ After=network-online.target + $ + $ [Service] + $ User=prometheus + $ Group=prometheus + $ Type=simple + $ ExecStart=/usr/local/bin/prometheus \ + $ --config.file /etc/prometheus/prometheus.yml \ + $ --storage.tsdb.path /var/lib/prometheus/ \ + $ --web.console.templates=/etc/prometheus/consoles \ + $ --web.console.libraries=/etc/prometheus/console_libraries + $ + $ [Install] + $ WantedBy=multi-user.target + +3. Register the prometheus service by reloading the **systemd** service: + + .. code-block:: console + + $ sudo systemctl daemon-reload + +4. Start the prometheus service: + + .. code-block:: console + + $ sudo systemctl start prometheus + +5. Check the status of the prometheus service: + + .. code-block:: console + + $ sudo systemctl status prometheus + + If the status is ``active (running)``, you have configured your Prometheus service file correctly. + +Back to :ref:`Installing Prometheus Using Binary Packages` + +Accessing the Prometheus User Interface +^^^^^^^^^^^^^^^ +After configuring your prometheus service file, you can access the Prometheus user interface. + +You can access the Prometheus user interface by running the following command: + +.. code-block:: console + + $ http://:9090/graph + +The Prometheus user interface is displayed. + +From the **Query** tab you can query metrics, as shown below: + +.. list-table:: + :widths: auto + :header-rows: 0 + + * - .. image:: /_static/images/3c9c4e8b-49bd-44a8-9829-81d1772ed962.gif + +Back to :ref:`Installing Prometheus Using Binary Packages` \ No newline at end of file diff --git a/installation_guides/installing_sqream_with_binary.rst b/installation_guides/installing_sqream_with_binary.rst new file mode 100644 index 000000000..dd1207ab7 --- /dev/null +++ b/installation_guides/installing_sqream_with_binary.rst @@ -0,0 +1,279 @@ +.. _installing_sqream_with_binary: + +********************************************* +Installing SQream Using Binary Packages +********************************************* +This procedure describes how to install SQream using Binary packages and must be done on all servers. + +**To install SQream using Binary packages:** + +1. Copy the SQream package to the **/home/sqream** directory for the current version: + + .. code-block:: console + + $ tar -xf sqream-db-v<2020.2>.tar.gz + +2. Append the version number to the name of the SQream folder. The version number in the following example is **v2020.2**: + + .. code-block:: console + + $ mv sqream sqream-db-v<2020.2> + +3. Move the new version of the SQream folder to the **/usr/local/** directory: + + .. code-block:: console + + $ sudo mv sqream-db-v<2020.2> /usr/local/ + +4. Change the ownership of the folder to **sqream folder**: + + .. code-block:: console + + $ sudo chown -R sqream:sqream /usr/local/sqream-db-v<2020.2> + +5. Navigate to the **/usr/local/** directory and create a symbolic link to SQream: + + .. code-block:: console + + $ cd /usr/local + $ sudo ln -s sqream-db-v<2020.2> sqream + +6. Verify that the symbolic link that you created points to the folder that you created: + + .. code-block:: console + + $ ls -l + +7. Verify that the symbolic link that you created points to the folder that you created: + + .. code-block:: console + + $ sqream -> sqream-db-v<2020.2> + +8. Create the SQream configuration file destination folders and set their ownership to **sqream**: + + .. code-block:: console + + $ sudo mkdir /etc/sqream + $ sudo chown -R sqream:sqream /etc/sqream + +9. Create the SQream service log destination folders and set their ownership to **sqream**: + + .. code-block:: console + + $ sudo mkdir /var/log/sqream + $ sudo chown -R sqream:sqream /var/log/sqream + +10. Navigate to the **/usr/local/** directory and copy the SQream configuration files from them: + + .. code-block:: console + + $ cd /usr/local/sqream/etc/ + $ cp * /etc/sqream + +The configuration files are **service configuration files**, and the JSON files are **SQream configuration files**, for a total of four files. The number of SQream configuration files and JSON files must be identical. + +**NOTICE** - Verify that the JSON files have been configured correctly and that all required flags have been set to the correct values. + +In each JSON file, the following parameters **must be updated**: + +* instanceId +* machineIP +* metadataServerIp +* spoolMemoryGB +* limitQueryMemoryGB +* gpu +* port +* ssl_port + +Note the following: + +* The value of the **metadataServerIp** parameter must point to the IP that the metadata is running on. +* The value of the **machineIP** parameter must point to the IP of your local machine. + +It would be same on server running metadataserver and different on other server nodes. + +11. **Optional** - To run additional SQream services, copy the required configuration files and create additional JSON files: + + .. code-block:: console + + $ cp sqream2_config.json sqream3_config.json + $ vim sqream3_config.json + +**NOTICE:** A unique **instanceID** must be used in each JSON file. IN the example above, the instanceID **sqream_2** is changed to **sqream_3**. + +12. **Optional** - If you created additional services in **Step 11**, verify that you have also created their additional configuration files: + + .. code-block:: console + + $ cp sqream2-service.conf sqream3-service.conf + $ vim sqream3-service.conf + +13. For each SQream service configuration file, do the following: + + 1. Change the **SERVICE_NAME=sqream2** value to **SERVICE_NAME=sqream3**. + + 2. Change **LOGFILE=/var/log/sqream/sqream2.log** to **LOGFILE=/var/log/sqream/sqream3.log**. + +**NOTE:** If you are running SQream on more than one server, you must configure the ``serverpicker`` and ``metadatserver`` services to start on only one of the servers. If **metadataserver** is running on the first server, the ``metadataServerIP`` value in the second server's /etc/sqream/sqream1_config.json file must point to the IP of the server on which the ``metadataserver`` service is running. + +14. Set up **servicepicker**: + + 1. Do the following: + + .. code-block:: console + + $ vim /etc/sqream/server_picker.conf + + 2. Change the IP **127.0.0.1** to the IP of the server that the **metadataserver** service is running on. + + 3. Change the **CLUSTER** to the value of the cluster path. + +15. Set up your service files: + + .. code-block:: console + + $ cd /usr/local/sqream/service/ + $ cp sqream2.service sqream3.service + $ vim sqream3.service + +16. Increment each **EnvironmentFile=/etc/sqream/sqream2-service.conf** configuration file for each SQream service file, as shown below: + + .. code-block:: console + + $ EnvironmentFile=/etc/sqream/sqream<3>-service.conf + +17. Copy and register your service files into systemd: + + .. code-block:: console + + $ sudo cp metadataserver.service /usr/lib/systemd/system/ + $ sudo cp serverpicker.service /usr/lib/systemd/system/ + $ sudo cp sqream*.service /usr/lib/systemd/system/ + +18. Verify that your service files have been copied into systemd: + + .. code-block:: console + + $ ls -l /usr/lib/systemd/system/sqream* + $ ls -l /usr/lib/systemd/system/metadataserver.service + $ ls -l /usr/lib/systemd/system/serverpicker.service + $ sudo systemctl daemon-reload + +19. Copy the license into the **/etc/license** directory: + + .. code-block:: console + + $ cp license.enc /etc/sqream/ + + +If you have an HDFS environment, see :ref:`Configuring an HDFS Environment for the User sqream `. + + + + + + +Upgrading SQream Version +------------------------- +Upgrading your SQream version requires stopping all running services while you manually upgrade SQream. + +**To upgrade your version of SQream:** + +1. Stop all actively running SQream services. + +**Notice-** All SQream services must remain stopped while the upgrade is in process. Ensuring that SQream services remain stopped depends on the tool being used. + +For an example of stopping actively running SQream services, see :ref:`Launching SQream with Monit `. + + + +2. Verify that SQream has stopped listening on ports **500X**, **510X**, and **310X**: + + .. code-block:: console + + $ sudo netstat -nltp #to make sure sqream stopped listening on 500X, 510X and 310X ports. + +3. Replace the old version ``sqream-db-v2020.2``, with the new version ``sqream-db-v2021.1``: + + .. code-block:: console + + $ cd /home/sqream + $ mkdir tempfolder + $ mv sqream-db-v2021.1.tar.gz tempfolder/ + $ tar -xf sqream-db-v2021.1.tar.gz + $ sudo mv sqream /usr/local/sqream-db-v2021.1 + $ cd /usr/local + $ sudo chown -R sqream:sqream sqream-db-v2021.1 + +4. Remove the symbolic link: + + .. code-block:: console + + $ sudo rm sqream + +5. Create a new symbolic link named "sqream" pointing to the new version: + + .. code-block:: console + + $ sudo ln -s sqream-db-v2021.1 sqream + +6. Verify that the symbolic SQream link points to the real folder: + + .. code-block:: console + + $ ls -l + + The following is an example of the correct output: + + .. code-block:: console + + $ sqream -> sqream-db-v2021.1 + +7. **Optional-** (for major versions) Upgrade your version of SQream storage cluster, as shown in the following example: + + .. code-block:: console + + $ cat /etc/sqream/sqream1_config.json |grep cluster + $ ./upgrade_storage + + The following is an example of the correct output: + + .. code-block:: console + + get_leveldb_version path{} + current storage version 23 + upgrade_v24 + upgrade_storage to 24 + upgrade_storage to 24 - Done + upgrade_v25 + upgrade_storage to 25 + upgrade_storage to 25 - Done + upgrade_v26 + upgrade_storage to 26 + upgrade_storage to 26 - Done + validate_leveldb + ... + upgrade_v37 + upgrade_storage to 37 + upgrade_storage to 37 - Done + validate_leveldb + storage has been upgraded successfully to version 37 + +8. Verify that the latest version has been installed: + + .. code-block:: console + + $ ./sqream sql --username sqream --password sqream --host localhost --databasename master -c "SELECT SHOW_VERSION();" + + The following is an example of the correct output: + + .. code-block:: console + + v2021.1 + 1 row + time: 0.050603s + +For more information, see the `upgrade_storage `_ command line program. + +For more information about installing Studio on a stand-alone server, see `Installing Studio on a Stand-Alone Server `_. \ No newline at end of file diff --git a/installation_guides/installing_sqream_with_kubernetes.rst b/installation_guides/installing_sqream_with_kubernetes.rst new file mode 100644 index 000000000..093f21ba3 --- /dev/null +++ b/installation_guides/installing_sqream_with_kubernetes.rst @@ -0,0 +1,1805 @@ +.. _installing_sqream_with_kubernetes: + +********************************************* +Installing SQream with Kubernetes +********************************************* +**Kubernetes**, also known as **k8s**, is a portable open source platform that automates Linux container operations. Kubernetes supports outsourcing data centers to public cloud service providers or can be scaled for web hosting. SQream uses Kubernetes as an orchestration and recovery solution. + +The **Installing SQream with Kubernetes** guide describes the following: + +.. contents:: + :local: + :depth: 1 + +.. _preparing_sqream_environment: + +Preparing the SQream Environment to Launch SQream Using Kubernetes +=============== + +The **Preparing the SQream environment to Launch SQream Using Kubernetes** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +-------------- + +A minimum of three servers is required for preparing the SQream environment using Kubernetes. + +Kubernetes uses clusters, which are sets of nodes running containterized applications. A cluster consists of at least two GPU nodes and one additional server without GPU to act as the quorum manager. + +Each server must have the following IP addresses: + +* An IP address located in the management network. +* An additional IP address from the same subnet to function as a floating IP. + +All servers must be mounted in the same shared storage folder. + +The following list shows the server host name format requirements: + +* A maximum of 253 characters. +* Only lowercase alphanumeric characters, such as ``-`` or ``.``. +* Starts and ends with alphanumeric characters. + +Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes` + + +Operating System Requirements +------------------------------ +The required operating system is a version of x86 CentOS/RHEL between 7.6 and 7.9. Regarding PPC64le, the required version is RHEL 7.6. + +Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes` + + +Compute Server Specifications +------------------------------ +Installing SQream with Kubernetes includes the following compute server specifications: + +* **CPU:** 4 cores +* **RAM:** 16GB +* **HD:** 500GB + +Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes` + +.. _set_up_your_hosts: + +Setting Up Your Hosts +=============================== +SQream requires you to set up your hosts. Setting up your hosts requires the following: + +.. contents:: + :local: + :depth: 1 + +Configuring the Hosts File +-------------------------------- +**To configure the /etc/hosts file:** + +1. Edit the **/etc/hosts** file: + + .. code-block:: console + + $ sudo vim /etc/hosts + +2. Call your local host: + + .. code-block:: console + + $ 127.0.0.1 localhost + $ + + +Installing the Required Packages +---------------------------------- +The first step in setting up your hosts is to install the required packages. + +**To install the required packages:** + +1. Run the following command based on your operating system: + + * RHEL: + + .. code-block:: postgres + + $ sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + + * CentOS: + + .. code-block:: postgres + + $ sudo yum install epel-release + $ sudo yum install pciutils openssl-devel python36 python36-pip kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc jq net-tools ntp + +2. Verify that that the required packages were successfully installed. The following is the correct output: + + .. code-block:: postgres + + ntpq --version + jq --version + python3 --version + pip3 --version + rpm -qa |grep kernel-devel-$(uname -r) + rpm -qa |grep kernel-headers-$(uname -r) + gcc --version + +3. Enable the **ntpd (Network Time Protocol daemon)** program on all servers: + + .. code-block:: postgres + + $ sudo systemctl start ntpd + $ sudo systemctl enable ntpd + $ sudo systemctl status ntpd + $ sudo ntpq -p + +Go back to :ref:`Setting Up Your Hosts` + + +Disabling the Linux UI +---------------------------------- +After installing the required packages, you must disable the Linux UI if it has been installed. + +You can disable Linux by running the following command: + + .. code-block:: postgres + + $ sudo systemctl set-default multi-user.target + +Go back to :ref:`Setting Up Your Hosts` + + +Disabling SELinux +---------------------------------- +After disabling the Linux UI you must disable SELinux. + +**To disable SELinux:** + + 1. Run the following command: + + .. code-block:: postgres + + $ sed -i -e s/enforcing/disabled/g /etc/selinux/config + $ sudo reboot + + 2. Reboot the system as a root user: + + .. code-block:: postgres + + $ sudo reboot + +Go back to :ref:`Setting Up Your Hosts` + +Disabling Your Firewall +---------------------------------- +After disabling SELinux, you must disable your firewall by running the following commands: + + .. code-block:: postgres + + $ sudo systemctl stop firewalld + $ sudo systemctl disable firewalld + +Go back to :ref:`Setting Up Your Hosts` + + +Checking the CUDA Version +---------------------------------- +After completing all of the steps above, you must check the CUDA version. + +**To check the CUDA version:** + +1. Check the CUDA version: + + .. code-block:: postgres + + $ nvidia-smi + + The following is an example of the correct output: + + .. code-block:: postgres + + $ +-----------------------------------------------------------------------------+ + $ | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + $ |-------------------------------+----------------------+----------------------+ + $ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + $ | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + $ |===============================+======================+======================| + $ | 0 GeForce GTX 105... Off | 00000000:01:00.0 Off | N/A | + $ | 32% 38C P0 N/A / 75W | 0MiB / 4039MiB | 0% Default | + $ +-------------------------------+----------------------+----------------------+ + $ + $ +-----------------------------------------------------------------------------+ + $ | Processes: GPU Memory | + $ | GPU PID Type Process name Usage | + $ |=============================================================================| + $ | No running processes found | + $ +-----------------------------------------------------------------------------+ + +In the above output, the CUDA version is **10.1**. + +If the above output is not generated, CUDA has not been installed. To install CUDA, see `Installing the CUDA driver `_. + + +Go back to :ref:`Setting Up Your Hosts` + +.. _install_kubernetes_cluster: + +Installing Your Kubernetes Cluster +=================================== +After setting up your hosts, you must install your Kubernetes cluster. The Kubernetes and SQream software must be installed from the management host, and can be installed on any server in the cluster. + +Installing your Kubernetes cluster requires the following: + +.. contents:: + :local: + :depth: 1 + +Generating and Sharing SSH Keypairs Across All Existing Nodes +------------------------------------ +You can generate and share SSH keypairs across all existing nodes. Sharing SSH keypairs across all nodes enables passwordless access from the management server to all nodes in the cluster. All nodes in the cluster require passwordless access. + +.. note:: You must generate and share an SSH keypair across all nodes even if you are installing the Kubernetes cluster on a single host. + +**To generate and share an SSH keypair:** + +1. Switch to root user access: + + .. code-block:: postgres + + $ sudo su - + +2. Generate an RSA key pair: + + .. code-block:: postgres + + $ ssh-keygen + +The following is an example of the correct output: + + .. code-block:: postgres + + $ ssh-keygen + $ Generating public/private rsa key pair. + $ Enter file in which to save the key (/root/.ssh/id_rsa): + $ Created directory '/root/.ssh'. + $ Enter passphrase (empty for no passphrase): + $ Enter same passphrase again: + $ Your identification has been saved in /root/.ssh/id_rsa. + $ Your public key has been saved in /root/.ssh/id_rsa.pub. + $ The key fingerprint is: + $ SHA256:xxxxxxxxxxxxxxdsdsdffggtt66gfgfg root@localhost.localdomain + $ The key's randomart image is: + $ +---[RSA 2048]----+ + $ | =*. | + $ | .o | + $ | ..o o| + $ | . .oo +.| + $ | = S =...o o| + $ | B + *..o+.| + $ | o * *..o .+| + $ | o * oo.E.o| + $ | . ..+..B.+o| + $ +----[SHA256]-----+ + +The generated file is ``/root/.ssh/id_rsa.pub``. + +3. Copy the public key to all servers in the cluster, including the one that you are running on. + + .. code-block:: postgres + + $ ssh-copy-id -i ~/.ssh/id_rsa.pub root@remote-host + +4. Replace the ``remote host`` with your host IP address. + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Installing and Deploying a Kubernetes Cluster Using Kubespray +------------------------------------ +SQream uses the Kubespray software package to install and deploy Kubernetes clusters. + +**To install and deploy a Kubernetes cluster using Kubespray:** + + +1. Clone Kubernetes: + + 1. Clone the **kubespray.git** repository: + + .. code-block:: postgres + + $ git clone https://github.com/kubernetes-incubator/kubespray.git + + 2. Nagivate to the **kubespray** directory: + + .. code-block:: postgres + + $ cd kubespray + + 3. Install the **requirements.txt** configuration file: + + .. code-block:: postgres + + $ pip3 install -r requirements.txt + +2. Create your SQream inventory directory: + + 1. Run the following command: + + .. code-block:: postgres + + $ cp -rp inventory/sample inventory/sqream + + 2. Replace the **** with the defined cluster node IP address(es). + + .. code-block:: postgres + + $ declare -a IPS=(, ) + + For example, the following replaces ``192.168.0.93`` with ``192.168.0.92``: + + .. code-block:: postgres + + $ declare -a IPS=(host-93,192.168.0.93 host-92,192.168.0.92) + +Note the following: + * Running a declare requires defining a pair (host name and cluster node IP address), as shown in the above example. + * You can define more than one pair. + +3. When the reboot is complete, switch back to the root user: + + .. code-block:: postgres + + $ sudo su - + +4. Navigate to **root/kubespray**: + + .. code-block:: postgres + + $ cd /root/kubespray + +5. Copy ``inventory/sample`` as ``inventory/sqream``: + + .. code-block:: postgres + + $ cp -rfp inventory/sample inventory/sqream + +6. Update the Ansible inventory file with the inventory builder: + + .. code-block:: postgres + + $ declare -a IPS=(, , ,) + +7. In the **kubespray hosts.yml** file, set the node IP's: + + .. code-block:: postgres + + $ CONFIG_FILE=inventory/sqream/hosts.yml python3 contrib/inventory_builder/inventory.py ${IPS[@]} + + If you do not set a specific hostname in declare, the server hostnames will change to ``node1``, ``node2``, etc. To maintain specific hostnames, run declare as in the following example: + + .. code-block:: postgres + + $ declare -a IPS=(eks-rhl-1,192.168.5.81 eks-rhl-2,192.168.5.82 eks-rhl-3,192.168.5.83) + + Note that the declare must contain pairs (hostname,ip). + +:: + +8. Verify that the following have been done: + + * That the **hosts.yml** file is configured correctly. + * That all children are included with their relevant nodes. + +You can save your current server hostname by replacing with your server hostname. + +9. Generate the content output of the **hosts.yml** file. Make sure to include the file's directory: + + .. code-block:: postgres + + $ cat inventory/sqream/hosts.yml + +The hostname can be lowercase and contain ``-`` or ``.`` only, and must be aligned with the server's hostname. + +The following is an example of the correct output. Each host and IP address that you provided in Step 2 should be displayed once: + + .. code-block:: postgres + + $ all: + $ hosts: + $ node1: + $ ansible_host: 192.168.5.81 + $ ip: 192.168.5.81 + $ access_ip: 192.168.5.81 + $ node2: + $ ansible_host: 192.168.5.82 + $ ip: 192.168.5.82 + $ access_ip: 192.168.5.82 + $ node3: + $ ansible_host: 192.168.5.83 + $ ip: 192.168.5.83 + $ access_ip: 192.168.5.83 + $ children: + $ kube-master: + $ hosts: + $ node1: + $ node2: + $ node3: + $ kube-node: + $ hosts: + $ node1: + $ node2: + $ node3: + $ etcd: + $ hosts: + $ node1: + $ node2: + $ node3: + $ k8s-cluster: + $ children: + $ kube-master: + $ kube-node: + $ calico-rr: + $ hosts: {} + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Adjusting Kubespray Deployment Values +------------------------------------- +After downloading and configuring Kubespray, you can adjust your Kubespray deployment values. A script is used to modify how the Kubernetes cluster is deployed, and you must set the cluster name variable before running this script. + +.. note:: The script must be run from the **kubespray** folder. + +**To adjust Kubespray deployment values:** + +1. Add the following export to the local user’s **~/.bashrc** file by replacing the with the user's Virtual IP address: + + .. code-block:: postgres + + $ export VIP_IP= + +2. Logout, log back in, and verify the following: + + .. code-block:: postgres + + $ echo $VIP_IP + +3. Make the following replacements to the **kubespray.settings.sh** file: + + .. code-block:: postgres + + $ cat < kubespray_settings.sh + $ sed -i "/cluster_name: cluster.local/c \cluster_name: cluster.local.$cluster_name" inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ sed -i "/dashboard_enabled/c \dashboard_enabled\: "false"" inventory/sqream/group_vars/k8s-cluster/addons.yml + $ sed -i "/kube_version/c \kube_version\: "v1.18.3"" inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ sed -i "/metrics_server_enabled/c \metrics_server_enabled\: "true"" inventory/sample/group_vars/k8s-cluster/addons.yml + $ echo 'kube_apiserver_node_port_range: "3000-6000"' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'kube_controller_node_monitor_grace_period: 20s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'kube_controller_node_monitor_period: 2s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'kube_controller_pod_eviction_timeout: 30s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'kubelet_status_update_frequency: 4s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml + $ echo 'ansible ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers + $ EOF + +.. note:: In most cases, the Docker data resides on the system disk. Because Docker requires a high volume of data (images, containers, volumes, etc.), you can change the default Docker data location to prevent the system disk from running out of space. + +4. *Optional* - Change the default Docker data location: + + .. code-block:: postgres + + $ sed -i "/docker_daemon_graph/c \docker_daemon_graph\: """ inventory/sqream/group_vars/all/docker.yml + +5. Make the **kubespray_settings.sh** file executable for your user: + + .. code-block:: postgres + + $ chmod u+x kubespray_settings.sh && ./kubespray_settings.sh + +6. Run the following script: + + .. code-block:: postgres + + $ ./kubespray_settings.sh + +7. Run a playbook on the **inventory/sqream/hosts.yml cluster.yml** file: + + .. code-block:: postgres + + $ ansible-playbook -i inventory/sqream/hosts.yml cluster.yml -v + +The Kubespray installation takes approximately 10 - 15 minutes. + +The following is an example of the correct output: + + .. code-block:: postgres + + $ PLAY RECAP + $ ********************************************************************************************* + $ node-1             : ok=680  changed=133  unreachable=0    failed=0 + $ node-2             : ok=583  changed=113  unreachable=0    failed=0 + $ node-3             : ok=586  changed=115  unreachable=0    failed=0 + $ localhost          : ok=1    changed=0    unreachable=0    failed=0 + +In the event that the output is incorrect, or a failure occurred during the installation, please contact a SQream customer support representative. + +Go back to :ref:`Installing Your Kubernetes Cluster`. + +Checking Your Kubernetes Status +------------------------------- +After adjusting your Kubespray deployment values, you must check your Kubernetes status. + +**To check your Kuberetes status:** + +1. Check the status of the node: + + .. code-block:: postgres + + $ kubectl get nodes + +The following is an example of the correct output: + + .. code-block:: postgres + + $ NAME STATUS ROLES AGE VERSION + $ eks-rhl-1 Ready control-plane,master 29m v1.21.1 + $ eks-rhl-2 Ready control-plane,master 29m v1.21.1 + $ eks-rhl-3 Ready 28m v1.21.1 + +2. Check the status of the pod: + + .. code-block:: postgres + + $ kubectl get pods --all-namespaces + + The following is an example of the correct output: + + .. code-block:: postgres + + $ NAMESPACE NAME READY STATUS RESTARTS AGE + $ kube-system calico-kube-controllers-68dc8bf4d5-n9pbp 1/1 Running 0 160m + $ kube-system calico-node-26cn9 1/1 Running 1 160m + $ kube-system calico-node-kjsgw 1/1 Running 1 160m + $ kube-system calico-node-vqvc5 1/1 Running 1 160m + $ kube-system coredns-58687784f9-54xsp 1/1 Running 0 160m + $ kube-system coredns-58687784f9-g94xb 1/1 Running 0 159m + $ kube-system dns-autoscaler-79599df498-hlw8k 1/1 Running 0 159m + $ kube-system kube-apiserver-k8s-host-1-134 1/1 Running 0 162m + $ kube-system kube-apiserver-k8s-host-194 1/1 Running 0 161m + $ kube-system kube-apiserver-k8s-host-68 1/1 Running 0 161m + $ kube-system kube-controller-manager-k8s-host-1-134 1/1 Running 0 162m + $ kube-system kube-controller-manager-k8s-host-194 1/1 Running 0 161m + $ kube-system kube-controller-manager-k8s-host-68 1/1 Running 0 161m + $ kube-system kube-proxy-5f42q 1/1 Running 0 161m + $ kube-system kube-proxy-bbwvk 1/1 Running 0 161m + $ kube-system kube-proxy-fgcfb 1/1 Running 0 161m + $ kube-system kube-scheduler-k8s-host-1-134 1/1 Running 0 161m + $ kube-system kube-scheduler-k8s-host-194 1/1 Running 0 161m + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Adding a SQream Label to Your Kubernetes Cluster Nodes +------------------------------------------------- +After checking your Kubernetes status, you must add a SQream label on your Kubernetes cluster nodes. + +**To add a SQream label on your Kubernetes cluster nodes:** + +1. Get the cluster node list: + + .. code-block:: postgres + + $ kubectl get nodes + + The following is an example of the correct output: + + .. code-block:: postgres + + $ NAME        STATUS   ROLES    AGE   VERSION + $ eks-rhl-1 Ready control-plane,master 29m v1.21.1 + $ eks-rhl-2 Ready control-plane,master 29m v1.21.1 + $ eks-rhl-3 Ready 28m v1.21.1 + +2. Set the node label, change the ``node-name`` to the node NAME(s) in the above example: + + .. code-block:: postgres + + $ kubectl label nodes cluster=sqream + + The following is an example of the correct output: + + .. code-block:: postgres + + $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-1 cluster=sqream + $ node/eks-rhl-1 labeled + $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-2 cluster=sqream + $ node/eks-rhl-2 labeled + $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-3 cluster=sqream + $ node/eks-rhl-3 labeled + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Copying Your Kubernetes Configuration API File to the Master Cluster Nodes +------------------------------------------------- +After adding a SQream label on your Kubernetes cluster nodes, you must copy your Kubernetes configuration API file to your Master cluster nodes. + +When the Kubernetes cluster installation is complete, an API configuration file is automatically created in the **.kube** folder of the root user. This file enables the **kubectl** command access Kubernetes' internal API service. Following this step lets you run **kubectl** commands from any node in the cluster. + + +.. warning:: You must perform this on the management server only! + +**To copy your Kubernetes configuration API file to your Master cluster nodes:** + +1. Create the **.kube** folder in the **local user** directory: + + .. code-block:: postgres + + $ mkdir /home//.kube + +2. Copy the configuration file from the root user directory to the directory: + + .. code-block:: postgres + + $ sudo cp /root/.kube/config /home//.kube + +3. Change the file owner from **root user** to the : + + .. code-block:: postgres + + $ sudo chown . /home//.kube/config + +4. Create the **.kube** folder in the other nodes located in the directory: + + .. code-block:: postgres + + $ ssh @ mkdir .kube + +5. Copy the configuration file from the management node to the other nodes: + + .. code-block:: postgres + + $ scp /home//.kube/config @:/home//.kube/ + +6. Under local user on each server you copied **.kube** to, run the following command: + + .. code-block:: postgres + + $ sudo usermod -aG docker $USER + +This grants the local user the necessary permissions to run Docker commands. + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Creating an env_file in Your Home Directory +------------------------------------------------- +After copying your Kubernetes configuration API file to your Master cluster nodes, you must create an **env_file** in your home directory, and must set the VIP address as a variable. + +.. warning:: You must perform this on the management server only! + + + +**To create an env_file for local users in the user's home directory:** + +1. Set a variable that includes the VIP IP address: + + .. code-block:: postgres + + $ export VIP_IP= + +.. note:: If you use Kerberos, replace the ``KRB5_SERVER`` value with the IP address of your Kerberos server. + +2. Do one of the following: + + * For local users: + + .. code-block:: postgres + + $ mkdir /home/$USER/.sqream + +3. Make the following replacements to the **kubespray.settings.sh** file, verifying that the ``KRB5_SERVER`` parameter is set to your server IP: + + + .. code-block:: postgres + + $ cat < /home/$USER/.sqream/env_file + SQREAM_K8S_VIP=$VIP_IP + SQREAM_ADMIN_UI_PORT=8080 + SQREAM_DASHBOARD_DATA_COLLECTOR_PORT=8100 + SQREAM_DATABASE_NAME=master + SQREAM_K8S_ADMIN_UI=sqream-admin-ui + SQREAM_K8S_DASHBOARD_DATA_COLLECTOR=dashboard-data-collector + SQREAM_K8S_METADATA=sqream-metadata + SQREAM_K8S_NAMESPACE=sqream + SQREAM_K8S_PICKER=sqream-picker + SQREAM_K8S_PROMETHEUS=prometheus + SQREAM_K8S_REGISTRY_PORT=6000 + SQREAM_METADATA_PORT=3105 + SQREAM_PICKER_PORT=3108 + SQREAM_PROMETHEUS_PORT=9090 + SQREAM_SPOOL_MEMORY_RATIO=0.25 + SQREAM_WORKER_0_PORT=5000 + KRB5CCNAME=FILE:/tmp/tgt + KRB5_SERVER=kdc.sq.com:1 + KRB5_CONFIG_DIR=${ $ SQREAM_MOUNT_DIR}/krb5 + KRB5_CONFIG_FILE=${KRB5_CONFIG_DIR}/krb5.conf + HADOOP_CONFIG_DIR=${ $ SQREAM_MOUNT_DIR}/hadoop + HADOOP_CORE_XML=${HADOOP_CONFIG_DIR}/core-site.xml + HADOOP_HDFS_XML=${HADOOP_CONFIG_DIR}/hdfs-site.xml + EOF + +Go back to :ref:`Installing Your Kubernetes Cluster` + + + + + +Creating a Base Kubernetes Namespace +------------------------------------ +After creating an env_file in the user's home directory, you must create a base Kubernetes namespace. + +You can create a Kubernetes namespace by running the following command: + +.. code-block:: postgres + + $ kubectl create namespace sqream-init + +The following is an example of the correct output: + +.. code-block:: postgres + + $ namespace/sqream-init created + +Go back to :ref:`Installing Your Kubernetes Cluster` + + +Pushing the **env_file** File to the Kubernetes Configmap +-------------------------------------- +After creating a base Kubernetes namespace, you must push the **env_file** to the Kubernetes configmap. You must push the **env_file** file to the Kubernetes **configmap** in the **sqream-init** namespace. + +This is done by running the following command: + +.. code-block:: postgres + + $ kubectl create configmap sqream-init -n sqream-init --from-env-file=/home/$USER/.sqream/env_file + +The following is an example of the correct output: + +.. code-block:: postgres + + $ configmap/sqream-init created + + +Go back to :ref:`Installing Your Kubernetes Cluster` + + +Installing the NVIDIA Docker2 Toolkit +------------------------------------- +After pushing the **env_file** file to the Kubernetes configmap, you must install the NVIDIA Docker2 Toolkit. The **NVIDIA Docker2 Toolkit** lets users build and run GPU-accelerated Docker containers, and must be run only on GPU servers. The NVIDIA Docker2 Toolkit includes a container runtime library and utilities that automatically configure containers to leverage NVIDIA GPUs. + + +Installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on CentOS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +**To install the NVIDIA Docker2 Toolkit on an x86_64 bit processor on CentOS:** + +1. Add the repository for your distribution: + + .. code-block:: postgres + + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ + $ sudo tee /etc/yum.repos.d/nvidia-docker.repo + +2. Install the **nvidia-docker2** package and reload the Docker daemon configuration: + + .. code-block:: postgres + + $ sudo yum install nvidia-docker2 + $ sudo pkill -SIGHUP dockerd + +3. Verify that the **nvidia-docker2** package has been installed correctly: + + .. code-block:: postgres + + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + + The following is an example of the correct output: + + .. code-block:: postgres + + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + $ Unable to find image 'nvidia/cuda:10.1-base' locally + $ 10.1-base: Pulling from nvidia/cuda + $ d519e2592276: Pull complete + $ d22d2dfcfa9c: Pull complete + $ b3afe92c540b: Pull complete + $ 13a10df09dc1: Pull complete + $ 4f0bc36a7e1d: Pull complete + $ cd710321007d: Pull complete + $ Digest: sha256:635629544b2a2be3781246fdddc55cc1a7d8b352e2ef205ba6122b8404a52123 + $ Status: Downloaded newer image for nvidia/cuda:10.1-base + $ Sun Feb 14 13:27:58 2021 + $ +-----------------------------------------------------------------------------+ + $ | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + $ |-------------------------------+----------------------+----------------------+ + $ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + $ | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + $ |===============================+======================+======================| + $ | 0 GeForce GTX 105... Off | 00000000:01:00.0 Off | N/A | + $ | 32% 37C P0 N/A / 75W | 0MiB / 4039MiB | 0% Default | + $ +-------------------------------+----------------------+----------------------+ + $ + $ +-----------------------------------------------------------------------------+ + $ | Processes: GPU Memory | + $ | GPU PID Type Process name Usage | + $ |=============================================================================| + $ | No running processes found | + $ +-----------------------------------------------------------------------------+ + +For more information on installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on CentOS, see `NVIDIA Docker Installation - CentOS distributions `_ + +Installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on Ubuntu +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +**To install the NVIDIA Docker2 Toolkit on an x86_64 bit processor on Ubuntu:** + +1. Add the repository for your distribution: + + .. code-block:: postgres + + $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \ + $ sudo apt-key add - + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \ + $ sudo tee /etc/apt/sources.list.d/nvidia-docker.list + $ sudo apt-get update + +2. Install the **nvidia-docker2** package and reload the Docker daemon configuration: + + .. code-block:: postgres + + $ sudo apt-get install nvidia-docker2 + $ sudo pkill -SIGHUP dockerd + +3. Verify that the nvidia-docker2 package has been installed correctly: + + .. code-block:: postgres + + $ docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi + +For more information on installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on Ubuntu, see `NVIDIA Docker Installation - Ubuntu distributions `_ + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Modifying the Docker Daemon JSON File for GPU and Compute Nodes +------------------------------------- +After installing the NVIDIA Docker2 toolkit, you must modify the Docker daemon JSON file for GPU and Compute nodes. + +Modifying the Docker Daemon JSON File for GPU Nodes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**To modify the Docker daemon JSON file for GPU nodes:** + +1. Enable GPU and set HTTP access to the local Kubernetes Docker registry. + +.. note:: The Docker daemon JSON file must be modified on all GPU nodes. + +.. note:: Contact your IT department for a virtual IP. + +2. Replace the ``VIP address`` with your assigned VIP address. + +:: + +3. Connect as a root user: + + .. code-block:: postgres + + $ sudo -i + +4. Set a variable that includes the VIP address: + + .. code-block:: postgres + + $ export VIP_IP= + +5. Replace the with the VIP address:  + + .. code-block:: postgres + + $ cat < /etc/docker/daemon.json + $ { + $ "insecure-registries": ["$VIP_IP:6000"], + $ "default-runtime": "nvidia", + $ "runtimes": { + $ "nvidia": { + $ "path": "nvidia-container-runtime", + $ "runtimeArgs": [] + $ } + $ } + $ } + $ EOF + +6. Apply the changes and restart Docker: + + .. code-block:: postgres + + $ systemctl daemon-reload && systemctl restart docker + +7. Exit the root user: + + .. code-block:: postgres + + $ exit + +Go back to :ref:`Installing Your Kubernetes Cluster` + + +Modifying the Docker Daemon JSON File for Compute Nodes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You must follow this procedure only if you have a Compute node. + +**To modify the Docker daemon JSON file for Compute nodes:** + +1. Switch to a root user: + + .. code-block:: postgres + + $ sudo -i + +2. Set a variable that includes a VIP address. + +.. note:: Contact your IT department for a virtual IP. + +3. Replace the ``VIP address`` with your assigned VIP address. + + .. code-block:: postgres + + $ cat < /etc/docker/daemon.json + $ { + $ "insecure-registries": ["$VIP_IP:6000"] + $ } + $ EOF + +4. Restart the services: + + .. code-block:: postgres + + $ systemctl daemon-reload && systemctl restart docker + +5. Exit the root user: + + + .. code-block:: postgres + + $ exit + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Installing the Nvidia-device-plugin Daemonset +---------------------------------------------- +After modifying the Docker daemon JSON file for GPU or Compute Nodes, you must installing the Nvidia-device-plugin daemonset. The Nvidia-device-plugin daemonset is only relevant to GPU nodes. + +**To install the Nvidia-device-plugin daemonset:** + +1. Set ``nvidia.com/gpu`` to ``true`` on all GPU nodes: + +.. code-block:: postgres + + $ kubectl label nodes nvidia.com/gpu=true + +2. Replace the ** with your GPU node name: + + For a complete list of GPU node names, run the ``kubectl get nodes`` command. + + The following is an example of the correct output: + + .. code-block:: postgres + + $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-1 nvidia.com/gpu=true + $ node/eks-rhl-1 labeled + $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-2 nvidia.com/gpu=true + $ node/eks-rhl-2 labeled + $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-3 nvidia.com/gpu=true + $ node/eks-rhl-3 labeled + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Creating an Nvidia Device Plugin +---------------------------------------------- +After installing the Nvidia-device-plugin daemonset, you must create an Nvidia-device-plugin. You can create an Nvidia-device-plugin by running the following command + +.. code-block:: postgres + + $ kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/1.0.0-beta6/nvidia-device-plugin.yml + +If needed, you can check the status of the Nvidia-device-plugin-daemonset pod status: + +.. code-block:: postgres + + $ kubectl get pods -n kube-system -o wide | grep nvidia-device-plugin + +The following is an example of the correct output: + +.. code-block:: postgres + + $ NAME READY STATUS RESTARTS AGE + $ nvidia-device-plugin-daemonset-fxfct 1/1 Running 0 6h1m + $ nvidia-device-plugin-daemonset-jdvxs 1/1 Running 0 6h1m + $ nvidia-device-plugin-daemonset-xpmsv 1/1 Running 0 6h1m + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Checking GPU Resources Allocatable to GPU Nodes +------------------------------------- +After creating an Nvidia Device Plugin, you must check the GPU resources alloctable to the GPU nodes. Each GPU node has records, such as ``nvidia.com/gpu: <#>``. The ``#`` indicates the number of allocatable, or available, GPUs in each node. + +You can output a description of allocatable resources by running the following command: + +.. code-block:: postgres + + $ kubectl describe node | grep -i -A 7 -B 2 allocatable: + +The following is an example of the correct output: + +.. code-block:: postgres + + $ Allocatable: + $ cpu: 3800m + $ ephemeral-storage: 94999346224 + $ hugepages-1Gi: 0 + $ hugepages-2Mi: 0 + $ memory: 15605496Ki + $ nvidia.com/gpu: 1 + $ pods: 110 + +Go back to :ref:`Installing Your Kubernetes Cluster` + +Preparing the WatchDog Monitor +------------------------------ +SQream's deployment includes installing two watchdog services. These services monitor Kuberenetes management and the server's storage network. + +You can enable the storage watchdogs by adding entries in the **/etc/hosts** file on each server: + +.. code-block:: postgres + + $
k8s-node1.storage + $
k8s-node2.storage + $
k8s-node3.storage + +The following is an example of the correct syntax: + +.. code-block:: postgres + + $ 10.0.0.1 k8s-node1.storage + $ 10.0.0.2 k8s-node2.storage + $ 10.0.0.3 k8s-node3.storage + +Go back to :ref:`Installing Your Kubernetes Cluster` + +.. _installing_sqream_software: + +Installing the SQream Software +================================= +Once you've prepared the SQream environment for launching it using Kubernetes, you can begin installing the SQream software. + +The **Installing the SQream Software** section describes the following: + +.. contents:: + :local: + :depth: 1 + + +.. _getting_sqream_package: + +Getting the SQream Package +-------------------------------- +The first step in installing the SQream software is getting the SQream package. Please contact the SQream Support team to get the **sqream_k8s-nnn-DBnnn-COnnn-SDnnn-.tar.gz** tarball file. + +This file includes the following values: + +* **sqream_k8s-** - the SQream installer version. +* **DB** - the SQreamDB version. +* **CO** - the SQream console version. +* **SD** - the SQream Acceleration Studio version. +* **arch** - the server architecture. + +You can extract the contents of the tarball by running the following command: + +.. code-block:: postgres + + $ tar -xvf sqream_k8s-1.0.15-DB2020.1.0.2-SD0.7.3-x86_64.tar.gz + $ cd sqream_k8s-1.0.15-DB2020.1.0.2-SD0.7.3-x86_64 + $ ls + +Extracting the contents of the tarball file generates a new folder with the same name as the tarball file. + +The following shows the output of the extracted file: + +.. code-block:: postgres + + drwxrwxr-x. 2 sqream sqream 22 Jan 27 11:39 license + lrwxrwxrwx. 1 sqream sqream 49 Jan 27 11:39 sqream -> .sqream/sqream-sql-v2020.3.1_stable.x86_64/sqream + -rwxrwxr-x. 1 sqream sqream 9465 Jan 27 11:39 sqream-install + -rwxrwxr-x. 1 sqream sqream 12444 Jan 27 11:39 sqream-start + +Go back to :ref:`Installing Your SQream Software` + +Setting Up and Configuring Hadoop +-------------------------------- +After getting the SQream package, you can set up and configure Hadoop by configuring the **keytab** and **krb5.conf** files. + +.. note:: You only need to configure the **keytab** and **krb5.conf** files if you use Hadoop with Kerberos authentication. + + +**To set up and configure Hadoop:** + +1. Contact IT for the **keytab** and **krb5.conf** files. + +:: + +2. Copy both files into the respective empty **.hadoop/** and **.krb5/** directories: + +.. code-block:: postgres + + $ cp hdfs.keytab krb5.conf .krb5/ + $ cp core-site.xml hdfs-site.xml .hadoop/ + +The SQream installer automatically copies the above files during the installation process. + +Go back to :ref:`Installing Your SQream Software` + +Starting a Local Docker Image Registry +-------------------------------- +After getting the SQream package, or (optionally) setting up and configuring Hadoop, you must start a local Docker image registry. Because Kubernetes is based on Docker, you must start the local Docker image registry on the host's shared folder. This allows all hosts to pull the SQream Docker images. + +**To start a local Docker image registry:** + +1. Create a Docker registry folder: + + .. code-block:: postgres + + $ mkdir /docker-registry/ + +2. Set the ``docker_path`` for the Docker registry folder: + + .. code-block:: postgres + + $ export docker_path= + +3. Apply the **docker-registry** service to the cluster: + + .. code-block:: postgres + + $ cat .k8s/admin/docker_registry.yaml | envsubst | kubectl create -f - + + The following is an example of the correct output: + + .. code-block:: postgres + + namespace/sqream-docker-registry created + configmap/sqream-docker-registry-config created + deployment.apps/sqream-docker-registry created + service/sqream-docker-registry created + +4. Check the pod status of the **docker-registry** service: + + .. code-block:: postgres + + $ kubectl get pods -n sqream-docker-registry + +The following is an example of the correct output: + + .. code-block:: postgres + + NAME READY STATUS RESTARTS AGE + sqream-docker-registry-655889fc57-hmg7h 1/1 Running 0 6h40m + +Go back to :ref:`Installing Your SQream Software` + +Installing the Kubernetes Dashboard +-------------------------------- +After starting a local Docker image registry, you must install the Kubernetes dashboard. The Kubernetes dashboard lets you see the Kubernetes cluster, nodes, services, and pod status. + +**To install the Kubernetes dashboard:** + +1. Apply the **k8s-dashboard** service to the cluster: + + .. code-block:: postgres + + $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml + + The following is an example of the correct output: + + .. code-block:: postgres + + namespace/kubernetes-dashboard created + serviceaccount/kubernetes-dashboard created + service/kubernetes-dashboard created + secret/kubernetes-dashboard-certs created + secret/kubernetes-dashboard-csrf created + secret/kubernetes-dashboard-key-holder created + configmap/kubernetes-dashboard-settings created + role.rbac.authorization.k8s.io/kubernetes-dashboard created + clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created + rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created + clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created + deployment.apps/kubernetes-dashboard created + service/dashboard-metrics-scraper created + deployment.apps/dashboard-metrics-scraper created + +2. Grant the user external access to the Kubernetes dashboard: + + .. code-block:: postgres + + $ cat .k8s/admin/kubernetes-dashboard-svc-metallb.yaml | envsubst | kubectl create -f - + + The following is an example of the correct output: + + .. code-block:: postgres + + service/kubernetes-dashboard-nodeport created + +3. Create the ``cluster-admin-sa.yaml`` file: + + .. code-block:: postgres + + $ kubectl create -f .k8s/admin/cluster-admin-sa.yaml + + The following is an example of the correct output: + + .. code-block:: postgres + + clusterrolebinding.rbac.authorization.k8s.io/cluster-admin-sa-cluster-admin created + +4. Check the pod status of the **K8s-dashboard** service: + + .. code-block:: postgres + + $ kubectl get pods -n kubernetes-dashboard + + The following is an example of the correct output: + + .. code-block:: postgres + + NAME READY STATUS RESTARTS AGE + dashboard-metrics-scraper-6b4884c9d5-n8p57 1/1 Running 0 4m32s + kubernetes-dashboard-7b544877d5-qc8b4 1/1 Running 0 4m32s + +5. Obtain the **k8s-dashboard** access token: + + .. code-block:: postgres + + $ kubectl -n kube-system describe secrets cluster-admin-sa-token + + The following is an example of the correct output: + + .. code-block:: postgres + + Name: cluster-admin-sa-token-rbl9p + Namespace: kube-system + Labels: + Annotations: kubernetes.io/service-account.name: cluster-admin-sa + kubernetes.io/service-account.uid: 81866d6d-8ef3-4805-840d-58618235f68d + + Type: kubernetes.io/service-account-token + + Data + ==== + ca.crt: 1025 bytes + namespace: 11 bytes + token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjRMV09qVzFabjhId09oamQzZGFFNmZBeEFzOHp3SlJOZWdtVm5lVTdtSW8ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJjbHVzdGVyLWFkbWluLXNhLXRva2VuLXJibDlwIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImNsdXN0ZXItYWRtaW4tc2EiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI4MTg2NmQ2ZC04ZWYzLTQ4MDUtODQwZC01ODYxODIzNWY2OGQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06Y2x1c3Rlci1hZG1pbi1zYSJ9.mNhp8JMr5y3hQ44QrvRDCMueyjSHSrmqZcoV00ZC7iBzNUqh3n-fB99CvC_GR15ys43jnfsz0tdsTy7VtSc9hm5ENBI-tQ_mwT1Zc7zJrEtgFiA0o_eyfYZOARdhdyFEJg84bzkIxJFPKkBWb4iPWU1Xb7RibuMCjNTarZMZbqzKYfQEcMZWJ5UmfUqp-HahZZR4BNbjSWybs7t6RWdcQZt6sO_rRCDrOeEJlqKKjx4-5jFZB8Du_0kKmnw2YJmmSCEOXrpQCyXIiZJpX08HyDDYfFp8IGzm61arB8HDA9dN_xoWvuz4Cj8klUtTzL9effJJPjHJlZXcEqQc9hE3jw + +6. Navigate to ``https://:5999``. + +:: + +7. Select the **Token** radio button, paste the token from the previous command output, and click **Sign in**. + +The Kubernetes dashboard is displayed. + +Go back to :ref:`Installing Your SQream Software` + +Installing the SQream Prometheus Package +-------------------------------- +After installing the Kubernetes dashboard, you must install the SQream Prometheus package. To properly monitor the host and GPU statistics the **exporter service** must be installed on each Kubernetes cluster node. + +This section describes how to install the following: + +* **node_exporter** - collects host data, such as CPU memory usage. +* **nvidia_exporter** - collects GPU utilization data. + + +.. note:: The steps in this section must be done on **all** cluster nodes. + +To install the **sqream-prometheus** package, you must do the following: + +1. :ref:`Install the exporter service ` + +:: + +2. :ref:`Check the exporter service ` + +Go back to :ref:`Installing Your SQream Software` + + +.. _install_exporter_service: + +Installing the Exporter Service +~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the exporter service:** + +1. Create a user and group that will be used to run the exporter services: + + .. code-block:: console + + $ sudo groupadd --system prometheus && sudo useradd -s /sbin/nologin --system -g prometheus prometheus + +2. Extract the **sqream_exporters_prometheus.0.1.tar.gz** file: + + .. code-block:: console + + $ cd .prometheus + $ tar -xf sqream_exporters_prometheus.0.1.tar.gz + +3. Copy the exporter software files to the **/usr/bin** directory: + + .. code-block:: console + + $ cd sqream_exporters_prometheus.0.1 + $ sudo cp node_exporter/node_exporter /usr/bin/ + $ sudo cp nvidia_exporter/nvidia_exporter /usr/bin/ + +4. Copy the exporters service file to the **/etc/systemd/system/** directory: + + .. code-block:: console + + $ sudo cp services/node_exporter.service /etc/systemd/system/ + $ sudo cp services/nvidia_exporter.service /etc/systemd/system/ + +5. Set the permission and group of the service files: + + .. code-block:: console + + $ sudo chown prometheus:prometheus /usr/bin/node_exporter + $ sudo chmod u+x /usr/bin/node_exporter + $ sudo chown prometheus:prometheus /usr/bin/nvidia_exporter + $ sudo chmod u+x /usr/bin/nvidia_exporter + +6. Reload the services: + + .. code-block:: console + + $ sudo systemctl daemon-reload + +7. Start both services and set them to start when the server is booted up: + + * Node_exporter: + + .. code-block:: console + + $ sudo systemctl start node_exporter && sudo systemctl enable node_exporter + + * Nvidia_exporter: + + .. code-block:: console + + $ sudo systemctl start nvidia_exporter && sudo systemctl enable nvidia_exporter + + + +.. _check_exporter_status: + +Checking the Exporter Status +~~~~~~~~~~~~~~~~~~~~~~~~ +After installing the **exporter** service, you must check its status. + +You can check the exporter status by running the following command: + +.. code-block:: console + + $ sudo systemctl status node_exporter && sudo systemctl status nvidia_exporter + +Go back to :ref:`Installing Your SQream Software` + + +.. _running_sqream_install_service: + +Running the Sqream-install Service +================================ +The **Running the Sqream-install Service** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Installing Your License +-------------------------------- +After install the SQream Prometheus package, you must install your license. + +**To install your license:** + +1. Copy your license package to the sqream **/license** folder. + +.. note:: You do not need to untar the license package after copying it to the **/license** folder because the installer script does it automatically. + +The following flags are **mandatory** during your first run: + +.. code-block:: console + + $ sudo ./sqream-install -i -k -m + +.. note:: If you cannot run the script with **sudo**, verify that you have the right permission (**rwx** for the user) on the relevant directories (config, log, volume, and data-in directories). + +Go back to :ref:`Running the SQream_install Service`. + +Changing Your Data Ingest Folder +-------------------------------- +After installing your license, you must change your data ingest folder. + +You can change your data ingest folder by running the following command: + +.. code-block:: console + + $ sudo ./sqream-install -d /media/nfs/sqream/data_in + +Go back to :ref:`Running the SQream_install Service`. + +Checking Your System Settings +-------------------------------- +After changing your data ingest folder, you must check your system settings. + +The following command shows you all the variables that your SQream system is running with: + +.. code-block:: console + + $ ./sqream-install -s + +After optionally checking your system settings, you can use the **sqream-start** application to control your Kubernetes cluster. + +Go back to :ref:`Running the SQream_install Service`. + +SQream Installation Command Reference +-------------------------------- +If needed, you can use the **sqream-install** flag reference for any needed flags by typing: + +.. code-block:: console + + $ ./sqream-install --help + +The following shows the **sqream--install** flag descriptions: + +.. list-table:: + :widths: 22 59 25 + :header-rows: 1 + + * - Flag + - Function + - Note + * - **-i** + - Loads all the software from the hidden **.docker** folder. + - Mandatory + * - **-k** + - Loads the license package from the **/license** directory. + - Mandatory + * - **-m** + - Sets the relative path for all SQream folders under the shared filesystem available from all nodes (sqreamdb, config, logs and data_in). No other flags are required if you use this flag (such as c, v, l or d). + - Mandatory + * - **-c** + - Sets the path where to write/read SQream configuration files from. The default is **/etc/sqream/**. + - Optional + * - **-v** + - Shows the location of the SQream cluster. ``v`` creates a cluster if none exist, and mounts it if does. + - Optional + * - **-l** + - Shows the location of the SQream system startup logs. The logs contain startup and Docker logs. The default is **/var/log/sqream/**. + - Optional + * - **-d** + - Shows the folder containing data that you want to import into or copy from SQream. + - Optional + * - **-n** + - Sets the Kubernetes namespace. The default is **sqream**. + - Optional + * - **-N** + - Deletes a specific Kubernetes namespace and sets the factory default namespace (sqream). + - Optional + * - **-f** + - Overwrite existing folders and all files located in mounted directories. + - Optional + * - **-r** + - Resets the system configuration. This flag is run without any other variables. + - Optional + * - **-s** + - Shows the system settings. + - Optional + * - **-e** + - Sets the Kubernetes cluster's virtual IP address. + - Optional + * - **-h** + - Help, shows all available flags. + - Optional + +Go back to :ref:`Running the SQream_install Service`. + +Controlling Your Kubernetes Cluster Using SQream Flags +-------------------------------- +You can control your Kubernetes cluster using SQream flags. + +The following command shows you the available Kubernetes cluster control options: + +.. code-block:: console + + $ ./sqream-start -h + +The following describes the **sqream-start** flags: + +.. list-table:: + :widths: 22 59 25 + :header-rows: 1 + + * - Flag + - Function + - Note + * - **-s** + - Starts the sqream services, starting metadata, server picker, and workers. The number of workers started is based on the number of available GPU’s. + - Mandatory + * - **-p** + - Sets specific ports to the workers services. You must enter the starting port for the sqream-start application to allocate it based on the number of workers. + - + * - **-j** + - Uses an external .json configuration file. The file must be located in the **configuration** directory. + - The workers must each be started individually. + * - **-m** + - Allocates worker spool memory. + - The workers must each be started individually. + * - **-a** + - Starts the SQream Administration dashboard and specifies the listening port. + - + * - **-d** + - Deletes all running SQream services. + - + * - **-h** + - Shows all available flags. + - Help + +Go back to :ref:`Running the SQream_install Service`. + +.. _using_sqream_start_commands: + +Using the sqream-start Commands +======================= +In addition to controlling your Kubernetes cluster using SQream flags, you can control it using **sqream-start** commands. + +The **Using the sqream-start Commands** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Starting Your SQream Services +------------------------ +You can run the **sqream-start** command with the **-s** flag to start SQream services on all available GPU's: + +.. code-block:: console + + $ sudo ./sqream-start -s + +This command starts the SQream metadata, server picker, and sqream workers on all available GPU’s in the cluster. + +The following is an example of the correct output: + +.. code-block:: console + + ./sqream-start -s + Initializing network watchdogs on 3 hosts... + Network watchdogs are up and running + + Initializing 3 worker data collectors ... + Worker data collectors are up and running + + Starting Prometheus ... + Prometheus is available at 192.168.5.100:9090 + + Starting SQream master ... + SQream master is up and running + + Starting up 3 SQream workers ... + All SQream workers are up and running, SQream-DB is available at 192.168.5.100:3108 + All SQream workers are up and running, SQream-DB is available at 192.168.5.100:3108 + + +Go back to :ref:`Using the SQream-start Commands`. + +Starting Your SQream Services in Split Mode +------------------------ +Starting SQream services in split mode refers to running multiple SQream workers on a single GPU. You can do this by running the **sqream-start** command with the **-s** and **-z** flags. In addition, you can define the amount of hosts to run the multiple workers on. In the example below, the command defines to run the multiple workers on three hosts. + +**To start SQream services in split mode:** + +1. Run the following command: + +.. code-block:: console + + $ ./sqream-start -s -z 3 + +This command starts the SQream metadata, server picker, and sqream workers on a single GPU for three hosts: + +The following is an example of the correct output: + +.. code-block:: console + + Initializing network watchdogs on 3 hosts... + Network watchdogs are up and running + + Initializing 3 worker data collectors ... + Worker data collectors are up and running + + Starting Prometheus ... + Prometheus is available at 192.168.5.101:9090 + + Starting SQream master ... + SQream master is up and running + + Starting up 9 SQream workers over <#> available GPUs ... + All SQream workers are up and running, SQream-DB is available at 192.168.5.101:3108 + +2. Verify all pods are properly running in k8s cluster (**STATUS** column): + +.. code-block:: console + + kubectl -n sqream get pods + + NAME READY STATUS RESTARTS AGE + prometheus-bcf877867-kxhld 1/1 Running 0 106s + sqream-metadata-fbcbc989f-6zlkx 1/1 Running 0 103s + sqream-picker-64b8c57ff5-ndfr9 1/1 Running 2 102s + sqream-split-workers-0-1-2-6bdbfbbb86-ml7kn 1/1 Running 0 57s + sqream-split-workers-3-4-5-5cb49d49d7-596n4 1/1 Running 0 57s + sqream-split-workers-6-7-8-6d598f4b68-2n9z5 1/1 Running 0 56s + sqream-workers-start-xj75g 1/1 Running 0 58s + watchdog-network-management-6dnfh 1/1 Running 0 115s + watchdog-network-management-tfd46 1/1 Running 0 115s + watchdog-network-management-xct4d 1/1 Running 0 115s + watchdog-network-storage-lr6v4 1/1 Running 0 116s + watchdog-network-storage-s29h7 1/1 Running 0 116s + watchdog-network-storage-sx9mw 1/1 Running 0 116s + worker-data-collector-62rxs 0/1 Init:0/1 0 54s + worker-data-collector-n8jsv 0/1 Init:0/1 0 55s + worker-data-collector-zp8vf 0/1 Init:0/1 0 54s + +Go back to :ref:`Using the SQream-start Commands`. + +Starting the Sqream Studio UI +-------------------------------- +You can run the following command the to start the SQream Studio UI (Editor and Dashboard): + +.. code-block:: console + + $ ./sqream-start -a + +The following is an example of the correct output: + +.. code-block:: console + + $ ./sqream-start -a + Please enter USERNAME: + sqream + Please enter PASSWORD: + ****** + Please enter port value or press ENTER to keep 8080: + + Starting up SQream Admin UI... + SQream admin ui is available at 192.168.5.100:8080 + +Go back to :ref:`Using the SQream-start Commands`. + +Stopping the SQream Services +-------------------------------- +You can run the following command to stop all SQream services: + +.. code-block:: console + + $ ./sqream-start -d + +The following is an example of the correct output: + +.. code-block:: console + + $ ./sqream-start -d + $ Cleaning all SQream services in sqream namespace ... + $ All SQream service removed from sqream namespace + +Go back to :ref:`Using the SQream-start Commands`. + +Advanced sqream-start Commands +-------------------------------- +Controlling Your SQream Spool Size +~~~~~~~~~~~~~~~~~~~~~~~~ +If you do not specify the SQream spool size, the console automatically distributes the available RAM between all running workers. + +You can define a specific spool size by running the following command: + +.. code-block:: console + + $ ./sqream-start -s -m 4 + +Using a Custom .json File +~~~~~~~~~~~~~~~~~~~~~~~~ +You have the option of using your own .json file for your own custom configurations. Your .json file must be placed within the path mounted in the installation. SQream recommends placing your .json file in the **configuration** folder. + +The SQream console does not validate the integrity of external .json files. + +You can use the following command (using the ``j`` flag) to set the full path of your .json file to the configuration file: + +.. code-block:: console + + $ ./sqream-start -s -f .json + +This command starts one worker with an external configuration file. + +.. note:: The configuration file must be available in the shared configuration folder. + + +Checking the Status of the SQream Services +~~~~~~~~~~~~~~~~~~~~~~~~ +You can show all running SQream services by running the following command: + +.. code-block:: console + + $ kubectl get pods -n -o wide + +This command shows all running services in the cluster and which nodes they are running in. + +Go back to :ref:`Using the SQream-start Commands`. + +Upgrading Your SQream Version +================================ +The **Upgrading Your SQream Version** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Before Upgrading Your System +---------------------------- +Before upgrading your system you must do the following: + +1. Contact SQream support for a new SQream package tarball file. + +:: + +2. Set a maintenance window. + + +.. note:: You must stop the system while upgrading it. + + +Upgrading Your System +---------------------------- +After completing the steps in **Before Upgrading Your System** above, you can upgrade your system. + +**To upgrade your system:** + +1. Extract the contents of the tarball file that you received from SQream support. Make sure to extract the contents to the same directory as in :ref:`getting_sqream_package` and for the same user: + + .. code-block:: console + + $ tar -xvf sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ + $ cd sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ + +2. Start the upgrade process run the following command: + + .. code-block:: console + + $ ./sqream-install -i + +The upgrade process checks if the SQream services are running and will prompt you to stop them. + +3. Do one of the following: + + * Stop the upgrade by writing ``No``. + * Continue the upgrade by writing ``Yes``. + +If you continue upgrading, all running SQream workers (master and editor) are stopped. When all services have been stopped, the new version is loaded. + + +.. note:: SQream periodically upgrades its metadata structure. If an upgrade version includes an upgraded metadata service, an approval request message is displayed. This approval is required to finish the upgrade process. Because SQream supports only specific metadata versions, all SQream services must be upgraded at the same time. + + +4. When SQream has successfully upgraded, load the SQream console and restart your services. + +For questions, contact SQream Support. diff --git a/installation_guides/installing_studio_on_stand_alone_server.rst b/installation_guides/installing_studio_on_stand_alone_server.rst new file mode 100644 index 000000000..874adba8d --- /dev/null +++ b/installation_guides/installing_studio_on_stand_alone_server.rst @@ -0,0 +1,578 @@ +.. _installing_studio_on_stand_alone_server: + +.. _install_studio_top: + +*********************** +Installing Studio on a Stand-Alone Server +*********************** + + +The **Installing Studio on a Stand-Alone Server** guide describes how to install SQream Studio on a stand-alone server. A stand-alone server is a server that does not run SQream based on binary files, Docker, or Kubernetes. + +The Installing Studio on a Stand-Alone Server guide includes the following sections: + +.. contents:: + :local: + :depth: 1 + +Installing NodeJS Version 12 on the Server +^^^^^^^^^^^^^^^ +Before installing Studio you must install NodeJS version 12 on the server. + +**To install NodeJS version 12 on the server:** + +1. Check if a version of NodeJS older than version *12.* has been installed on the target server. + + .. code-block:: console + + $ node -v + + The following is the output if a version of NodeJS has already been installed on the target server: + + .. code-block:: console + + bash: /usr/bin/node: No such file or directory + +2. If a version of NodeJS older than *12.* has been installed, remove it as follows: + + * On CentOS: + + .. code-block:: console + + $ sudo yum remove -y nodejs + + * On Ubuntu: + + .. code-block:: console + + $ sudo apt remove -y nodejs + +3. If you have not installed NodeJS version 12, run the following commands: + + * On CentOS: + + .. code-block:: console + + $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - + $ sudo yum clean all && sudo yum makecache fast + $ sudo yum install -y nodejs + + * On Ubuntu: + + .. code-block:: console + + $ curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - + $ sudo apt-get install -y nodejs + + The following output is displayed if your installation has completed successfully: + + .. code-block:: console + + Transaction Summary + ============================================================================================================================== + Install 1 Package + + Total download size: 22 M + Installed size: 67 M + Downloading packages: + warning: /var/cache/yum/x86_64/7/nodesource/packages/nodejs-12.22.1-1nodesource.x86_64.rpm: Header V4 RSA/SHA512 Signature, key ID 34fa74dd: NOKEY + Public key for nodejs-12.22.1-1nodesource.x86_64.rpm is not installed + nodejs-12.22.1-1nodesource.x86_64.rpm | 22 MB 00:00:02 + Retrieving key from file:///etc/pki/rpm-gpg/NODESOURCE-GPG-SIGNING-KEY-EL + Importing GPG key 0x34FA74DD: + Userid : "NodeSource " + Fingerprint: 2e55 207a 95d9 944b 0cc9 3261 5ddb e8d4 34fa 74dd + Package : nodesource-release-el7-1.noarch (installed) + From : /etc/pki/rpm-gpg/NODESOURCE-GPG-SIGNING-KEY-EL + Running transaction check + Running transaction test + Transaction test succeeded + Running transaction + Warning: RPMDB altered outside of yum. + Installing : 2:nodejs-12.22.1-1nodesource.x86_64 1/1 + Verifying : 2:nodejs-12.22.1-1nodesource.x86_64 1/1 + + Installed: + nodejs.x86_64 2:12.22.1-1nodesource + + Complete! + +4. Confirm the Node version. + + .. code-block:: console + + $ node -v + + The following is an example of the correct output: + + .. code-block:: console + + v12.22.1 + +5. Install Prometheus using binary packages. + + For more information on installing Prometheus using binary packages, see :ref:`installing_prometheus_using_binary_packages`. + +Back to :ref:`Installing Studio on a Stand-Alone Server` + + + +Installing Studio +^^^^^^^^^^^^^^^ +After installing the Dashboard Data Collector, you can install Studio. + +**To install Studio:** + +1. Copy the SQream Studio package from SQream Artifactory into the target server. For access to the Sqream Studio package, contact SQream Support. + +:: + +2. Extract the package: + + .. code-block:: console + + $ tar -xvf sqream-acceleration-studio-.x86_64.tar.gz + +:: + +3. Navigate to the new package folder. + + .. code-block:: console + + $ cd sqream-admin + +.. _add_parameter: + +4. Build the configuration file to set up Sqream Studio. You can use IP address **127.0.0.1** on a single server. + + .. code-block:: console + + $ npm run setup -- -y --host= --port=3108 + + The above command creates the **sqream-admin-config.json** configuration file in the **sqream-admin** folder and shows the following output: + + .. code-block:: console + + Config generated successfully. Run `npm start` to start the app. + + For more information about the available set-up arguments, see :ref:`Set-Up Arguments`. + + :: + +5. If you have installed Studio on a server where SQream is already installed, move the **sqream-admin-config.json** file to **/etc/sqream/**: + + .. code-block:: console + + $ mv sqream-admin-config.json /etc/sqream + +Back to :ref:`Installing Studio on a Stand-Alone Server` + +Starting Studio Manually +^^^^^^^^^^^^^^^ +You can start Studio manually by running the following command: + +.. code-block:: console + + $ cd /home/sqream/sqream-admin + $ NODE_ENV=production pm2 start ./server/build/main.js --name=sqream-studio -- start + +The following output is displayed: + +.. code-block:: console + + [PM2] Starting /home/sqream/sqream-admin/server/build/main.js in fork_mode (1 instance) + [PM2] Done. + ┌─────┬──────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐ + │ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │ + ├─────┼──────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤ + │ 0 │ sqream-studio │ default │ 0.1.0 │ fork │ 11540 │ 0s │ 0 │ online │ 0% │ 15.6mb │ sqream │ disabled │ + └─────┴──────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘ + +Starting Studio as a Service +^^^^^^^^^^^^^^^ +Sqream uses the **Process Manager (PM2)** to maintain Studio. + +**To start Studio as a service:** + +1. Run the following command: + + .. code-block:: console + + $ sudo npm install -g pm2 + +:: + +2. Verify that the PM2 has been installed successfully. + + .. code-block:: console + + $ pm2 list + + The following is the output: + + .. code-block:: console + + ┌─────┬──────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐ + │ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │ + ├─────┼──────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤ + │ 0 │ sqream-studio │ default │ 0.1.0 │ fork │ 11540 │ 2m │ 0 │ online │ 0% │ 31.5mb │ sqream │ disabled │ + └─────┴──────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘ + +:: + +2. Start the service with PM2: + + * If the **sqream-admin-config.json** file is located in **/etc/sqream/**, run the following command: + + .. code-block:: console + + $ cd /home/sqream/sqream-admin + $ NODE_ENV=production pm2 start ./server/build/main.js --name=sqream-studio -- start --config-location=/etc/sqream/sqream-admin-config.json + + * If the **sqream-admin-config.json** file is not located in **/etc/sqream/**, run the following command: + + .. code-block:: console + + $ cd /home/sqream/sqream-admin + $ NODE_ENV=production pm2 start ./server/build/main.js --name=sqream-studio -- start + +:: + +3. Verify that Studio is running. + + .. code-block:: console + + $ netstat -nltp + +4. Verify that SQream_studio is listening on port 8080, as shown below: + + .. code-block:: console + + (Not all processes could be identified, non-owned process info + will not be shown, you would have to be root to see it all.) + Active Internet connections (only servers) + Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name + tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - + tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN - + tcp6 0 0 :::8080 :::* LISTEN 11540/sqream-studio + tcp6 0 0 :::22 :::* LISTEN - + tcp6 0 0 ::1:25 :::* LISTEN - + + + +:: + +5. Verify the following: + + 1. That you can access Studio from your browser (``http://:8080``). + + :: + + 2. That you can log in to SQream. + +6. Save the configuration to run on boot. + + .. code-block:: console + + $ pm2 startup + + The following is an example of the output: + + .. code-block:: console + + $ sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sqream --hp /home/sqream + +7. Copy and paste the output above and run it. + +:: + +8. Save the configuration. + + .. code-block:: console + + $ pm2 save + +Back to :ref:`Installing Studio on a Stand-Alone Server` + +Accessing Studio +^^^^^^^^^^^^^^^ +The Studio page is available on port 8080: ``http://:8080``. + +If port 8080 is blocked by the server firewall, you can unblock it by running the following command: + + .. code-block:: console + + $ firewall-cmd --zone=public --add-port=8080/tcp --permanent + $ firewall-cmd --reload + +Back to :ref:`Installing Studio on a Stand-Alone Server` + +Maintaining Studio with the Process Manager (PM2) +^^^^^^^^^^^^^^^ +Sqream uses the **Process Manager (PM2)** to maintain Studio. + +You can use PM2 to do one of the following: + +* To check the PM2 service status: ``pm2 list`` + + :: + +* To restart the PM2 service: ``pm2 reload sqream-studio`` + + :: + +* To see the PM2 service logs: ``pm2 logs sqream-studio`` + +Back to :ref:`Installing Studio on a Stand-Alone Server` + +Upgrading Studio +^^^^^^^^^^^^^^^ +To upgrade Studio you need to stop the version that you currently have. + +**To stop the current version of Studio:** + +1. List the process name: + + .. code-block:: console + + $ pm2 list + + The process name is displayed. + + .. code-block:: console + + + +:: + +2. Run the following command with the process name: + + .. code-block:: console + + $ pm2 stop + +:: + +3. If only one process is running, run the following command: + + .. code-block:: console + + $ pm2 stop all + +:: + +4. Change the name of the current **sqream-admin** folder to the old version. + + .. code-block:: console + + $ mv sqream-admin sqream-admin- + +:: + +5. Extract the new Studio version. + + .. code-block:: console + + $ tar -xf sqream-acceleration-studio-tar.gz + +:: + +6. Rebuild the configuration file. You can use IP address **127.0.0.1** on a single server. + + .. code-block:: console + + $ npm run setup -- -y --host= --port=3108 + + The above command creates the **sqream-admin-config.json** configuration file in the **sqream_admin** folder. + +:: + +7. Copy the **sqream-admin-config.json** configuration file to **/etc/sqream/** to overwrite the old configuration file. + +:: + +8. Start PM2. + + .. code-block:: console + + $ pm2 start all + +Back to :ref:`Installing Studio on a Stand-Alone Server` + +.. _install_studio_docker_container: + +Installing Studio in a Docker Container +^^^^^^^^^^^^^^^^^^^^^^^ +This guide explains how to install SQream Studio in a Docker container and includes the following sections: + +.. contents:: + :local: + :depth: 1 + +Installing Studio +-------------- +If you have already installed Docker, you can install Studio in a Docker container. + +**To install Studio:** + +1. Copy the downloaded image onto the target server. + +:: + +2. Load the Docker image. + + .. code-block:: console + + $ docker load -i + +:: + +3. If the downloaded image is called **sqream-acceleration-studio-5.1.3.x86_64.docker18.0.3.tar,** run the following command: + + .. code-block:: console + + $ docker load -i sqream-acceleration-studio-5.1.3.x86_64.docker18.0.3.tar + +:: + +4. Start the Docker container. + + .. code-block:: console + + $ docker run -d --restart=unless-stopped -p :8080 -e runtime=docker -e SQREAM_K8S_PICKER= -e SQREAM_PICKER_PORT= -e SQREAM_DATABASE_NAME= -e SQREAM_ADMIN_UI_PORT=8080 --name=sqream-admin-ui + + The following is an example of the command above: + + .. code-block:: console + + $ docker run -d --name sqream-studio -p 8080:8080 -e runtime=docker -e SQREAM_K8S_PICKER=192.168.0.183 -e SQREAM_PICKER_PORT=3108 -e SQREAM_DATABASE_NAME=master -e SQREAM_ADMIN_UI_PORT=8080 sqream-acceleration-studio:5.1.3 + +Back to :ref:`Installing Studio in a Docker Container` + +Accessing Studio +----------------- +You can access Studio from Port 8080: ``http://:8080``. + +If you want to use Studio over a secure connection (https), you must use the parameter values shown in the following table: + +.. list-table:: + :widths: 10 25 65 + :header-rows: 1 + + * - Parameter + - Default Value + - Description + * - ``--web-ssl-port`` + - 8443 + - + * - ``--web-ssl-key-path`` + - None + - The path of SSL key PEM file for enabling https. Leave empty to disable. + * - ``--web-ssl-cert-path`` + - None + - The path of SSL certificate PEM file for enabling https. Leave empty to disable. + +You can configure the above parameters using the following syntax: + +.. code-block:: console + + $ npm run setup -- -y --host=127.0.0.1 --port=3108 + +.. _using_docker_container_commands: + +Back to :ref:`Installing Studio in a Docker Container` + +Using Docker Container Commands +--------------- +When installing Studio in Docker, you can run the following commands: + +* View Docker container logs: + + .. code-block:: console + + $ docker logs -f sqream-admin-ui + +* Restart the Docker container: + + .. code-block:: console + + $ docker restart sqream-admin-ui + +* Kill the Docker container: + + .. code-block:: console + + $ docker rm -f sqream-admin-ui + +Back to :ref:`Installing Studio in a Docker Container` + +Setting Up Argument Configurations +---------------- +When creating the **sqream-admin-config.json** configuration file, you can add ``-y`` to create the configuration file in non-interactive mode. Configuration files created in non-interactive mode use all the parameter defaults not provided in the command. + +The following table shows the available arguments: + +.. list-table:: + :widths: 10 25 65 + :header-rows: 1 + + * - Parameter + - Default Value + - Description + * - ``--web--host`` + - 8443 + - + * - ``--web-port`` + - 8080 + - + * - ``--web-ssl-port`` + - 8443 + - + * - ``--web-ssl-key-path`` + - None + - The path of the SSL Key PEM file for enabling https. Leave empty to disable. + * - ``--web-ssl-cert-path`` + - None + - The path of the SSL Certificate PEM file for enabling https. Leave empty to disable. + * - ``--debug-sqream (flag)`` + - false + - + * - ``--host`` + - 127.0.0.1 + - + * - ``--port`` + - 3108 + - + * - ``is-cluster (flag)`` + - true + - + * - ``--service`` + - sqream + - + * - ``--ssl (flag)`` + - false + - Enables the SQream SSL connection. + * - ``--name`` + - default + - + * - ``--data-collector-url`` + - localhost:8100/api/dashboard/data + - Enables the Dashboard. Leaving this blank disables the Dashboard. Using a mock URL uses mock data. + * - ``--cluster-type`` + - standalone (``standalone`` or ``k8s``) + - + * - ``--config-location`` + - ./sqream-admin-config.json + - + * - ``--network-timeout`` + - 60000 (60 seconds) + - + * - ``--access-key`` + - None + - If defined, UI access is blocked unless ``?ui-access=`` is included in the URL. + +Back to :ref:`Installing Studio in a Docker Container` + + :: + +Back to :ref:`Installing Studio on a Stand-Alone Server` diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst new file mode 100644 index 000000000..e0d8cad11 --- /dev/null +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -0,0 +1,1158 @@ +.. _recommended_pre-installation_configurations: + +********************************************* +Recommended Pre-Installation Configurations +********************************************* +The **Recommended Pre-Installation Configuration** page describes SQream's recommended configuration settings for production deployments. + +After :ref:`installing SQream`, we recommend you to configure your system for improved performance and stability. + +The Recommended Pre-Installation Configuration page describes the following: + +.. contents:: + :local: + :depth: 1 + +Recommended BIOS Settings +========================== +The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. + +It is safe to skip any and all of the configuration steps, but this may impact performance. + +If any doubt arises, consult the documentation for your server or your hardware vendor for the correct way to apply the settings. + +.. list-table:: + :widths: 25 25 50 + :header-rows: 1 + + * - Item + - Setting + - Rationale + * - **Management console access** + - **Connected** + - Connection to OOB required to preserve continuous network uptime. + * - **All drives.** + - **Connected and displayed on RAID interface** + - Prerequisite for cluster or OS installation. + * - **RAID volumes.** + - **Configured according to project guidelines. Must be rebooted to take effect.** + - Clustered to increase logical volume and provide redundancy. + * - **Fan speed Thermal Configuration.** + - Dell fan speed: **High Maximum**. Specified minimum setting: **60**. HPe thermal configuration: **Increased cooling**. + - NVIDIA Tesla GPUs are passively cooled and require high airflow to operate at full performance. + * - Power regulator or iDRAC power unit policy + - HPe: **HP static high performance** mode enabled. Dell: **iDRAC power unit policy** (power cap policy) disabled. + - Other power profiles (such as "balanced") throttle the CPU and diminishes performance. Throttling may also cause GPU failure. + * - **System Profile**, **Power Profile**, or **Performance Profile** + - **High Performance** + - The Performance profile provides potentially increased performance by maximizing processor frequency, and the disabling certain power saving features such as C-states. Use this setting for environments that are not sensitive to power consumption. + * - **Power Cap Policy** or **Dynamic power capping** + - **Disabled** + - Other power profiles (like "balanced") throttle the CPU and may diminish performance or cause GPU failure. This setting may appear together with the above (Power profile or Power regulator). This setting allows disabling system ROM power calibration during the boot process. Power regulator settings are named differently in BIOS and iLO/iDRAC. + +.. + **Comment: is it necessary to show the different power regulator setting names in this document?** + * - **Intel Turbo Boost** + - **Enabled** + - Intel Turbo Boost enables overclocking the processor to boost CPU-bound operation performance. Overclocking may risk computational jitter due to changes in the processor's turbo frequency. This causes brief pauses in processor operation, introducing uncertainty into application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. + * - **Logical Processor** + - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** + - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. + * - **Intel Virtualization Technology** (VT-d) + - **Disable** + - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. + * - **Logical Processor** + - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** + - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. + * - **Intel Virtualization Technology** (VT-d) + - **Disable** + - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. + * - **Processor C-States** (Minimum processor idle power core state) + - **Disable** + - Processor C-States reduce server power when the system is in an idle state. This causes slower cold-starts when the system transitions from an idle to a load state, and may reduce query performance by up to 15%. **Comment: a hyperlinked footnote to an internal source was inserted into the Confluence doc here. Do we want to include this in the final version? Linked URL: https://www.dell.com/support/kbdoc/en-il/000060621/what-is-the-c-state** + * - **HPe**: **Energy/Performance bias** + - **Maximum performance** + - Configures processor sub-systems for high-performance and low-latency. Other power profiles (like "balanced") throttle the CPU and may diminish performance. Use this setting for environments that are not sensitive to power consumption. + * - **HPe**: **DIMM voltage** + - **Optimized for Performance** + - Setting a higher voltage for DIMMs may increase performance. + * - **Memory Operating Mode** + - **Optimizer Mode**, **Disable Node Interleaving**, **Auto Memory Operating Voltage** + - Memory Operating Mode is tuned for performance in **Optimizer** mode. Other modes may improve reliability, but reduce performance. **Node Interleaving** should be disabled because enabling it interleaves the memory between memory nodes, which harms NUMA-aware applications such as SQream DB. + * - **HPe**: **Memory power savings mode** + - **Maximum performance** + - This setting configures several memory parameters to optimize the performance of memory sub-systems. The default setting is **Balanced**. + * - HPe **ACPI SLIT** + - **Enabled** + - ACPI SLIT sets the relative access times between processors and memory and I/O sub-systems. ACPI SLIT enables operating systems to use this data to improve performance by more efficiently allocating resources and workloads. + * - **QPI Snoop** **Comment: should we write that it is HPe or Intel? HPe: QPI Snoop** + - **Cluster on Die** or **Home Snoop** + - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. + + + + + + +Installing the Operating System +=================================================== +Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.6-7.9) must be installed before installing the SQream database. Either the customer or a SQream representative can perform the installation. + +.. + **Comment: I recommend leaving contact information here - Please call xxx-xxx-xxxx to contact a SQream representative.** + +**To install the operating system:** + +#. Select a language (English recommended). +#. From **Software Selection**, select **Minimal**. +#. Select the **Development Tools** group checkbox. +#. Continue the installation. +#. Set up the necessary drives and users as per the installation process. + + Using Debugging Tools is recommended for future problem-solving if necessary. + + .. + **Comment: In Step 4, why don't we document the entire procedure? I.e., why do we stop here and say "Continue the installation" and "Set up the necessary drives..."?** + +Selecting the **Development Tools** group installs the following tools: + + * autoconf + * automake + * binutils + * bison + * flex + * gcc + * gcc-c++ + * gettext + * libtool + * make + * patch + * pkgconfig + * redhat-rpm-config + * rpm-build + * rpm-sign + + + +The root user is created and the OS shell is booted up. + +Configuring the Operating System +=================================================== +When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. + +Logging In to the Server +-------------------------------- +You can log in to the server using the server's IP address and password for the **root** user. The server's IP address and **root** user were created while installing the operating system above. + +Automatically Creating a SQream User +------------------------------------ + +**To automatically create a SQream user:** + +#. If a SQream user was created during installation, verify that the same ID is used on every server: + + .. code-block:: console + + $ sudo id sqream + +The ID **1000** is used on each server in the following example: + + .. code-block:: console + + $ uid=1000(sqream) gid=1000(sqream) groups=1000(sqream) + +2. If the ID's are different, delete the SQream user and SQream group from both servers: + + .. code-block:: console + + $ sudo userdel sqream + +3. Recreate it using the same ID: + + .. code-block:: console + + $ sudo rm /var/spool/mail/sqream + +Manually Creating a SQream User +-------------------------------- + +**To manually create a SQream user:** + +SQream enables you to manually create users. This section shows you how to manually create a user with the UID **1111**. You cannot manually create during the operating system installation procedure. + +1. Add a user with an identical UID on all cluster nodes: + + .. code-block:: console + + $ useradd -u 1111 sqream + +2. Add the user **sqream** to the **wheel** group. + + .. code-block:: console + + $ sudo usermod -aG wheel sqream + +You can remove the SQream user from the **wheel** group when the installation and configuration are complete: + + .. code-block:: console + + $ passwd sqream + +3. Log out and log back in as **sqream**. + +**Note:** If you deleted the **sqream** user and recreated it with different ID, to avoid permission errors, you must change its ownership to /home/sqream. + +4. Change the **sqream** user's ownership to /home/sqream: + + .. code-block:: console + + $ sudo chown -R sqream:sqream /home/sqream + +Setting Up A Locale +-------------------------------- + +SQream enables you to set up a locale. In this example, the locale used is your own location. + +**To set up a locale:** + +1. Set the language of the locale: + + .. code-block:: console + + $ sudo localectl set-locale LANG=en_US.UTF-8 + +2. Set the time stamp (time and date) of the locale: + + .. code-block:: console + + $ sudo timedatectl set-timezone Asia/Jerusalem + +If needed, you can run the **timedatectl list-timezones** command to see your current time-zone. + + +Installing the Required Packages +-------------------------------- +You can install the required packages by running the following command: + +.. code-block:: console + + $ sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq + + +Installing the Recommended Tools +-------------------------------- +You can install the recommended tools by running the following command: + +.. code-block:: console + + $ sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix + + +Installing Python 3.6.7 +-------------------------------- +1. Download the Python 3.6.7 source code tarball file from the following URL into the **/home/sqream** directory: + + .. code-block:: console + + $ wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz + +2. Extract the Python 3.6.7 source code into your current directory: + + .. code-block:: console + + $ tar -xf Python-3.6.7.tar.xz + +3. Navigate to the Python 3.6.7 directory: + + .. code-block:: console + + $ cd Python-3.6.7/Python-3 + +4. Run the **./configure** script: + + .. code-block:: console + + $ ./configure + +5. Build the software: + + .. code-block:: console + + $ make -j30 + +6. Install the software: + + .. code-block:: console + + $ sudo make install + +7. Verify that Python 3.6.7 has been installed: + + .. code-block:: console + + $ python3.6.7 + +Installing NodeJS on CentOS +-------------------------------- +**To install the node.js on CentOS:** + +1. Download the `setup_12.x file `__ as a root user logged in shell: + + .. code-block:: console + + $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - + +2. Clear the YUM cache and update the local metadata: + + .. code-block:: console + + $ sudo yum clean all && sudo yum makecache fast + +3. Install the **node.js**) file: + + .. code-block:: console + + $ sudo yum install -y nodejs + +Installing NodeJS on Ubuntu +-------------------------------- +**To install the node.js file on Ubuntu:** + +1. Download the `setup_12.x file `__ as a root user logged in shell: + + .. code-block:: console + + $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - + +2. Install the node.js file: + + .. code-block:: console + + $ sudo apt-get install -y nodejs + +3. Verify the node version: + +.. + **Comment: - is this step relevant only for installing on Ubuntu, or on CentOS as well?** + + .. code-block:: console + + $ node -v + +Configuring the Network Time Protocol (NTP) +------------------------------------------- +This section describes how to configure your NTP. + +If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server `__. + +.. + **Comment: - Is this the correct procedure on the linked URL: Configure NTP Client to Synchronize with NTP Server?* + +**To configure your NTP:** + +1. Install the NTP file. + + .. code-block:: console + + $ sudo yum install ntp + +2. Enable the **ntpd** program. + + .. code-block:: console + + $ sudo systemctl enable ntpd + +3. Start the **ntdp** program. + + .. code-block:: console + + $ sudo systemctl start ntpd + +4. Print a list of peers known to the server and a summary of their states. + + .. code-block:: console + + $ sudo ntpq -p + +Configuring the Network Time Protocol Server +-------------------------------------------- +If your organization has an NTP server, you can configure it. + +**To configure your NTP server:** + +1. Output your NTP server address and append ``/etc/ntpd.conf`` to the outuput. + + .. code-block:: console + + $ echo -e "\nserver \n" | sudo tee -a /etc/ntp.conf + +2. Restart the service. + + .. code-block:: console + + $ sudo systemctl restart ntpd + +3. Check that synchronization is enabled: + + .. code-block:: console + + $ sudo timedatectl + +Checking that synchronization is enabled generates the following output: + + .. code-block:: console + + $ Local time: Sat 2019-10-12 17:26:13 EDT + Universal time: Sat 2019-10-12 21:26:13 UTC + RTC time: Sat 2019-10-12 21:26:13 + Time zone: America/New_York (EDT, -0400) + NTP enabled: yes + NTP synchronized: yes + RTC in local TZ: no + DST active: yes + Last DST change: DST began at + Sun 2019-03-10 01:59:59 EST + Sun 2019-03-10 03:00:00 EDT + Next DST change: DST ends (the clock jumps one hour backwards) at + Sun 2019-11-03 01:59:59 EDT + Sun 2019-11-03 01:00:00 EST + + + +Configuring the Server to Boot Without the UI +--------------------------------------------- +You can configure your server to boot without a UI in cases when it is not required (recommended) by running the following command: + +.. code-block:: console + + $ sudo systemctl set-default multi-user.target + +Running this command activates the **NO-UI** server mode. + +Configuring the Security Limits +-------------------------------- +The security limits refers to the number of open files, processes, etc. + +You can configure the security limits by running the **echo -e** command as a root user logged in shell: + +.. code-block:: console + + $ sudo bash + +.. code-block:: console + + $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + +Configuring the Kernel Parameters +--------------------------------- +**To configure the kernel parameters:** + +1. Insert a new line after each kernel parameter: + + .. code-block:: console + + $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf + +**Notice:** In the past, the **vm.zone_reclaim_mode** parameter was set to **7.** In the latest Sqream version, the vm.zone_reclaim_mode parameter must be set to **0**. If it is not set to **0**, when a numa node runs out of memory, the system will get stuck and will be unable to pull memory from other numa nodes. + +2. Check the maximum value of the **fs.file**. + + .. code-block:: console + + $ sysctl -n fs.file-max + +3. *Optional* - If the maximum value of the **fs.file** is smaller than **2097152**, run the following command: + + .. code-block:: console + + $ echo "fs.file-max=2097152" >> /etc/sysctl.conf + +**IP4 forward** must be enabled for Docker and K8s installation only. + +Configuring the Firewall +-------------------------------- +The example in this section shows the open ports for four sqreamd sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. + +**To configure the firewall:** + +1. Start the service and enable FirewallID on boot: + + .. code-block:: console + + $ systemctl start firewalld + +2. Add the following ports to the permanent firewall: + + .. code-block:: console + + $ firewall-cmd --zone=public --permanent --add-port=8080/tcp + $ firewallfirewall-cmd --zone=public --permanent --add-port=3105/tcp + $ firewall-cmd --zone=public --permanent --add-port=3108/tcp + $ firewall-cmd --zone=public --permanent --add-port=5000-5003/tcp + $ firewall-cmd --zone=public --permanent --add-port=5100-5103/tcp + $ firewall-cmd --permanent --list-all + + +.. + **Comment: - does *--list-all* add the entire list of ports to the permanent firewall?** + +3. Reload the firewall: + + .. code-block:: console + + $ firewall-cmd --reload + +4. Start the service and enable FirewallID on boot: + + .. code-block:: console + + $ systemctl start firewalld + + If you do not need the firewall, you can disable it: + + .. code-block:: console + + $ sudo systemctl disable firewalld + + +Disabling selinux +-------------------------------- +**To disable selinux:** + +1. Show the status of **selinux**: + + .. code-block:: console + + $ sudo sestatus + +2. If the output is not **disabled**, edit the **/etc/selinux/config** file: + + .. code-block:: console + + $ sudo vim /etc/selinux/config + +3. Change **SELINUX=enforcing** to **SELINUX=disabled**. + +The above changes will only take effect after rebooting the server. + +You can disable selinux immediately after rebooting the server by running the following command: + +.. code-block:: console + + $ sudo setenforce 0 + +Configuring the /etc/hosts File +-------------------------------- +**To configure the /etc/hosts file:** + +1. Edit the **/etc/hosts** file: + + .. code-block:: console + + $ sudo vim /etc/hosts + +2. Call your local host: + + .. code-block:: console + + $ 127.0.0.1 localhost + $ + +.. + **Comment: - Is the above an output or a step?** + +Configuring the DNS +-------------------------------- +**To configure the DNS:** + +1. Run the **ifconfig** commasnd to check your NIC name. In the following example, **eth0** is the NIC name: + + .. code-block:: console + + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-eth0 + +2. Replace the DNS lines from the example above with your own DNS addresses : + + .. code-block:: console + + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-4.4.4.4 + $ sudo vim /etc/sysconfig/network-scripts/ifcfg-8.8.8.8 + + +.. + **Comment: - is the above input correct?** + +Installing the Nvidia CUDA Driver +=================================================== + + +**Warning:** If your UI runs on the server, the server must be stopped before installing the CUDA drivers. + +CUDA Driver Prerequisites +-------------------------------- +1. Verify that the NVIDIA card has been installed and is detected by the system: + + .. code-block:: console + + $ lspci | grep -i nvidia + +2. Check which version of gcc has been installed: + + .. code-block:: console + + $ gcc --version + +3. If gcc has not been installed, install it for one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console + + $ sudo yum install -y gcc + + * On Ubuntu: + + .. code-block:: console + + $ sudo apt-get install gcc + + +Updating the Kernel Headers +-------------------------------- +**To update the kernel headers:** + +1. Update the kernel headers on one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console + + $ sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) + + * On Ubuntu: + + .. code-block:: console + + $ sudo apt-get install linux-headers-$(uname -r) + +2. Install **wget** one of the following operating systems: + + * On RHEL/CentOS: + + .. code-block:: console + + $ sudo yum install wget + + * On Ubuntu: + + .. code-block:: console + + $ sudo apt-get install wget + +Disabling Nouveau +-------------------------------- +You can disable Nouveau, which is the default driver. + +**To disable Nouveau:** + +1. Check if the Nouveau driver has been loaded: + + .. code-block:: console + + $ lsmod | grep nouveau + +If the Nouveau driver has been loaded, the command above generates output. + +2. Blacklist the Nouveau drivers to disable them: + + .. code-block:: console + + $ cat <`__ for the additional set-up requirements. + + + c. **For K80**: + + .. code-block:: console + + $ nvidia-persistenced + $ nvidia-smi -pm 1 + $ nvidia-smi -acp 0 + $ nvidia-smi --auto-boost-permission=0 + $ nvidia-smi --auto-boost-default=0 + +4. Reboot the server and run the **NVIDIA System Management Interface (NVIDIA SMI)**: + + .. code-block:: console + + $ nvidia-smi + + +Disabling Automatic Bug Reporting Tools +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**To disable automatic bug reporting tools:** + +1. Run the following **abort** commands: + + .. code-block:: console + + $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done + + +The server is ready for the SQream software installation. + + +2. Run the following checks: + + a. Check the OS release: + + .. code-block:: console + + $ cat /etc/os-release + + b. Verify that a SQream user exists and has the same ID on all cluster member services: + + .. code-block:: console + + $ id sqream + + c. Verify that the storage is mounted: + + .. code-block:: console + + $ mount + + d. Verify that the driver has been installed correctly: + + .. code-block:: console + + $ nvidia-smi + + e. Check the maximum value of the **fs.file**: + + .. code-block:: console + + $ sysctl -n fs.file-max + + The desired output when checking the maximum value of the **fs.file** is greater or equal to **2097152**. + + f. Run the following command as a SQream user: + +.. + **Comment: - **Question - what do the following command parameter do? -c?** + + .. code-block:: console + + $ ulimit -c -u -n + +.. + **Comment: - See https://ss64.com/bash/ulimit.html** + + The following shows the desired output when ****: + + .. code-block:: console + + $ core file size (blocks, -c) unlimited + $ max user processes (-u) 1000000 + $ open files (-n) 1000000 + +3. Configure the security limits by running the **echo -e** command as a root user logged in shell: + + .. code-block:: console + + $ sudo bash + $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + +Enabling Core Dumps +=================================================== + +Enabling core dumps is recommended, but optional. + +**To enable core dumps:** + +1. Check the **abrtd** Status + +2. Set the limits + +3. Create the core dumps directory. + + +Checking the abrtd Status +--------------------------------------------------- + +**To check the abrtd status:** + +1. Check if **abrtd** is running: + + .. code-block:: console + + $ sudo ps -ef |grep abrt + +2. If **abrtd** is running, stop it: + + .. code-block:: console + + $ sudo service abrtd stop + $ sudo chkconfig abrt-ccpp off + $ sudo chkconfig abrt-oops off + $ sudo chkconfig abrt-vmcore off + $ sudo chkconfig abrt-xorg off + $ sudo chkconfig abrtd off + + +Setting the Limits +--------------------------------------------------- + +**To set the limits:** + +1. Set the limits: + + .. code-block:: console + + $ ulimit -c + +2. If the output is **0**, add the following lines to the **limits.conf** file (/etc/security): + + .. code-block:: console + + $ * soft core unlimited + $ * hard core unlimited + +3. Log out and log in to apply the limit changes. + +Creating the Core Dumps Directory +--------------------------------------------------- + +**To set the core dumps directory:** + +1. Make the **/tmp/core_dumps** directory: + + .. code-block:: console + + $ mkdir /tmp/core_dumps + +2. Set the ownership of the **/tmp/core_dumps** directory: + + .. code-block:: console + + $ sudo chown sqream.sqream /tmp/core_dumps + +3. Grant read, write, and execute permissions to all users: + + .. code-block:: console + + $ sudo chmod -R 777 /tmp/core_dumps + +Setting the Output Directory of the /etc/sysctl.conf File +----------------------------------------------------------------- + +**To set the output directory of the /etc/sysctl.conf file:** + +1. Edit the **/etc/sysctl.conf** file: + + .. code-block:: console + + $ sudo vim /etc/sysctl.conf + +2. Add the following to the bottom of the file: + + .. code-block:: console + + $ kernel.core_uses_pid = 1 + $ kernel.core_pattern = //core-%e-%s-%u-%g-%p-%t + $ fs.suid_dumpable = 2 + +.. + **Comment: - leave a note that the user can choose his correct location of the folder.** + +3. To apply the changes without rebooting the server, run: + + .. code-block:: console + + $ sudo sysctl -p + +4. Check that the core output directory points to the following: + + .. code-block:: console + + $ sudo cat /proc/sys/kernel/core_pattern + + The following shows the correct generated output: + + .. code-block:: console + + $ /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t + +5. Verify that the core dumping works: + + .. code-block:: console + + $ select abort_server(); + + +Verifying that the Core Dumps Work +--------------------------------------------------- +You can verify that the core dumps work only after installing and running SQream. This causes the server to crash and a new core.xxx file to be included in the folder that is written in **/etc/sysctl.conf** + +**To verify that the core dumps work:** + +1. Stop and restart all SQream services. + +2. Connect to SQream with ClientCmd and run the following command: + + .. code-block:: console + + $ select abort_server(); + + +.. + **Comment: - what did the author mean by "Stage 3"?** + +Troubleshooting Core Dumping +--------------------------------------------------- +This section describes the troubleshooting procedure to be followed if all parameters have been configured correctly, but the cores have not been created. + +**To troubleshoot core dumping:** + +1. Reboot the server. + +2. Verify that you have folder permissions: + + .. code-block:: console + + $ sudo chmod -R 777 /tmp/core_dumps + +3. Verify that the limits have been set correctly: + + .. code-block:: console + + $ ulimit -c + + If all parameters have been configured correctly, the correct output is: + + .. code-block:: console + + $ unlimited + +4. If all parameters have been configured correctly, but running **ulimit -c** outputs **0**, run the following: + + .. code-block:: console + + $ sudo vim /etc/profile + +5. Search for line and tag it with the **hash** symbol: + + .. code-block:: console + + $ ulimit -S -c 0 > /dev/null 2>&1 + + +6. If the line is not found in **/etc/profile** directory, do the following: + + a. Run the following command: + + .. code-block:: console + + $ sudo vim /etc/init.d/functions + + b. Search for the following: + + .. code-block:: console + + $ ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 + + c. If the line is found, tag it with the **hash** symbol and reboot the server. diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst new file mode 100644 index 000000000..35b96b3be --- /dev/null +++ b/installation_guides/running_sqream_in_a_docker_container.rst @@ -0,0 +1,1490 @@ +.. _running_sqream_in_a_docker_container: + + + +*********************** +Installing and Running SQream in a Docker Container +*********************** +The **Running SQream in a Docker Container** page describes how to prepare your machine's environment for installing and running SQream in a Docker container. + +This page describes the following: + +.. contents:: + :local: + :depth: 1 + +Setting Up a Host +==================================== + +Operating System Requirements +------------------------------------ +SQream was tested and verified on the following versions of Linux: + + * x86 CentOS/RHEL 7.6 - 7.9 + * IBM RHEL 7.6 + +SQream recommends installing a clean OS on the host to avoid any installation issues. + +.. warning:: Docker-based installation supports only single host deployment and cannot be used on a multi-node cluster. Installing Docker on a single host you will not be able to scale it to a multi-node cluster. + + +Creating a Local User +---------------- +To run SQream in a Docker container you must create a local user. + +**To create a local user:** + +1. Add a local user: + + .. code-block:: console + + $ useradd -m -U + +2. Set the local user's password: + + .. code-block:: console + + $ passwd + +3. Add the local user to the ``wheel`` group: + + .. code-block:: console + + $ usermod -aG wheel + + You can remove the local user from the ``wheel`` group when you have completed the installation. + +4. Log out and log back in as the local user. + +Setting a Local Language +---------------- +After creating a local user you must set a local language. + +**To set a local language:** + +1. Set the local language: + + .. code-block:: console + + $ sudo localectl set-locale LANG=en_US.UTF-8 + +2. Set the time stamp (time and date) of the locale: + + .. code-block:: console + + $ sudo timedatectl set-timezone Asia/Jerusalem + +You can run the ``timedatectl list-timezones`` command to see your timezone. + +Adding the EPEL Repository +---------------- +After setting a local language you must add the EPEL repository. + +**To add the EPEL repository:** + +1. As a root user, upgrade the **epel-release-latest-7.noarch.rpm** repository: + + 1. RedHat (RHEL 7): + + .. code-block:: console + + $ sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + + 2. CentOS 7 + + .. code-block:: console + + $ sudo yum install epel-release + +Installing the Required NTP Packages +---------------- +After adding the EPEL repository, you must install the required NTP packages. + +You can install the required NTP packages by running the following command: + +.. code-block:: console + + $ sudo yum install ntp pciutils python36 kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc + +Installing the Recommended Tools +---------------- +After installin gthe required NTP packages you must install the recommended tools. + +SQream recommends installing the following recommended tools: + +.. code-block:: console + + $ sudo yum install bash-completion.noarch vim-enhanced.x86_64 vim-common.x86_64 net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix + +Updating to the Current Version of the Operating System +---------------- +After installing the recommended tools you must update to the current version of the operating system. + +SQream recommends updating to the current version of the operating system. This is not recommended if the nvidia driver has **not been installed.** + + + +Configuring the NTP Package +---------------- +After updating to the current version of the operating system you must configure the NTP package. + +**To configure the NTP package:** + +1. Add your local servers to the NTP configuration. + + :: + +2. Configure the **ntpd** service to begin running when your machine is started: + + .. code-block:: console + + $ sudo systemctl enable ntpd + $ sudo systemctl start ntpd + $ sudo ntpq -p + +Configuring the Performance Profile +---------------- +After configuring the NTP package you must configure the performance profile. + +**To configure the performance profile:** + +1. Switch the active profile: + + .. code-block:: console + + $ sudo tuned-adm profile throughput-performance + +2. Change the multi-user's default run level: + + .. code-block:: console + + $ sudo systemctl set-default multi-user.target + +Configuring Your Security Limits +---------------- +After configuring the performance profile you must configure your security limits. Configuring your security limits refers to configuring the number of open files, processes, etc. + +**To configure your security limits:** + +1. Run the **bash** shell as a super-user: + + .. code-block:: console + + $ sudo bash + +2. Run the following command: + + .. code-block:: console + + $ echo -e "sqream soft nproc 500000\nsqream hard nproc 500000\nsqream soft nofile 500000\nsqream hard nofile 500000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + +3. Run the following command: + + .. code-block:: console + + $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.zone_reclaim_mode = 0 \n vm.vfs_cache_pressure = 200 \n" >> /etc/sysctl.conf + +Disabling Automatic Bug-Reporting Tools +---------------- +After configuring your security limits you must disable the following automatic bug-reporting tools: + +* ccpp.service +* oops.service +* pstoreoops.service +* vmcore.service +* xorg.service + +You can abort the above but-reporting tools by running the following command: + +.. code-block:: console + + $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done + +Installing the Nvidia CUDA Driver +------------------------------------- + +1. Verify that the Tesla NVIDIA card has been installed and is detected by the system: + + .. code-block:: console + + $ lspci | grep -i nvidia + + The correct output is a list of Nvidia graphic cards. If you do not receive this output, verify that an NVIDIA GPU card has been installed. + +#. Verify that the open-source upstream Nvidia driver is running: + + .. code-block:: console + + $ lsmod | grep nouveau + + No output should be generated. + +#. If you receive any output, do the following: + + 1. Disable the open-source upstream Nvidia driver: + + .. code-block:: console + + $ sudo bash + $ echo "blacklist nouveau" > /etc/modprobe.d/blacklist-nouveau.conf + $ echo "options nouveau modeset=0" >> /etc/modprobe.d/blacklist-nouveau.conf + $ dracut --force + $ modprobe --showconfig | grep nouveau + + 2. Reboot the server and verify that the Nouveau model has not been loaded: + + .. code-block:: console + + $ lsmod | grep nouveau + +#. Check if the Nvidia CUDA driver has already been installed: + + .. code-block:: console + + $ nvidia-smi + + The following is an example of the correct output: + + .. code-block:: console + + nvidia-smi + Wed Oct 30 14:05:42 2019 + +-----------------------------------------------------------------------------+ + | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + |-------------------------------+----------------------+----------------------+ + | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + |===============================+======================+======================| + | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | + | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | + | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + + +-----------------------------------------------------------------------------+ + | Processes: GPU Memory | + | GPU PID Type Process name Usage | + |=============================================================================| + | No running processes found | + +-----------------------------------------------------------------------------+ + +#. Verify that the installed CUDA version shown in the output above is ``10.1``. + + :: + + +#. Do one of the following: + + :: + + 1. If CUDA version 10.1 has already been installed, skip to Docktime Runtime (Community Edition). + :: + + 2. If CUDA version 10.1 has not been installed yet, continue with Step 7 below. + +#. Do one of the following: + + * Install :ref:`CUDA Driver version 10.1 for x86_64 `. + + :: + + * Install :ref:`CUDA driver version 10.1 for IBM Power9 `. + +.. _CUDA_10.1_x8664: + +Installing the CUDA Driver Version 10.1 for x86_64 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the CUDA driver version 10.1 for x86_64:** + +1. Make the following target platform selections: + + :: + + * **Operating system**: Linux + * **Architecture**: x86_64 + * **Distribution**: CentOS + * **Version**: 7 + * **Installer type**: the relevant installer type + +For installer type, SQream recommends selecting **runfile (local)**. The available selections shows only the supported platforms. + +2. Download the base installer for Linux CentOS 7 x86_64: + + .. code-block:: console + + wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm + + +3. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: + + .. code-block:: console + + $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm + $ sudo yum clean all + $ sudo yum install nvidia-driver-latest-dkms + +.. warning:: Verify that the output indicates that driver **418.87** will be installed. + +4. Follow the command line prompts. + + + :: + + +5. Enable the Nvidia service to start at boot and start it: + + .. code-block:: console + + $ sudo systemctl enable nvidia-persistenced.service && sudo systemctl start nvidia-persistenced.service + +6. Create a symbolic link from the **/etc/systemd/system/multi-user.target.wants/nvidia-persistenced.service** file to the **/usr/lib/systemd/system/nvidia-persistenced.service** file. + + :: + +7. Reboot the server. + + :: +8. Verify that the Nvidia driver has been installed and shows all available GPU's: + + .. code-block:: console + + $ nvidia-smi + + The following is the correct output: + + .. code-block:: console + + nvidia-smi + Wed Oct 30 14:05:42 2019 + +-----------------------------------------------------------------------------+ + | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + |-------------------------------+----------------------+----------------------+ + | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + |===============================+======================+======================| + | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | + | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | + | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + + +-----------------------------------------------------------------------------+ + | Processes: GPU Memory | + | GPU PID Type Process name Usage | + |=============================================================================| + | No running processes found | + +-----------------------------------------------------------------------------+ + +.. _CUDA_10.1_IBMPower9: + +Installing the CUDA Driver Version 10.1 for IBM Power9 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the CUDA driver version 10.1 for IBM Power9:** + +1. Download the base installer for Linux CentOS 7 PPC64le: + + .. code-block:: console + + wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm + + +#. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: + + .. code-block:: console + + $ sudo rpm -i cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm + $ sudo yum clean all + $ sudo yum install nvidia-driver-latest-dkms + +.. warning:: Verify that the output indicates that driver **418.87** will be installed. + + + +3. Copy the file to the **/etc/udev/rules.d** directory. + + :: + +4. If you are using RHEL 7 version (7.6 or later), comment out, remove, or change the hot-pluggable memory rule located in file copied to the **/etc/udev/rules.d** directory by running the following command: + + .. code-block:: console + + $ sudo cp /lib/udev/rules.d/40-redhat.rules /etc/udev/rules.d + $ sudo sed -i 's/SUBSYSTEM!="memory",.*GOTO="memory_hotplug_end"/SUBSYSTEM=="*", GOTO="memory_hotplug_end"/' /etc/udev/rules.d/40-redhat.rules + +#. Enable the **nvidia-persisted.service** file: + + .. code-block:: console + + $ sudo systemctl enable nvidia-persistenced.service + +#. Create a symbolic link from the **/etc/systemd/system/multi-user.target.wants/nvidia-persistenced.service** file to the **/usr/lib/systemd/system/nvidia-persistenced.service** file. + + :: + +#. Reboot your system to initialize the above modifications. + + :: + +#. Verify that the Nvidia driver and the **nvidia-persistenced.service** files are running: + + .. code-block:: console + + $ nvidia smi + + The following is the correct output: + + .. code-block:: console + + nvidia-smi + Wed Oct 30 14:05:42 2019 + +-----------------------------------------------------------------------------+ + | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + |-------------------------------+----------------------+----------------------+ + | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + |===============================+======================+======================| + | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | + | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | + | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | + +-------------------------------+----------------------+----------------------+ + + +-----------------------------------------------------------------------------+ + | Processes: GPU Memory | + | GPU PID Type Process name Usage | + |=============================================================================| + | No running processes found | + +-----------------------------------------------------------------------------+ + +#. Verify that the **nvidia-persistenced** service is running: + + .. code-block:: console + + $ systemctl status nvidia-persistenced + + The following is the correct output: + + .. code-block:: console + + root@gpudb ~]systemctl status nvidia-persistenced + nvidia-persistenced.service - NVIDIA Persistence Daemon + Loaded: loaded (/usr/lib/systemd/system/nvidia-persistenced.service; enabled; vendor preset: disabled) + Active: active (running) since Tue 2019-10-15 21:43:19 KST; 11min ago + Process: 8257 ExecStart=/usr/bin/nvidia-persistenced --verbose (code=exited, status=0/SUCCESS) + Main PID: 8265 (nvidia-persiste) + Tasks: 1 + Memory: 21.0M + CGroup: /system.slice/nvidia-persistenced.service + └─8265 /usr/bin/nvidia-persistenced --verbose + +Installing the Docker Engine (Community Edition) +======================= +After installing the Nvidia CUDA driver you must install the Docker engine. + +This section describes how to install the Docker engine using the following processors: + +* :ref:`Using x86_64 processor on CentOS ` +* :ref:`Using x86_64 processor on Ubuntu ` +* :ref:`Using IBM Power9 (PPC64le) processor ` + + +.. _dockerx8664centos: + +Installing the Docker Engine Using an x86_64 Processor on CentOS +--------------------------------- +The x86_64 processor supports installing the **Docker Community Edition (CE)** versions 18.03 and higher. + +For more information on installing the Docker Engine CE on an x86_64 processor, see `Install Docker Engine on CentOS `_ + + + +.. _dockerx8664ubuntu: + +Installing the Docker Engine Using an x86_64 Processor on Ubuntu +----------------------------------------------------- + + +The x86_64 processor supports installing the **Docker Community Edition (CE)** versions 18.03 and higher. + +For more information on installing the Docker Engine CE on an x86_64 processor, see `Install Docker Engine on Ubuntu `_ + +.. _docker_ibmpower9: + +Installing the Docker Engine on an IBM Power9 Processor +---------------------------------------- +The x86_64 processor only supports installing the **Docker Community Edition (CE)** version 18.03. + + +**To install the Docker Engine on an IBM Power9 processor:** + +You can install the Docker Engine on an IBM Power9 processor by running the following command: + +.. code-block:: console + + $ wget + $ http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm + $ wget + $ http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm + $ yum install -y container-selinux-2.9-4.el7.noarch.rpm + $ docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm + + + +For more information on installing the Docker Engine CE on an IBM Power9 processor, see `Install Docker Engine on Ubuntu `_. + +Docker Post-Installation +================================= +After installing the Docker engine you must configure Docker on your local machine. + +**To configure Docker on your local machine:** + +1. Enable Docker to start on boot: + + .. code-block:: console + + $ sudo systemctl enable docker && sudo systemctl start docker + +2. Enable managing Docker as a non-root user: + + .. code-block:: console + + $ sudo usermod -aG docker $USER + +3. Log out and log back in via SSH. This causes Docker to re-evaluate your group membership. + + :: + +4. Verify that you can run the following Docker command as a non-root user (without ``sudo``): + + .. code-block:: console + + $ docker run hello-world + +If you can run the above Docker command as a non-root user, the following occur: + +* Docker downloads a test image and runs it in a container. +* When the container runs, it prints an informational message and exits. + +For more information on installing the Docker Post-Installation, see `Docker Post-Installation `_. + +Installing the Nvidia Docker2 ToolKit +========================================== +After configuring Docker on your local machine you must install the Nvidia Docker2 ToolKit. The NVIDIA Docker2 Toolkit lets you build and run GPU-accelerated Docker containers. The Toolkit includes a container runtime library and related utilities for automatically configuring containers to leverage NVIDIA GPU's. + +This section describes the following: + +* :ref:`Installing the NVIDIA Docker2 Toolkit on an x86_64 processor. ` +* :ref:`Installing the NVIDIA Docker2 Toolkit on a PPC64le processor. ` + +.. _install_nvidia_docker2_toolkit_x8664_processor: + +Installing the NVIDIA Docker2 Toolkit on an x86_64 Processor +---------------------------------------- + +This section describes the following: + +* :ref:`Installing the NVIDIA Docker2 Toolkit on a CentOS operating system ` + +* :ref:`Installing the NVIDIA Docker2 Toolkit on an Ubuntu operating system ` + +.. _install_nvidia_docker2_toolkit_centos: + +Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the NVIDIA Docker2 Toolkit on a CentOS operating system:** + +1. Install the repository for your distribution: + + .. code-block:: console + + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L + $ https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ + $ sudo tee /etc/yum.repos.d/nvidia-docker.repo + +2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: + + .. code-block:: console + + $ sudo yum install nvidia-docker2 + $ sudo pkill -SIGHUP dockerd + +3. Do one of the following: + + * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 `. + * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 `. + +.. _step_4_centos: + +4. Do the following: + + 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: + + + .. code-block:: console + + https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: + [Errno -1] repomd.xml signature could not be verified for nvidia-docker + + 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. + +.. _step_5_centos: + +5. Verify that the NVIDIA-Docker run has been installed correctly: + + .. code-block:: console + + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + +For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on a CentOS operating system ` + + +.. _install_nvidia_docker2_toolkit_ubuntu: + +Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To install the NVIDIA Docker2 Toolkit on an Ubuntu operating system:** + +1. Install the repository for your distribution: + + .. code-block:: console + + $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \ + $ sudo apt-key add - + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L + $ https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \ + $ sudo tee /etc/apt/sources.list.d/nvidia-docker.list + $ sudo apt-get update + +2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: + + .. code-block:: console + + $ sudo apt-get install nvidia-docker2 + $ sudo pkill -SIGHUP dockerd +3. Do one of the following: + * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 `. + * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 `. + + .. _step_4_ubuntu: + +4. Do the following: + + 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: + + .. code-block:: console + + https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: + [Errno -1] repomd.xml signature could not be verified for nvidia-docker + + 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. + +.. _step_5_ubuntu: + +5. Verify that the NVIDIA-Docker run has been installed correctly: + + .. code-block:: console + + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + +For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on an Ubuntu operating system ` + +.. _install_nvidia_docker2_toolkit_ppc64le_processor: + +Installing the NVIDIA Docker2 Toolkit on a PPC64le Processor +-------------------------------------- + +This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL operating system: + +**To install the NVIDIA Docker2 Toolkit on an IBM RHEL operating system:** + +1. Import the repository and install the ``libnvidia-container`` and the ``nvidia-container-runtime`` containers. + + .. code-block:: console + + $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ + sudo tee /etc/yum.repos.d/nvidia-docker.repo + $ sudo yum install -y libnvidia-container* + +2. Do one of the following: + + * If you received an error when installing the containers, skip to :ref:`Step 3 `. + * If you successfully installed the containers, skip to :ref:`Step 4 `. + +.. _step_3_installing_nvidia_docker2_toolkit_ppc64le_processor: + +3. Do the following: + + 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the containers: + + .. code-block:: console + + https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: + [Errno -1] repomd.xml signature could not be verified for nvidia-docker + + 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. + + :: + + 3. Install the ``libnvidia-container`` container. + + .. code-block:: console + + $ sudo yum install -y libnvidia-container* + + .. _step_4_installing_nvidia_docker2_toolkit_ppc64le_processor: + +4. Install the ``nvidia-container-runtime`` container: + + .. code-block:: console + + $ sudo yum install -y nvidia-container-runtime* + +5. Add ``nvidia runtime`` to the Docker daemon: + + .. code-block:: console + + $ sudo mkdir -p /etc/systemd/system/docker.service.d/ + $ sudo vi /etc/systemd/system/docker.service.d/override.conf + + $ [Service] + $ ExecStart= + $ ExecStart=/usr/bin/dockerd + +6. Restart Docker: + + .. code-block:: console + + $ sudo systemctl daemon-reload + $ sudo systemctl restart docker + +7. Verify that the NVIDIA-Docker run has been installed correctly: + + .. code-block:: console + + $ docker run --runtime=nvidia --rm nvidia/cuda-ppc64le nvidia-smi + +.. _accessing_hadoop_kubernetes_configuration_files: + +Accessing the Hadoop and Kubernetes Configuration Files +-------------------------------------- +The information this section is optional and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, contact your IT department for access to the following configuration files: + +* Hadoop configuration files: + + * core-site.xml + * hdfs-site.xml + + :: + +* Kubernetes files: + + * Configuration file - krb.conf + * Kubernetes Hadoop client certificate - hdfs.keytab + +Once you have the above files, you must copy them into the correct folders in your working directory. + +For more information about the correct directory to copy the above files into, see the :ref:`Installing the SQream Software ` section below. + +For related information, see the following sections: + +* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. +* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + +.. _installing_sqream_software: + +Installing the SQream Software +============================== + +Preparing Your Local Environment +------------------------- +After installing the Nvidia Docker2 toolKit you must prepare your local environment. + +.. note:: You must install the SQream software under a *sqream* and not a *root* user. + +The Linux user preparing the local environment must have **read/write** access to the following directories for the SQream software to correctly read and write the required resources: + +* **Log directory** - default: /var/log/sqream/ +* **Configuration directory** - default: /etc/sqream/ +* **Cluster directory** - the location where SQream writes its DB system, such as */mnt/sqreamdb* +* **Ingest directory** - the location where the required data is loaded, such as */mnt/data_source/* + +.. _download_sqream_software: + +Deploying the SQream Software +------------------------- +After preparing your local environment you must deploy the SQream software. Deploying the SQream software requires you to access and extract the required files and to place them in the correct directory. + +**To deploy the SQream software:** + +1. Contact the SQream Support team for access to the **sqream_installer-nnn-DBnnn-COnnn-EDnnn-.tar.gz** file. + +The **sqream_installer-nnn-DBnnn-COnnn-EDnnn-.tar.gz** file includes the following parameter values: + +* **sqream_installer-nnn** - sqream installer version +* **DBnnn** - SQreamDB version +* **COnnn** - SQream console version +* **EDnnn** - SQream editor version +* **arch** - server arch (applicable to X86.64 and ppc64le) + +2. Extract the tarball file: + + .. code-block:: console + + $ tar -xvf sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz + +When the tarball file has been extracted, a new folder will be created. The new folder is automatically given the name of the tarball file: + + .. code-block:: console + + drwxrwxr-x 9 sqream sqream 4096 Aug 11 11:51 sqream_istaller-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64/ + -rw-rw-r-- 1 sqream sqream 3130398797 Aug 11 11:20 sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz + +3. Change the directory to the new folder that you created in the previous step. + +:: + +4. Verify that the folder you just created contains all of the required files. + + .. code-block:: console + + $ ls -la + + The following is an example of the files included in the new folder: + + .. code-block:: console + + drwxrwxr-x. 10 sqream sqream 198 Jun 3 17:57 . + drwx------. 25 sqream sqream 4096 Jun 7 18:11 .. + drwxrwxr-x. 2 sqream sqream 226 Jun 7 18:09 .docker + drwxrwxr-x. 2 sqream sqream 64 Jun 3 12:55 .hadoop + drwxrwxr-x. 2 sqream sqream 4096 May 31 14:18 .install + drwxrwxr-x. 2 sqream sqream 39 Jun 3 12:53 .krb5 + drwxrwxr-x. 2 sqream sqream 22 May 31 14:18 license + drwxrwxr-x. 2 sqream sqream 82 May 31 14:18 .sqream + -rwxrwxr-x. 1 sqream sqream 1712 May 31 14:18 sqream-console + -rwxrwxr-x. 1 sqream sqream 4608 May 31 14:18 sqream-install + +For information relevant to Hadoop users, see the following sections: + +* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. +* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. +* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + +.. _configure_hadoop_kubernetes_configuration_files: + +Configuring the Hadoop and Kubernetes Configuration Files +----------------------------- +The information in this section is optional and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, you must copy the Hadoop and Kubernetes files into the correct folders in your working directory as shown below: + +* .hadoop/core-site.xml +* .hadoop/hdfs-site.xml +* .krb5/krb5.conf +* .krb5/hdfs.keytab + +For related information, see the following sections: + +* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. +* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + +Configuring the SQream Software +------------------------------- +After deploying the SQream software, and optionally configuring the Hadoop and Kubernetes configuration files, you must configure the SQream software. + +Configuring the SQream software requires you to do the following: + +* Configure your local environment +* Understand the ``sqream-install`` flags +* Install your SQream license +* Validate your SQream icense +* Change your data ingest folder + +Configuring Your Local Environment +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've downloaded the SQream software, you can begin configuring your local environment. The following commands must be run (as **sudo**) from the same directory that you located your packages. + +For example, you may have saved your packages in **/home/sqream/sqream-console-package/**. + +The following table shows the flags that you can use to configure your local directory: + +.. list-table:: + :widths: 10 50 40 + :header-rows: 1 + + * - Flag + - Function + - Note + * - **-i** + - Loads all software from the hidden folder **.docker**. + - Mandatory + * - **-k** + - Loads all license packages from the **/license** directory. + - Mandatory + * - **-f** + - Overwrites existing folders. **Note** Using ``-f`` overwrites **all files** located in mounted directories. + - Mandatory + * - **-c** + - Defines the origin path for writing/reading SQream configuration files. The default location is ``/etc/sqream/``. + - If you are installing the Docker version on a server that already works with SQream, do not use the default path. + * - **-v** + - The SQream cluster location. If a cluster does not exist yet, ``-v`` creates one. If a cluster already exists, ``-v`` mounts it. + - Mandatory + * - **-l** + - SQream system startup logs location, including startup logs and docker logs. The default location is ``/var/log/sqream/``. + - + * - **-d** + - The directory containing customer data to be imported and/or copied to SQream. + - + * - **-s** + - Shows system settings. + - + * - **-r** + - Resets the system configuration. This value is run without any other variables. + - Mandatory + * - **-h** + - Help. Shows the available flags. + - Mandatory + * - **-K** + - Runs license validation + - + * - **-e** + - Used for inserting your RKrb5 server DNS name. For more information on setting your Kerberos configuration parameters, see :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + - + * - **-p** + - Used for inserting your Kerberos user name. For more information on setting your Kerberos configuration parameters, see :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. + - + + +Installing Your License +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've configured your local environment, you must install your license by copying it into the SQream installation package folder located in the **./license** folder: + +.. code-block:: console + + $ sudo ./sqream-install -k + +You do not need to extract this folder after uploading into the **./license**. + + +Validating Your License +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You can copy your license package into the SQream console folder located in the **/license** folder by running the following command: + +.. code-block:: console + + $ sudo ./sqream-install -K + +The following mandatory flags must be used in the first run: + +.. code-block:: console + + $ sudo ./sqream-install -i -k -v + +The following is an example of the correct command syntax: + +.. code-block:: console + + $ sudo ./sqream-install -i -k -c /etc/sqream -v /home/sqream/sqreamdb -l /var/log/sqream -d /home/sqream/data_ingest + +.. _setting_hadoop_kubernetes_connectivity_parameters: + +Setting the Hadoop and Kubernetes Connectivity Parameters +------------------------------- +The information in this section is optional, and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, you must set their connectivity parameters. + +The following is the correct syntax when setting the Hadoop and Kubernetes connectivity parameters: + +.. code-block:: console + + $ sudo ./sqream-install -p -e : + +The following is an example of setting the Hadoop and Kubernetes connectivity parameters: + +.. code-block:: console + + $ sudo ./sqream-install -p -e kdc.sq.com:<192.168.1.111> + +For related information, see the following sections: + +* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. +* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. + +Modifying Your Data Ingest Folder +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've validated your license, you can modify your data ingest folder after the first run by running the following command: + +.. code-block:: console + + $ sudo ./sqream-install -d /home/sqream/data_in + +Configuring Your Network for Docker +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've modified your data ingest folder (if needed), you must validate that the server network and Docker network that you are setting up do not overlap. + +**To configure your network for Docker:** + +1. To verify that your server network and Docker network do not overlap, run the following command: + +.. code-block:: console + + $ ifconfig | grep 172. + +2. Do one of the following: + + * If running the above command output no results, continue the installation process. + * If running the above command output results, run the following command: + + .. code-block:: console + + $ ifconfig | grep 192.168. + + +Checking and Verifying Your System Settings +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once you've configured your network for Docker, you can check and verify your system settings. + +Running the following command shows you all the variables used by your SQream system: + +.. code-block:: console + + $ ./sqream-install -s + +The following is an example of the correct output: + +.. code-block:: console + + SQREAM_CONSOLE_TAG=1.5.4 + SQREAM_TAG=2019.2.1 + SQREAM_EDITOR_TAG=3.0.0 + license_worker_0=f0:cc: + license_worker_1=26:91: + license_worker_2=20:26: + license_worker_3=00:36: + SQREAM_VOLUME=/media/sqreamdb + SQREAM_DATA_INGEST=/media/sqreamdb/data_in + SQREAM_CONFIG_DIR=/etc/sqream/ + LICENSE_VALID=true + SQREAM_LOG_DIR=/var/log/sqream/ + SQREAM_USER=sqream + SQREAM_HOME=/home/sqream + SQREAM_ENV_PATH=/home/sqream/.sqream/env_file + PROCESSOR=x86_64 + METADATA_PORT=3105 + PICKER_PORT=3108 + NUM_OF_GPUS=2 + CUDA_VERSION=10.1 + NVIDIA_SMI_PATH=/usr/bin/nvidia-smi + DOCKER_PATH=/usr/bin/docker + NVIDIA_DRIVER=418 + SQREAM_MODE=single_host + +Using the SQream Console +========================= +After configuring the SQream software and veriying your system settings you can begin using the SQream console. + +SQream Console - Basic Commands +--------------------------------- +The SQream console offers the following basic commands: + +* :ref:`Starting your SQream console ` +* :ref:`Starting Metadata and Picker ` +* :ref:`Starting the running services ` +* :ref:`Listing the running services ` +* :ref:`Stopping the running services ` +* :ref:`Using the SQream editor ` +* :ref:`Using the SQream Client ` + +.. _starting_sqream_console: + +Starting Your SQream Console +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can start your SQream console by running the following command: + +.. code-block:: console + + $ ./sqream-console + +.. _starting_metadata_and_picker: + +Starting the SQream Master +~~~~~~~~~~~~~~~~~ + +**To listen to metadata and picker:** + +1. Start the metadata server (default port 3105) and picker (default port 3108) by running the following command: + + .. code-block:: console + + $ sqream master --start + + The following is the correct output: + + .. code-block:: console + + sqream-console> sqream master --start + starting master server in single_host mode ... + sqream_single_host_master is up and listening on ports: 3105,3108 + + +2. *Optional* - Change the metadata and server picker ports by adding ``-p `` and ``-m ``: + + .. code-block:: console + + $ sqream-console>sqream master --start -p 4105 -m 43108 + $ starting master server in single_host mode ... + $ sqream_single_host_master is up and listening on ports: 4105,4108 + + + +.. _starting_running_services: + +Starting SQream Workers +~~~~~~~~~~~~~~~~~ + + +When starting SQream workers, setting the ```` value sets how many workers to start. Leaving the ```` value unspecified runs all of the available resources. + + +.. code-block:: console + + $ sqream worker --start + + The following is an example of expected output when setting the ```` value to ``2``: + + .. code-block:: console + + sqream-console>sqream worker --start 2 + started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 + started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 + + +.. _listing_running_services: + +Listing the Running Services +~~~~~~~~~~~~~~~~~ + +You can list running SQream services to look for container names and ID's by running the following command: + +.. code-block:: console + + $ sqream master --list + +The following is an example of the expected output: + +.. code-block:: console + + sqream-console>sqream master --list + container name: sqream_single_host_worker_0, container id: c919e8fb78c8 + container name: sqream_single_host_master, container id: ea7eef80e038-- + + +.. _stopping_running_services: + +Stopping the Running Services +~~~~~~~~~~~~~~~~~ + +You can stop running services either for a single SQream worker, or all SQream services for both master and worker. + +The following is the command for stopping a running service for a single SQream worker: + +.. code-block:: console + + $ sqream worker --stop + +The following is an example of expected output when stopping a running service for a single SQream worker: + +.. code-block:: console + + sqream worker stop + stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 + + +You can stop all running SQream services (both master and worker) by running the following command: + +.. code-block:: console + + $ sqream-console>sqream master --stop --all + +The following is an example of expected output when stopping all running services: + +.. code-block:: console + + sqream-console>sqream master --stop --all + stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 + stopped container sqream_single_host_master, id: 55cb7e38eb22 + + +.. _using_sqream_editor: + +Using SQream Studio +~~~~~~~~~~~~~~~~~ +SQream Studio is an SQL statement editor. + +**To start SQream Studio:** + +1. Run the following command: + + .. code-block:: console + + $ sqream studio --start + +The following is an example of the expected output: + + .. code-block:: console + + SQream Acceleration Studio is available at http://192.168.1.62:8080 + +2. Click the ``http://192.168.1.62:8080`` link shown in the CLI. + + +**To stop SQream Studio:** + +You can stop your SQream Studio by running the following command: + +.. code-block:: console + + $ sqream studio --stop + +The following is an example of the expected output: + +.. code-block:: console + + sqream_admin stopped + + +.. _using_sqream_client: + +Using the SQream Client +~~~~~~~~~~~~~~~~~ + + +You can use the embedded SQream Client on the following nodes: + +* Master node +* Worker node + + +When using the SQream Client on the Master node, the following default settings are used: + +* **Default port**: 3108. You can change the default port using the ``-p`` variable. +* **Default database**: master. You can change the default database using the ``-d`` variable. + +The following is an example: + +.. code-block:: console + + $ sqream client --master -u sqream -w sqream + + +When using the SQream Client on a Worker node (or nodes), you should use the ``-p`` variable for Worker ports. The default database is ``master``, but you can use the ``-d`` variable to change databases. + +The following is an example: + +.. code-block:: console + + $ sqream client --worker -p 5000 -u sqream -w sqream + + +Moving from Docker Installation to Standard On-Premises Installation +----------------------------------------------- + +Because Docker creates all files and directories on the host at the **root** level, you must grant ownership of the SQream storage folder to the working directory user. + +SQream Console - Advanced Commands +----------------------------- + +The SQream console offers the following advanced commands: + + +* :ref:`Controlling the spool size ` +* :ref:`Splitting a GPU ` +* :ref:`Splitting a GPU and setting the spool size ` +* :ref:`Using a custom configuration file ` +* :ref:`Clustering your Docker environment ` + + + + +.. _controlling_spool_size: + +Controlling the Spool Size +~~~~~~~~~~~~~~~~~~ + +From the console you can define a spool size value. + +The following example shows the spool size being set to ``50``: + +.. code-block:: console + + $ sqream-console>sqream worker --start 2 -m 50 + + +If you don't define the SQream spool size, the SQream console automatically distributes the available RAM between all running workers. + +.. _splitting_gpu: + +Splitting a GPU +~~~~~~~~~~~~~~~~~~ + +You can start more than one sqreamd on a single GPU by splitting it. + + +The following example shows the GPU being split into **two** sqreamd's on the GPU in **slot 0**: + +.. code-block:: console + + $ sqream-console>sqream worker --start 2 -g 0 + +.. _splitting_gpu_setting_spool_size: + +Splitting GPU and Setting the Spool Size +~~~~~~~~~~~~~~~~~~ + +You can simultaneously split a GPU and set the spool size by appending the ``-m`` flag: + +.. code-block:: console + + $ sqream-console>sqream worker --start 2 -g 0 -m 50 + +.. note:: The console does not validate whether the user-defined spool size is available. Before setting the spool size, verify that the requested resources are available. + +.. _using_custom_configuration_file: + +Using a Custom Configuration File +~~~~~~~~~~~~~~~~~~ + +SQream lets you use your own external custom configuration json files. You must place these json files in the path mounted in the installation. SQream recommends placing the json file in the Configuration folder. + +The SQream console does not validate the integrity of your external configuration files. + +When using your custom configuration file, you can use the ``-j`` flag to define the full path to the Configuration file, as in the example below: + +.. code-block:: console + + $ sqream-console>sqream worker --start 1 -j /etc/sqream/configfile.json + +.. note:: To start more than one sqream daemon, you must provide files for each daemon, as in the example below: + +.. code-block:: console + + $ sqream worker --start 2 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json + +.. note:: To split a specific GPU, you must also list the GPU flag, as in the example below: + +.. code-block:: console + + $ sqream worker --start 2 -g 0 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json + +.. _clustering_docker_environment: + +Clustering Your Docker Environment +~~~~~~~~~~~~~~~~~~ + +SQream lets you connect to a remote Master node to start Docker in Distributed mode. If you have already connected to a Slave node server in Distributed mode, the **sqream Master** and **Client** commands are only available on the Master node. + +.. code-block:: console + + $ --master-host + $ sqream-console>sqream worker --start 1 --master-host 192.168.0.1020 + +Checking the Status of SQream Services +--------------------------- +SQream lets you check the status of SQream services from the following locations: + +* :ref:`From the Sqream console ` +* :ref:`From outside the Sqream console ` + +.. _inside_sqream_console: + +Checking the Status of SQream Services from the SQream Console +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +From the SQream console, you can check the status of SQream services by running the following command: + +.. code-block:: console + + $ sqream-console>sqream master --list + +The following is an example of the expected output: + +.. code-block:: console + + $ sqream-console>sqream master --list + $ checking 3 sqream services: + $ sqream_single_host_worker_1 up, listens on port: 5001 allocated gpu: 1 + $ sqream_single_host_worker_0 up, listens on port: 5000 allocated gpu: 1 + $ sqream_single_host_master up listens on ports: 3105,3108 + +.. _outside_sqream_console: + +Checking the Status of SQream Services from Outside the SQream Console +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +From outside the Sqream Console, you can check the status of SQream services by running the following commands: + +.. code-block:: console + + $ sqream-status + $ NAMES STATUS PORTS + $ sqream_single_host_worker_1 Up 3 minutes 0.0.0.0:5001->5001/tcp + $ sqream_single_host_worker_0 Up 3 minutes 0.0.0.0:5000->5000/tcp + $ sqream_single_host_master Up 3 minutes 0.0.0.0:3105->3105/tcp, 0.0.0.0:3108->3108/tcp + $ sqream_editor_3.0.0 Up 3 hours (healthy) 0.0.0.0:3000->3000/tcp + +Upgrading Your SQream System +---------------------------- +This section describes how to upgrade your SQream system. + +**To upgrade your SQream system:** + +1. Contact the SQream Support team for access to the new SQream package tarball file. + + :: + +2. Set a maintenance window to enable stopping the system while upgrading it. + + :: + +3. Extract the following tarball file received from the SQream Support team, under it with the same user and in the same folder that you used while :ref:`Downloading the SQream Software <_download_sqream_software>`. + + + .. code-block:: console + + $ tar -xvf sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ + +4. Navigate to the new folder created as a result of extracting the tarball file: + + .. code-block:: console + + $ cd sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ + +5. Initiate the upgrade process: + + .. code-block:: console + + $ ./sqream-install -i + + Initiating the upgrade process checks if any SQream services are running. If any services are running, you will be prompted to stop them. + +6. Do one of the following: + + * Select **Yes** to stop all running SQream workers (Master and Editor) and continue the upgrade process. + * Select **No** to stop the upgrade process. + + SQream periodically upgrades the metadata structure. If an upgrade version includes a change to the metadata structure, you will be prompted with an approval request message. Your approval is required to finish the upgrade process. + + Because SQream supports only certain metadata versions, all SQream services must be upgraded at the same time. + +7. When the upgrade is complete, load the SQream console and restart your services. + + For assistance, contact SQream Support. diff --git a/installation_guides/sqream_studio_installation.rst b/installation_guides/sqream_studio_installation.rst new file mode 100644 index 000000000..751e56dc7 --- /dev/null +++ b/installation_guides/sqream_studio_installation.rst @@ -0,0 +1,20 @@ +.. _sqream_studio_installation: + +************************* +Installing SQream Studio +************************* +The **Installing SQream Studio** page incudes the following installation guides: + +.. toctree:: + :maxdepth: 1 + :glob: + + running_sqream_in_a_docker_container + installing_studio_on_stand_alone_server + installing_prometheus_exporters + installing_prometheus_using_binary_packages + installing_dashboard_data_collector + + + + From cecbeac2322576c444e0cccd55fdb85e4976738d Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 12 Jan 2022 11:08:27 +0200 Subject: [PATCH 167/300] Update index.rst Added installation_guides/index --- index.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.rst b/index.rst index 858106ae6..d8e1bb996 100644 --- a/index.rst +++ b/index.rst @@ -90,9 +90,10 @@ If you're looking for an older version of the documentation, versions 1.10 throu :titlesonly: :hidden: - first_steps xxfeatures_tour + first_steps guides/index + installation_guides/index reference/index releases/index glossary From 6f0c08ebee330219fa2100eae6e9843504330fc3 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 12 Jan 2022 12:27:29 +0200 Subject: [PATCH 168/300] Updated Index Will merge this branch with 2020.1 (THE PRIVATE BRANCH, not 2020-1). --- installation_guides/index.rst | 9 +++++---- .../installing_and_launching_sqream.rst | 19 +++++++++++++++++++ .../sqream_studio_installation.rst | 1 - 3 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 installation_guides/installing_and_launching_sqream.rst diff --git a/installation_guides/index.rst b/installation_guides/index.rst index 7fd1014f3..d77e357be 100644 --- a/installation_guides/index.rst +++ b/installation_guides/index.rst @@ -11,11 +11,12 @@ The **Installation Guides** page incudes the following installation guides: :glob: sqream_studio_installation - recommended_pre-installation_configurations + installing_and_launching_sqream + xxrecommended_pre-installation_configurations xxrunning_sqream_in_a_docker_container - installing_sqream_with_binary - installing_monit - installing_sqream_with_kubernetes + xxinstalling_sqream_with_binary + xxinstalling_monit + xxinstalling_sqream_with_kubernetes xxinstalling_prometheus_exporters xxinstalling_studio_on_stand_alone_server diff --git a/installation_guides/installing_and_launching_sqream.rst b/installation_guides/installing_and_launching_sqream.rst new file mode 100644 index 000000000..7953f7cc3 --- /dev/null +++ b/installation_guides/installing_and_launching_sqream.rst @@ -0,0 +1,19 @@ +.. _installing_and_launching_sqream: + +************************* +Installing and Launching SQream +************************* +The **Installing SQream Studio** page incudes the following installation guides: + +.. toctree:: + :maxdepth: 1 + :glob: + + recommended_pre-installation_configurations + installing_sqream_with_binary + running_sqream_in_a_docker_container + installing_sqream_with_kubernetes + installing_monit + + + diff --git a/installation_guides/sqream_studio_installation.rst b/installation_guides/sqream_studio_installation.rst index 751e56dc7..8d6c16546 100644 --- a/installation_guides/sqream_studio_installation.rst +++ b/installation_guides/sqream_studio_installation.rst @@ -9,7 +9,6 @@ The **Installing SQream Studio** page incudes the following installation guides: :maxdepth: 1 :glob: - running_sqream_in_a_docker_container installing_studio_on_stand_alone_server installing_prometheus_exporters installing_prometheus_using_binary_packages From 46d5aa23eb0405e0f06af865fb1ed454cdc7501b Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 12 Jan 2022 15:24:47 +0200 Subject: [PATCH 169/300] Update index.rst xx'd out certain pages. --- guides/operations/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/operations/index.rst b/guides/operations/index.rst index fb1eedb4a..174de1fd3 100644 --- a/guides/operations/index.rst +++ b/guides/operations/index.rst @@ -12,7 +12,7 @@ The guides in this section include information about best practices, monitoring, :glob: optimization_best_practices - recommended_pre-installation_configurations + xxrecommended_pre-installation_configurations xxinstalling_monit xxlaunching_sqream_with_monit xxinstalling_sqream_with_binary From ba9259cd755f6765d68d0da1d86457165253d380 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 12 Jan 2022 16:14:29 +0200 Subject: [PATCH 170/300] Update first_steps.rst --- first_steps.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/first_steps.rst b/first_steps.rst index a3a37fa33..805517b0e 100644 --- a/first_steps.rst +++ b/first_steps.rst @@ -46,7 +46,7 @@ Before installing SQream, do the following: For more information, see the following: * `Hardware Guide `_ -* `Recommended Pre-Installation Configuration `_ +* `Recommended Pre-Installation Configuration `_ From 38701fba53078bf39574eb30b24cdd553a8fe035 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 16 Jan 2022 12:18:53 +0200 Subject: [PATCH 171/300] Update conf.py Corrected Line 29: release = '2020.3.2.1' --- conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf.py b/conf.py index 707f6e0f9..c6b56c9e9 100644 --- a/conf.py +++ b/conf.py @@ -26,7 +26,7 @@ # The full version, including alpha/beta/rc tags -release = '2020.3.2' +release = '2020.3.2.1' @@ -110,4 +110,4 @@ base_version = release.split('-')[0] rst_epilog = """ .. |latest_version| replace:: v{} -""".format(base_version) \ No newline at end of file +""".format(base_version) From 09320ea0b0336e2d2664e220ff65938daf1d0891 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 19 Jan 2022 12:52:36 +0200 Subject: [PATCH 172/300] Update index.rst --- guides/operations/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/guides/operations/index.rst b/guides/operations/index.rst index 174de1fd3..500249e83 100644 --- a/guides/operations/index.rst +++ b/guides/operations/index.rst @@ -30,3 +30,4 @@ The guides in this section include information about best practices, monitoring, statement_editor hardware_guide security + sqream_studio_5.4.2 From e0b0886e9553f526b83c2a41f2b6d26a3efb0350 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 19 Jan 2022 13:03:41 +0200 Subject: [PATCH 173/300] Update index.rst --- guides/operations/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/operations/index.rst b/guides/operations/index.rst index 500249e83..db6315c91 100644 --- a/guides/operations/index.rst +++ b/guides/operations/index.rst @@ -30,4 +30,4 @@ The guides in this section include information about best practices, monitoring, statement_editor hardware_guide security - sqream_studio_5.4.2 + sqream_studio_5.3.3 From dd1223a3fb0d9053e781cf023ef157254afdc242 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 25 Jan 2022 14:49:47 +0200 Subject: [PATCH 174/300] Delete recommended_pre-installation_configurations.rst File was copied to Installation Guides. Deleted file to prevent duplicate search results. --- ...mended_pre-installation_configurations.rst | 1157 ----------------- 1 file changed, 1157 deletions(-) delete mode 100644 guides/operations/recommended_pre-installation_configurations.rst diff --git a/guides/operations/recommended_pre-installation_configurations.rst b/guides/operations/recommended_pre-installation_configurations.rst deleted file mode 100644 index 9193d41a3..000000000 --- a/guides/operations/recommended_pre-installation_configurations.rst +++ /dev/null @@ -1,1157 +0,0 @@ -.. _recommended_pre-installation_configurations: - -********************************************* -Recommended Pre-Installation Configuration -********************************************* - - -Before installing SQream, we recommend you to tune your system for better performance and stability. - -This page provides recommendations for production deployments of SQream DB. - -.. contents:: In this topic: - :local: - -Recommended BIOS Settings -========================== -The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. - -It is safe to skip any and all of the configuration steps, but this may impact performance. - -If any doubt arises, consult the documentation for your server or your hardware vendor for the correct way to apply the settings. - -.. list-table:: - :widths: 25 25 50 - :header-rows: 1 - - * - Item - - Setting - - Rationale - * - **Management console access** - - **Connected** - - Connection to OOB required to preserve continuous network uptime. - * - **All drives.** - - **Connected and displayed on RAID interface** - - Prerequisite for cluster or OS installation. - * - **RAID volumes.** - - **Configured according to project guidelines. Must be rebooted to take effect.** - - Clustered to increase logical volume and provide redundancy. - * - **Fan speed Thermal Configuration.** - - Dell fan speed: **High Maximum**. Specified minimum setting: **60**. HPe thermal configuration: **Increased cooling**. - - NVIDIA Tesla GPUs are passively cooled and require high airflow to operate at full performance. - * - Power regulator or iDRAC power unit policy - - HPe: **HP static high performance** mode enabled. Dell: **iDRAC power unit policy** (power cap policy) disabled. - - Other power profiles (such as "balanced") throttle the CPU and diminishes performance. Throttling may also cause GPU failure. - * - **System Profile**, **Power Profile**, or **Performance Profile** - - **High Performance** - - The Performance profile provides potentially increased performance by maximizing processor frequency, and the disabling certain power saving features such as C-states. Use this setting for environments that are not sensitive to power consumption. - * - **Power Cap Policy** or **Dynamic power capping** - - **Disabled** - - Other power profiles (like "balanced") throttle the CPU and may diminish performance or cause GPU failure. This setting may appear together with the above (Power profile or Power regulator). This setting allows disabling system ROM power calibration during the boot process. Power regulator settings are named differently in BIOS and iLO/iDRAC. - -.. - **Comment: is it necessary to show the different power regulator setting names in this document?** - * - **Intel Turbo Boost** - - **Enabled** - - Intel Turbo Boost enables overclocking the processor to boost CPU-bound operation performance. Overclocking may risk computational jitter due to changes in the processor's turbo frequency. This causes brief pauses in processor operation, introducing uncertainty into application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. - * - **Logical Processor** - - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** - - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. - * - **Intel Virtualization Technology** (VT-d) - - **Disable** - - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. - * - **Logical Processor** - - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** - - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. - * - **Intel Virtualization Technology** (VT-d) - - **Disable** - - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. - * - **Processor C-States** (Minimum processor idle power core state) - - **Disable** - - Processor C-States reduce server power when the system is in an idle state. This causes slower cold-starts when the system transitions from an idle to a load state, and may reduce query performance by up to 15%. **Comment: a hyperlinked footnote to an internal source was inserted into the Confluence doc here. Do we want to include this in the final version? Linked URL: https://www.dell.com/support/kbdoc/en-il/000060621/what-is-the-c-state** - * - **HPe**: **Energy/Performance bias** - - **Maximum performance** - - Configures processor sub-systems for high-performance and low-latency. Other power profiles (like "balanced") throttle the CPU and may diminish performance. Use this setting for environments that are not sensitive to power consumption. - * - **HPe**: **DIMM voltage** - - **Optimized for Performance** - - Setting a higher voltage for DIMMs may increase performance. - * - **Memory Operating Mode** - - **Optimizer Mode**, **Disable Node Interleaving**, **Auto Memory Operating Voltage** - - Memory Operating Mode is tuned for performance in **Optimizer** mode. Other modes may improve reliability, but reduce performance. **Node Interleaving** should be disabled because enabling it interleaves the memory between memory nodes, which harms NUMA-aware applications such as SQream DB. - * - **HPe**: **Memory power savings mode** - - **Maximum performance** - - This setting configures several memory parameters to optimize the performance of memory sub-systems. The default setting is **Balanced**. - * - HPe **ACPI SLIT** - - **Enabled** - - ACPI SLIT sets the relative access times between processors and memory and I/O sub-systems. ACPI SLIT enables operating systems to use this data to improve performance by more efficiently allocating resources and workloads. - * - **QPI Snoop** **Comment: should we write that it is HPe or Intel? HPe: QPI Snoop** - - **Cluster on Die** or **Home Snoop** - - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. - - - - - - -Installing the Operating System -=================================================== -Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.6-7.9) must be installed before installing the SQream database. Either the customer or a SQream representative can perform the installation. - -.. - **Comment: I recommend leaving contact information here - Please call xxx-xxx-xxxx to contact a SQream representative.** - -**To install the operating system:** - -#. Select a language (English recommended). -#. From **Software Selection**, select **Minimal**. -#. Select the **Development Tools** group checkbox. -#. Continue the installation. -#. Set up the necessary drives and users as per the installation process. - - Using Debugging Tools is recommended for future problem-solving if necessary. - - .. - **Comment: In Step 4, why don't we document the entire procedure? I.e., why do we stop here and say "Continue the installation" and "Set up the necessary drives..."?** - -Selecting the **Development Tools** group installs the following tools: - - * autoconf - * automake - * binutils - * bison - * flex - * gcc - * gcc-c++ - * gettext - * libtool - * make - * patch - * pkgconfig - * redhat-rpm-config - * rpm-build - * rpm-sign - - - -The root user is created and the OS shell is booted up. - -Configuring the Operating System -=================================================== -When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. - -Logging In to the Server --------------------------------- -You can log in to the server using the server's IP address and password for the **root** user. The server's IP address and **root** user were created while installing the operating system above. - -Automatically Creating a SQream User ------------------------------------- - -**To automatically create a SQream user:** - -#. If a SQream user was created during installation, verify that the same ID is used on every server: - - .. code-block:: console - - $ sudo id sqream - -The ID **1000** is used on each server in the following example: - - .. code-block:: console - - $ uid=1000(sqream) gid=1000(sqream) groups=1000(sqream) - -2. If the ID's are different, delete the SQream user and SQream group from both servers: - - .. code-block:: console - - $ sudo userdel sqream - -3. Recreate it using the same ID: - - .. code-block:: console - - $ sudo rm /var/spool/mail/sqream - -Manually Creating a SQream User --------------------------------- - -**To manually create a SQream user:** - -SQream enables you to manually create users. This section shows you how to manually create a user with the UID **1111**. You cannot manually create during the operating system installation procedure. - -1. Add a user with an identical UID on all cluster nodes: - - .. code-block:: console - - $ useradd -u 1111 sqream - -2. Add the user **sqream** to the **wheel** group. - - .. code-block:: console - - $ sudo usermod -aG wheel sqream - -You can remove the SQream user from the **wheel** group when the installation and configuration are complete: - - .. code-block:: console - - $ passwd sqream - -3. Log out and log back in as **sqream**. - -**Note:** If you deleted the **sqream** user and recreated it with different ID, to avoid permission errors, you must change its ownership to /home/sqream. - -4. Change the **sqream** user's ownership to /home/sqream: - - .. code-block:: console - - $ sudo chown -R sqream:sqream /home/sqream - -Setting Up A Locale --------------------------------- - -SQream enables you to set up a locale. In this example, the locale used is your own location. - -**To set up a locale:** - -1. Set the language of the locale: - - .. code-block:: console - - $ sudo localectl set-locale LANG=en_US.UTF-8 - -2. Set the time stamp (time and date) of the locale: - - .. code-block:: console - - $ sudo timedatectl set-timezone Asia/Jerusalem - -If needed, you can run the **timedatectl list-timezones** command to see your current time-zone. - - -Installing the Required Packages --------------------------------- -You can install the required packages by running the following command: - -.. code-block:: console - - $ sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq - - -Installing the Recommended Tools --------------------------------- -You can install the recommended tools by running the following command: - -.. code-block:: console - - $ sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix - - -Installing Python 3.6.7 --------------------------------- -1. Download the Python 3.6.7 source code tarball file from the following URL into the **/home/sqream** directory: - - .. code-block:: console - - $ wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz - -2. Extract the Python 3.6.7 source code into your current directory: - - .. code-block:: console - - $ tar -xf Python-3.6.7.tar.xz - -3. Navigate to the Python 3.6.7 directory: - - .. code-block:: console - - $ cd Python-3.6.7/Python-3 - -4. Run the **./configure** script: - - .. code-block:: console - - $ ./configure - -5. Build the software: - - .. code-block:: console - - $ make -j30 - -6. Install the software: - - .. code-block:: console - - $ sudo make install - -7. Verify that Python 3.6.7 has been installed: - - .. code-block:: console - - $ python3.6.7 - -Installing NodeJS on CentOS --------------------------------- -**To install the node.js on CentOS:** - -1. Download the `setup_12.x file `__ as a root user logged in shell: - - .. code-block:: console - - $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - - -2. Clear the YUM cache and update the local metadata: - - .. code-block:: console - - $ sudo yum clean all && sudo yum makecache fast - -3. Install the **node.js**) file: - - .. code-block:: console - - $ sudo yum install -y nodejs - -Installing NodeJS on Ubuntu --------------------------------- -**To install the node.js file on Ubuntu:** - -1. Download the `setup_12.x file `__ as a root user logged in shell: - - .. code-block:: console - - $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - - -2. Install the node.js file: - - .. code-block:: console - - $ sudo apt-get install -y nodejs - -3. Verify the node version: - -.. - **Comment: - is this step relevant only for installing on Ubuntu, or on CentOS as well?** - - .. code-block:: console - - $ node -v - -Configuring the Network Time Protocol (NTP) -------------------------------------------- -This section describes how to configure your NTP. - -If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server `__. - -.. - **Comment: - Is this the correct procedure on the linked URL: Configure NTP Client to Synchronize with NTP Server?* - -**To configure your NTP:** - -1. Install the NTP file. - - .. code-block:: console - - $ sudo yum install ntp - -2. Enable the **ntpd** program. - - .. code-block:: console - - $ sudo systemctl enable ntpd - -3. Start the **ntdp** program. - - .. code-block:: console - - $ sudo systemctl start ntpd - -4. Print a list of peers known to the server and a summary of their states. - - .. code-block:: console - - $ sudo ntpq -p - -Configuring the Network Time Protocol Server --------------------------------------------- -If your organization has an NTP server, you can configure it. - -**To configure your NTP server:** - -1. Output your NTP server address and append ``/etc/ntpd.conf`` to the outuput. - - .. code-block:: console - - $ echo -e "\nserver \n" | sudo tee -a /etc/ntp.conf - -2. Restart the service. - - .. code-block:: console - - $ sudo systemctl restart ntpd - -3. Check that synchronization is enabled: - - .. code-block:: console - - $ sudo timedatectl - -Checking that synchronization is enabled generates the following output: - - .. code-block:: console - - $ Local time: Sat 2019-10-12 17:26:13 EDT - Universal time: Sat 2019-10-12 21:26:13 UTC - RTC time: Sat 2019-10-12 21:26:13 - Time zone: America/New_York (EDT, -0400) - NTP enabled: yes - NTP synchronized: yes - RTC in local TZ: no - DST active: yes - Last DST change: DST began at - Sun 2019-03-10 01:59:59 EST - Sun 2019-03-10 03:00:00 EDT - Next DST change: DST ends (the clock jumps one hour backwards) at - Sun 2019-11-03 01:59:59 EDT - Sun 2019-11-03 01:00:00 EST - - - -Configuring the Server to Boot Without the UI ---------------------------------------------- -You can configure your server to boot without a UI in cases when it is not required (recommended) by running the following command: - -.. code-block:: console - - $ sudo systemctl set-default multi-user.target - -Running this command activates the **NO-UI** server mode. - -Configuring the Security Limits --------------------------------- -The security limits refers to the number of open files, processes, etc. - -You can configure the security limits by running the **echo -e** command as a root user logged in shell: - -.. code-block:: console - - $ sudo bash - -.. code-block:: console - - $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf - -Configuring the Kernel Parameters ---------------------------------- -**To configure the kernel parameters:** - -1. Insert a new line after each kernel parameter: - - .. code-block:: console - - $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf - -**Notice:** In the past, the **vm.zone_reclaim_mode** parameter was set to **7.** In the latest Sqream version, the vm.zone_reclaim_mode parameter must be set to **0**. If it is not set to **0**, when a numa node runs out of memory, the system will get stuck and will be unable to pull memory from other numa nodes. - -2. Check the maximum value of the **fs.file**. - - .. code-block:: console - - $ sysctl -n fs.file-max - -3. *Optional* - If the maximum value of the **fs.file** is smaller than **2097152**, run the following command: - - .. code-block:: console - - $ echo "fs.file-max=2097152" >> /etc/sysctl.conf - -**IP4 forward** must be enabled for Docker and K8s installation only. - -Configuring the Firewall --------------------------------- -The example in this section shows the open ports for four sqreamd sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. - -**To configure the firewall:** - -1. Start the service and enable FirewallID on boot: - - .. code-block:: console - - $ systemctl start firewalld - -2. Add the following ports to the permanent firewall: - - .. code-block:: console - - $ firewall-cmd --zone=public --permanent --add-port=8080/tcp - $ firewallfirewall-cmd --zone=public --permanent --add-port=3105/tcp - $ firewall-cmd --zone=public --permanent --add-port=3108/tcp - $ firewall-cmd --zone=public --permanent --add-port=5000-5003/tcp - $ firewall-cmd --zone=public --permanent --add-port=5100-5103/tcp - $ firewall-cmd --permanent --list-all - - -.. - **Comment: - does *--list-all* add the entire list of ports to the permanent firewall?** - -3. Reload the firewall: - - .. code-block:: console - - $ firewall-cmd --reload - -4. Start the service and enable FirewallID on boot: - - .. code-block:: console - - $ systemctl start firewalld - - If you do not need the firewall, you can disable it: - - .. code-block:: console - - $ sudo systemctl disable firewalld - - -Disabling selinux --------------------------------- -**To disable selinux:** - -1. Show the status of **selinux**: - - .. code-block:: console - - $ sudo sestatus - -2. If the output is not **disabled**, edit the **/etc/selinux/config** file: - - .. code-block:: console - - $ sudo vim /etc/selinux/config - -3. Change **SELINUX=enforcing** to **SELINUX=disabled**. - -The above changes will only take effect after rebooting the server. - -You can disable selinux immediately after rebooting the server by running the following command: - -.. code-block:: console - - $ sudo setenforce 0 - -Configuring the /etc/hosts File --------------------------------- -**To configure the /etc/hosts file:** - -1. Edit the **/etc/hosts** file: - - .. code-block:: console - - $ sudo vim /etc/hosts - -2. Call your local host: - - .. code-block:: console - - $ 127.0.0.1 localhost - $ - -.. - **Comment: - Is the above an output or a step?** - -Configuring the DNS --------------------------------- -**To configure the DNS:** - -1. Run the **ifconfig** commasnd to check your NIC name. In the following example, **eth0** is the NIC name: - - .. code-block:: console - - $ sudo vim /etc/sysconfig/network-scripts/ifcfg-eth0 - -2. Replace the DNS lines from the example above with your own DNS addresses : - - .. code-block:: console - - $ sudo vim /etc/sysconfig/network-scripts/ifcfg-4.4.4.4 - $ sudo vim /etc/sysconfig/network-scripts/ifcfg-8.8.8.8 - - -.. - **Comment: - is the above input correct?** - -Installing the Nvidia CUDA Driver -=================================================== - - -**Warning:** If your UI runs on the server, the server must be stopped before installing the CUDA drivers. - -CUDA Driver Prerequisites --------------------------------- -1. Verify that the NVIDIA card has been installed and is detected by the system: - - .. code-block:: console - - $ lspci | grep -i nvidia - -2. Check which version of gcc has been installed: - - .. code-block:: console - - $ gcc --version - -3. If gcc has not been installed, install it for one of the following operating systems: - - * On RHEL/CentOS: - - .. code-block:: console - - $ sudo yum install -y gcc - - * On Ubuntu: - - .. code-block:: console - - $ sudo apt-get install gcc - - -Updating the Kernel Headers --------------------------------- -**To update the kernel headers:** - -1. Update the kernel headers on one of the following operating systems: - - * On RHEL/CentOS: - - .. code-block:: console - - $ sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) - - * On Ubuntu: - - .. code-block:: console - - $ sudo apt-get install linux-headers-$(uname -r) - -2. Install **wget** one of the following operating systems: - - * On RHEL/CentOS: - - .. code-block:: console - - $ sudo yum install wget - - * On Ubuntu: - - .. code-block:: console - - $ sudo apt-get install wget - -Disabling Nouveau --------------------------------- -You can disable Nouveau, which is the default driver. - -**To disable Nouveau:** - -1. Check if the Nouveau driver has been loaded: - - .. code-block:: console - - $ lsmod | grep nouveau - -If the Nouveau driver has been loaded, the command above generates output. - -2. Blacklist the Nouveau drivers to disable them: - - .. code-block:: console - - $ cat <`__ for the additional set-up requirements. - - - c. **For K80**: - - .. code-block:: console - - $ nvidia-persistenced - $ nvidia-smi -pm 1 - $ nvidia-smi -acp 0 - $ nvidia-smi --auto-boost-permission=0 - $ nvidia-smi --auto-boost-default=0 - -4. Reboot the server and run the **NVIDIA System Management Interface (NVIDIA SMI)**: - - .. code-block:: console - - $ nvidia-smi - - -Disabling Automatic Bug Reporting Tools -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -**To disable automatic bug reporting tools:** - -1. Run the following **abort** commands: - - .. code-block:: console - - $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done - - -The server is ready for the SQream software installation. - - -2. Run the following checks: - - a. Check the OS release: - - .. code-block:: console - - $ cat /etc/os-release - - b. Verify that a SQream user exists and has the same ID on all cluster member services: - - .. code-block:: console - - $ id sqream - - c. Verify that the storage is mounted: - - .. code-block:: console - - $ mount - - d. Verify that the driver has been installed correctly: - - .. code-block:: console - - $ nvidia-smi - - e. Check the maximum value of the **fs.file**: - - .. code-block:: console - - $ sysctl -n fs.file-max - - The desired output when checking the maximum value of the **fs.file** is greater or equal to **2097152**. - - f. Run the following command as a SQream user: - -.. - **Comment: - **Question - what do the following command parameter do? -c?** - - .. code-block:: console - - $ ulimit -c -u -n - -.. - **Comment: - See https://ss64.com/bash/ulimit.html** - - The following shows the desired output when ****: - - .. code-block:: console - - $ core file size (blocks, -c) unlimited - $ max user processes (-u) 1000000 - $ open files (-n) 1000000 - -3. Configure the security limits by running the **echo -e** command as a root user logged in shell: - - .. code-block:: console - - $ sudo bash - $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf - -Enabling Core Dumps -=================================================== - -Enabling core dumps is recommended, but optional. - -**To enable core dumps:** - -1. Check the **abrtd** Status - -2. Set the limits - -3. Create the core dumps directory. - - -Checking the abrtd Status ---------------------------------------------------- - -**To check the abrtd status:** - -1. Check if **abrtd** is running: - - .. code-block:: console - - $ sudo ps -ef |grep abrt - -2. If **abrtd** is running, stop it: - - .. code-block:: console - - $ sudo service abrtd stop - $ sudo chkconfig abrt-ccpp off - $ sudo chkconfig abrt-oops off - $ sudo chkconfig abrt-vmcore off - $ sudo chkconfig abrt-xorg off - $ sudo chkconfig abrtd off - - -Setting the Limits ---------------------------------------------------- - -**To set the limits:** - -1. Set the limits: - - .. code-block:: console - - $ ulimit -c - -2. If the output is **0**, add the following lines to the **limits.conf** file (/etc/security): - - .. code-block:: console - - $ * soft core unlimited - $ * hard core unlimited - -3. Log out and log in to apply the limit changes. - -Creating the Core Dumps Directory ---------------------------------------------------- - -**To set the core dumps directory:** - -1. Make the **/tmp/core_dumps** directory: - - .. code-block:: console - - $ mkdir /tmp/core_dumps - -2. Set the ownership of the **/tmp/core_dumps** directory: - - .. code-block:: console - - $ sudo chown sqream.sqream /tmp/core_dumps - -3. Grant read, write, and execute permissions to all users: - - .. code-block:: console - - $ sudo chmod -R 777 /tmp/core_dumps - -Setting the Output Directory of the /etc/sysctl.conf File ------------------------------------------------------------------ - -**To set the output directory of the /etc/sysctl.conf file:** - -1. Edit the **/etc/sysctl.conf** file: - - .. code-block:: console - - $ sudo vim /etc/sysctl.conf - -2. Add the following to the bottom of the file: - - .. code-block:: console - - $ kernel.core_uses_pid = 1 - $ kernel.core_pattern = //core-%e-%s-%u-%g-%p-%t - $ fs.suid_dumpable = 2 - -.. - **Comment: - leave a note that the user can choose his correct location of the folder.** - -3. To apply the changes without rebooting the server, run: - - .. code-block:: console - - $ sudo sysctl -p - -4. Check that the core output directory points to the following: - - .. code-block:: console - - $ sudo cat /proc/sys/kernel/core_pattern - - The following shows the correct generated output: - - .. code-block:: console - - $ /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t - -5. Verify that the core dumping works: - - .. code-block:: console - - $ select abort_server(); - - -Verifying that the Core Dumps Work ---------------------------------------------------- -You can verify that the core dumps work only after installing and running SQream. This causes the server to crash and a new core.xxx file to be included in the folder that is written in **/etc/sysctl.conf** - -**To verify that the core dumps work:** - -1. Stop and restart all SQream services. - -2. Connect to SQream with ClientCmd and run the following command: - - .. code-block:: console - - $ select abort_server(); - - -.. - **Comment: - what did the author mean by "Stage 3"?** - -Troubleshooting Core Dumping ---------------------------------------------------- -This section describes the troubleshooting procedure to be followed if all parameters have been configured correctly, but the cores have not been created. - -**To troubleshoot core dumping:** - -1. Reboot the server. - -2. Verify that you have folder permissions: - - .. code-block:: console - - $ sudo chmod -R 777 /tmp/core_dumps - -3. Verify that the limits have been set correctly: - - .. code-block:: console - - $ ulimit -c - - If all parameters have been configured correctly, the correct output is: - - .. code-block:: console - - $ unlimited - -4. If all parameters have been configured correctly, but running **ulimit -c** outputs **0**, run the following: - - .. code-block:: console - - $ sudo vim /etc/profile - -5. Search for line and tag it with the **hash** symbol: - - .. code-block:: console - - $ ulimit -S -c 0 > /dev/null 2>&1 - - -6. If the line is not found in **/etc/profile** directory, do the following: - - a. Run the following command: - - .. code-block:: console - - $ sudo vim /etc/init.d/functions - - b. Search for the following: - - .. code-block:: console - - $ ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 - - c. If the line is found, tag it with the **hash** symbol and reboot the server. From 285dcfc0c5b5f2033d7c849c6c0f3d78bd9a8ab5 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 25 Jan 2022 14:50:24 +0200 Subject: [PATCH 175/300] Updated Updated with Slavi. --- ...mended_pre-installation_configurations.rst | 54 +++++++++++++------ 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index e0d8cad11..2c8fa5284 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -1,17 +1,17 @@ .. _recommended_pre-installation_configurations: ********************************************* -Recommended Pre-Installation Configurations +Recommended Pre-Installation Configuration ********************************************* -The **Recommended Pre-Installation Configuration** page describes SQream's recommended configuration settings for production deployments. -After :ref:`installing SQream`, we recommend you to configure your system for improved performance and stability. +Before :ref:`installing SQream DB`, SQream recommends you to tune your system for better performance and stability. -The Recommended Pre-Installation Configuration page describes the following: +This page provides recommendations for production deployments of SQream and describes the following: -.. contents:: +.. contents:: :local: - :depth: 1 + :depth: 1 + Recommended BIOS Settings ========================== @@ -575,8 +575,9 @@ Configuring the DNS .. code-block:: console - $ sudo vim /etc/sysconfig/network-scripts/ifcfg-4.4.4.4 - $ sudo vim /etc/sysconfig/network-scripts/ifcfg-8.8.8.8 + DNS1="4.4.4.4" + DNS2="8.8.8.8" + .. @@ -686,11 +687,13 @@ If the Nouveau driver has been loaded, the command above generates output. Installing the CUDA Driver -------------------------------- -This section describes how to install the CUDA driver. +This section describes how to install the CUDA driver. + +.. note:: The version of the driver installed on the customer's server must be equal or higher than the driver included in the Sqream release package. Contact a Sqream customer service representative to identify the correct version to install. + -**Notice:** The version of the driver installed on the customer's server must be equal or higher than the driver included in the Sqream release package. Contact a Sqream customer service representative to identify the correct version to install. -Installing the CUDA Driver from the Repository +Installing the CUDA from the Repository ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Installing the CUDA driver from the Repository is the recommended installation method. @@ -714,15 +717,36 @@ Installing the CUDA driver from the Repository is the recommended installation m .. code-block:: console - $ sudo yum install dkms libvdpau + $ sudo yum install dkms libvdpau + +.. warning:: For Power9 and Intel servers using V100 GPUs, CUDA driver version **10.1 update 2** must be installed. For A series GPU, CUDA driver version 11.4.3 must be installed. Installing the CUDA depedendencies from the **epel** repository is only required for installing **runfile**. -3. Download the required local repository: +3. Do one of the following: - .. code-block:: console + * For CUDA driver version 10.1, download the required local repository: + + **For Intel** (x86_64): + + .. code-block:: console + + $ wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm + $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm + + **For IBM Power9**: + + .. code-block:: console + + $ wget https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm + $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm + + * For CUDA driver version 11.4.3: + + .. code-block:: console - $ wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm + $ wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm + $ sudo yum localinstall cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm 4. Install the required local repository: From 450e9220cc866bcf20570151c992f3d35dc70a38 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 30 Jan 2022 16:04:41 +0200 Subject: [PATCH 176/300] Update index.rst Corrected all links. Included only RN links relevant to this release. --- index.rst | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/index.rst b/index.rst index 0b8516698..a4e314eaf 100644 --- a/index.rst +++ b/index.rst @@ -1,18 +1,16 @@ .. _index: - ************************* SQream DB Documentation ************************* For SQream DB |latest_version|. -1 .. only:: html .. tip:: Want to read this offline? - `Download the documentation as a single PDF `_ . + `Download the documentation as a single PDF `_ . .. only:: pdf or latex @@ -22,8 +20,7 @@ SQream DB is a columnar analytic SQL database management system. SQream DB supports regular SQL including :ref:`a substantial amount of ANSI SQL`, uses :ref:`serializable transactions`, and :ref:`scales horizontally` for concurrent statements. -Even a :ref:`basic SQream DB machine` can support tens to hundreds of terabytes of data. - +Even a `basic SQream DB machine `_ can support tens to hundreds of terabytes of data. SQream DB easily plugs in to third-party tools like :ref:`Tableau` comes with standard SQL client drivers, including :ref:`JDBC`, :ref:`ODBC`, and :ref:`Python DB-API`. @@ -34,7 +31,7 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` - - :ref:`SQL reference` + :ref:`SQL Reference` :ref:`sql_statements` :ref:`sql_functions` - - + - + `Setting up SQream `_ + :ref:`Best practices` :ref:`connect_to_tableau` * - **Releases** - - **Driver and deployment** - - **Help & Support** + - **Driver and Deployment** + - **Help and Support** * - - :ref:`2020.3.2.1<2020.3.2.1>` - - :ref:`2020.3.2<2020.3.2>` - - :ref:`2020.3.1<2020.3.1>` - :ref:`2020.3<2020.3>` :ref:`2020.2<2020.2>` @@ -92,7 +85,7 @@ If you couldn't find what you're looking for, we're always happy to help. Visit .. rubric:: Looking for older versions? - +This version of the documentation is for SQream DB |latest_version|. If you're looking for an older version of the documentation, versions 1.10 through 2019.2.1 are available at http://previous.sqream.com . @@ -103,8 +96,8 @@ If you're looking for an older version of the documentation, versions 1.10 throu :titlesonly: :hidden: - xxfeatures_tour first_steps + xxfeatures_tour guides/index installation_guides/index reference/index From bcacbfe1e739a013140b7a86db9505d7c6880947 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 30 Jan 2022 16:09:22 +0200 Subject: [PATCH 177/300] Updated Corrected all links. Included only RN links relevant to this release. --- index.rst | 29 +++++++++++------------------ releases/index.rst | 4 +--- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/index.rst b/index.rst index 0b8516698..a4e314eaf 100644 --- a/index.rst +++ b/index.rst @@ -1,18 +1,16 @@ .. _index: - ************************* SQream DB Documentation ************************* For SQream DB |latest_version|. -1 .. only:: html .. tip:: Want to read this offline? - `Download the documentation as a single PDF `_ . + `Download the documentation as a single PDF `_ . .. only:: pdf or latex @@ -22,8 +20,7 @@ SQream DB is a columnar analytic SQL database management system. SQream DB supports regular SQL including :ref:`a substantial amount of ANSI SQL`, uses :ref:`serializable transactions`, and :ref:`scales horizontally` for concurrent statements. -Even a :ref:`basic SQream DB machine` can support tens to hundreds of terabytes of data. - +Even a `basic SQream DB machine `_ can support tens to hundreds of terabytes of data. SQream DB easily plugs in to third-party tools like :ref:`Tableau` comes with standard SQL client drivers, including :ref:`JDBC`, :ref:`ODBC`, and :ref:`Python DB-API`. @@ -34,7 +31,7 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` - - :ref:`SQL reference` + :ref:`SQL Reference` :ref:`sql_statements` :ref:`sql_functions` - - + - + `Setting up SQream `_ + :ref:`Best practices` :ref:`connect_to_tableau` * - **Releases** - - **Driver and deployment** - - **Help & Support** + - **Driver and Deployment** + - **Help and Support** * - - :ref:`2020.3.2.1<2020.3.2.1>` - - :ref:`2020.3.2<2020.3.2>` - - :ref:`2020.3.1<2020.3.1>` - :ref:`2020.3<2020.3>` :ref:`2020.2<2020.2>` @@ -92,7 +85,7 @@ If you couldn't find what you're looking for, we're always happy to help. Visit .. rubric:: Looking for older versions? - +This version of the documentation is for SQream DB |latest_version|. If you're looking for an older version of the documentation, versions 1.10 through 2019.2.1 are available at http://previous.sqream.com . @@ -103,8 +96,8 @@ If you're looking for an older version of the documentation, versions 1.10 throu :titlesonly: :hidden: - xxfeatures_tour first_steps + xxfeatures_tour guides/index installation_guides/index reference/index diff --git a/releases/index.rst b/releases/index.rst index bc82d4fbc..5810d3675 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -10,8 +10,6 @@ Releases * - Version - Release Date - * - :ref:`2020.3.2.1` - - February 24, 2021 * - :ref:`2020.3.2` - January 28, 2021 * - :ref:`2020.3.1` @@ -37,4 +35,4 @@ Releases 2020.3 2020.2 2020.1 - 2019.2.1 + 2019.2.1 \ No newline at end of file From cabfc2eaee89378bf157bd412a41c603a0f49b88 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 30 Jan 2022 16:28:30 +0200 Subject: [PATCH 178/300] Update index.rst Corrected all links. Included only RN links relevant to this release. --- releases/index.rst | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/releases/index.rst b/releases/index.rst index 5810d3675..e7ed2a03c 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -10,18 +10,13 @@ Releases * - Version - Release Date - * - :ref:`2020.3.2` - - January 28, 2021 - * - :ref:`2020.3.1` - - January 11, 2021 * - :ref:`2020.3` - October 8, 2020 * - :ref:`2020.2` - July 22, 2020 * - :ref:`2020.1` - January 15, 2020 - * - :ref:`2019.2.1` - - July 25, 2019 + .. toctree:: @@ -29,10 +24,6 @@ Releases :glob: :hidden: - 2020.3.2.1 - 2020.3.2 - 2020.3.1 2020.3 2020.2 - 2020.1 - 2019.2.1 \ No newline at end of file + 2020.1 \ No newline at end of file From df585df08906d972dc3c58b220954a4e40c04855 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 1 Feb 2022 12:50:38 +0200 Subject: [PATCH 179/300] Update hardware_guide.rst Slavi required some changes. --- guides/operations/hardware_guide.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/guides/operations/hardware_guide.rst b/guides/operations/hardware_guide.rst index 15ddd38a2..42c4889a3 100644 --- a/guides/operations/hardware_guide.rst +++ b/guides/operations/hardware_guide.rst @@ -166,8 +166,7 @@ SQream can run on the following 64-bit Linux operating systems: * Red Hat Enterprise Linux (RHEL) v7 * CentOS v7 * Amazon Linux 2018.03 - * Ubuntu v16.04 LTS, v18.04 LTS - * Other Linux distributions may be supported via nvidia-docker + * Other Linux distributions may be supported via nvidia-docker (single-node cluster only) Storage ----------- From 5b557d71a8e89af51f599422d150a07e029a991a Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 1 Feb 2022 17:08:10 +0200 Subject: [PATCH 180/300] Update hardware_guide.rst Slavi's updates. --- guides/operations/hardware_guide.rst | 59 ++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/guides/operations/hardware_guide.rst b/guides/operations/hardware_guide.rst index 42c4889a3..d66797223 100644 --- a/guides/operations/hardware_guide.rst +++ b/guides/operations/hardware_guide.rst @@ -40,19 +40,21 @@ An average single-node cluster can be a rackmount server or workstation, contain * - Component - Type * - Server - - Dell T640, Dell R750, Dell R940xa, HP ProLiant DL380 Gen10 or similar + - Dell R750, Dell R940xa, HP ProLiant DL380 Gen10 or similar (Intel only) * - Processor - - 2x Intel Xeon Gold 6240 (18C/36HT) 2.6GHz + - 2x Intel Xeon Gold 6240 (18C/36HT) 2.6GHz or similar * - RAM - - 512 GB - 1 TB + - 1.5 TB * - Onboard storage - - * 2x 960GB SSD 2.5in Hot-plug for OS, RAID1 - * 14x 3.84TB SSD 2.5in Hot-plug for storage, RAID6 + * 2x 960GB SSD 2.5in hot plug for OS, RAID1 * 2x 2TB SSD or NVMe, for temporary spooling, RAID1 + * 10x 3.84TB SSD 2.5in Hot plug for storage, RAID6 * - GPU - - 2x or 4x NVIDIA Tesla T4, V100, or A100 + - 2x A100 NVIDIA + * - Operating System + - Red Hat Enterprise Linux v7.x or CentOS v7.x or Amazon Linux .. note:: If you are using internal storage, your volumes must be formatted as xfs. @@ -74,25 +76,47 @@ The following table shows SQream's recommended hardware specifications: * - Component - Type * - Server - - High-density GPU-capable rackmount server, like Dell C4140, Dell R940xa, Dell R750, Lenovo SR650 or similar. + - Dell R750, Dell R940xa, HP ProLiant DL380 Gen10 or similar (Intel only) * - Processor - - 2x Intel Xeon Gold 6240 (18C/36HT) 2.6GHz or 2x IBM POWER9 + - 2x Intel Xeon Gold 6240 (18C/36HT) 2.6GHz or similar * - RAM - - 1 - 2TB + - 2 TB * - Onboard storage - - * 2x 960GB SSD 2.5in, for OS, RAID1 + * 2x 960GB SSD 2.5in hot plug for OS, RAID1 * 2x 2TB SSD or NVMe, for temporary spooling, RAID1 - * - Networking - - - - - Mellanox Connectx 5 100 Gbps for storage fabric or similar. + * - External Storage + - + * Mellanox Connectx5/6 100G NVIDIA Network Card (if applicable) or other high speed network card minimum 40G compatible to customer’s infrastructure + * 50 TB (NAS connected over GPFS, Lustre, or NFS) GPFS recommended * - GPU - - 4x NVIDIA Tesla V100 32GB or A100 + - 2x A100 NVIDIA + * - Operating System + - Red Hat Enterprise Linux v7.x or CentOS v7.x or Amazon Linux .. note:: With a NAS connected over GPFS, Lustre, or NFS, each SQream worker can read data at up to 5GB/s. +SQream Studio Server Example +----------------------------------- +The following table shows SQream's recommended Studio server specifications: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Component + - Type + * - Server + - Physical or virtual machine + * - Processor + - 1x Intel Core i7 + * - RAM + - 16 GB + * - Onboard storage + - 50 GB SSD 2.5in Hot plug for OS, RAID1 + * - Operating System + - Red Hat Enterprise Linux v7.x or CentOS v7.x + @@ -166,7 +190,8 @@ SQream can run on the following 64-bit Linux operating systems: * Red Hat Enterprise Linux (RHEL) v7 * CentOS v7 * Amazon Linux 2018.03 - * Other Linux distributions may be supported via nvidia-docker (single-node cluster only) + * Ubuntu v16.04 LTS, v18.04 LTS + * Other Linux distributions may be supported via nvidia-docker Storage ----------- From 0fb92d0e1315038b5724184ab22cfdb1d17ea82d Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 2 Feb 2022 10:31:09 +0200 Subject: [PATCH 181/300] Update installing_prometheus_using_binary_packages.rst --- .../installing_prometheus_using_binary_packages.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/installation_guides/installing_prometheus_using_binary_packages.rst b/installation_guides/installing_prometheus_using_binary_packages.rst index 6864dd793..a6104bdd0 100644 --- a/installation_guides/installing_prometheus_using_binary_packages.rst +++ b/installation_guides/installing_prometheus_using_binary_packages.rst @@ -28,7 +28,7 @@ You must install Prometheus before installing the Dashboard Data Collector. 1. That you have **sudo** access to your Linux server. 2. That your server has access to the internet (for downloading the Prometheus binary package). - 3. That your firewall rules are opened (**Comment** *- does "open" mean "disabled"?*) for accessing Prometheus Port 9090. + 3. That your firewall rules are opened for accessing Prometheus Port 9090. 2. Navigate to the Prometheus `Download `_ page and download the **prometheus-2.32.0-rc.1.linux-amd64.tar.gz** package. @@ -60,7 +60,7 @@ You must install Prometheus before installing the Dashboard Data Collector. $ sudo useradd --no-create-home --shell /bin/false prometheus -5. Create your required directories: (**Comment** - *Does the user have to make these exact directories, or can they be whatever he wants?*) +5. Create your required directories: .. code-block:: console @@ -238,4 +238,4 @@ From the **Query** tab you can query metrics, as shown below: * - .. image:: /_static/images/3c9c4e8b-49bd-44a8-9829-81d1772ed962.gif -Back to :ref:`Installing Prometheus Using Binary Packages` \ No newline at end of file +Back to :ref:`Installing Prometheus Using Binary Packages` From 218f7afd16acd4f539e0339d27ce15dba12f4093 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 2 Feb 2022 10:35:45 +0200 Subject: [PATCH 182/300] Update installing_dashboard_data_collector.rst --- installation_guides/installing_dashboard_data_collector.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/installation_guides/installing_dashboard_data_collector.rst b/installation_guides/installing_dashboard_data_collector.rst index ba0475a6d..04efc81fe 100644 --- a/installation_guides/installing_dashboard_data_collector.rst +++ b/installation_guides/installing_dashboard_data_collector.rst @@ -12,8 +12,6 @@ After accessing the Prometheus user interface, you can install the **Dashboard D .. note:: Before installing the Dashboard Data collector, verify that Prometheus has been installed and configured for the cluster. -How to install Prometheus from tarball - **Comment - this needs to be its own page.** - **To install the Dashboard Data Collector:** 1. Store the Data Collector Package obtained from `SQream Artifactory `_. @@ -47,7 +45,7 @@ How to install Prometheus from tarball - **Comment - this needs to be its own pa $ --dashboard-password=sqream \ $ --prometheus-url=http://127.0.0.1:9090/api/v1/query -5. Debug the Data Collector: (**Comment** - *using the npm project manager*). +5. Debug the Data Collector: .. code-block:: console @@ -143,7 +141,7 @@ How to install Prometheus from tarball - **Comment - this needs to be its own pa .. note:: Verify that all machines and workers are correctly registered. -6. Press **CTRL + C** to stop ``npm start`` (**Comment** - *It may be better to refer to it as the npm project manager*). +6. Press **CTRL + C** to stop ``npm start``. :: From 6b713b4a081fd6eb3d2505c0daac0e73dc22aed2 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 7 Feb 2022 10:29:29 +0200 Subject: [PATCH 183/300] Update create_table.rst Removed table at end of page. --- .../ddl_commands/create_table.rst | 127 +++++++++++++++--- 1 file changed, 105 insertions(+), 22 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index 83fbe568d..b660e442c 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -4,19 +4,17 @@ CREATE TABLE ***************** -``CREATE TABLE`` creates a new table in an existing database. +The ``CREATE TABLE`` statement is used to create a new table in an existing database. .. tip:: * To create a table based on the result of a select query, see :ref:`CREATE TABLE AS `. * To create a table based on files like Parquet and ORC, see :ref:`CREATE FOREIGN TABLE ` -Permissions -============= -The role must have the ``CREATE`` permission at the schema level. Syntax ========== +The following is the correct syntax for creating a table: .. code-block:: postgres @@ -44,6 +42,7 @@ Syntax Parameters ============ +The following parameters can be used when creating a table: .. list-table:: :widths: auto @@ -52,7 +51,7 @@ Parameters * - Parameter - Description * - ``OR REPLACE`` - - Create a new table, and overwrite any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. + - Creates a new tables and overwrites any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. * - ``schema_name`` - The name of the schema in which to create the table. * - ``table_name`` @@ -64,20 +63,25 @@ Parameters A commma separated list of clustering column keys. See :ref:`data_clustering` for more information. - + * - ``LIKE`` + - Duplicates the column structure of an existing table. + + .. _default_values: -Default values +Default Value Constraints =============== -The ``DEFAULT`` value constraint specifies a value to use if a value isn't defined in an :ref:`insert` or :ref:`copy_from` statement. +The ``DEFAULT`` value constraint specifies a value to use if one is not defined in an :ref:`insert` or :ref:`copy_from` statement. -The value may be either a literal or `GETDATE()`, which is s evaluated at the time the row is created. +The value may be either a literal or **GETDATE()**, which is evaluated at the time the row is created. .. note:: The ``DEFAULT`` constraint only applies if the column does not have a value specified in the :ref:`insert` or :ref:`copy_from` statement. You can still insert a ``NULL`` into an nullable column by explicitly inserting ``NULL``. For example, ``INSERT INTO cool_animals VALUES (1, 'Gnu', NULL)``. Syntax --------- +The following is the correct syntax for using the **DEFAULT** value constraints: + .. code-block:: postgres @@ -99,15 +103,16 @@ Syntax .. _identity: -Identity (sequence) +Identity ----------------------- +The ``Identity`` (or sequence) columns can be used for generating key values. Some databases call this ``AUTOINCREMENT``. -Identity columns can be used for generating key values. Some databases call this ``AUTOINCREMENT``. - -The identity property on a column guarantees that each new row inserted is generated based on the current seed & increment. +The **identity** property on a column guarantees that each new row inserted is generated based on the current seed & increment. .. warning:: The identity property on a column does not guarantee uniqueness. The identity value can be bypassed by specifying it in an :ref:`insert` command. + +The following table describes the identity parameters: .. list-table:: :widths: auto @@ -122,9 +127,15 @@ The identity property on a column guarantees that each new row inserted is gener Examples =========== +This section includes the following examples: + +.. contents:: + :local: + :depth: 1 -A simple table +Creating a Standard Table ----------------- +The following is an example of the syntax used to create a standard table: .. code-block:: postgres @@ -135,8 +146,10 @@ A simple table is_agressive BOOL ); -A table with default values for some columns +Creating a Table with Default Value Constraints for Some Columns --------------------------------------------------- +The following is an example of the syntax used to create a table with default value constraints for some columns: + .. code-block:: postgres @@ -149,8 +162,10 @@ A table with default values for some columns .. note:: The nullable/non-nullable constraint appears at the end, after the default option -A table with an identity (autoincrement) column +Creating a Table with an Identity Column --------------------------------------------------- +The following is an example of the syntax used to create a table with an identity (auto-increment) column: + .. code-block:: postgres @@ -165,25 +180,25 @@ A table with an identity (autoincrement) column * Identity does not enforce the uniqueness of values. The identity value can be bypassed by specifying it in an :ref:`insert` command. -Creating a table from a SELECT query +Creating a Table from a SELECT Query ----------------------------------------- - -Use a :ref:`CREATE TABLE AS ` statement to create a new table from the results of a SELECT query. +The following is an example of the syntax used to create a table from a SELECT query: .. code-block:: postgres CREATE TABLE users_uk AS SELECT * FROM users WHERE country = 'United Kingdom'; + +For more information on creating a new table from the results of a SELECT query, see :ref:`CREATE TABLE AS `. -Creating a table with a clustering key +Creating a Table with a Clustering Key ---------------------------------------------- - When data in a table is stored in a sorted order, the sorted columns are considered clustered. Good clustering can have a significant positive impact on performance. In the following example, we expect the ``start_date`` column to be naturally clustered, as new users sign up and get a newer start date. When the clustering key is set, if the incoming data isn’t naturally clustered, it will be clustered by SQream DB during insert or bulk load. -See :ref:`data_clustering` for more information. +The following is an example of the syntax used to create a table with a clustering key: .. code-block:: postgres @@ -192,4 +207,72 @@ See :ref:`data_clustering` for more information. start_date datetime not null, country VARCHAR(30) DEFAULT 'Unknown' NOT NULL ) CLUSTER BY start_date; + +For more information on data clustering, see :ref:`data_clustering`. + +Duplicating the Column Structure of an Existing Table +----------------- + +Syntax +************ +The following is the correct syntax for duplicating the column structure of an existing table: + +.. code-block:: postgres + + CREATE [OR REPLACE] TABLE table_name + { + (column_name column_type [{NULL | NOT NULL}] [,...]) + | LIKE source_table_name + } + [CLUSTER BY ...] + ; + +Examples +************** +This section includes the following examples of duplicating the column structure of an existing table using the ``LIKE`` clause: + +.. contents:: + :local: + :depth: 3 +Creating a Table Using an Explicit Column List +~~~~~~~~~~~~ +The following is an example of creating a table using an explict column list: + +.. code-block:: postgres + + CREATE TABLE t1(x int default 0 not null, y text(10) null); + +Creating a Second Table Based on the Structure of Another Table +~~~~~~~~~~~~ +Either of the following examples can be used to create a second table based on the structure of another table. + +**Example 1** + +.. code-block:: postgres + + CREATE TABLE t2 LIKE t1; + +**Example 2** + +.. code-block:: postgres + + CREATE TABLE t2(x int default 0 not null, y text(10) null); + +The generated output of both of the statements above is identical. + +Creating a Table based on External Tables and Views +~~~~~~~~~~~~ +The following is example of creating a table based on external tables and views: + + +.. code-block:: postgres + + CREATE VIEW v as SELECT x+1,y,y || 'abc' from t1; + CREATE TABLE t3 LIKE v; + +When duplicating the column structure of an existing table, the target table of the ``LIKE`` clause can be a regular or an external table, or a view. + +Permissions +============= +The role must have the ``CREATE`` permission at the schema level. From 32d66d91d371eabe91d15ba565856cf24feb34f6 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 8 Feb 2022 16:31:23 +0200 Subject: [PATCH 184/300] Updated Menu. --- .../filesystem_and_filesystem_usage.rst | 0 .../architecture => architecture}/index.rst | 2 +- .../internals_architecture.rst | 2 +- .../processes_and_network_architecture.rst | 2 +- configuration_guides/admin/admin_flags.rst | 44 + configuration_guides/admin/bin_sizes.rst | 12 + .../admin/check_cuda_memory.rst | 12 + .../admin/compiler_gets_only_ufs.rst | 12 + configuration_guides/admin_cluster_flags.rst | 14 + configuration_guides/admin_flags.rst | 18 + configuration_guides/admin_regular_flags.rst | 35 + configuration_guides/admin_worker_flags.rst | 15 + configuration_guides/bin_sizes.rst | 13 + configuration_guides/check_cuda_memory.rst | 11 + .../compiler_gets_only_ufs.rst | 11 + .../cpu_reduce_hashtable_size.rst | 11 + configuration_guides/csv_limit_row_length.rst | 11 + .../cuda_mem_cpy_max_size_bytes.rst | 11 + .../cuda_mem_cpy_synchronous.rst | 11 + configuration_guides/cuda_mem_quota.rst | 11 + configuration_guides/developer_mode.rst | 11 + .../enable_device_debug_messages.rst | 11 + configuration_guides/enable_log_debug.rst | 11 + .../enable_nv_prof_markers.rst | 11 + configuration_guides/end_log_message.rst | 11 + .../extent_storage_file_size_mb.rst | 11 + configuration_guides/flip_join_order.rst | 11 + configuration_guides/gather_mem_stat.rst | 11 + .../generic/generic_flags.rst | 18 + configuration_guides/generic/spooling.rst | 69 + configuration_guides/generic_flags.rst | 17 + .../generic_regular_flags.rst | 15 + configuration_guides/generic_worker_flags.rst | 12 + .../increase_chunk_size_before_reduce.rst | 11 + configuration_guides/increase_mem_factors.rst | 11 + configuration_guides/index.rst | 20 + .../level_db_write_buffer_size.rst | 11 + .../limit_query_memory_gb.rst | 11 + configuration_guides/log_sys_level.rst | 19 + configuration_guides/machine_ip.rst | 11 + .../max_avg_blob_size_to_compress_on_gpu.rst | 11 + .../memory_reset_trigger_mb.rst | 11 + configuration_guides/metadata_server_port.rst | 11 + configuration_guides/mt_read.rst | 11 + configuration_guides/mt_read_workers.rst | 11 + configuration_guides/orc_implicit_casts.rst | 11 + .../statement_lock_timeout.rst | 11 + configuration_guides/use_config_ip.rst | 11 + .../use_legacy_decimal_literals.rst | 11 + .../use_legacy_string_literals.rst | 11 + .../csv.rst | 4 +- data_ingestion_guides/index.rst | 17 + .../inserting_data.rst | 82 +- .../nba-t10.csv | 0 .../oracle.rst | 86 +- .../orc.rst | 26 +- .../parquet.rst | 4 +- .../to_csv.sql | 0 .../access_control.rst | 4 +- .../compression.rst | 2 +- .../concurrency_and_locks.rst | 33 +- .../concurrency_and_scaling_in_sqream.rst | 4 +- feature_guides/flexible_data_clustering.rst | 16 + .../flexible_data_clustering_chunks.rst | 18 + ...ata_clustering_data_clustering_methods.rst | 183 ++ ...flexible_data_clustering_data_examples.rst | 22 + ...e_data_clustering_data_rechunking_data.rst | 11 + .../flexible_data_clustering_overview.rst | 16 + feature_guides/index.rst | 24 + .../python_functions.rst | 4 +- .../sqream_installer_cli_ref_admin.rst | 142 ++ .../transactions.rst | 2 +- .../workload_manager.rst | 99 +- features_tour.rst | 189 -- .../connecting_clients_to_sqream.rst | 26 + getting_started/creating_your_first_table.rst | 80 + getting_started/deleting_rows.rst | 48 + .../executing_statements_in_sqream.rst | 10 + .../getting_started.rst | 14 +- getting_started/index.rst | 16 + getting_started/ingesting_data.rst | 8 + getting_started/inserting_rows.rst | 86 + getting_started/installing_sqream.rst | 11 + getting_started/listing_tables.rst | 13 + .../performing_basic_sqream_operations.rst | 18 + ...eparing_your_machine_to_install_sqream.rst | 40 + getting_started/querying_data.rst | 51 + getting_started/running_queries.rst | 121 ++ .../running_the_sqream_sql_client.rst | 22 + ...ing_query_results_to_a_csv_or_psv_file.rst | 24 + guides/client_drivers/index.rst | 106 - guides/features/access_control_notes.rst | 357 ---- guides/features/chunks_and_extents.rst | 93 - guides/features/data_clustering.rst | 79 - guides/features/delete.rst | 214 -- guides/features/external_data/hdfs.rst | 323 --- guides/features/index.rst | 34 - guides/features/metadata_system.rst | 71 - .../features/time_based_data_management.rst | 106 - guides/index.rst | 36 - guides/migration/avro_foreign_data_format.rst | 352 ---- guides/migration/nba-t10.csv | 10 - guides/operations/configuration.rst | 952 --------- guides/operations/index.rst | 33 - guides/operations/installing_monit.rst | 319 --- .../installing_sqream_with_binary.rst | 278 --- .../installing_sqream_with_kubernetes.rst | 1805 ----------------- .../launching_sqream_with_monit.rst | 290 --- guides/operations/monitoring.rst | 87 - .../running_sqream_in_a_docker_container.rst | 1489 -------------- guides/operations/sqream_studio.rst | 578 ------ .../starting_and_stopping_the_system.rst | 21 - guides/operations/statement_editor.rst | 290 --- guides/operations/troubleshooting.rst | 163 -- guides/queries.rst | 10 - guides/third_party_tools/talend.rst | 11 - index.rst | 28 +- .../creating_or_cloning_a_storage_cluster.rst | 14 +- operational_guides/exporting_data.rst | 15 + .../external_data.rst | 7 +- .../external_tables.rst | 123 +- .../hardware_guide.rst | 0 operational_guides/hdfs.rst | 252 +++ operational_guides/index.rst | 26 + .../logging.rst | 6 +- .../monitoring_query_performance.rst | 186 +- .../optimization_best_practices.rst | 128 +- .../s3.rst | 0 .../saved_queries.rst | 4 +- .../security.rst | 4 - .../viewing_system_objects_as_ddl.rst | 6 +- .../configuring_your_instance_of_sqream.rst | 23 + ...ing_and_managing_roles_and_permissions.rst | 98 + ...ts_and_running_queries_from_the_editor.rst | 416 ++++ sqream_studio_5.4.3/getting_started.rst | 61 + sqream_studio_5.4.3/index.rst | 19 + ...orkers_and_services_from_the_dashboard.rst | 265 +++ sqream_studio_5.4.3/viewing_logs.rst | 122 ++ .../client_drivers/cpp/connect_test.cpp | 0 .../client_drivers/cpp/index.rst | 0 .../client_drivers/cpp/insert_test.cpp | 0 third_party_tools/client_drivers/index.rst | 113 ++ .../client_drivers/jdbc/index.rst | 32 +- .../client_drivers/jdbc/sample.java | 0 .../client_drivers/nodejs/index.rst | 0 .../client_drivers/nodejs/sample.js | 0 .../client_drivers/odbc/index.rst | 0 .../odbc/install_configure_odbc_linux.rst | 0 .../odbc/install_configure_odbc_windows.rst | 19 +- .../client_drivers/python/api-reference.rst | 0 .../client_drivers/python/index.rst | 1 - .../client_drivers/python}/nba-t10.csv | 0 .../client_drivers/python/test.py | 0 .../client_platforms}/connect.sas | 0 .../client_platforms}/index.rst | 8 +- .../client_platforms/microstrategy.rst | 185 ++ .../client_platforms}/odbc-sqream.tdc | 0 .../client_platforms/pentaho.rst | 288 +++ .../client_platforms}/php.rst | 4 +- .../client_platforms}/r.rst | 6 +- .../client_platforms}/sas_viya.rst | 4 +- .../client_platforms}/sql_workbench.rst | 6 +- .../client_platforms}/tableau.rst | 15 +- third_party_tools/client_platforms/talend.rst | 204 ++ .../client_platforms}/test.php | 0 third_party_tools/connectivity_ecosystem.jpg | Bin 0 -> 149570 bytes third_party_tools/index.rst | 18 + .../core_dumping_related_issues.rst | 58 + troubleshooting/examining_logs.rst | 6 + .../identifying_configuration_issues.rst | 32 + troubleshooting/index.rst | 25 + .../information_for_support.rst | 13 +- troubleshooting/lock_related_issues.rst | 29 + troubleshooting/log_related_issues.rst | 133 ++ troubleshooting/node_js_related_issues.rst | 54 + troubleshooting/remedying_slow_queries.rst | 79 + troubleshooting/resolving_common_issues.rst | 60 + troubleshooting/sas_viya_related_issues.rst | 55 + .../solving_code_126_odbc_errors.rst | 14 + ...sqream_sql_installation_related_issues.rst | 33 + troubleshooting/tableau_related_issues.rst | 73 + 181 files changed, 4868 insertions(+), 8866 deletions(-) rename {guides/architecture => architecture}/filesystem_and_filesystem_usage.rst (100%) rename {guides/architecture => architecture}/index.rst (96%) rename {guides/architecture => architecture}/internals_architecture.rst (99%) rename {guides/architecture => architecture}/processes_and_network_architecture.rst (96%) create mode 100644 configuration_guides/admin/admin_flags.rst create mode 100644 configuration_guides/admin/bin_sizes.rst create mode 100644 configuration_guides/admin/check_cuda_memory.rst create mode 100644 configuration_guides/admin/compiler_gets_only_ufs.rst create mode 100644 configuration_guides/admin_cluster_flags.rst create mode 100644 configuration_guides/admin_flags.rst create mode 100644 configuration_guides/admin_regular_flags.rst create mode 100644 configuration_guides/admin_worker_flags.rst create mode 100644 configuration_guides/bin_sizes.rst create mode 100644 configuration_guides/check_cuda_memory.rst create mode 100644 configuration_guides/compiler_gets_only_ufs.rst create mode 100644 configuration_guides/cpu_reduce_hashtable_size.rst create mode 100644 configuration_guides/csv_limit_row_length.rst create mode 100644 configuration_guides/cuda_mem_cpy_max_size_bytes.rst create mode 100644 configuration_guides/cuda_mem_cpy_synchronous.rst create mode 100644 configuration_guides/cuda_mem_quota.rst create mode 100644 configuration_guides/developer_mode.rst create mode 100644 configuration_guides/enable_device_debug_messages.rst create mode 100644 configuration_guides/enable_log_debug.rst create mode 100644 configuration_guides/enable_nv_prof_markers.rst create mode 100644 configuration_guides/end_log_message.rst create mode 100644 configuration_guides/extent_storage_file_size_mb.rst create mode 100644 configuration_guides/flip_join_order.rst create mode 100644 configuration_guides/gather_mem_stat.rst create mode 100644 configuration_guides/generic/generic_flags.rst create mode 100644 configuration_guides/generic/spooling.rst create mode 100644 configuration_guides/generic_flags.rst create mode 100644 configuration_guides/generic_regular_flags.rst create mode 100644 configuration_guides/generic_worker_flags.rst create mode 100644 configuration_guides/increase_chunk_size_before_reduce.rst create mode 100644 configuration_guides/increase_mem_factors.rst create mode 100644 configuration_guides/index.rst create mode 100644 configuration_guides/level_db_write_buffer_size.rst create mode 100644 configuration_guides/limit_query_memory_gb.rst create mode 100644 configuration_guides/log_sys_level.rst create mode 100644 configuration_guides/machine_ip.rst create mode 100644 configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst create mode 100644 configuration_guides/memory_reset_trigger_mb.rst create mode 100644 configuration_guides/metadata_server_port.rst create mode 100644 configuration_guides/mt_read.rst create mode 100644 configuration_guides/mt_read_workers.rst create mode 100644 configuration_guides/orc_implicit_casts.rst create mode 100644 configuration_guides/statement_lock_timeout.rst create mode 100644 configuration_guides/use_config_ip.rst create mode 100644 configuration_guides/use_legacy_decimal_literals.rst create mode 100644 configuration_guides/use_legacy_string_literals.rst rename {guides/migration => data_ingestion_guides}/csv.rst (99%) create mode 100644 data_ingestion_guides/index.rst rename {guides => data_ingestion_guides}/inserting_data.rst (78%) rename {guides/client_drivers/python => data_ingestion_guides}/nba-t10.csv (100%) rename {guides/migration => data_ingestion_guides}/oracle.rst (82%) rename {guides/migration => data_ingestion_guides}/orc.rst (94%) rename {guides/migration => data_ingestion_guides}/parquet.rst (99%) rename {guides/migration => data_ingestion_guides}/to_csv.sql (100%) rename {guides/features => feature_guides}/access_control.rst (99%) rename {guides/features => feature_guides}/compression.rst (99%) rename {guides/features => feature_guides}/concurrency_and_locks.rst (81%) rename {guides/features => feature_guides}/concurrency_and_scaling_in_sqream.rst (94%) create mode 100644 feature_guides/flexible_data_clustering.rst create mode 100644 feature_guides/flexible_data_clustering_chunks.rst create mode 100644 feature_guides/flexible_data_clustering_data_clustering_methods.rst create mode 100644 feature_guides/flexible_data_clustering_data_examples.rst create mode 100644 feature_guides/flexible_data_clustering_data_rechunking_data.rst create mode 100644 feature_guides/flexible_data_clustering_overview.rst create mode 100644 feature_guides/index.rst rename {guides/features => feature_guides}/python_functions.rst (98%) create mode 100644 feature_guides/sqream_installer_cli_ref_admin.rst rename {guides/features => feature_guides}/transactions.rst (97%) rename {guides/features => feature_guides}/workload_manager.rst (60%) delete mode 100644 features_tour.rst create mode 100644 getting_started/connecting_clients_to_sqream.rst create mode 100644 getting_started/creating_your_first_table.rst create mode 100644 getting_started/deleting_rows.rst create mode 100644 getting_started/executing_statements_in_sqream.rst rename first_steps.rst => getting_started/getting_started.rst (94%) create mode 100644 getting_started/index.rst create mode 100644 getting_started/ingesting_data.rst create mode 100644 getting_started/inserting_rows.rst create mode 100644 getting_started/installing_sqream.rst create mode 100644 getting_started/listing_tables.rst create mode 100644 getting_started/performing_basic_sqream_operations.rst create mode 100644 getting_started/preparing_your_machine_to_install_sqream.rst create mode 100644 getting_started/querying_data.rst create mode 100644 getting_started/running_queries.rst create mode 100644 getting_started/running_the_sqream_sql_client.rst create mode 100644 getting_started/saving_query_results_to_a_csv_or_psv_file.rst delete mode 100644 guides/client_drivers/index.rst delete mode 100644 guides/features/access_control_notes.rst delete mode 100644 guides/features/chunks_and_extents.rst delete mode 100644 guides/features/data_clustering.rst delete mode 100644 guides/features/delete.rst delete mode 100644 guides/features/external_data/hdfs.rst delete mode 100644 guides/features/index.rst delete mode 100644 guides/features/metadata_system.rst delete mode 100644 guides/features/time_based_data_management.rst delete mode 100644 guides/index.rst delete mode 100644 guides/migration/avro_foreign_data_format.rst delete mode 100644 guides/migration/nba-t10.csv delete mode 100644 guides/operations/configuration.rst delete mode 100644 guides/operations/index.rst delete mode 100644 guides/operations/installing_monit.rst delete mode 100644 guides/operations/installing_sqream_with_binary.rst delete mode 100644 guides/operations/installing_sqream_with_kubernetes.rst delete mode 100644 guides/operations/launching_sqream_with_monit.rst delete mode 100644 guides/operations/monitoring.rst delete mode 100644 guides/operations/running_sqream_in_a_docker_container.rst delete mode 100644 guides/operations/sqream_studio.rst delete mode 100644 guides/operations/starting_and_stopping_the_system.rst delete mode 100644 guides/operations/statement_editor.rst delete mode 100644 guides/operations/troubleshooting.rst delete mode 100644 guides/queries.rst delete mode 100644 guides/third_party_tools/talend.rst rename {guides/operations => operational_guides}/creating_or_cloning_a_storage_cluster.rst (85%) create mode 100644 operational_guides/exporting_data.rst rename guides/features/external_data/index.rst => operational_guides/external_data.rst (74%) rename {guides/features => operational_guides}/external_tables.rst (66%) rename {guides/operations => operational_guides}/hardware_guide.rst (100%) create mode 100644 operational_guides/hdfs.rst create mode 100644 operational_guides/index.rst rename {guides/operations => operational_guides}/logging.rst (99%) rename {guides/operations => operational_guides}/monitoring_query_performance.rst (97%) rename {guides/operations => operational_guides}/optimization_best_practices.rst (55%) rename {guides/features/external_data => operational_guides}/s3.rst (100%) rename {guides/features => operational_guides}/saved_queries.rst (98%) rename {guides/operations => operational_guides}/security.rst (95%) rename {guides/features => operational_guides}/viewing_system_objects_as_ddl.rst (97%) create mode 100644 sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst create mode 100644 sqream_studio_5.4.3/creating_assigning_and_managing_roles_and_permissions.rst create mode 100644 sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst create mode 100644 sqream_studio_5.4.3/getting_started.rst create mode 100644 sqream_studio_5.4.3/index.rst create mode 100644 sqream_studio_5.4.3/monitoring_workers_and_services_from_the_dashboard.rst create mode 100644 sqream_studio_5.4.3/viewing_logs.rst rename {guides => third_party_tools}/client_drivers/cpp/connect_test.cpp (100%) rename {guides => third_party_tools}/client_drivers/cpp/index.rst (100%) rename {guides => third_party_tools}/client_drivers/cpp/insert_test.cpp (100%) create mode 100644 third_party_tools/client_drivers/index.rst rename {guides => third_party_tools}/client_drivers/jdbc/index.rst (77%) rename {guides => third_party_tools}/client_drivers/jdbc/sample.java (100%) rename {guides => third_party_tools}/client_drivers/nodejs/index.rst (100%) rename {guides => third_party_tools}/client_drivers/nodejs/sample.js (100%) rename {guides => third_party_tools}/client_drivers/odbc/index.rst (100%) rename {guides => third_party_tools}/client_drivers/odbc/install_configure_odbc_linux.rst (100%) rename {guides => third_party_tools}/client_drivers/odbc/install_configure_odbc_windows.rst (91%) rename {guides => third_party_tools}/client_drivers/python/api-reference.rst (100%) rename {guides => third_party_tools}/client_drivers/python/index.rst (99%) rename {guides/features => third_party_tools/client_drivers/python}/nba-t10.csv (100%) rename {guides => third_party_tools}/client_drivers/python/test.py (100%) rename {guides/third_party_tools => third_party_tools/client_platforms}/connect.sas (100%) rename {guides/third_party_tools => third_party_tools/client_platforms}/index.rst (92%) create mode 100644 third_party_tools/client_platforms/microstrategy.rst rename {guides/third_party_tools => third_party_tools/client_platforms}/odbc-sqream.tdc (100%) create mode 100644 third_party_tools/client_platforms/pentaho.rst rename {guides/third_party_tools => third_party_tools/client_platforms}/php.rst (96%) rename {guides/third_party_tools => third_party_tools/client_platforms}/r.rst (98%) rename {guides/third_party_tools => third_party_tools/client_platforms}/sas_viya.rst (98%) rename {guides/third_party_tools => third_party_tools/client_platforms}/sql_workbench.rst (97%) rename {guides/third_party_tools => third_party_tools/client_platforms}/tableau.rst (95%) create mode 100644 third_party_tools/client_platforms/talend.rst rename {guides/third_party_tools => third_party_tools/client_platforms}/test.php (100%) create mode 100644 third_party_tools/connectivity_ecosystem.jpg create mode 100644 third_party_tools/index.rst create mode 100644 troubleshooting/core_dumping_related_issues.rst create mode 100644 troubleshooting/examining_logs.rst create mode 100644 troubleshooting/identifying_configuration_issues.rst create mode 100644 troubleshooting/index.rst rename {guides/operations => troubleshooting}/information_for_support.rst (93%) create mode 100644 troubleshooting/lock_related_issues.rst create mode 100644 troubleshooting/log_related_issues.rst create mode 100644 troubleshooting/node_js_related_issues.rst create mode 100644 troubleshooting/remedying_slow_queries.rst create mode 100644 troubleshooting/resolving_common_issues.rst create mode 100644 troubleshooting/sas_viya_related_issues.rst create mode 100644 troubleshooting/solving_code_126_odbc_errors.rst create mode 100644 troubleshooting/sqream_sql_installation_related_issues.rst create mode 100644 troubleshooting/tableau_related_issues.rst diff --git a/guides/architecture/filesystem_and_filesystem_usage.rst b/architecture/filesystem_and_filesystem_usage.rst similarity index 100% rename from guides/architecture/filesystem_and_filesystem_usage.rst rename to architecture/filesystem_and_filesystem_usage.rst diff --git a/guides/architecture/index.rst b/architecture/index.rst similarity index 96% rename from guides/architecture/index.rst rename to architecture/index.rst index 7705abe91..5e4d6c867 100644 --- a/guides/architecture/index.rst +++ b/architecture/index.rst @@ -1,7 +1,7 @@ .. _architecture: *********************** -Architecture +System Architecture *********************** This topic includes guides that walk an end-user, database administrator, or system architect through the main ideas behind SQream DB. diff --git a/guides/architecture/internals_architecture.rst b/architecture/internals_architecture.rst similarity index 99% rename from guides/architecture/internals_architecture.rst rename to architecture/internals_architecture.rst index f25dfeb22..97019ec71 100644 --- a/guides/architecture/internals_architecture.rst +++ b/architecture/internals_architecture.rst @@ -1,7 +1,7 @@ .. _internals_architecture: *************************** -Internals and architecture +Internals and Architecture *************************** SQream DB internals diff --git a/guides/architecture/processes_and_network_architecture.rst b/architecture/processes_and_network_architecture.rst similarity index 96% rename from guides/architecture/processes_and_network_architecture.rst rename to architecture/processes_and_network_architecture.rst index 8a458f8d5..53a6afb6a 100644 --- a/guides/architecture/processes_and_network_architecture.rst +++ b/architecture/processes_and_network_architecture.rst @@ -1,7 +1,7 @@ .. _processes_and_network_architecture: ************************************* -Processes and network architecture +Processes and Network Architecture ************************************* A SQream DB installation contains several components: diff --git a/configuration_guides/admin/admin_flags.rst b/configuration_guides/admin/admin_flags.rst new file mode 100644 index 000000000..c4c170841 --- /dev/null +++ b/configuration_guides/admin/admin_flags.rst @@ -0,0 +1,44 @@ +.. _admin_flags: + +************************* +Administration Flags +************************* + +The **Administration Flags** page describes the following flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: + + +.. toctree:: + :maxdepth: 1 + :glob: + + bin_sizes + check_Cuda_Memory + compiler_Gets_Only_UFs + copy_To_Restrict_Utf8 + cpu_Reduce_Hashtable_Size + csv_Limit_Row_Length + cuda_Mem_cpy_Max_Size_Bytes + Cuda_Mem_cpy_Synchronous + cuda_Mem_Quota + developer_Mode + enable_Device_Debug_Messages + enable_LogDebug + enable_Nv_prof_Markers + end_Log_Message + extent_Storage_File_Size_MB + gather_Mem_Stat + increase_Chunk_Size_Before_Reduce + increase_Mem_Factors + level_db_Write_Buffer_Size + machine_IP + memory_Reset_Trigger_MB + metadata_Server_Port + mt_Read + mt_Read_Workers + orc_Implicit_Casts + statement_Lock_Timeout + use_Config_IP + use_Legacy_Decimal_Literals + use_Legacy_String_Literals + + diff --git a/configuration_guides/admin/bin_sizes.rst b/configuration_guides/admin/bin_sizes.rst new file mode 100644 index 000000000..d058c0ac9 --- /dev/null +++ b/configuration_guides/admin/bin_sizes.rst @@ -0,0 +1,12 @@ +.. _bin_sizes: + +************************* +Bin Size +************************* +The ``binSizes`` flag sets the custom bin size in the cache to enable high granularity over bin control. + +The following describes the ``binSizes`` flag: + +* **Modification type** - Regular +* **Data type** - string +* **Default value** - ``16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,786432000,107374,1824,1342177280,1610612736,1879048192,2147483648,2415919104,2684354560,2952790016,3221225472`` \ No newline at end of file diff --git a/configuration_guides/admin/check_cuda_memory.rst b/configuration_guides/admin/check_cuda_memory.rst new file mode 100644 index 000000000..6952968f5 --- /dev/null +++ b/configuration_guides/admin/check_cuda_memory.rst @@ -0,0 +1,12 @@ +.. _check_cuda_memory: + +************************* +Check CUDA Memory +************************* +The ``checkCudaMemory`` flag sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. + +The following describes the ``checkCudaMemory`` flag: + +* **Modification type** - Regular +* **Data type** - boolean +* **Default value** - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/admin/compiler_gets_only_ufs.rst b/configuration_guides/admin/compiler_gets_only_ufs.rst new file mode 100644 index 000000000..2216dc5cf --- /dev/null +++ b/configuration_guides/admin/compiler_gets_only_ufs.rst @@ -0,0 +1,12 @@ +.. _compiler_gets_only_ufs: + +************************* +compilerGetsOnlyUFs +************************* +The ``compilerGetsOnlyUFs`` flag sets the runtime to pass only utility functions names to the compiler. + +The following describes the ``compilerGetsOnlyUFs`` flag: + + +* **Data type** - boolean +* **Default value** - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/admin_cluster_flags.rst b/configuration_guides/admin_cluster_flags.rst new file mode 100644 index 000000000..e1120b468 --- /dev/null +++ b/configuration_guides/admin_cluster_flags.rst @@ -0,0 +1,14 @@ +.. _admin_cluster_flags: + +************************* +Cluster Administration Flags +************************* + +The **Cluster Administration Flags** page describes **Cluster** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: + +.. toctree:: + :maxdepth: 1 + :glob: + + csv_limit_row_length + extent_storage_file_size_mb \ No newline at end of file diff --git a/configuration_guides/admin_flags.rst b/configuration_guides/admin_flags.rst new file mode 100644 index 000000000..e71b9f761 --- /dev/null +++ b/configuration_guides/admin_flags.rst @@ -0,0 +1,18 @@ +.. _admin_flags: + +************************* +Administration Flags +************************* + +The **Administration Flags** page describes the following flag types, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: + + +.. toctree:: + :maxdepth: 1 + :glob: + + admin_regular_flags + admin_cluster_flags + admin_worker_flags + + diff --git a/configuration_guides/admin_regular_flags.rst b/configuration_guides/admin_regular_flags.rst new file mode 100644 index 000000000..7ee3fe555 --- /dev/null +++ b/configuration_guides/admin_regular_flags.rst @@ -0,0 +1,35 @@ +.. _admin_regular_flags: + +************************* +Regular Administration Flags +************************* + +The **Regular Administration Flags** page describes **Regular** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: + +.. toctree:: + :maxdepth: 1 + :glob: + + bin_sizes + check_cuda_memory + compiler_gets_only_ufs + copy_to_restrict_utf8 + cpu_reduce_hashtable_size + cuda_mem_cpy_max_size_bytes + cuda_mem_cpy_synchronous + developer_mode + enable_device_debug_messages + enable_log_debug + enable_nv_prof_markers + end_log_message + gather_mem_stat + increase_chunk_size_before_reduce + increase_mem_factors + level_db_write_buffer_size + memory_reset_trigger_mb + mt_read + mt_read_workers + orc_implicit_casts + statement_lock_timeout + use_legacy_decimal_literals + use_legacy_string_literals \ No newline at end of file diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst new file mode 100644 index 000000000..c5eddb721 --- /dev/null +++ b/configuration_guides/admin_worker_flags.rst @@ -0,0 +1,15 @@ +.. _admin_worker_flags: + +************************* +Worker Administration Flags +************************* +The **Worker Administration Flags** page describes **Worker** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: + +.. toctree:: + :maxdepth: 1 + :glob: + + cuda_mem_quota + machine_ip + metadata_server_port + use_config_ip \ No newline at end of file diff --git a/configuration_guides/bin_sizes.rst b/configuration_guides/bin_sizes.rst new file mode 100644 index 000000000..9cdd8e0e8 --- /dev/null +++ b/configuration_guides/bin_sizes.rst @@ -0,0 +1,13 @@ +.. _bin_sizes: + +************************* +Setting Bin Size +************************* +The ``binSizes`` flag sets the custom bin size in the cache to enable high granularity over bin control. + +The following describes the ``binSizes`` flag: + +* **Data type** - string + +The **Default value** for the ``binSizes`` flag is ``16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,786432000,107374,1824,`` +``1342177280,1610612736,1879048192,2147483648,2415919104,2684354560,2952790016,3221225472`` \ No newline at end of file diff --git a/configuration_guides/check_cuda_memory.rst b/configuration_guides/check_cuda_memory.rst new file mode 100644 index 000000000..84eec3f07 --- /dev/null +++ b/configuration_guides/check_cuda_memory.rst @@ -0,0 +1,11 @@ +.. _check_cuda_memory: + +************************* +Setting CUDA Memory +************************* +The ``checkCudaMemory`` flag sets the pad device memory allocation with safety buffers to catch out-of-bounds writes. + +The following describes the ``checkCudaMemory`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/compiler_gets_only_ufs.rst b/configuration_guides/compiler_gets_only_ufs.rst new file mode 100644 index 000000000..1190adc3e --- /dev/null +++ b/configuration_guides/compiler_gets_only_ufs.rst @@ -0,0 +1,11 @@ +.. _compiler_gets_only_ufs: + +************************* +Limiting Runtime to Utility Functions +************************* +The ``compilerGetsOnlyUFs`` flag sets the runtime to pass only utility functions names to the compiler. + +The following describes the ``compilerGetsOnlyUFs`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/cpu_reduce_hashtable_size.rst b/configuration_guides/cpu_reduce_hashtable_size.rst new file mode 100644 index 000000000..c2b01604c --- /dev/null +++ b/configuration_guides/cpu_reduce_hashtable_size.rst @@ -0,0 +1,11 @@ +.. _cpu_reduce_hashtable_size: + +************************* +Enabling High Bin Control Granularity +************************* +The ``copyToRestrictUtf8`` flag sets the custom bin size in the cache to enable high bin control granularity. + +The following describes the ``checkCudaMemory`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/csv_limit_row_length.rst b/configuration_guides/csv_limit_row_length.rst new file mode 100644 index 000000000..03f31c697 --- /dev/null +++ b/configuration_guides/csv_limit_row_length.rst @@ -0,0 +1,11 @@ +.. _csv_limit_row_length: + +************************* +Setting Maximum CSV Row Length +************************* +The ``csvLimitRowLength`` flag sets the maximum supported CSV row length. + +The following describes the ``csvLimitRowLength`` flag: + +* **Data type** - uint +* **Default value** - ``100000`` \ No newline at end of file diff --git a/configuration_guides/cuda_mem_cpy_max_size_bytes.rst b/configuration_guides/cuda_mem_cpy_max_size_bytes.rst new file mode 100644 index 000000000..371c9bda4 --- /dev/null +++ b/configuration_guides/cuda_mem_cpy_max_size_bytes.rst @@ -0,0 +1,11 @@ +.. _cuda_mem_cpy_max_size_bytes: + +************************* +Setting Chunk Size for Copying from CPU to GPU +************************* +The ``cudaMemcpyMaxSizeBytes`` flag sets the chunk size for copying from CPU to GPU. If this value is set to ``0``, do not divide. + +The following describes the ``cudaMemcpyMaxSizeBytes`` flag: + +* **Data type** - uint +* **Default value** - ``0`` \ No newline at end of file diff --git a/configuration_guides/cuda_mem_cpy_synchronous.rst b/configuration_guides/cuda_mem_cpy_synchronous.rst new file mode 100644 index 000000000..81e762071 --- /dev/null +++ b/configuration_guides/cuda_mem_cpy_synchronous.rst @@ -0,0 +1,11 @@ +.. _cuda_mem_cpy_synchronous: + +************************* +Indicating GPU Synchronicity +************************* +The ``CudaMemcpySynchronous`` flag indicates if copying from/to GPU is synchronous. + +The following describes the ``CudaMemcpySynchronous`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/cuda_mem_quota.rst b/configuration_guides/cuda_mem_quota.rst new file mode 100644 index 000000000..43f9d4943 --- /dev/null +++ b/configuration_guides/cuda_mem_quota.rst @@ -0,0 +1,11 @@ +.. _cuda_mem_quota: + +************************* +Setting Total Device Memory Usage in SQream Instance +************************* +The ``cudaMemQuota`` flag sets the percentage of total device memory used by your instance of SQream. + +The following describes the ``cudaMemQuota`` flag: + +* **Data type** - uint +* **Default value** - ``90`` diff --git a/configuration_guides/developer_mode.rst b/configuration_guides/developer_mode.rst new file mode 100644 index 000000000..fbb6c0cec --- /dev/null +++ b/configuration_guides/developer_mode.rst @@ -0,0 +1,11 @@ +.. _developer_mode: + +************************* +Enabling Modification of R&D Flags +************************* +The ``developerMode`` flag enables modifying R&D flags. + +The following describes the ``developerMode`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` diff --git a/configuration_guides/enable_device_debug_messages.rst b/configuration_guides/enable_device_debug_messages.rst new file mode 100644 index 000000000..c7d340b65 --- /dev/null +++ b/configuration_guides/enable_device_debug_messages.rst @@ -0,0 +1,11 @@ +.. _enable_device_debug_messages: + +************************* +Checking for Post-Production CUDA Errors +************************* +The ``enableDeviceDebugMessages`` flag checks for CUDA errors after producing each chunk. + +The following describes the ``enableDeviceDebugMessages`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` diff --git a/configuration_guides/enable_log_debug.rst b/configuration_guides/enable_log_debug.rst new file mode 100644 index 000000000..1566c4882 --- /dev/null +++ b/configuration_guides/enable_log_debug.rst @@ -0,0 +1,11 @@ +.. _enable_log_debug: + +************************* +Enabling Modification of clientLogger_debug File +************************* +The ``enableLogDebug`` flag enables creating and logging in the **clientLogger_debug** file. + +The following describes the ``enableLogDebug`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/enable_nv_prof_markers.rst b/configuration_guides/enable_nv_prof_markers.rst new file mode 100644 index 000000000..9edbf28e3 --- /dev/null +++ b/configuration_guides/enable_nv_prof_markers.rst @@ -0,0 +1,11 @@ +.. _enable_nv_prof_markers: + +************************* +Activating the NVidia Profiler Markers +************************* +The ``enableNvprofMarkers`` flag activates the NVidia Profiler (nvprof) markers. + +The following describes the ``enableNvprofMarkers`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/end_log_message.rst b/configuration_guides/end_log_message.rst new file mode 100644 index 000000000..46a1c71ae --- /dev/null +++ b/configuration_guides/end_log_message.rst @@ -0,0 +1,11 @@ +.. _end_log_message: + +************************* +Appending String at End of Log Lines +************************* +The ``endLogMessage`` flag appends a string at the end of each log line. + +The following describes the ``endLogMessage`` flag: + +* **Data type** - string +* **Default value** - ``EOM`` \ No newline at end of file diff --git a/configuration_guides/extent_storage_file_size_mb.rst b/configuration_guides/extent_storage_file_size_mb.rst new file mode 100644 index 000000000..dd4cddec7 --- /dev/null +++ b/configuration_guides/extent_storage_file_size_mb.rst @@ -0,0 +1,11 @@ +.. _extent_storage_file_size_mb: + +************************* +Setting Minimum Extent Size for Bulk Table Data +************************* +The ``extentStorageFileSizeMB`` flag sets the minimum size in mebibytes of extents for bulk table data. + +The following describes the ``extentStorageFileSizeMB`` flag: + +* **Data type** - uint +* **Default value** - ``20`` \ No newline at end of file diff --git a/configuration_guides/flip_join_order.rst b/configuration_guides/flip_join_order.rst new file mode 100644 index 000000000..341f12ada --- /dev/null +++ b/configuration_guides/flip_join_order.rst @@ -0,0 +1,11 @@ +.. _flip_join_order: + +************************* +Flipping Join Order to Force Equijoins +************************* +The ``flipJoinOrder`` flag reorders join to force equijoins and/or equijoins sorted by table size. + +The following describes the ``flipJoinOrder`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/gather_mem_stat.rst b/configuration_guides/gather_mem_stat.rst new file mode 100644 index 000000000..802e12b1f --- /dev/null +++ b/configuration_guides/gather_mem_stat.rst @@ -0,0 +1,11 @@ +.. _gather_mem_stat: + +************************* +Monitoring and Printing Pinned Allocation Reports +************************* +The ``gatherMemStat`` flag monitors all pinned allocations and all **memcopies** to and from a device, and prints a report of pinned allocations that were not **memcopied** to and from the device using the **dump_pinned_misses** utility function. + +The following describes the ``gatherMemStat`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/generic/generic_flags.rst b/configuration_guides/generic/generic_flags.rst new file mode 100644 index 000000000..4a79c94b8 --- /dev/null +++ b/configuration_guides/generic/generic_flags.rst @@ -0,0 +1,18 @@ +.. _generic_flags: + +************************* +Generic Flags +************************* + +The **Administration Flags** page describes the following flags, which can be modified by standard users on a session basis: + + +.. toctree:: + :maxdepth: 1 + :glob: + + flip_Join_Order + limit_Query_Memory_GB + log_Sys_Level + max_Avg_Blob_Size_To_Compress_On_Gpu + spool_Memory_GB \ No newline at end of file diff --git a/configuration_guides/generic/spooling.rst b/configuration_guides/generic/spooling.rst new file mode 100644 index 000000000..dcf1c775f --- /dev/null +++ b/configuration_guides/generic/spooling.rst @@ -0,0 +1,69 @@ +.. _spooling: + +************************** +Configuring the Spooling Feature +************************** +The **Configuring the Spooling Feature** page includes the following topics: + +.. contents:: + :local: + :depth: 1 + + +Overview +---------- +From the SQream Acceleration Studio you can allocate the amount of memory (GB) available to the server for spooling using the ``spoolMemoryGB`` flag. SQream recommends setting the ``spoolMemoryGB`` flag to 90% of the ``limitQueryMemoryGB`` flag. The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. + +In addition, the ``limitQueryMemoryGB`` defines how much total system memory is used by each worker. SQream recommends setting ``limitQueryMemoryGB`` to 5% less than the total host memory divided by the amount of ``sqreamd`` workers on host. + +Note that ``spoolMemoryGB`` must bet set to less than the ``limitQueryMemoryGB``. + +Example Configurations +---------- +The **Example Configurations** section shows the following example configurations: + +.. contents:: + :local: + :depth: 1 + +Example 1 - Recommended Settings +~~~~~~~~~~~ +The following is an example of the recommended settings for a machine with 512GB of RAM and 4 workers: + +.. code-block:: console + + limitQueryMemoryGB - ⌊(512 * 0.95 / 4)⌋ → ~ 486 / 4 → 121 + spoolMemoryGB - ⌊( 0.9 * limitQueryMemoryGB )⌋ → ⌊( 0.9 * 121 )⌋ → 108 + +Example 2 - Setting Spool Memory +~~~~~~~~~~~ +The following is an example of setting ``spoolMemoryGB`` value in the current configuration method per-worker for 512GB of RAM and 4 workers: + +.. code-block:: console + + { + “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, + “gpu”: 0, + “licensePath”: “home/test_user/SQream/tests/license.enc”, + “machineIP”: “127.0.0.1”, + “metadataServerIp”: “127.0.0.1”, + “metadataServerPort”: “3105, + “port”: 5000, + “useConfigIP”” true, + “limitQueryMemoryGB" : 121, + “spoolMemoryGB" : 108 + “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” + } + +The following is an example of setting ``spoolMemoryGB`` value in the previous configuration method per-worker for 512GB of RAM and 4 workers: + +.. code-block:: console + + “runtimeFlags”: { + “limitQueryMemoryGB” : 121, + “spoolMemoryGB” : 108 + +For more information about configuring the ``spoolMemoryGB`` flag, see the following: + +* **Current configuration method**: Configuration flags +* **Previous configuration method**: Runtime global flags \ No newline at end of file diff --git a/configuration_guides/generic_flags.rst b/configuration_guides/generic_flags.rst new file mode 100644 index 000000000..2f17e8202 --- /dev/null +++ b/configuration_guides/generic_flags.rst @@ -0,0 +1,17 @@ +.. _generic_flags: + +************************* +Generic Flags +************************* + +The **Generic Flags** page describes the following flag types, which can be modified by standard users on a session basis: + +.. toctree:: + :maxdepth: 1 + :glob: + + generic_regular_flags + generic_cluster_flags + generic_worker_flags + + diff --git a/configuration_guides/generic_regular_flags.rst b/configuration_guides/generic_regular_flags.rst new file mode 100644 index 000000000..0181f1ce1 --- /dev/null +++ b/configuration_guides/generic_regular_flags.rst @@ -0,0 +1,15 @@ +.. _generic_regular_flags: + +************************* +Regular Generic Flags +************************* + +The **Regular Generic Flags** page describes **Regular** modification type flags, which can be modified by standard users on a session basis: + +.. toctree:: + :maxdepth: 1 + :glob: + + flip_join_order + log_sys_level + max_avg_blob_size_to_compress_on_gpu \ No newline at end of file diff --git a/configuration_guides/generic_worker_flags.rst b/configuration_guides/generic_worker_flags.rst new file mode 100644 index 000000000..14f2de0c6 --- /dev/null +++ b/configuration_guides/generic_worker_flags.rst @@ -0,0 +1,12 @@ +.. _generic_worker_flags: + +************************* +Worker Generic Flags +************************* +The Worker Generic Flags** page describes **Worker** modification type flags, which can be modified by standard users on a session basis: + +.. toctree:: + :maxdepth: 1 + :glob: + + limit_query_memory_gb \ No newline at end of file diff --git a/configuration_guides/increase_chunk_size_before_reduce.rst b/configuration_guides/increase_chunk_size_before_reduce.rst new file mode 100644 index 000000000..982d3db35 --- /dev/null +++ b/configuration_guides/increase_chunk_size_before_reduce.rst @@ -0,0 +1,11 @@ +.. _increase_chunk_size_before_reduce: + +************************* +Increasing Chunk Size to Reduce Query Speed +************************* +The ``increaseChunkSizeBeforeReduce`` flag increases the chunk size to reduce query speed. + +The following describes the ``increaseChunkSizeBeforeReduce`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` diff --git a/configuration_guides/increase_mem_factors.rst b/configuration_guides/increase_mem_factors.rst new file mode 100644 index 000000000..166a57e14 --- /dev/null +++ b/configuration_guides/increase_mem_factors.rst @@ -0,0 +1,11 @@ +.. _increase_mem_factors: + +************************* +Adding Rechunker before Expensing Chunk Producer +************************* +The ``increaseMemFactors`` flag adds a rechunker before expensive chunk producer. + +The following describes the ``increaseMemFactors`` flag: + +* **Data type** - boolean +* **Default value** - ``TRUE`` \ No newline at end of file diff --git a/configuration_guides/index.rst b/configuration_guides/index.rst new file mode 100644 index 000000000..8e1e81728 --- /dev/null +++ b/configuration_guides/index.rst @@ -0,0 +1,20 @@ +.. _configuration_guides: + +************************* +Configuration Guides +************************* +Once installed, you can configure your instance of SQream using the SQream Acceleration Studio. + +The SQream Acceleration Studio divides flags into the following roles, each with their own set of permissions: + +.. toctree:: + :maxdepth: 2 + :glob: + + admin_flags + generic_flags + +For more information, see the following: + +* :ref:`SQream Acceleration Studio 5.4.2` +* :ref:`Configuring Your Instance of SQream` \ No newline at end of file diff --git a/configuration_guides/level_db_write_buffer_size.rst b/configuration_guides/level_db_write_buffer_size.rst new file mode 100644 index 000000000..c3cd60516 --- /dev/null +++ b/configuration_guides/level_db_write_buffer_size.rst @@ -0,0 +1,11 @@ +.. _level_db_write_buffer_size: + +************************* +Setting the Buffer Size +************************* +The ``leveldbWriteBufferSize`` flag sets the buffer size. + +The following describes the ``leveldbWriteBufferSize`` flag: + +* **Data type** - uint +* **Default value** - ``524288`` \ No newline at end of file diff --git a/configuration_guides/limit_query_memory_gb.rst b/configuration_guides/limit_query_memory_gb.rst new file mode 100644 index 000000000..7099674f2 --- /dev/null +++ b/configuration_guides/limit_query_memory_gb.rst @@ -0,0 +1,11 @@ +.. _limit_query_memory_gb: + +************************* +Setting Query Memory Processing Limit +************************* +The ``limitQueryMemoryGB`` flag prevents a query from processing more memory than the defined value. + +The following describes the ``limitQueryMemoryGB`` flag: + +* **Data type** - uint +* **Default value** - ``100000`` \ No newline at end of file diff --git a/configuration_guides/log_sys_level.rst b/configuration_guides/log_sys_level.rst new file mode 100644 index 000000000..07e1e5800 --- /dev/null +++ b/configuration_guides/log_sys_level.rst @@ -0,0 +1,19 @@ +.. _log_sys_level: + +************************* +Determining Client Level +************************* +The ``logSysLevel`` flag determines the client log level, as follows: + +* **0** - L_SYSTEM +* **1** - L_FATAL +* **2** - L_ERROR +* **3** - L_WARN +* **4** - L_INFO +* **5** - L_DEBUG +* **6** - L_TRACE + +The following describes the ``logSysLevel`` flag: + +* **Data type** - uint +* **Default value** - ``100000`` \ No newline at end of file diff --git a/configuration_guides/machine_ip.rst b/configuration_guides/machine_ip.rst new file mode 100644 index 000000000..66a8a9a10 --- /dev/null +++ b/configuration_guides/machine_ip.rst @@ -0,0 +1,11 @@ +.. _machine_ip: + +************************* +Enabling Manually Setting Reported IP +************************* +The ``machineIP`` flag enables you to manually set the reported IP. + +The following describes the ``machineIP`` flag: + +* **Data type** - string +* **Default value** - ``127.0.0.1`` \ No newline at end of file diff --git a/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst b/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst new file mode 100644 index 000000000..1081e0225 --- /dev/null +++ b/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst @@ -0,0 +1,11 @@ +.. _max_avg_blob_size_to_compress_on_gpu: + +************************* +Setting CPU to Compress Defined Columns +************************* +The ``maxAvgBlobSizeToCompressOnGpu`` flag sets the CPU to compress columns with size above * . + +The following describes the ``maxAvgBlobSizeToCompressOnGpu`` flag: + +* **Data type** - uint +* **Default value** - ``120`` \ No newline at end of file diff --git a/configuration_guides/memory_reset_trigger_mb.rst b/configuration_guides/memory_reset_trigger_mb.rst new file mode 100644 index 000000000..bb8a383bb --- /dev/null +++ b/configuration_guides/memory_reset_trigger_mb.rst @@ -0,0 +1,11 @@ +.. _memory_reset_trigger_mb: + +************************* +Setting Memory Used to Abort Server +************************* +The ``memoryResetTriggerMB`` flag sets the size of memory used during a query to trigger aborting the server. + +The following describes the ``memoryResetTriggerMB`` flag: + +* **Data type** - uint +* **Default value** - ``0`` diff --git a/configuration_guides/metadata_server_port.rst b/configuration_guides/metadata_server_port.rst new file mode 100644 index 000000000..20f9a2db8 --- /dev/null +++ b/configuration_guides/metadata_server_port.rst @@ -0,0 +1,11 @@ +.. _metadata_server_port: + +************************* +Setting Port Used for Metadata Server Connection +************************* +The ``metadataServerPort`` flag sets the port used to connect to the metadata server. SQream recommends using port ranges above 1024 because ports below 1024 are usually reserved, although there are no strict limitations. You can use any positive number (1 - 65535) while setting this flag. + +The following describes the ``metadataServerPort`` flag: + +* **Data type** - uint +* **Default value** - ``3105`` \ No newline at end of file diff --git a/configuration_guides/mt_read.rst b/configuration_guides/mt_read.rst new file mode 100644 index 000000000..4aca17185 --- /dev/null +++ b/configuration_guides/mt_read.rst @@ -0,0 +1,11 @@ +.. _mt_read: + +************************* +Splitting Large Reads for Concurrent Execution +************************* +The ``mtRead`` flag splits large reads into multiple smaller ones and executes them concurrently. + +The following describes the ``mtRead`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` diff --git a/configuration_guides/mt_read_workers.rst b/configuration_guides/mt_read_workers.rst new file mode 100644 index 000000000..5f18fd4b3 --- /dev/null +++ b/configuration_guides/mt_read_workers.rst @@ -0,0 +1,11 @@ +.. _mt_read_workers: + +************************* +Setting Worker Amount to Handle Concurrent Reads +************************* +The ``mtReadWorkers`` flag sets the number of workers to handle smaller concurrent reads. + +The following describes the ``mtReadWorkers`` flag: + +* **Data type** - uint +* **Default value** - ``30`` diff --git a/configuration_guides/orc_implicit_casts.rst b/configuration_guides/orc_implicit_casts.rst new file mode 100644 index 000000000..04cc903e9 --- /dev/null +++ b/configuration_guides/orc_implicit_casts.rst @@ -0,0 +1,11 @@ +.. _orc_implicit_casts: + +************************* +Setting Implicit Casts in ORC Files +************************* +The ``orcImplicitCasts`` flag sets the implicit cast in orc files, such as **int** to **tinyint** and vice versa. + +The following describes the ``orcImplicitCasts`` flag: + +* **Data type** - boolean +* **Default value** - ``TRUE`` diff --git a/configuration_guides/statement_lock_timeout.rst b/configuration_guides/statement_lock_timeout.rst new file mode 100644 index 000000000..639f5d02d --- /dev/null +++ b/configuration_guides/statement_lock_timeout.rst @@ -0,0 +1,11 @@ +.. _statement_lock_timeout: + +************************* +Setting Timeout Limit for Locking Objects before Executing Statements +************************* +The ``statementLockTimeout`` flag sets the timeout (seconds) for acquiring object locks before executing statements. + +The following describes the ``statementLockTimeout`` flag: + +* **Data type** - uint +* **Default value** - ``3`` diff --git a/configuration_guides/use_config_ip.rst b/configuration_guides/use_config_ip.rst new file mode 100644 index 000000000..8779899b1 --- /dev/null +++ b/configuration_guides/use_config_ip.rst @@ -0,0 +1,11 @@ +.. _use_config_ip: + +************************* +Assigning Local Network IP +************************* +The ``useConfigIP`` flag activates the machineIP (``true``). Setting this flag to ``false`` ignores the machineIP and automatically assigns a local network IP. This cannot be activated in a cloud scenario (on-premises only). + +The following describes the ``useConfigIP`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/use_legacy_decimal_literals.rst b/configuration_guides/use_legacy_decimal_literals.rst new file mode 100644 index 000000000..63650a95b --- /dev/null +++ b/configuration_guides/use_legacy_decimal_literals.rst @@ -0,0 +1,11 @@ +.. _use_legacy_decimal_literals: + +************************* +Interpreting Decimal Literals as Double Instead of Numeric +************************* +The ``useLegacyDecimalLiterals`` flag interprets decimal literals as **Double** instead of **Numeric**. This flag is used to preserve legacy behavior in existing customers. + +The following describes the ``useLegacyDecimalLiterals`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` diff --git a/configuration_guides/use_legacy_string_literals.rst b/configuration_guides/use_legacy_string_literals.rst new file mode 100644 index 000000000..a00e2f7eb --- /dev/null +++ b/configuration_guides/use_legacy_string_literals.rst @@ -0,0 +1,11 @@ +.. _use_legacy_string_literals: + +************************* +Interpreting VARCHAR as TEXT +************************* +The ``useLegacyStringLiterals`` flag interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. This flag is used to preserve legacy behavior in existing customers. + +The following describes the ``useLegacyStringLiterals`` flag: + +* **Data type** - boolean +* **Default value** - ``FALSE`` \ No newline at end of file diff --git a/guides/migration/csv.rst b/data_ingestion_guides/csv.rst similarity index 99% rename from guides/migration/csv.rst rename to data_ingestion_guides/csv.rst index 431ec259f..f44c3c9e9 100644 --- a/guides/migration/csv.rst +++ b/data_ingestion_guides/csv.rst @@ -1,10 +1,10 @@ .. _csv: ********************** -Insert from CSV +Inserting Data from a CSV File ********************** -This guide covers inserting data from CSV files into SQream DB using the :ref:`copy_from` method. +This guide covers inserting data from CSV files into SQream DB using the :ref:`copy_from` method. .. contents:: In this topic: diff --git a/data_ingestion_guides/index.rst b/data_ingestion_guides/index.rst new file mode 100644 index 000000000..09c121fcd --- /dev/null +++ b/data_ingestion_guides/index.rst @@ -0,0 +1,17 @@ +.. _data_ingestion_guides: + +************************* +Data Ingestion Sources +************************* +The **Data Ingestion Sources** page provides information about the following data ingestion sources: + +.. toctree:: + :maxdepth: 1 + :glob: + + csv + parquet + orc + oracle + +For information about database tools and interfaces that SQream supports, see `Third Party Tools `_. diff --git a/guides/inserting_data.rst b/data_ingestion_guides/inserting_data.rst similarity index 78% rename from guides/inserting_data.rst rename to data_ingestion_guides/inserting_data.rst index 5e6f1bcdb..93200d927 100644 --- a/guides/inserting_data.rst +++ b/data_ingestion_guides/inserting_data.rst @@ -1,19 +1,19 @@ .. _inserting_data: *************************** -Inserting Data +Inserting data *************************** -This guide covers inserting data into SQream, with subguides on inserting data from a variety of sources and locations. +This guide covers inserting data into SQream DB, with subguides on inserting data from a variety of sources and locations. .. contents:: In this topic: :local: -Data Loading Overview +Data loading overview ================================ -SQream supports importing data from the following sources: +SQream DB supports importing data from the following sources: * Using :ref:`insert` with :ref:`a client driver` * Using :ref:`copy_from`: @@ -29,19 +29,19 @@ SQream supports importing data from the following sources: - :ref:`hdfs` -SQream supports loading files in the following formats: +SQream DB supports loading files in the following formats: * Text - CSV, TSV, PSV * Parquet * ORC -Data Loading Considerations +Data loading considerations ================================ -Verifying Data and Performance When Load is Completed +Verify data and performance after load ----------------------------------------- -Like other RDBMSs, SQream has its own set of best practcies for table design and query optimization. +Like other RDBMSs, SQream DB has its own set of best practcies for table design and query optimization. SQream therefore recommends: @@ -55,17 +55,17 @@ SQream therefore recommends: * Data types were not over-provisioned (e.g. don't use VARCHAR(2000) to store a short string) -File Source location for Loading +File source location for loading -------------------------------- During loading using :ref:`copy_from`, the statement can run on any worker. If you are running multiple nodes, make sure that all nodes can see the source the same. If you load from a local file which is only on 1 node and not on shared storage, it will fail some of the time. (If you need to, you can also control which node a statement runs on using the :ref:`workload_manager`). -Supported Load Methods +Supported load methods ------------------------------- -SQream's :ref:`COPY FROM` syntax can be used to load CSV files, but can't be used for Parquet and ORC. +SQream DB's :ref:`COPY FROM` syntax can be used to load CSV files, but can't be used for Parquet and ORC. -The :ref:`FOREIGN TABLE` statement can be used to load text files, Parquet, and ORC files, and can also transform the data prior to materialization as a full table. +:ref:`FOREIGN TABLE` can be used to load text files, Parquet, and ORC files, and can also transform the data prior to materialization as a full table. .. list-table:: :widths: auto @@ -78,34 +78,34 @@ The :ref:`FOREIGN TABLE` statement can be used to load text fil - ORC - Streaming data * - :ref:`copy_from` - - Can be used - - Cannot be used - - Cannot be used - - Cannot be used + - ✓ + - ✗ + - ✗ + - ✗ * - :ref:`external_tables` - - Can be used - - Can be used - - Can be used - - Cannot be used + - ✓ + - ✓ + - ✓ + - ✗ * - :ref:`insert` - - Cannot be used - - Cannot be used - - Cannot be used - - Can be used (Python, JDBC, Node.JS) + - ✗ + - ✗ + - ✗ + - ✓ (Python, JDBC, Node.JS) -Unsupported Data Types +Unsupported data types ----------------------------- -SQream doesn't support the entire set of features that some other database systems may have, such as ``ARRAY``, ``BLOB``, ``ENUM``, ``SET``, etc. +SQream DB doesn't support the entire set of features that some other database systems may have, such as ``ARRAY``, ``BLOB``, ``ENUM``, ``SET``, etc. These data types will have to be converted before load. For example, ``ENUM`` can often be stored as a ``VARCHAR``. -Extended Error Handling +Extended error handling ---------------------------- -While :ref:`foreign tables` can be used to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options, as well as extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. +While :ref:`external tables` can be used to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options, as well as extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. -Best Practices for CSV +Best practices for CSV ------------------------------ Text files like CSV rarely conform to `RFC 4180 `_ , so alterations may be required: @@ -126,26 +126,26 @@ Text files like CSV rarely conform to `RFC 4180 `_ , specifically the `Data Pump Export utility `_ . -2. Exporting Your Schema +2. Export the desired schema =================================== Use the Data Pump Export utility to export the database schema. @@ -33,18 +33,16 @@ The resulting Oracle-only schema is stored in a dump file. Examples ------------ -Dump All Tables +Dump all tables ^^^^^^^^^^^^^^^^^^^^^^ -The following shows the correct syntax for dumping all tables: .. code-block:: console $ expdp rhendricks/secretpassword DIRECTORY=dpumpdir DUMPFILE=tables.dmp CONTENT=metadata_only NOLOGFILE -Dumping Specific Tables +Dump only specific tables ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The following shows the correct syntax for dumping specific tables: In this example, we specify two tables for dumping. @@ -52,12 +50,12 @@ In this example, we specify two tables for dumping. $ expdp rhendricks/secretpassword DIRECTORY=dpumpdir DUMPFILE=tables.dmp CONTENT=metadata_only TABLES=employees,jobs NOLOGFILE -3. Converting the Oracle Dump to Standard SQL +3. Convert the Oracle dump to standard SQL ======================================================= -Oracle's Data Pump Import utility helps convert the dump from the previous step to standard SQL. +Oracle's Data Pump Import utility will help us convert the dump from the previous step to standard SQL. -The following is the correct Import utility format: +The format for using the Import utility is ``impdp / DIRECTORY= DUMPFILE= SQLFILE= TRANSFORM=SEGMENT_ATTRIBUTES:N:table PARTITION_OPTIONS=MERGE`` @@ -67,34 +65,33 @@ The following is the correct Import utility format: Example ---------- -The following shows the correct syntax for converting the Oracle dump to standard SQL: .. code-block:: console $ impdp rhendricks/secretpassword DIRECTORY=dpumpdir DUMPFILE=tables.dmp SQLFILE=sql_export.sql TRANSFORM=SEGMENT_ATTRIBUTES:N:table PARTITION_OPTIONS=MERGE -4. Identify Database Structures +4. Figure out the database structures =============================================== -Using the SQL file created in the previous step, write ``CREATE TABLE`` statements to match the schemas of the tables. +Using the SQL file created in the previous step, write CREATE TABLE statements to match the schemas of the tables. -Removing Unsupported Attributes +Remove unsupported attributes ----------------------------------- Trim unsupported primary keys, indexes, constraints, and other unsupported Oracle attributes. -Matching Data Types +Match data types --------------------- -Refer to the table below to match the Oracle source data type to a new SQream type: +Refer to the table below to match the Oracle source data type to a new SQream DB type: -.. list-table:: Data Types +.. list-table:: Data types :widths: auto :header-rows: 1 - * - Oracle Data Type + * - Oracle Data type - Precision - - SQream Data Type + - SQream DB data type * - ``CHAR(n)``, ``CHARACTER(n)`` - Any ``n`` - ``VARCHAR(n)`` @@ -144,9 +141,8 @@ Refer to the table below to match the Oracle source data type to a new SQream ty Read more about :ref:`supported data types in SQream DB`. -Additional Considerations +Additional considerations ----------------------------- -Note the following when migrating from Oracle to SQream using CSV files: * Understand how :ref:`tables are created in SQream DB` @@ -154,13 +150,16 @@ Note the following when migrating from Oracle to SQream using CSV files: * Oracle roles and user management commands need to be rewritten to SQream DB's format. SQream DB supports :ref:`full role-based access control (RBAC)` similar to Oracle. -5. Creating the Tables in SQream +5. Create the tables in SQream DB ====================================== -After rewriting the table strucutres, you can create them in SQream. + +After rewriting the table strucutres, create them in SQream DB. Example --------- -The following example of creating a table in SQream is based on Oracle's ``HR.EMPLOYEES`` sample table: + + +Consider Oracle's ``HR.EMPLOYEES`` sample table: .. code-block:: sql @@ -202,7 +201,7 @@ The following example of creating a table in SQream is based on Oracle's ``HR.EM REFERENCES employees ) ; -This table is rewritten for SQream as follows: +This table rewritten for SQream DB would be created like this: .. code-block:: postgres @@ -222,18 +221,20 @@ This table is rewritten for SQream as follows: ); -6. Exporting Tables to CSV Files +6. Export tables to CSVs =============================== -The following options can be used for exporting tables to CSV files: +Exporting CSVs from Oracle servers is not a trivial task. -.. contents:: +.. contents:: Options for exporting to CSVs :local: -Using SQL*Plus to Export Data Lists +Using SQL*Plus to export data lists ------------------------------------------ -The following is a :download:`sample SQL*Plus script ` for exporting PSVs in a SQream readable format: +Here's a sample SQL*Plus script that will export PSVs in a format that SQream DB can read: + +:download:`Download to_csv.sql ` .. literalinclude:: to_csv.sql :language: sql @@ -253,14 +254,14 @@ Enter SQL*Plus and export tables one-by-one interactively: Each table is exported as a data list file (``.lst``). -Creating CSVs Using Stored Procedures +Creating CSVs using stored procedures ------------------------------------------- -You can use stored procedures if they have been set-up. +You can use stored procedures if you have them set-up. Examples of `stored procedures for generating CSVs `_` can be found in the Ask The Oracle Mentors forums. -CSV Generation Considerations +CSV generation considerations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Files should be a valid CSV. By default, SQream DB's CSV parser can handle `RFC 4180 standard CSVs `_ , but can also be modified to support non-standard CSVs (with multi-character delimiters, unquoted fields, etc). @@ -292,7 +293,7 @@ CSV Generation Considerations .. note:: If a text field is quoted but contains no content (``""``) it is considered an empty text field. It is not considered ``NULL``. -7. Storing CSV Files in a SQream Worker Accessible Location +7. Place CSVs where SQream DB workers can access ======================================================= During data load, the :ref:`copy_from` command can run on any worker (unless explicitly speficied with the :ref:`workload_manager`). @@ -304,7 +305,7 @@ It is important that every node has the same view of the storage being used - me * For S3, ensure network access to the S3 endpoint -8. Bulk Load CSV Files +8. Bulk load the CSVs ================================= Issue the :ref:`copy_from` commands to SQream DB to insert a table from the CSVs created. @@ -313,18 +314,21 @@ Repeat the ``COPY FROM`` command for each table exported from Oracle. Example ------------- -The following shows the correct syntax of bulk loading CSV files based on the ``employees`` table: + +For the ``employees`` table, run the following command: .. code-block:: postgres COPY employees FROM 'employees.lst' WITH DELIMITER '|'; -9. Rewriting Oracle Queries +9. Rewrite Oracle queries ===================================== -SQream supports a large subset of ANSI SQL. You must refactor much of Oracle's SQL and functions that often are not ANSI SQL. +SQream DB supports a large subset of ANSI SQL. + +You will have to refactor much of Oracle's SQL and functions that often are not ANSI SQL. -SQream recommends the following resources: +We recommend the following resources: * :ref:`sql_feature_support` - to understand SQream DB's SQL feature support. @@ -346,4 +350,4 @@ SQream recommends the following resources: * :ref:`Views` - SQream DB supports logical views, but does not support materialized views. -* :ref:`window_functions` - SQream DB supports a wide array of window functions. +* :ref:`window_functions` - SQream DB supports a wide array of window functions. \ No newline at end of file diff --git a/guides/migration/orc.rst b/data_ingestion_guides/orc.rst similarity index 94% rename from guides/migration/orc.rst rename to data_ingestion_guides/orc.rst index cac4aadd8..d199e958e 100644 --- a/guides/migration/orc.rst +++ b/data_ingestion_guides/orc.rst @@ -1,13 +1,13 @@ .. _orc: ********************** -Insert from ORC +Inserting Data from an ORC File ********************** -This guide covers inserting data from ORC files into SQream DB using :ref:`FOREIGN TABLE`. +This guide covers inserting data from ORC files into SQream DB using :ref:`FOREIGN TABLE`. -1. Preparing Your Files +1. Prepare the files ===================== Prepare the source ORC files, with the following requirements: @@ -145,7 +145,7 @@ Prepare the source ORC files, with the following requirements: .. rubric:: Footnotes -.. [#f0] Text values include ``TEXT`` and ``VARCHAR``. +.. [#f0] Text values include ``TEXT``, ``VARCHAR``, and ``NVARCHAR`` .. [#f5] Boolean values are cast to 0, 1 @@ -153,7 +153,7 @@ Prepare the source ORC files, with the following requirements: .. [#f7] Will succeed if all values fit the destination type -2. Storing CSV Files in a SQream Worker Accessible Location +2. Place ORC files where SQream DB workers can access them ================================================================ Any worker may try to access files (unless explicitly speficied with the :ref:`workload_manager`). @@ -165,7 +165,7 @@ It is important that every node has the same view of the storage being used - me * For S3, ensure network access to the S3 endpoint. See our :ref:`s3` guide for more information. -3. Determining Your Table Structure +3. Figure out the table structure =============================================== Prior to loading data, you will need to write out the table structure, so that it matches the file structure. @@ -209,7 +209,7 @@ We will make note of the file structure to create a matching ``CREATE FOREIGN TA If the column type isn't supported, a possible workaround is to set it to any arbitrary type and then exclude it from subsequent queries. -4. Verify Your Table of Contents +4. Verify table contents ==================================== External tables do not verify file integrity or structure, so verify that the table definition matches up and contains the correct data. @@ -232,7 +232,7 @@ External tables do not verify file integrity or structure, so verify that the ta If any errors show up at this stage, verify the structure of the ORC files and match them to the external table structure you created. -5. Copying Your Data into SQream +5. Copying data into SQream DB =================================== To load the data into SQream DB, use the :ref:`create_table_as` statement: @@ -242,7 +242,7 @@ To load the data into SQream DB, use the :ref:`create_table_as` statement: CREATE TABLE nba AS SELECT * FROM ext_nba; -Working Around Unsupported Column Types +Working around unsupported column types --------------------------------------------- Suppose you only want to load some of the columns - for example, if one of the columns isn't supported. @@ -259,7 +259,7 @@ For this example, assume that the ``Position`` column isn't supported because of -- We ommitted the unsupported column `Position` from this query, and replaced it with a default ``NULL`` value, to maintain the same table structure. -Modifying Data During the Copy Process +Modifying data during the copy process ------------------------------------------ One of the main reasons for staging data with ``EXTERNAL TABLE`` is to examine the contents and modify them before loading them. @@ -276,13 +276,13 @@ Similar to the previous example, we will also set the ``Position`` column as a d ORDER BY weight; -Additional ORC Loading Examples +Further ORC loading examples ======================================= :ref:`create_foreign_table` contains several configuration options. See more in :ref:`the CREATE FOREIGN TABLE parameters section`. -Loading a Table from a Directory of ORC Files on HDFS +Loading a table from a directory of ORC files on HDFS ------------------------------------------------------------ .. code-block:: postgres @@ -297,7 +297,7 @@ Loading a Table from a Directory of ORC Files on HDFS CREATE TABLE users AS SELECT * FROM ext_users; -Loading a Table from a Bucket of Files on S3 +Loading a table from a bucket of files on S3 ----------------------------------------------- .. code-block:: postgres diff --git a/guides/migration/parquet.rst b/data_ingestion_guides/parquet.rst similarity index 99% rename from guides/migration/parquet.rst rename to data_ingestion_guides/parquet.rst index 7f80ab206..800c3122a 100644 --- a/guides/migration/parquet.rst +++ b/data_ingestion_guides/parquet.rst @@ -1,10 +1,10 @@ .. _parquet: ********************** -Insert from Parquet +Inserting Data from a Parquet File ********************** -This guide covers inserting data from Parquet files into SQream DB using :ref:`FOREIGN TABLE`. +This guide covers inserting data from Parquet files into SQream DB using :ref:`FOREIGN TABLE`. .. contents:: In this topic: :local: diff --git a/guides/migration/to_csv.sql b/data_ingestion_guides/to_csv.sql similarity index 100% rename from guides/migration/to_csv.sql rename to data_ingestion_guides/to_csv.sql diff --git a/guides/features/access_control.rst b/feature_guides/access_control.rst similarity index 99% rename from guides/features/access_control.rst rename to feature_guides/access_control.rst index 9aced4b02..7f92f8eaf 100644 --- a/guides/features/access_control.rst +++ b/feature_guides/access_control.rst @@ -1,7 +1,7 @@ .. _access_control: ************** -Access control +Access Control ************** .. contents:: In this topic: @@ -10,7 +10,7 @@ Access control Overview ========== -Access control provides authentication and authorization in SQream DB. +Access control provides authentication and authorization in SQream DB. SQream DB manages authentication and authorization using a role-based access control system (RBAC), like ANSI SQL and other SQL products. diff --git a/guides/features/compression.rst b/feature_guides/compression.rst similarity index 99% rename from guides/features/compression.rst rename to feature_guides/compression.rst index 662eda044..710641036 100644 --- a/guides/features/compression.rst +++ b/feature_guides/compression.rst @@ -15,7 +15,7 @@ When data is stored in a columnar format, it is often in a common format. This i Because encoding uses specific data formats and encodings, it increases performance and reduces data size. -SQream DB encodes data in several ways depending on the data type. For example, a date is stored as an integer, with March 1st 1CE as the start. This is a lot more efficient than encoding the date as a string, and offers a wider range than storing it relative to the Unix Epoch. +SQream DB encodes data in several ways depending on the data type. For example, a date is stored as an integer, with March 1st 1CE as the start. This is a lot more efficient than encoding the date as a string, and offers a wider range than storing it relative to the Unix Epoch. Compression ============== diff --git a/guides/features/concurrency_and_locks.rst b/feature_guides/concurrency_and_locks.rst similarity index 81% rename from guides/features/concurrency_and_locks.rst rename to feature_guides/concurrency_and_locks.rst index f917bb128..e18dea015 100644 --- a/guides/features/concurrency_and_locks.rst +++ b/feature_guides/concurrency_and_locks.rst @@ -1,10 +1,10 @@ .. _concurrency_and_locks: *********************** -Concurrency and locks +Concurrency and Locks *********************** -Locks are used in SQream DB to provide consistency when there are multiple concurrent transactions updating the database. +Locks are used in SQream DB to provide consistency when there are multiple concurrent transactions updating the database. Read only transactions are never blocked, and never block anything. Even if you drop a database while concurrently running a query on it, both will succeed correctly (as long as the query starts running before the drop database commits). @@ -101,34 +101,7 @@ In this example, we create a table based on results (:ref:`create_table_as`), bu 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 +For more information on troubleshooting lock related issues, see -Troubleshooting locks -========================== -Sometimes, a rare situation can occur where a lock is never freed. -The workflow for troubleshooting locks is: - -#. Identify which statement has obtained locks -#. Understand if the statement is itself stuck, or waiting for another statement -#. Try to abort the offending statement -#. Force the stale locks to be removed - -Example ------------ - -We will assume that the statement from the previous example is stuck (statement #\ ``287``). We can attempt to abort it using :ref:`stop_statement`: - -.. code-block:: psql - - t=> SELECT STOP_STATEMENT(287); - executed - -If the locks still appear in the :ref:`show_locks` utility, we can force remove the stale locks: - -.. code-block:: psql - - t=> SELECT RELEASE_DEFUNCT_LOCKS(); - executed - -.. warning:: This operation can cause some statements to fail on the specific worker on which they are queued. This is intended as a "last resort" to solve stale locks. diff --git a/guides/features/concurrency_and_scaling_in_sqream.rst b/feature_guides/concurrency_and_scaling_in_sqream.rst similarity index 94% rename from guides/features/concurrency_and_scaling_in_sqream.rst rename to feature_guides/concurrency_and_scaling_in_sqream.rst index aafdda2b5..0370913fa 100644 --- a/guides/features/concurrency_and_scaling_in_sqream.rst +++ b/feature_guides/concurrency_and_scaling_in_sqream.rst @@ -1,10 +1,10 @@ .. _concurrency_and_scaling_in_sqream: *************************************** -Concurrency and scaling in SQream DB +Concurrency and Scaling in SQream DB *************************************** -A SQream DB cluster can concurrently run one regular statement per worker process. A number of small statements will execute alongside these statements without waiting or blocking anything. +A SQream DB cluster can concurrently run one regular statement per worker process. A number of small statements will execute alongside these statements without waiting or blocking anything. SQream DB supports ``n`` concurrent statements by having ``n`` workers in a cluster. Each worker uses a fixed slice of a GPU's memory, with usual values are around 8-16GB of GPU memory per worker. This size is ideal for queries running on large data with potentially large row sizes. diff --git a/feature_guides/flexible_data_clustering.rst b/feature_guides/flexible_data_clustering.rst new file mode 100644 index 000000000..ce0f3d321 --- /dev/null +++ b/feature_guides/flexible_data_clustering.rst @@ -0,0 +1,16 @@ +.. _flexible_data_clustering: + +*********************** +Flexible Data Clustering +*********************** +The **Flexible Data Clustering** section describes the following: + +.. toctree:: + :maxdepth: 4 + :titlesonly: + + flexible_data_clustering_overview + flexible_data_clustering_chunks + flexible_data_clustering_data_clustering_methods + flexible_data_clustering_data_rechunking_data + flexible_data_clustering_data_examples \ No newline at end of file diff --git a/feature_guides/flexible_data_clustering_chunks.rst b/feature_guides/flexible_data_clustering_chunks.rst new file mode 100644 index 000000000..b8146d0fc --- /dev/null +++ b/feature_guides/flexible_data_clustering_chunks.rst @@ -0,0 +1,18 @@ +.. _flexible_data_clustering_chunks: + +*********************** +What are Chunks? +*********************** +Chunks, sometimes referred to as **partitions**, are a contiguous number of rows in a specific column. SQream relies on an advanced partitioning method called **chunking**, which provides all static partitioning capabilities without the known limitations. + +The following figure shows a table rows grouped as chunks: + +.. figure:: /_static/images/chunking2.png + :scale: 75 % + :align: center + +The following figure shows the rows from the table above converted into chunks: + +.. figure:: /_static/images/chunking_metadata2.png + :scale: 75 % + :align: center \ No newline at end of file diff --git a/feature_guides/flexible_data_clustering_data_clustering_methods.rst b/feature_guides/flexible_data_clustering_data_clustering_methods.rst new file mode 100644 index 000000000..87ba7e5cf --- /dev/null +++ b/feature_guides/flexible_data_clustering_data_clustering_methods.rst @@ -0,0 +1,183 @@ +.. _flexible_data_clustering_data_clustering_methods: + +*********************** +Data Clustering Methods +*********************** +The following data clustering methods can be used in tandem or separately to enhance query performance: + +.. contents:: + :local: + :depth: 1 + +Using Time-Based Data Management +============ +Overview +~~~~~~~~~~ +**Time-based data management** refers to sorting table data along naturally occuring dimensions. The most common and naturally occuring sorting mechanism is a **timestamp**, which indicates the point in time at which data was inserted into SQream. Because SQream is a columnar storage system, timestamped metadata facilitates quick and easy query processing. + +The following is the correct syntax for timestamping a chunk: + +.. code-block:: postgres + + SELECT DATEPART(HOUR, timestamp), + MIN(transaction_amount), + MAX(transaction_amount), + avg(transaction_amount) + FROM transactions + WHERE timestamp BETWEEN (CURRENT_TIMESTAMP AND DATEADD(MONTH,-3,CURRENT_TIMESTAMP)) + GROUP BY 1; + +Timestamping data includes the following properties: + +* Data is loaded in a natural order while being inserted. + + :: + +* Updates are infrequent or non-existent. Updates occur by inserting new rows, which have their own timestamps. + + :: + +* Queries on timestamped data is typically on continuous time range. + + :: + +* Inserting and reading data are performed independently, not in the operation or transaction. + + :: + +* Timestamped data has a high data volume and accumulates faster than typical online transactional processing workloads. + +The following are some scenarios ideal for timestamping: + +* Running analytical queries spanning specific date ranges (such as the sum of transactions during August-July 2020 versus August-July 2019). + + :: + +* Deleting data older than a specific number of months old. + + :: + +* Regulations require you to maintain several years of data that you do not need to query on a regular basis. + +Best Practices for Time-Based Management +~~~~~~~~~~ +Data inserted in bulks is automatically timestamped with the insertion date and time. Therefore, inserting data through small and frequent bulks has the effect of naturally ordering data according to timestamp. Frequent bulks generally refers to short time frames, such as at 15-minute, hourly, or daily intervals. As you insert new data, SQream chunks and appends it into your existing tables according to its timestamp. + +The ``DATE`` and ``DATETIME`` types were created to improve performance, minimze storage size, and maintain data integrity. SQream recommends using them instead of ``VARCHAR``. + +Using Clustering Keys +============ +Overview +~~~~~~~~~~ +While data clustering occurs relatively naturally within a table, certain practices can be used to actively enhance query performance and runtime. Defining **clustering keys** increases performance by explicitly co-locating your data, enabling SQream to avoid processing irrelevant chunks. + +A clustering key is a subset of table columns or expressions and is defined using the ``CLUSTER BY`` statement, as shown below: + +.. code-block:: postgres + + CREATE TABLE users ( + name VARCHAR(30) NOT NULL, + start_date datetime not null, + country VARCHAR(30) DEFAULT 'Unknown' NOT NULL + ) CLUSTER BY country; + + + +The ``CLUSTER BY`` statement splits ingested data based on the range of data corresponding to the clustering key. This helps create chunks based on specific or related data, avoiding mixed chunks as much as possible. For example, instead of creating chunks based on a fixed number of rows, the ``CLUSTER_BY`` statement creates them based on common values. This optimizes the ``DELETE`` command as well, which deletes rows based on their location in a table. + +For more information, see the following: + +* `The CLUSTER_BY statement `_ +* `The DELETE statement `_ +* `The Deleting Data guide `_ + +Inspecting Clustered Table Health +~~~~~~~~~~ +You can use the ``clustering_health`` utility function to check how well a table is clustered, as shown below: + +.. code-block:: postgres + + SELECT CLUSTERING_HEALTH('table_name','clustering_keys'); + +The ``CLUSTERING_HEALTH`` function returns the average clustering depth of your table relative to the clustering keys. A lower value indicates a well-clustered table. + +Clustering keys are useful for restructuring large tables not optimally ordered when inserted or as a result of extensive DML. A table that uses clustering keys is referred to as a **clustered table**. Tables that are not clustered require SQream's query optimizer to scan entire tables while running queries, dramatically increasing runtime. Some queries significantly benefit from clustering, such as filtering or joining extensively on clustered columns. + +SQream partially sorts data that you load into a clustered table. Note that while clustering tables increases query performance, clustering during the insertion stage can decrease performance by 75%. Nevertheless, once a table is clustered subsequent queries run more quickly. + +.. note:: + + To determine whether clustering will enhance performance, SQream recommends end-to-end testing your clustering keys on a small subset of your data before committing them to permanent use. This is relevant for testing insert and query performance. + +For more information, see the following: + +* **Data Manipulation commands (DML)** - see `Data Manipulation Commands (DML) `_. + +* **Creating tables** - see :ref:`create_table`. When you create a table, all new data is clustered upon insert. + +* **Modifying tables** - see :ref:`cluster_by`. + +* **Modifying a table schema** - see :ref:`alter_table`. + +Using Metadata +============ +SQream uses an automated and transparent system for collecting metadata describing each chunk. This metadata enables skipping unnecessary chunks and extents during query runtime. The system collects chunk metadata when data is inserted into SQream. This is done by splitting data into chunks and collecting and storing specific parameters to be used later. + +Because collecting metadata is not process-heavy and does not contribute significantly to query processing, it occurs continuously as a background process. Most metadata collection is typically performed by the GPU. For example, for a 10TB dataset, the metadata storage overhead is approximately 0.5GB. + +When a query includes a filter (such as a ``WHERE`` or ``JOIN`` condition) on a range of values spanning a fraction of the table values, SQream scans only the filtered segment of the table. + +Once collected, several metadata parameters are stored for later use, including: + +* The range of values on each column chunk (minimum, maximum). + + :: + +* The number of values. + + :: + +* Additional information for query optimization. + +Data is collected automatically and transparently on every column type. + +Queries filtering highly granular date and time ranges are the most effective, particularly when data is timestamped, and when tables contain a large amount of historical data. + +Using Chunks and Extents +============ +SQream stores data in logical tables made up of rows spanning one or more columns. Internally, data is stored in vertical partitions by column, and horizontally by chunks. The **Using Chunks and Extents** section describes how to leverge chunking to optimize query performance. + +A **chunk** is a contiguous number of rows in a specific column. Depending on data type, a chunk's uncompressed size typically ranges between 1MB and a few hundred megabytes. This size range is suitable for filtering and deleting data from large tables, which may contain between hundreds, millions, or billions of chunks. + +An **extent** is a specific number of contiguous chunks. Extents optimize disk access patterns, at around 20MB uncompressed, on-disk. Extents typically include between one and 25 chunks based on the compressed size of each chunk. + +.. note:: + + SQream compresses all data. In addition, all tables are automatically and transparently chunked. + +Unlike node-partitioning (or sharding), chunks are: + +* Small enough to be read concurrently by multiple workers. + + :: + +* Optimized for inserting data quickly. + + :: + +* Capable of carrying metadata, which narrows down their contents for the query optimizer. + + :: + +* Ideal for data retension because they can be deleted in bulk. + + :: + +* Optimized for reading into RAM and the GPU. + + :: + +* Compressed individually to improve compression and data locality. + + + diff --git a/feature_guides/flexible_data_clustering_data_examples.rst b/feature_guides/flexible_data_clustering_data_examples.rst new file mode 100644 index 000000000..0c720ff04 --- /dev/null +++ b/feature_guides/flexible_data_clustering_data_examples.rst @@ -0,0 +1,22 @@ +.. _flexible_data_clustering_data_examples: + +*********************** +Examples +*********************** +The **Examples** includes the following examples: + +.. contents:: + :local: + :depth: 1 + +Creating a Clustered Table +----------------------------- +The following is an example of syntax for creating a clustered table on a table naturally ordered by ``start_date``. An alternative cluster key can be defined on such a table to improve performance on queries already ordered by ``country``: + +.. code-block:: postgres + + CREATE TABLE users ( + name VARCHAR(30) NOT NULL, + start_date datetime not null, + country VARCHAR(30) DEFAULT 'Unknown' NOT NULL + ) CLUSTER BY country; \ No newline at end of file diff --git a/feature_guides/flexible_data_clustering_data_rechunking_data.rst b/feature_guides/flexible_data_clustering_data_rechunking_data.rst new file mode 100644 index 000000000..30a74bbaa --- /dev/null +++ b/feature_guides/flexible_data_clustering_data_rechunking_data.rst @@ -0,0 +1,11 @@ +.. _flexible_data_clustering_data_rechunking_data: + +*********************** +Rechunking Data +*********************** +SQream performs background storage reorganization operations to optimize I/O and read patterns. + +For example, when small batches of data are inserted, SQream runs two background processes called **rechunk** and **reextent** to reorganize the data into larger contiguous chunks and extents. This is also what happens when data is deleted. + + +Instead of overwriting data, SQream writes new optimized chunks and extents to replace old ones. After rewriting all old data, SQream switches to the new optimized chunks and extents and deletes the old data. \ No newline at end of file diff --git a/feature_guides/flexible_data_clustering_overview.rst b/feature_guides/flexible_data_clustering_overview.rst new file mode 100644 index 000000000..3ba59a603 --- /dev/null +++ b/feature_guides/flexible_data_clustering_overview.rst @@ -0,0 +1,16 @@ +.. _flexible_data_clustering_overview: + +*********************** +Overeview +*********************** +**Flexible data clustering** refers to sorting table data along naturally occuring dimensions, such as name, date, or location. Data clustering optimizes table structure to significantly improve query performance, especially on very large tables. A well-clustered table increases the effectivity of the metadata collected by focusing on a specific and limited range of rows, called **chunks**. + +The following are some scenarios ideal for data clustering: + +* Queries containg a ``WHERE`` predicate written as ``column COMPARISON value``, such as ``date_column > '2019-01-01'`` or ``id = 107`` when the columns referenced are clustering keys. + + In such a case SQream reads the portion of data that contain values matching these predicates only. + +* Two clustered tables joined by their respective clustering keys. + + In such a case SQream uses metadata to more easily identify matching chunks. \ No newline at end of file diff --git a/feature_guides/index.rst b/feature_guides/index.rst new file mode 100644 index 000000000..7a7309733 --- /dev/null +++ b/feature_guides/index.rst @@ -0,0 +1,24 @@ +.. _feature_guides: + +*********************** +Feature Guides +*********************** +The **Feature Guides** section describes background processes that SQream uses to manage several areas of operation, such as data ingestion, load balancing, and access control. + +This section describes the following features: + +.. toctree:: + :maxdepth: 1 + :titlesonly: + + + xxconfiguring_your_database + access_control + compression + xxflexible_data_clustering + python_functions + workload_manager + transactions + concurrency_and_locks + concurrency_and_scaling_in_sqream + xxinternational_languages_and_character_sets \ No newline at end of file diff --git a/guides/features/python_functions.rst b/feature_guides/python_functions.rst similarity index 98% rename from guides/features/python_functions.rst rename to feature_guides/python_functions.rst index 3d3c6f00f..3717cdcd8 100644 --- a/guides/features/python_functions.rst +++ b/feature_guides/python_functions.rst @@ -1,10 +1,10 @@ .. _python_functions: ************************************* -Python UDF (user-defined functions) +Python UDF (User-Defined Functions) ************************************* -User-defined functions (UDFs) are a feature that extends SQream DB's built in SQL functionality. SQream DB's Python UDFs allow developers to create new functionality in SQL by writing the lower-level language implementation in Python. +User-defined functions (UDFs) are a feature that extends SQream DB's built in SQL functionality. SQream DB's Python UDFs allow developers to create new functionality in SQL by writing the lower-level language implementation in Python. .. contents:: In this topic: :local: diff --git a/feature_guides/sqream_installer_cli_ref_admin.rst b/feature_guides/sqream_installer_cli_ref_admin.rst new file mode 100644 index 000000000..fad8107b9 --- /dev/null +++ b/feature_guides/sqream_installer_cli_ref_admin.rst @@ -0,0 +1,142 @@ +.. _sqream_installer_cli_ref_admin: + +********************************* +SQream Installer +********************************* +``sqream-installer`` is an application that prepares and configures a dockerized SQream DB installation. + +This page serves as a reference for the options and parameters. + +.. contents:: In this topic: + :local: + + +Operations and flag reference +=============================== + +Command line flags +----------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Flag + - Description + * - ``-i`` + - Loads the docker images for installation + * - ``-k`` + - Load new licenses from the ``license`` subdirectory + * - ``-K`` + - Validate licenses + * - ``-f`` + - Force overwrite any existing installation **and data directories currently in use** + * - ``-c `` + - Specifies a path to read and store configuration files in. Defaults to ``/etc/sqream``. + * - ``-v `` + - Specifies a path to the storage cluster. The path is created if it does not exist. + * - ``-l `` + - Specifies a path to store system startup logs. Defaults to ``/var/log/sqream`` + * - ``-d `` + - Specifies a path to expose to SQream DB workers. To expose several paths, repeat the usage of this flag. + * - ``-s`` + - Shows system settings + * - ``-r`` + - Reset the system configuration. This flag can't be combined with other flags. + +Usage +============= + +Install SQream DB for the first time +---------------------------------------- + +Assuming license package tarball has been placed in the ``license`` subfolder. + +* The path where SQream DB will store data is ``/home/rhendricks/sqream_storage``. + +* Logs will be stored in /var/log/sqream + +* Source CSV, Parquet, and ORC files can be accessed from ``/home/rhendricks/source_data``. All other directory paths are hidden from the Docker container. + +.. code-block:: console + + # ./sqream-install -i -k -v /home/rhendricks/sqream_storage -l /var/log/sqream -c /etc/sqream -d /home/rhendricks/source_data + +.. note:: Installation commands should be run with ``sudo`` or root access. + +Modify exposed directories +------------------------------- + +To expose more directory paths for SQream DB to read and write data from, re-run the installer with additional directory flags. + +.. code-block:: console + + # ./sqream-install -d /home/rhendricks/more_source_data + +There is no need to specify the initial installation flags - only the modified exposed directory paths flag. + + +Install a new license package +---------------------------------- + +Assuming license package tarball has been placed in the ``license`` subfolder. + +.. code-block:: console + + # ./sqream-install -k + +View system settings +---------------------------- + +This information may be useful to identify problems accessing directory paths, or locating where data is stored. + +.. code-block:: console + + # ./sqream-install -s + SQREAM_CONSOLE_TAG=1.7.4 + SQREAM_TAG=2020.1 + SQREAM_EDITOR_TAG=3.1.0 + license_worker_0=[...] + license_worker_1=[...] + license_worker_2=[...] + license_worker_3=[...] + SQREAM_VOLUME=/home/rhendricks/sqream_storage + SQREAM_DATA_INGEST=/home/rhendricks/source_data + SQREAM_CONFIG_DIR=/etc/sqream/ + LICENSE_VALID=true + SQREAM_LOG_DIR=/var/log/sqream/ + SQREAM_USER=sqream + SQREAM_HOME=/home/sqream + SQREAM_ENV_PATH=/home/sqream/.sqream/env_file + PROCESSOR=x86_64 + METADATA_PORT=3105 + PICKER_PORT=3108 + NUM_OF_GPUS=8 + CUDA_VERSION=10.1 + NVIDIA_SMI_PATH=/usr/bin/nvidia-smi + DOCKER_PATH=/usr/bin/docker + NVIDIA_DRIVER=418 + SQREAM_MODE=single_host + + +.. _upgrade_with_docker: + +Upgrading to a new version of SQream DB +---------------------------------------------- + +When upgrading to a new version with Docker, most settings don't need to be modified. + +The upgrade process replaces the existing docker images with new ones. + +#. Obtain the new tarball, and untar it to an accessible location. Enter the newly extracted directory. + +#. + Install the new images + + .. code-block:: console + + # ./sqream-install -i + +#. The upgrade process will check for running SQream DB processes. If any are found running, the installer will ask to stop them in order to continue the upgrade process. Once all services are stopped, the new version will be loaded. + +#. After the upgrade, open :ref:`sqream_console_cli_reference` and restart the desired services. \ No newline at end of file diff --git a/guides/features/transactions.rst b/feature_guides/transactions.rst similarity index 97% rename from guides/features/transactions.rst rename to feature_guides/transactions.rst index f63c3a9c6..675957d51 100644 --- a/guides/features/transactions.rst +++ b/feature_guides/transactions.rst @@ -4,7 +4,7 @@ Transactions *********************** -SQream DB supports serializable transactions. This is also called 'ACID compliance'. +SQream DB supports serializable transactions. This is also called 'ACID compliance'. The implementation of transactions means that commit, rollback and recovery are all extremely fast. diff --git a/guides/features/workload_manager.rst b/feature_guides/workload_manager.rst similarity index 60% rename from guides/features/workload_manager.rst rename to feature_guides/workload_manager.rst index 03f99d093..5b79f4675 100644 --- a/guides/features/workload_manager.rst +++ b/feature_guides/workload_manager.rst @@ -1,15 +1,15 @@ .. _workload_manager: *********************** -Workload manager +Workload Manager *********************** -The workload manager (WLM) allows SQream DB workers to identify their availability to clients with specific service names. The load balancer will then use that information to route statements to specific workers. +The **Workload Manager** allows SQream DB workers to identify their availability to clients with specific service names. The load balancer uses that information to route statements to specific workers. -Why use the workload manager? +Overview =============================== -The workload manager allows a system engineer or database administrator to allocate specific workers and compute resoucres for various tasks. +The Workload Manager allows a system engineer or database administrator to allocate specific workers and compute resoucres for various tasks. For example: @@ -17,19 +17,18 @@ For example: #. Creating a service for the company's leadership during working hours for dedicated access, and disabling this service at night to allow maintenance operations to use the available compute. -Setting up service queues +Setting Up Service Queues ========================== By default, every worker subscribes to the ``sqream`` service queue. Additional service names are configured in the configuration file for every worker, but can also be :ref:`set on a per-session basis`. -Example - Allocating resources for ETL +Example - Allocating ETL Resources ======================================== +Allocating ETL resources ensures high quality service without requiring management users to wait. -We want to allocate resources for ETL to ensure a good quality of service, but we also have management users who don't like waiting. - -The configuration in this example allocates resources as follows: +The configuration in this example allocates resources as shown below: * 1 worker for ETL work * 3 workers for general queries @@ -61,14 +60,14 @@ The configuration in this example allocates resources as follows: - ✓ - ✓ -This configuration gives the ETL queue dedicated access to two workers, one of which can't be used by regular queries. +This configuration gives the ETL queue dedicated access to two workers, one of which cannot be used by regular queries. -Queries from management will use any available worker. +Queries from management uses any available worker. -Creating this configuration +Creating the Configuration ----------------------------------- -The persistent configuration for this setup is listed in these four configuration files. +The persistent configuration for this set-up is listed in the four configuration files shown below. Each worker gets a comma-separated list of service queues that it subscribes to. These services are specified in the ``initialSubscribedServices`` attribute. @@ -112,12 +111,17 @@ Each worker gets a comma-separated list of service queues that it subscribes to. } } -.. tip:: This configuration can be created temporarily (for the current session only) by using the :ref:`subscribe_service` and :ref:`unsubscribe_service` statements. +.. tip:: You can create this configuration temporarily (for the current session only) by using the :ref:`subscribe_service` and :ref:`unsubscribe_service` statements. -Verifying the configuration +Verifying the Configuration ----------------------------------- -Use :ref:`show_subscribed_instances` to view service subscriptions for each worker. Use ref:`show_server_status` to see the statement queues. +Use :ref:`show_subscribed_instances` to view service subscriptions for each worker. Use `SHOW_SERVER_STATUS `_ to see the statement queues. + + + + + .. code-block:: psql @@ -133,13 +137,30 @@ Use :ref:`show_subscribed_instances` to view service subscriptions for each work query | node_9551 | 192.168.1.91 | 5000 management | node_9551 | 192.168.1.91 | 5000 -Configuring a client to connect to a specific service +Configuring a Client Connection to a Specific Service =========================================================== +You can configure a client connection to a specific service in one of the following ways: -Using :ref:`sqream_sql_cli_reference` +.. contents:: + :local: + +Using SQream Studio -------------------------------------------- +When using **SQream Studio**, you can configure a client connection to a specific service from the SQream Studio, as shown below: + +.. image:: /_static/images/TPD_33.png + + + +For more information, in Studio, see `Executing Statements from the Toolbar `_. + + + + -Add ``--service=`` to the command line. +Using the SQream SQL CLI Reference +-------------------------------------------- +When using the **SQream SQL CLI Reference**, you can configure a client connection to a specific service by adding ``--service=`` to the command line, as shown below: .. code-block:: psql @@ -150,21 +171,27 @@ Add ``--service=`` to the command line. To quit, use ^D or \q. master=>_ + +For more information, see the :ref:`sqream_sql_cli_reference`. + -Using :ref:`JDBC` --------------------------------------------- -Add ``--service=`` to the command line. +Using a JDBC Client Driver +-------------------------------------------- +When using a **JDBC client driver**, you can configure a client connection to a specific service by adding ``--service=`` to the command line, as shown below: .. code-block:: none - :caption: JDBC connection string + :caption: JDBC Connection String jdbc:Sqream://127.0.0.1:3108/raviga;user=rhendricks;password=Tr0ub4dor&3;service=etl;cluster=true;ssl=false; + -Using :ref:`odbc` --------------------------------------------- +For more information, see the `JDBC Client Driver `_. -On Linux, modify the :ref:`DSN parameters` in ``odbc.ini``. + +Using an ODBC Client Driver +-------------------------------------------- +When using an **ODBC client driver**, you can configure a client connection to a specific service on Linux by modifying the :ref:`DSN parameters` in ``odbc.ini``. For example, ``Service="etl"``: @@ -186,10 +213,12 @@ For example, ``Service="etl"``: On Windows, change the parameter in the :ref:`DSN editing window`. -Using :ref:`pysqream` --------------------------------------------- +For more information, see the `ODBC Client Driver `_. -In Python, set the ``service`` parameter in the connection command: + +Using a Python Client Driver +-------------------------------------------- +When using a **Python client driver**, you can configure a client connection to a specific service by setting the ``service`` parameter in the connection command, as shown below: .. code-block:: python :caption: Python @@ -198,14 +227,16 @@ In Python, set the ``service`` parameter in the connection command: con = pysqream.connect(host='127.0.0.1', port=3108, database='raviga' , username='rhendricks', password='Tr0ub4dor&3' , clustered=True, use_ssl = False, service='etl') + +For more information, see the `Python (pysqream) connector `_. -Using :ref:`nodejs` --------------------------------------------- -Add the service to the connection settings: +Using a Node.js Client Driver +-------------------------------------------- +When using a **Node.js client driver**, you can configure a client connection to a specific service by adding the service to the connection settings, as shown below: .. code-block:: javascript - :caption: Node.JS + :caption: Node.js :emphasize-lines: 5 const Connection = require('sqreamdb'); @@ -218,3 +249,5 @@ Add the service to the connection settings: cluster: 'true', service: 'etl' }; + +For more information, see the `Node.js Client Driver `_. diff --git a/features_tour.rst b/features_tour.rst deleted file mode 100644 index b300ff68e..000000000 --- a/features_tour.rst +++ /dev/null @@ -1,189 +0,0 @@ -.. _features_tour: - -***************************** -Tour of the SQream DB product -***************************** - -Overview -========= - -SQream DB is a columnar analytic SQL database management system. SQream DB uses GPUs to load and analyze large amounts of data. - -SQL Features -============ - -Types ------ - -bool -tinyint, smallint, int, bigint -real, double -varchar, nvarchar -date -timestamp - - -Queries -------- - -select lists -from -where -tablerefs, joins -order by -limit -set operators (only union all) -distinct -aggregates, having -what are all the aggregate fns? -also show agg distinct - -window functions -what are all the window fns -show aggs in windwos -partition, order - - - -nested queries -ctes - -query external table - - -.. - not enough interesting to say about scalar expressions here specifically - here are some things to try to work into the other examples: - - 'string literal' - 'something with ''quotes'' and stuff' - 1 - 0.2 - 3e-4 - null - true - false - a + b - and, or, comparisons, - ||, like, rlike - not true - is null/ is not null - a in (1,2,3) - between - extract - coalesce - nullif - case 2 variations - * - function app - - cast(a as b) - a :: b - - - - - -Tables ------- - -create table -columns + types -schema -defaults -null, not null - - -alter table: add column, drop column, rename column, rename table - -create table as - -Inserting data --------------- - -insert - -external tables -select insert -copy - - -delete ------------ - -delete from t; -truncate t; -delete from t where ... - -views ------ - -create and drop - -saved queries -------------- - -udfs ------- - -access control --------------- - -roles as users/logins: -create, alter, drop role -rename role - -permissions -grant, revoke - -groups - -default permissions - -notes -============= - -figure out how to put these in sections -maybe some of it should go before the sql features and some after - - - -5TB to 500TB+ - -columnar -external algos -scaling -gpus - -catalog - -wlm - -cluster/concurrency/ha system - -docker - -metadata system - - -can support 30+ concurrent users - -has high availability - -runs on prem or on the cloud - -we see customers able to go from 3 months to 12 years data - -extremely fast data loading speed - -robust serializable transactions and concurrency control - -wide range of client drivers - -integrates with a wide range of third party components - -performance -cost/ tco - -highly responsive team, including new feature development - diff --git a/getting_started/connecting_clients_to_sqream.rst b/getting_started/connecting_clients_to_sqream.rst new file mode 100644 index 000000000..9a376cc3d --- /dev/null +++ b/getting_started/connecting_clients_to_sqream.rst @@ -0,0 +1,26 @@ +.. _connecting_clients_to_sqream: + +**************************** +Connecting Clients to SQream +**************************** +SQream supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualiztion tools and utilities. + +SQream supports the following client platforms: + +* Connect to SQream Using SQL Workbench +* Connecting to SQream Using Tableau +* Connect to SQream Using Pentaho Data Integration +* Connect to SQream Using MicroStrategy +* Connect to SQream Using R +* Connect to SQream Using PHP +* Connect to SQream Using SAS Viya + +SQream supports the following client drivers: + +* JDBC +* Python (pysqream) +* Node.JS +* ODBC +* C++ Driver + +For more information, see `Third Party Tools`_. \ No newline at end of file diff --git a/getting_started/creating_your_first_table.rst b/getting_started/creating_your_first_table.rst new file mode 100644 index 000000000..c070b43ed --- /dev/null +++ b/getting_started/creating_your_first_table.rst @@ -0,0 +1,80 @@ +.. _creating_your_first_table: + +**************************** +Creating Your First Table +**************************** +The **Creating Your First Table** section describes the following: + +* :ref:`Creating a table` +* :ref:`Replacing a table` +* :ref:`Listing a CREATE TABLE statement` +* :ref:`Dropping a table` + + +.. _creating_a_table: + +**Creating a Table** + +The ``CREATE TABLE`` syntax is used to create your first table. This table includes a table name and column specifications, as shown in the following example: + +.. code-block:: postgres + + CREATE TABLE cool_animals ( + id INT NOT NULL, + name VARCHAR(20), + weight INT + ); + +For more information on creating a table, see :ref:`create_table`. + +.. _replacing_a_table: + +**Replacing a Table** + +You can drop an existing table and create a new one by adding the ``OR REPLACE`` parameter after the ``CREATE`` keyword, as shown in the following example: + +.. code-block:: postgres + + CREATE OR REPLACE TABLE cool_animals ( + id INT NOT NULL, + name VARCHAR(20), + weight INT + ); + +.. TODO: cool_animals? I think we need to decide if the customer for this documenation is 12 years old, or an IT professional. + +.. _listing_a_create_table_statement: + +**Listing a CREATE TABLE Statement** + +You can list the full, verbose ``CREATE TABLE`` statement for a table by using the **GET DDL** function with the table name as shown in the following example: + +.. code-block:: psql + + test=> SELECT GET_DDL('cool_animals'); + create table "public"."cool_animals" ( + "id" int not null, + "name" varchar(20), + "weight" int + ); + +.. note:: + + * SQream DB identifier names such as table names and column names are not case sensitive. SQream DB lowercases all identifiers bu default. If you want to maintain case, enclose the identifiers with double-quotes. + * SQream DB places all tables in the `public` schema, unless another schema is created and specified as part of the table name. + +For information on listing a ``CREATE TABLE`` statement, see :ref:`get_ddl`. + +.. _dropping_a_table: + +**Dropping a Table** + +When you have finished working with your table, you can drop the table to remove it table and its content, as shown in the following example: + +.. code-block:: psql + + test=> DROP TABLE cool_animals; + + executed + +For more information on dropping tables, see :ref:`drop_table`. \ No newline at end of file diff --git a/getting_started/deleting_rows.rst b/getting_started/deleting_rows.rst new file mode 100644 index 000000000..2ff33b8dc --- /dev/null +++ b/getting_started/deleting_rows.rst @@ -0,0 +1,48 @@ +.. _deleting_rows: + +**************************** +Deleting Rows +**************************** +The **Deleting Rows** section describes the following: + +* :ref:`Deleting selected rows` +* :ref:`Deleting all rows` + +.. _deleting_selected_rows: + +**Deleting Selected Rows** + +You can delete rows in a table selectively using the ``DELETE`` command. You must include a table name and `WHERE` clause to specify the rows to delete, as shown in the following example: + +.. code-block:: psql + + test=> DELETE FROM cool_animals WHERE weight is null; + + executed + master=> SELECT * FROM cool_animals; + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 4,Elephant ,6500 + 5,Rhinoceros ,2100 + + 5 rows + +.. _deleting_all_rows: + +**Deleting All Rows** + +You can delete all rows in a table using the ``TRUNCATE`` command followed by the table name, as shown in the following example: + +.. code-block:: psql + + test=> TRUNCATE TABLE cool_animals; + + executed + +.. note:: While :ref:`truncate` deletes data from disk immediately, :ref:`delete` does not physically remove the deleted rows. + +For more information, see the following: + +* Deleting selected rows - :ref:`DELETE` +* Deleting all rows - :ref:`TRUNCATE` \ No newline at end of file diff --git a/getting_started/executing_statements_in_sqream.rst b/getting_started/executing_statements_in_sqream.rst new file mode 100644 index 000000000..bab18ec76 --- /dev/null +++ b/getting_started/executing_statements_in_sqream.rst @@ -0,0 +1,10 @@ +.. _executing_statements_in_sqream: + +**************************** +Executing Statements in SQream +**************************** +You can execute statements in SQream using one of the following tools: + +* `SQream SQL CLI `_ - a command line interface +* `SQream Acceleration Studio `_ - an intuitive and easy-to-use interface. + diff --git a/first_steps.rst b/getting_started/getting_started.rst similarity index 94% rename from first_steps.rst rename to getting_started/getting_started.rst index 805517b0e..b9cc2f894 100644 --- a/first_steps.rst +++ b/getting_started/getting_started.rst @@ -4,7 +4,7 @@ Getting Started **************************** -The **Getting Started** page describes the following: +The **Getting Started** page describes the following: .. contents:: :local: @@ -45,8 +45,8 @@ Before installing SQream, do the following: * A SQream license - Contact support@sqream.com or your SQream account manager for your license key. For more information, see the following: -* `Hardware Guide `_ -* `Recommended Pre-Installation Configuration `_ +* :ref:`recommended_pre-installation_configurations` +* :ref:`Hardware Guide` @@ -58,15 +58,15 @@ Installing SQream ============================ The **Installing SQream** section includes the following SQream installation methods: -* `Installing SQream natively `_ - Describes installing SQream using binary packages provided by SQream. -* `Installing SQream with Kubernetes `_ - Describes installing SQream using the Kubernetes open source platform. -* `Installing and running SQream in a Docker container `_ - Describes how to run SQream in a Docker container. +* `Installing SQream natively `_ - Describes installing SQream using binary packages provided by SQream. +* `Installing SQream with Kubernetes `_ - Describes installing SQream using the Kubernetes open source platform. +* `Installing and running SQream in a Docker container `_ - Describes how to run SQream in a Docker container. Using the SQream SQL Command Line Interface ============================================ SQream includes a built-in client for executing SQL statements either interactively or using the Command Line Interface (CLI). The **SQream SQL CLI Reference** page provides a reference for the options and parameters. -For more information, see `SQream SQL CLI Reference `_. +For more information, see `SQream SQL CLI Reference `_. Performing Basic SQream Operations ==================================== diff --git a/getting_started/index.rst b/getting_started/index.rst new file mode 100644 index 000000000..f9a57a460 --- /dev/null +++ b/getting_started/index.rst @@ -0,0 +1,16 @@ +.. _getting_started: + +************************* +Getting Started +************************* +The **Getting Started** page describes the following things you need to start using SQream: + +.. toctree:: + :maxdepth: 1 + :glob: + + preparing_your_machine_to_install_sqream + installing_sqream + creating_a_database + executing_statements_in_sqream + performing_basic_sqream_operations \ No newline at end of file diff --git a/getting_started/ingesting_data.rst b/getting_started/ingesting_data.rst new file mode 100644 index 000000000..8d57a8019 --- /dev/null +++ b/getting_started/ingesting_data.rst @@ -0,0 +1,8 @@ +.. _ingesting_data: + +**************************** +Ingesting Data +**************************** +After creating a database you can begin ingesting data into SQream. + +For more information about ingesting data, see `Data Ingestion Guides `_. \ No newline at end of file diff --git a/getting_started/inserting_rows.rst b/getting_started/inserting_rows.rst new file mode 100644 index 000000000..890befebf --- /dev/null +++ b/getting_started/inserting_rows.rst @@ -0,0 +1,86 @@ +.. _inserting_rows: + +**************************** +Inserting Rows +**************************** +The **Inserting Rows** section describes the following: + +* :ref:`Inserting basic rows` +* :ref:`Changing value order` +* :ref:`Inserting multiple rows` +* :ref:`Omitting columns` + + +.. _inserting_basic_rows: + +**Inserting Basic Rows** + +You can insert basic rows into a table using the ``INSERT`` statement. The inserted statement includes the table name, an optional list of column names, and column values listed in the same order as the column names, as shown in the following example: + +.. code-block:: psql + + test=> INSERT INTO cool_animals VALUES (1, 'Dog', 7); + + executed + +.. _changing_value_order: + +**Changing Value Order** + +You can change the order of values by specifying the column order, as shown in the following example: + +.. code-block:: psql + + test=> INSERT INTO cool_animals(weight, id, name) VALUES (3, 2, 'Possum'); + + executed + +.. _inserting_multiple_rows: + +**Inserting Multiple Rows** + +You can insert multiple rows using the ``INSERT`` statement by using sets of parentheses separated by commas, as shown in the following example: + +.. code-block:: psql + + test=> INSERT INTO cool_animals VALUES + (3, 'Cat', 5) , + (4, 'Elephant', 6500) , + (5, 'Rhinoceros', 2100); + + executed + +.. note:: You can load large data sets using bulk loading methods instead. For more information, see :ref:`inserting_data`. + +.. _omitting_columns: + +**Omitting Columns** + +Omitting columns that have a default values (including default ``NULL`` values) uses the default value, as shown in the following example: + +.. code-block:: psql + + test=> INSERT INTO cool_animals (id) VALUES (6); + + executed + +.. code-block:: psql + + test=> INSERT INTO cool_animals (id) VALUES (6); + + executed + test=> SELECT * FROM cool_animals; + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 4,Elephant ,6500 + 5,Rhinoceros ,2100 + 6,\N,\N + + 6 rows + +.. note:: Null row values are represented as ``\N`` + +For more information on inserting rows, see :ref:`insert`. + +For more information on default values, see :ref:`default value`. \ No newline at end of file diff --git a/getting_started/installing_sqream.rst b/getting_started/installing_sqream.rst new file mode 100644 index 000000000..cf7c9517b --- /dev/null +++ b/getting_started/installing_sqream.rst @@ -0,0 +1,11 @@ +.. _installing_sqream: + +**************************** +Installing SQream +**************************** + +The **Installing SQream** section includes the following SQream installation methods: + +* `Installing SQream natively `_ - Describes installing SQream using binary packages provided by SQream. +* `Installing SQream with Kubernetes `_ - Describes installing SQream using the Kubernetes open source platform. +* `Installing and running SQream in a Docker container `_ - Describes how to run SQream in a Docker container. \ No newline at end of file diff --git a/getting_started/listing_tables.rst b/getting_started/listing_tables.rst new file mode 100644 index 000000000..d376cb7ee --- /dev/null +++ b/getting_started/listing_tables.rst @@ -0,0 +1,13 @@ +.. _listing_tables: + +**************************** +Listing Tables +**************************** +To see the tables in the current database you can query the catalog, as shown in the following example: + +.. code-block:: psql + + test=> SELECT table_name FROM sqream_catalog.tables; + cool_animals + + 1 rows \ No newline at end of file diff --git a/getting_started/performing_basic_sqream_operations.rst b/getting_started/performing_basic_sqream_operations.rst new file mode 100644 index 000000000..ba0a6fc3f --- /dev/null +++ b/getting_started/performing_basic_sqream_operations.rst @@ -0,0 +1,18 @@ +.. _performing_basic_sqream_operations: + +**************************** +Performing Basic SQream Operations +**************************** +After installing SQream you can perform the operations described on this page: + +.. toctree:: + :maxdepth: 1 + :glob: + + running_the_sqream_sql_client + creating_your_first_table + listing_tables + inserting_rows + running_queries + deleting_rows + saving_query_results_to_a_csv_or_psv_file \ No newline at end of file diff --git a/getting_started/preparing_your_machine_to_install_sqream.rst b/getting_started/preparing_your_machine_to_install_sqream.rst new file mode 100644 index 000000000..9a5e61956 --- /dev/null +++ b/getting_started/preparing_your_machine_to_install_sqream.rst @@ -0,0 +1,40 @@ +.. _preparing_your_machine_to_install_sqream: + +**************************** +Preparing Your Machine to Install SQream +**************************** +To prepare your machine to install SQream, do the following: + + * Set up your local machine according to SQream's recommended pre-installation configurations. + + :: + + * Verify you have an NVIDIA-capable server, either on-premise or on supported cloud platforms: + + * Red Hat Enterprise Linux v7.x + + + * CentOS v7.x + + + * Ubuntu 18.04 + + + * Amazon Linux + + * Verify that you have the following: + + * An NVIDIA GPU - SQream recommends using a Tesla GPU. + + + * An SSH connection to your server. + + + * SUDO permissions for installation and configuration purposes. + + + * A SQream license - Contact support@sqream.com or your SQream account manager for your license key. +For more information, see the following: + +* :ref:`recommended_pre-installation_configurations` +* `Hardware Guide `_ \ No newline at end of file diff --git a/getting_started/querying_data.rst b/getting_started/querying_data.rst new file mode 100644 index 000000000..36bf9e78b --- /dev/null +++ b/getting_started/querying_data.rst @@ -0,0 +1,51 @@ +.. _querying_data: + +**************************** +Querying Data +**************************** +One of the most basic operations when using SQream is querying data. + +To begin familiarizing yourself with querying data, you can create the following table using the ``CREATE TABLE`` statement: + +.. code-block:: postgres + + CREATE TABLE nba + ( + Name varchar(40), + Team varchar(40), + Number tinyint, + Position varchar(2), + Age tinyint, + Height varchar(4), + Weight real, + College varchar(40), + Salary float + ); + + +You can down download the above (:download:`nba.csv table `) if needed, shown below: + +.. csv-table:: nba.csv + :file: nba-t10.csv + :widths: auto + :header-rows: 1 + +The above query gets the following from the table above, limited to showing the first ten results: + +* Name +* Team name +* Age + +.. code-block:: psql + + nba=> SELECT Name, Team, Age FROM nba LIMIT 10; + Avery Bradley,Boston Celtics,25 + Jae Crowder,Boston Celtics,25 + John Holland,Boston Celtics,27 + R.J. Hunter,Boston Celtics,22 + Jonas Jerebko,Boston Celtics,29 + Amir Johnson,Boston Celtics,29 + Jordan Mickey,Boston Celtics,21 + Kelly Olynyk,Boston Celtics,25 + Terry Rozier,Boston Celtics,22 + Marcus Smart,Boston Celtics,22 \ No newline at end of file diff --git a/getting_started/running_queries.rst b/getting_started/running_queries.rst new file mode 100644 index 000000000..57f6811d7 --- /dev/null +++ b/getting_started/running_queries.rst @@ -0,0 +1,121 @@ +.. _running_queries: + +**************************** +Running Queries +**************************** +The **Running Queries** section describes the following: + +* :ref:`Running basic queries` +* :ref:`Outputting all columns` +* :ref:`Outputting shorthand table values` +* :ref:`Filtering results` +* :ref:`Sorting results` +* :ref:`Filtering null rows` + + +.. _running_basic_queries: + +**Running Basic Queries** + +You can run a basic query using the ``SELECT`` keyword, followed by a list of columns and values to be returned, and the table to get the data from, as shown in the following example: + +.. code-block:: psql + + test=> SELECT id, name, weight FROM cool_animals; + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 4,Elephant ,6500 + 5,Rhinoceros ,2100 + 6,\N,\N + + 6 rows + +For more information on the ``SELECT`` keyword, see :ref:`select`. + +.. _outputting_all_columns: + +**To Output All Columns** + +You can output all columns without specifying them using the star operator ``*``, as shown in the following example: + +.. code-block:: psql + + test=> SELECT * FROM cool_animals; + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 4,Elephant ,6500 + 5,Rhinoceros ,2100 + 6,\N,\N + + 6 rows + +.. _outputting_shorthand_table_values: + +**Outputting Shorthand Table Values** + +You can output the number of values in a table without getting the full result set by using the ``COUNT`` statement: + +.. code-block:: psql + + test=> SELECT COUNT(*) FROM cool_animals; + 6 + + 1 row + +.. _filtering_results: + +**Filtering Results** + +You can filter results by adding a ``WHERE`` clause and specifying the filter condition, as shown in the following example: + +.. code-block:: psql + + test=> SELECT id, name, weight FROM cool_animals WHERE weight > 1000; + 4,Elephant ,6500 + 5,Rhinoceros ,2100 + + 2 rows + +.. _sorting_results: + +**Sorting Results** + +You can sort results by adding an ``ORDER BY`` clause and specifying ascending (``ASC``) or descending (``DESC``) order, as shown in the following example: + +.. code-block:: psql + + test=> SELECT * FROM cool_animals ORDER BY weight DESC; + 4,Elephant ,6500 + 5,Rhinoceros ,2100 + 1,Dog ,7 + 3,Cat ,5 + 2,Possum ,3 + 6,\N,\N + + 6 rows + +.. _filtering_null_rows: + +**Filtering Null Rows** + +You can filter null rows by adding an ``IS NOT NULL`` filter, as shown in the following example: + +.. code-block:: psql + + test=> SELECT * FROM cool_animals WHERE weight IS NOT NULL ORDER BY weight DESC; + 4,Elephant ,6500 + 5,Rhinoceros ,2100 + 1,Dog ,7 + 3,Cat ,5 + 2,Possum ,3 + + 5 rows + +For more information, see the following: + +* Outputting the number of values in a table without getting the full result set - :ref:`COUNT(*)`. +* Filtering results - :ref:`WHERE` +* Sorting results - :ref:`ORDER BY` +* Filtering rows - :ref:`IS NOT NULL` \ No newline at end of file diff --git a/getting_started/running_the_sqream_sql_client.rst b/getting_started/running_the_sqream_sql_client.rst new file mode 100644 index 000000000..faba6494d --- /dev/null +++ b/getting_started/running_the_sqream_sql_client.rst @@ -0,0 +1,22 @@ +.. _running_the_sqream_sql_client: + +**************************** +Running the SQream SQL Client +**************************** +The following example shows how to run the SQream SQL client: + +.. code-block:: psql + + $ sqream sql --port=5000 --username=rhendricks -d master + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=> _ + +Running the SQream SQL client prompts you to provide your password. Use the username and password that you have set up, or your DBA has provided. + +.. tip:: + * You can exit the shell by typing ``\q`` or :kbd:`Ctrl-d`. + * A new SQream cluster contains a database named `master,` which is the database used in the examples on this page. \ No newline at end of file diff --git a/getting_started/saving_query_results_to_a_csv_or_psv_file.rst b/getting_started/saving_query_results_to_a_csv_or_psv_file.rst new file mode 100644 index 000000000..9a40ad440 --- /dev/null +++ b/getting_started/saving_query_results_to_a_csv_or_psv_file.rst @@ -0,0 +1,24 @@ +.. _saving_query_results_to_a_csv_or_psv_file: + +**************************** +Saving Query Results to a CSV or PSV File +**************************** +You can save query results to a CSV or PSV file using the ``sqream sql`` command from a CLI client. This saves your query results to the selected delimited file format, as shown in the following example: + +.. code-block:: console + + $ sqream sql --username=mjordan --database=nba --host=localhost --port=5000 -c "SELECT * FROM nba LIMIT 5" --results-only --delimiter='|' > nba.psv + $ cat nba.psv + Avery Bradley |Boston Celtics |0|PG|25|6-2 |180|Texas |7730337 + Jae Crowder |Boston Celtics |99|SF|25|6-6 |235|Marquette |6796117 + John Holland |Boston Celtics |30|SG|27|6-5 |205|Boston University |\N + R.J. Hunter |Boston Celtics |28|SG|22|6-5 |185|Georgia State |1148640 + Jonas Jerebko |Boston Celtics |8|PF|29|6-10|231|\N|5000000 + +For more output options, see :ref:`Controlling the Client Output`. + +.. rubric:: What's next? + +* Explore all of SQream DB's :ref:`SQL Syntax `. +* See the full :ref:`SQream SQL CLI reference `. +* Connect a :ref:`third party tool ` to start analyzing data. \ No newline at end of file diff --git a/guides/client_drivers/index.rst b/guides/client_drivers/index.rst deleted file mode 100644 index 598e3c6ff..000000000 --- a/guides/client_drivers/index.rst +++ /dev/null @@ -1,106 +0,0 @@ -.. _client_drivers: - -************************************ -Client Drivers for 2020.3.2.1 -************************************ - -These guides explain how to use the SQream DB client drivers, and how to use client applications with SQream DB. - -Client driver downloads -============================= - -All operating systems ---------------------------- - -* - - **JDBC** - `sqream-jdbc v4.3.1 (.jar) `_ - - - :ref:`java_jdbc` Driver - - (SQream recommends installing via ``mvn``) - -* - **Python** - `pysqream v3.1.3 (.tar.gz) `_ - - - :ref:`pysqream` - Python driver - - (SQream recommends installing via ``pip``) - -* - **Node.JS** - `sqream-v4.2.4 (.tar.gz) `_ - - :ref:`nodejs` - Node.JS driver - - (SQream recommends installing via ``npm``) - -* - **Tableau Connector** - `SQreamDB (.taco) `_ - - :ref:`Tableau connector` - Tableau connector for manual installation - -Windows --------------- - -* - **JDBC installer** - `SQream_JDBC_Driver_v2020.2.0.exe `_ - - Windows installer for JDBC driver, with Tableau connector. - -* - **ODBC installer** - ``SQream Drivers v2020.2.0`` - - :ref:`Windows installer for ODBC and JDBC`, with Tableau customizations. Please contact your SQream representative to get this installer. - -* **.Net driver** - `SQream .Net driver v2.0.0 `_ - - - -Linux --------------- - -* - **SQream SQL** (x86) - `sqream-sql-v2020.1.1_stable.x86_64.tar.gz `_ - - - :ref:`sqream sql` - Interactive command-line SQL client for Intel-based machines - -* - **SQream SQL** (IBM POWER9) - `sqream-sql-v2020.1.1_stable.ppc64le.tar.gz `_ - - - :ref:`sqream sql` - Interactive command-line SQL client for IBM POWER9-based machines - -* - **ODBC installer** - ``sqream_odbc_4.0.0_x86_64_linux.tar.gz`` - - :ref:`Linux installer for ODBC`. Please contact your SQream representative to get this installer. - -* - **C++ connector** - `libsqream-4.0 `_ - - :ref:`C++ shared object` library - - -.. toctree:: - :maxdepth: 4 - :caption: Client driver documentation: - :titlesonly: - - python/index - cpp/index - jdbc/index - odbc/index - nodejs/index - - - -.. rubric:: Need help? - -If you couldn't find what you're looking for, we're always happy to help. Visit `SQream's support portal `_ for additional support. - -.. rubric:: Looking for older drivers? - -If you're looking for an older version of SQream DB drivers, versions 1.10 through 2019.2.1 are available at https://sqream.com/product/client-drivers/ . diff --git a/guides/features/access_control_notes.rst b/guides/features/access_control_notes.rst deleted file mode 100644 index 4dacb78ee..000000000 --- a/guides/features/access_control_notes.rst +++ /dev/null @@ -1,357 +0,0 @@ -.. _access_control_notes: - -************** -Access control -************** - -.. contents:: In this topic: - :local: - -The system which provides basic authentication and authorization for -users in SQream DB. - -Authentication: this is how the system checks that you are who you say -you are. This is done using the familiar usernames and passwords. - -Authorization: this is how the system checks that you are allowed to -do the action that you are trying to do. - -Compared to ANSI SQL and other SQL products: - -* - SQream DB has roles as users and as groups, like ANSI SQL and other SQL products a user may be familiar with - -* - SQream DB has a default permissions system based on the system in Postgres, but with more power. - In most cases, this allows an administrator to set things up so that every object gets permissions set - automatically. - -* SQream DB does not have row based permissions - -* SQream DB does not have object ownership - -.. http://docs.sqream.com/latest/manual/Content/Guides/Quick_Guides/Quick_guide_to_roles_and_permissions/Quick_guide_to_roles_and_permissions.htm - -.. http://docs.sqream.com/latest/manual/Content/Concepts/12_1.10_Catalog_(information_schema).htm?tocpath=Concepts%7CCatalog%20(information%20schema)%7C_____0#Catalog_(information_schema)_..198 - -.. http://docs.sqream.com/latest/manual/Content/SQL_Reference_Guide/16_2.1_Data_Definition_Language.htm?tocpath=SQream%20DB%20%20SQL%20Reference%20Guide%7CData%20Definition%20Language%7C_____0#Database_Roles_and_Permissions_..322 - - - -Introductory examples -===================== - -go through some basic permissions - -show a user trying to do something without permission - -then add the permission - -then show it succeeding - -show adding a new login user - -show adding a user to another role - -show adding a superuser - - -Reference for all permissions -============================= - -attributes for a role: name and optional password - -permissions: - -* superuser -* login -* connect to database -* create, ddl, superuser, create function -* create, ddl, usage, superuser -* select, insert, delete, ddl
-* * -* execute | ddl - -what happens when e.g. a database doesn't exist - -what if you drop it then recreate it - -what are the options for default permissions - -Permissions catalog -=================== - -show the permissions as data structures - -make sure all this appears in the catalog - -do the catalog reference/guide here for now - -establish a better catalog: write create tables statements too -do full examples of querying the catalog - -sqream_catalog.roles - -sqream_catalog.role_memberships - -sqream_catalog.table_permissions - -sqream_catalog.database_permissions - -sqream_catalog.schema_permissions - -sqream_catalog.permission_types - - -How the permissions work -======================== - - -How to work out if a user has permission to execute a statement? --> go through all the options - -the two parts are - -1. work out what permissions are needed from a statement - -2. work out what permissions a user has by role membership - -how do default permissions work -------------------------------- - -when you create an object: - -the system looks for default permissions statements which match the -current role or a group the current role is in, and the object being -created - -each match will behave as if a grant permissions statement was also -run, on the created object, granted to the target role in the default -permissions match, with the permissions in the default permissions -match - -utility functions -================= - -what utility functions are relevant for permissions - -how do they interact with permissions - -Syntax reference -================ - -Roles ------ - -.. code-block:: postgresql - - create | alter | drop role - grant - - -- Alter default permissions - - CREATE ROLE role_name ; - GRANT PASSWORD 'new_password' to role_name ; - - DROP ROLE role_name ; - - -- Alter - rename only: - - ALTER ROLE role_name RENAME TO new_role_name ; - - -Granting permissions --------------------- - -to create a database installation wide superuser: - -.. code-block:: postgresql - - GRANT SUPERUSER to - - -does a super user have login + connect to all databases? - -to allow a user to login, and to connect to a database - -.. code-block:: postgresql - - GRANT LOGIN to role_name ; - GRANT CONNECT ON DATABASE database_name to role_name ; - - -can a user have one and not the other? - -when should a user have a password - -.. code-block:: postgresql - - GRANT - { SUPERUSER - | LOGIN - | PASSWORD '' - } - TO [, ...] - - GRANT [, ...] - TO - [WITH ADMIN OPTION] - - -From the current docs, it's not that clear what all these mean - -granting permissions to objects -------------------------------- - -.. code-block:: postgresql - - -- Grant permissions at the database level: - GRANT {{CREATE | CONNECT| DDL | SUPERUSER | CREATE FUNCTION} [, ...] | ALL [PERMISSIONS]} - - ON DATABASE [, ...] - TO [, ...] - - -- Grant permissions at the schema level: - GRANT {{ CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [ - PERMISSIONS ]} - ON SCHEMA [, ...] - TO [, ...] - - -- Grant permissions at the object level: - GRANT {{SELECT | INSERT | DELETE | DDL } [, ...] | ALL [PERMISSIONS]} - ON { TABLE [, ...] | ALL TABLES IN SCHEMA [, ...]} - TO [, ...] - - -- Grant execute function permission: - GRANT {ALL | EXECUTE | DDL} ON FUNCTION function_name - TO role; - - -alter default permissions -------------------------- - -.. code-block:: postgresql - - ALTER DEFAULT PERMISSIONS FOR - IN FOR TABLES - GRANT { SELECT | INSERT | DELETE [,...] } TO ; - -I think you can also do it for schemas? - -how do you undo a default permissions - use revoke? something isn't -quite right about that - -revoking permissions --------------------- - -.. code-block:: postgresql - - -- Revoke permissions at the cluster level: - REVOKE - { SUPERUSER - | LOGIN - | PASSWORD - } - FROM [, ...] - - -- Revoke permissions at the database level: - REVOKE {{CREATE | CONNECT | DDL | SUPERUSER | CREATE FUNCTION}[, ...] |ALL [PERMISSIONS]} - ON DATABASE [, ...] - FROM [, ...] - - -- Revoke permissions at the schema level: - REVOKE { { CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [PERMISSIONS]} - ON SCHEMA [, ...] - FROM [, ...] - - -- Revoke permissions at the object level: - REVOKE { { SELECT | INSERT | DELETE | DDL } [, ...] | ALL } - ON { [ TABLE ] [, ...] | ALL TABLES IN SCHEMA - - [, ...] } - FROM [, ...] - - -- Revoke privileges from other roles by granting one role to another: - REVOKE [, ...] FROM [, ...] WITH ADMIN OPTION - - -Behaviour reference -=================== - -show examples of every permission? Or just a subset - -example will have the permission fail - -then the add permission statement - -then the permission succeed - -can also go through something similar for default permissions - -Usage guides -============ - -minimal permission system use ------------------------------ - -Trivial use of permissions system in sqream: use super user - -how to add a new superuser role - -what this means - -adding a guest user - -simple user, with limited read only ability - - -Basic use ---------- - -how to set up a group with permissions database wide for the following: - -* security officer -* database architect -* updater -* reader -* udf author - -how to maintain this - - -Advanced use ------------- - -permissions/group per schema - -show a list of roles for a schema, how you set it up - -then show how to maintain this system - -variation: roles which cover multiple schemas - -* what does a superuser need to do -* what can a division 'owner' do - -maintain - how to add something missing or modify: - -* a new schema - -* a new division - -* a new user - -* remove access - -* fix an existing schema to add permissions - - * maybe a mistake - - * maybe a division gets new access to an existing schema - -key secure things: - -* what can only superusers do -* what are normal users restricted from doing -* who else can do stuff with the permissions system -* how are divisions protected from other divisions diff --git a/guides/features/chunks_and_extents.rst b/guides/features/chunks_and_extents.rst deleted file mode 100644 index 200235891..000000000 --- a/guides/features/chunks_and_extents.rst +++ /dev/null @@ -1,93 +0,0 @@ -.. _chunks_and_extents: - -*********************** -Chunks and extents -*********************** - -All data in SQream DB is stored in logical tables. Each table is made up of rows, spanning one or more columns. - -Internally however, SQream DB stores data partitioned vertically by column, and horizontally by **chunks**. - -This topic describes the chunk concept, which can be helpful for tuning SQream DB workloads and table structures. - -What are chunks? What are extents? -====================================== - -Chunks ------------ - -All data in a table is automatically partitioned into columns, and each column is divided up further into chunks. - -A **chunk** is a contiguous number of rows from a specific column. It can be thought of as an automatic partition that spans several millions of records of one column. - -.. figure:: /_static/images/chunking.png - :scale: 80 % - - Chunks are collections of rows from a column - -A chunk is often between 1MB to a couple hundred megabytes uncompressed, depending on the data type (however, all data in SQream DB is stored compressed). - -This chunk size is suitable for filtering and deleting data from large tables, which can contain hundreds of millions or even billions of chunks. - -SQream DB adds :ref:`metadata` to chunks automatically. - -.. note:: Chunking is automatic and transparent for all tables in SQream DB. - - -Extents ----------- - -The next step up from the chunk, an **extent** is a specific number of contiguous chunks. - -Extents are designed to optimize disk access patterns, at around 20MB compressed, on-disk. - -An extent will therefore include between 1 and 25 chunks, based on the actual compressed chunk size. - -.. figure:: /_static/images/extents.png - :scale: 80 % - - Extents are a collection of several contiguous chunks - - -Why was SQream DB built with chunks and extents? -======================================================= - -Benefits of chunking ---------------------------- - -Unlike node-partitioning (or sharding), chunking carries several benefits: - -* Chunks are small enough to allow multiple workers to read them concurrently - -* Chunks are optimized for fast insertion of data - -* Chunks carry metadata, which narrows down their contents for the optimizer - -* Chunks are ideal for data retension as they can be deleted en-masse - -* Chunks are optimized for reading into RAM and the GPU - -* Chunks are compressed individually, which improves compression and data locality - -Storage reorganization --------------------------- - -SQream DB performs some background storage reorganization to optimize I/O and read patterns. - -For example, when data is inserted in small batches, SQream DB will run two background processes called **rechunk** and **reextent** to reorganize the data into larger contiguous chunks and extents. -This is also what happens when :ref:`data is deleted`. - -Data is never overwritten in SQream DB. Instead, new optimized chunks and extents are written to replace the old chunks and extents. Once all data has been rewritten, SQream DB will swap over to the new optimized chunks and extents and remove the old, unoptimized data. - - -Metadata ------------- - -The chunk metadata that SQream DB collects enables effective skipping of chunks and extents when queries are executed. When a query specifies a filter (e.g. ``WHERE`` or ``JOIN`` condition) on a range of values that spans a fraction of the table values, SQream DB will optimally scan only that fraction of the table chunks. - -Queries that filter on fine-grained date and time ranges will be the most effective, particularly when :ref:`data is timestamped`, and when tables contain a large amount of historical data. - -See more in our :ref:`time_based_data_management` guide and our :ref:`metadata_system` guide. - - - diff --git a/guides/features/data_clustering.rst b/guides/features/data_clustering.rst deleted file mode 100644 index deeedf9d8..000000000 --- a/guides/features/data_clustering.rst +++ /dev/null @@ -1,79 +0,0 @@ -.. _data_clustering: - -*********************** -Data clustering -*********************** - -Together with the :ref:`chunking` and :ref:`metadata_system`, SQream DB uses information to execute queries efficiently. - -SQream DB automatically collects metadata on incoming data. This works well when the data is naturally ordered (e.g. :ref:`with time-based data`). - -There are situations where you know more about the incoming data than SQream DB. If you help by defining **clustering keys**, SQream DB can automatically improve query processing. SQream DB's query optimizer typically selects the most efficient method when executing queries. If no clustering keys are available, it may have to scan tables physically. - -Clustered tables -====================== - -A table is considered "clustered" by one or more clustering keys if rows containing similar values with regard to these expressions are more likely to be located together on disk. - -For example, a table containing a date column whose values cover a whole month but each chunk on disk covers less than a specific day is considered clustered by this column. - -Good clustering has a significant positive impact on query performance. - -When does clustering help? -=================================== - -When a table is well-clustered, the metadata collected for each chunk is much more effective (the ranges are more localized). - -In turn, SQream DB's query engine chooses to read fewer irrelevant chunks (or just avoid processing them). - -Here are some common scenarios in which data clustering is beneficial: - -* - When a query contains a ``WHERE`` predicate of the form ``column COMPARISON value``. - For example, ``date_column > '2019-01-01'`` or ``id = 107`` and the columns referenced are clustering keys/ - - SQream DB will only read the portion of the data containing values matching these predicates. - -* When two clustered tables are joined on their respective clustering keys, SQream DB will utilize the metadata to identify the matching chunks more easily. - - -Controlling data clustering -================================= - -Some tables are naturally clustered. For example - a call log table containing CDRs can be naturally clustered by call date if data is inserted as it is generated, or bulk loaded in batches. Data can also be clustered by a region ID, per city, or customer type, depending on the source. - - -If the incoming data is not well-clustered (by the desired key), it is possible to tell SQream DB which keys it should cluster by. - -This can be done upon table creation (:ref:`create_table`), or retroactively (:ref:`cluster_by`). New data will be clustered upon insert. - -When data is loaded to an explicitly clustered table, SQream DB partially sorts it. While this slows down the insert time, it is often beneficial for subsequent queries. - -.. note:: - - Some queries significantly benefit from the decision to use clustering. - For example, queries that filter or join extensively on clustered columns will benefit. - - - However, clustering can slow down data insertion. Some insert workloads can be up to 75% slower. - - If you are not sure whether or not a specific scenario will benefit from clustering, we recommended testing end-to-end (both insert and query performance) on a small subset of the data before commiting to permanent clustering keys. - - -Examples -========== - -Creating a clustered table ------------------------------ - -Even when the table is naturally ordered by ``start_date``, we can specify a cluster key that is different. This will likely improve performance for queries that order by or rely on users' ``country``. - -.. code-block:: postgres - - CREATE TABLE users ( - name VARCHAR(30) NOT NULL, - start_date datetime not null, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL - ) CLUSTER BY country; - - diff --git a/guides/features/delete.rst b/guides/features/delete.rst deleted file mode 100644 index b72a9617b..000000000 --- a/guides/features/delete.rst +++ /dev/null @@ -1,214 +0,0 @@ -.. _delete_guide: - -*********************** -Deleting data -*********************** - -SQream DB supports deleting data, but it's important to understand how this works and how to maintain deleted data. - -How does deleting in SQream DB work? -======================================== - -In SQream DB, when you run a delete statement, any rows that match the delete predicate will no longer be returned when running subsequent queries. -Deleted rows are tracked in a separate location, in *delete predicates*. - -After the delete statement, a separate process can be used to reclaim the space occupied by these rows, and to remove the small overhead that queries will have until this is done. - -Some benefits to this design are: - -#. Delete transactions complete quickly - -#. The total disk footprint overhead at any time for a delete transaction or cleanup process is small and bounded (while the system still supports low overhead commit, rollback and recovery for delete transactions). - - -Phase 1: Delete ---------------------------- - -.. TODO: isn't the delete cleanup able to complete a certain amount of work transactionally, so that you can do a massive cleanup in stages? - -.. TODO: our current best practices is to use a cron job with sqream sql to run the delete cleanup. we should document how to do this, we have customers with very different delete schedules so we can give a few extreme examples and when/why you'd use them - -When a :ref:`delete` statement is run, SQream DB records the delete predicates used. These predicates will be used to filter future statements on this table until all this delete predicate's matching rows have been physically cleaned up. - -This filtering process takes full advantage of SQream's zone map feature. - -Phase 2: Clean-up --------------------- - -The cleanup process is not automatic. This gives control to the user or DBA, and gives flexibility on when to run the clean up. - -Files marked for deletion during the logical deletion stage are removed from disk. This is achieved by calling both utility function commands: ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` sequentially. - -.. note:: - * :ref:`alter_table` and other DDL operations are blocked on tables that require clean-up. See more in the :ref:`concurrency_and_locks` guide. - * If the estimated time for a cleanup processs is beyond a threshold, you will get an error message about it. The message will explain how to override this limitation and run the process anywhere. - -Notes on data deletion -========================================= - -.. note:: - * If the number of deleted records crosses the threshold defined by the ``mixedColumnChunksThreshold`` parameter, the delete operation will be aborted. - * This is intended to alert the user that the large number of deleted records may result in a large number of mixed chuncks. - * To circumvent this alert, replace XXX with the desired number of records before running the delete operation: - -.. code-block:: postgres - - set mixedColumnChunksThreshold=XXX; - - -Deleting data does not free up space ------------------------------------------ - -With the exception of a full table delete (:ref:`TRUNCATE`), deleting data does not free up disk space. To free up disk space, trigger the cleanup process. - -``SELECT`` performance on deleted rows ----------------------------------------- - -Queries on tables that have deleted rows may have to scan data that hasn't been cleaned up. -In some cases, this can cause queries to take longer than expected. To solve this issue, trigger the cleanup process. - -Use ``TRUNCATE`` instead of ``DELETE`` ---------------------------------------- -For tables that are frequently emptied entirely, consider using :ref:`truncate` rather than :ref:`delete`. TRUNCATE removes the entire content of the table immediately, without requiring a subsequent cleanup to free up disk space. - -Cleanup is I/O intensive -------------------------------- - -The cleanup process actively compacts tables by writing a complete new version of column chunks with no dead space. This minimizes the size of the table, but can take a long time. It also requires extra disk space for the new copy of the table, until the operation completes. - -Cleanup operations can create significant I/O load on the database. Consider this when planning the best time for the cleanup process. - -If this is an issue with your environment, consider using ``CREATE TABLE AS`` to create a new table and then rename and drop the old table. - - -Example -============= - -Deleting values from a table ------------------------------- - -.. code-block:: psql - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N - - 6 rows - - farm=> DELETE FROM cool_animals WHERE weight > 1000; - executed - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 6,\N,\N - - 4 rows - -Deleting values based on more complex predicates ---------------------------------------------------- - -.. code-block:: psql - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N - - 6 rows - - farm=> DELETE FROM cool_animals WHERE weight > 1000; - executed - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 6,\N,\N - - 4 rows - -Identifying and cleaning up tables ---------------------------------------- - -List tables that haven't been cleaned up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - farm=> SELECT t.table_name FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - GROUP BY 1; - cool_animals - - 1 row - -Identify predicates for clean-up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; - weight > 1000 - - 1 row - -Triggering a cleanup -^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - -- Chunk reorganization (aka SWEEP) - farm=> SELECT CLEANUP_CHUNKS('public','cool_animals'); - executed - - -- Delete leftover files (aka VACUUM) - farm=> SELECT CLEANUP_EXTENTS('public','cool_animals'); - executed - - - farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; - - 0 rows - - - -Best practices for data deletion -===================================== - -* Run ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` after large ``DELETE`` operations. - -* When deleting large proportions of data from very large tables, consider running a ``CREATE TABLE AS`` operation instead, then rename and drop the original table. - -* Avoid killing ``CLEANUP_EXTENTS`` operations after they've started. - -* SQream DB is optimised for time-based data. When data is naturally ordered by a date or timestamp, deleting based on those columns will perform best. For more information, see our :ref:`time based data management guide`. - - - -.. soft update concept - -.. delete cleanup and it's properties. automatic/manual, in transaction or background - -.. automatic background gives fast delete, minimal transaction overhead, -.. small cost to queries until background reorganised - -.. when does delete use the metadata effectively - -.. more examples - diff --git a/guides/features/external_data/hdfs.rst b/guides/features/external_data/hdfs.rst deleted file mode 100644 index 71135163f..000000000 --- a/guides/features/external_data/hdfs.rst +++ /dev/null @@ -1,323 +0,0 @@ -.. _hdfs: - -*********************** -HDFS -*********************** - -SQream DB has a native HDFS connector for inserting data. The ``hdfs://`` URI specifies an external file path on a Hadoop Distributed File System. - -File names may contain wildcard characters and the files can be a CSV or columnar format like Parquet and ORC. - - -.. contents:: In this topic: - :local: - -Verifying HDFS configuration -============================== - -SQream DB's built-in HDFS relies on the host's Hadoop HDFS configuration. - -Before you can use HDFS, you should verify that all SQream DB hosts are configured correctly. - -Use built-in Hadoop libraries -------------------------------- - -SQream DB comes with Hadoop libraries built-in. In a typical SQream DB installation, you'll find Hadoop and JDK libraries in the ``hdfs`` subdirectory of the package. - -If you are using the built-in libraries, it's important to note where they are. - -For example, if SQream DB was installed to ``/opt/sqream``, here's how to set-up the environment variables from the shell: - -.. _set_hadoop_classpath: - -.. code-block:: console - - $ export JAVA_HOME=/opt/sqream/hdfs/jdk - $ export HADOOP_INSTALL=/opt/sqream/hdfs/hadoop - - $ export PATH=$PATH:${HADOOP_INSTALL}/bin:${HADOOP_INSTALL}/sbin - $ export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native - $ export CLASSPATH=$CLASSPATH:`${HADOOP_INSTALL}/bin/hadoop classpath --glob` - $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HADOOP_COMMON_LIB_NATIVE_DIR - - $ export HADOOP_MAPRED_HOME=$HADOOP_INSTALL - $ export HADOOP_COMMON_HOME=$HADOOP_INSTALL - $ export HADOOP_HDFS_HOME=$HADOOP_INSTALL - $ export YARN_HOME=$HADOOP_INSTALL - - $ export HADOOP_CONF_DIR=$HADOOP_INSTALL/etc/hadoop - $ export YARN_CONF_DIR=$HADOOP_INSTALL/etc/hadoop - $ export HADOOP_HOME=$HADOOP_INSTALL - $ export HADOOP_OPTS="$HADOOP_OPTS -Djava.library.path=${HADOOP_COMMON_LIB_NATIVE_DIR}" - $ export ARROW_LIBHDFS_DIR=${HADOOP_COMMON_LIB_NATIVE_DIR} - - -You'll find ``core-site.xml`` and other configuration files in ``/opt/sqream/hdfs/hadoop/etc/hadoop`` - -To persist these settings, place these variable settings in a 'run commands' file like ``.bashrc``. Test this by examining the output of ``$ echo $ARROW_LIBHDFS_DIR``. - -.. note:: - - * This process needs to be repeated for every host in the SQream DB cluster, and from SQream DB's host username (often ``sqream``) - - * Restart SQream DB workers on the host after setting these parameters for them to take effect. - -(Optional) Overriding the Hadoop environment ------------------------------------------------------- - -If you have an existing Hadoop environment set-up on the host, you can override SQream DB's built-in Hadoop by setting the environment variables accordingly. - -For example, - -.. code-block:: console - - $ export JAVA_HOME=/usr/local/java-1.8.0/ - $ export HADOOP_INSTALL=/usr/local/hadoop-3.2.1 - - $ export PATH=$PATH:${HADOOP_INSTALL}/bin:${HADOOP_INSTALL}/sbin - $ export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native - $ export CLASSPATH=$CLASSPATH:`${HADOOP_INSTALL}/bin/hadoop classpath --glob` - $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HADOOP_COMMON_LIB_NATIVE_DIR - - $ export HADOOP_MAPRED_HOME=$HADOOP_INSTALL - $ export HADOOP_COMMON_HOME=$HADOOP_INSTALL - $ export HADOOP_HDFS_HOME=$HADOOP_INSTALL - $ export YARN_HOME=$HADOOP_INSTALL - - $ export HADOOP_CONF_DIR=$HADOOP_INSTALL/etc/hadoop - $ export YARN_CONF_DIR=$HADOOP_INSTALL/etc/hadoop - $ export HADOOP_HOME=$HADOOP_INSTALL - $ export HADOOP_OPTS="$HADOOP_OPTS -Djava.library.path=${HADOOP_COMMON_LIB_NATIVE_DIR}" - $ export ARROW_LIBHDFS_DIR=${HADOOP_COMMON_LIB_NATIVE_DIR} - - -To persist these settings, place these variable settings in a 'run commands' file like ``.bashrc``. Test this by examining the output of ``$ echo $ARROW_LIBHDFS_DIR``. - -.. note:: - - * This process needs to be repeated for every host in the SQream DB cluster, and from SQream DB's host username (often ``sqream``) - - * Restart SQream DB workers on the host after setting these parameters for them to take effect. - -Configuring the node -====================== - -A Hadoop administrator will want to edit the configuration XMLs to allow access to your Hadoop cluster. - -If using the SQream DB Hadoop libraries, modify the following files to match your cluster settings: - -* ``/opt/sqream/hdfs/hadoop/etc/hadoop/core-site.xml`` -* ``/opt/sqream/hdfs/hadoop/etc/hadoop/yarn-site.xml`` -* ``/opt/sqream/hdfs/hadoop/etc/hadoop/hdfs-site.xml`` - -If using the system Hadoop libraries, be sure to override ``JAVA_HOME``, ``CLASSPATH``, ``HADOOP_HOME``, and ``ARROW_LIBHDFS_DIR`` as described above. - -Verifying Hadoop configuration -================================== - -To test HDFS access, try accessing files using the HDFS shell: - -.. code-block:: console - - $ hdfs dfs -ls - Found 2 items - -rw-r--r-- 3 hdfs supergroup 63446 2020-02-29 16:37 MD1.csv - -rw-r--r-- 3 hdfs supergroup 63906 2020-02-29 16:37 MD2.csv - $ hdfs dfs -tail MD1.csv - 985,Obediah,Reith,oreithrc@time.com,Male,Colombia,859.28 - 986,Lennard,Hairesnape,lhairesnaperd@merriam-webster.com,Male,North Korea,687.60 - 987,Valaree,Pieper,vpieperre@tinyurl.com,Female,Kazakhstan,1116.23 - 988,Rosemaria,Legan,rleganrf@slideshare.net,Female,Indonesia,62.19 - 989,Rafaellle,Hartill,rhartillrg@marketwatch.com,Male,Albania,1308.17 - 990,Symon,Edmett,sedmettrh@tinyurl.com,Male,China,1216.97 - 991,Hiram,Slayton,hslaytonri@amazon.de,Male,China,510.55 - 992,Sylvan,Dalgliesh,sdalglieshrj@booking.com,Male,China,1503.60 - 993,Alys,Sedgebeer,asedgebeerrk@va.gov,Female,Moldova,1947.58 - 994,Ninette,Hearl,nhearlrl@sakura.ne.jp,Female,Palau,917.66 - 995,Tommy,Atterley,tatterleyrm@homestead.com,Female,Philippines,1660.22 - 996,Sean,Mully,smullyrn@rakuten.co.jp,Female,Brunei,938.04 - 997,Gabe,Lytell,glytellro@cnn.com,Male,China,491.12 - 998,Clementius,Battison,cbattisonrp@dedecms.com,Male,Norway,1781.92 - 999,Kyle,Vala,kvalarq@paginegialle.it,Male,France,11.26 - 1000,Korrie,Odd,koddrr@bigcartel.com,Female,China,471.96 - -If the command succeeded and the file was read correctly, you HDFS has been configured correctly and can now be used in SQream DB. - -If an access error occured, check your Hadoop configuration or contact SQream support. - - -Configuring HDFS for Kerberos access -======================================== - -This section describes how to configure SQream DB to access HDFS secured with Kerberos. - -When a Hadoop cluster is Kerberized, SQream DB's user must be configured to to authenticate through Kerberos. - -Prerequisites ----------------- - -This section assumes you already have Java and Hadoop installed on your SQream DB hosts. - -* SQream DB hosts and Kerberos servers should have the same JCE (Java Cryptography Extension). You can copy the JCE files from the Kerberos server to the SQream DB hosts if needed, to the ``$JAVA_HOME/jre/lib/security`` path. - -* Install the Kerberos clients - - CentOS / RHEL: ``$ sudo yum install krb5-libs krb5-workstation`` - - Ubuntu: ``$ sudo apt-get install krb5-user`` - -* Configure Hadoop as per your distribution. - -Creating keytabs ----------------------- - -#. Sign into your Kerberos Key Distribution Center (KDC) as a root user - -#. - Create a new principal for the SQream DB OS users (e.g. ``sqream`` by default): - - .. code-block:: console - - # kadmin.local -q "addprinc -randkey sqream@KRLM.PIEDPIPER.COM" - - Make sure to replace the realm (``KRLM.PIEDPIPER.COM``) with your actual Kerberos realm. - -#. - Create a Kerberos service principal for each SQream DB host in the cluster. - - In this example, three cluster hosts: - - .. code-block:: console - - # kadmin.local -q "addprinc -randkey sqream/sqreamdb-01.piedpiper.com@KRLM.PIEDPIPER.COM" - # kadmin.local -q "addprinc -randkey sqream/sqreamdb-02.piedpiper.com@KRLM.PIEDPIPER.COM" - # kadmin.local -q "addprinc -randkey sqream/sqreamdb-03.piedpiper.com@KRLM.PIEDPIPER.COM" - - The format for each principal is ``user/host@realm``, where: - - * ``user`` is the OS username - - * ``host`` is the hostname (typically the output of ``hostname -f``) - - * ``realm`` is the Kerberos realm - -#. Generate a keytab for each principal. - - .. code-block:: console - - # kadmin.local -q "xst -k /etc/security/keytabs/sqreamdb-01.service.keytab sqream/sqreamdb-01 sqream/sqreamdb-01.piedpiper.com@KRLM.PIEDPIPER.COM" - # kadmin.local -q "xst -k /etc/security/keytabs/sqreamdb-02.service.keytab sqream/sqreamdb-02 sqream/sqreamdb-02.piedpiper.com@KRLM.PIEDPIPER.COM" - # kadmin.local -q "xst -k /etc/security/keytabs/sqreamdb-03.service.keytab sqream/sqreamdb-03 sqream/sqreamdb-03.piedpiper.com@KRLM.PIEDPIPER.COM" - - You can now exit ``kadmin``. - -#. Change permissions and ownership on each keytab: - - .. code-block:: console - - # chown sqream:sqream /etc/security/keytabs/sqreamdb* - # chmod 440 /etc/security/keytabs/sqreamdb* - -#. Copy the keytab files for each service principal to its respective SQream DB host: - - .. code-block:: console - - # scp /etc/security/keytabs/sqreamdb-01.service.keytab sqreamdb-01.piedpiper.com:/home/sqream/sqreamdb-01.service.keytab - # scp /etc/security/keytabs/sqreamdb-02.service.keytab sqreamdb-02.piedpiper.com:/home/sqream/sqreamdb-02.service.keytab - # scp /etc/security/keytabs/sqreamdb-03.service.keytab sqreamdb-03.piedpiper.com:/home/sqream/sqreamdb-03.service.keytab - -Configuring HDFS for Kerberos ---------------------------------- - -#. - Edit the ``core-site.xml`` configuration file on each SQream DB host to enable authorization. - - For example, editing ``/opt/sqream/hdfs/hadoop/etc/hadoop/core-site.xml``: - - .. code-block:: xml - - - hadoop.security.authorization - true - - -#. Edit the ``yarn-site.xml`` configuration file on each SQream DB host to set the Yarn Kerberos principal - - For example, editing ``/opt/sqream/hdfs/hadoop/etc/hadoop/yarn-site.xml``: - - .. code-block:: xml - - - yarn.resourcemanager.address - hadoop-nn.piedpiper.com:8032 - - - yarn.resourcemanager.principal - yarn/_hostname@KRLM.PIEDPIPER.COM - - -#. - - Edit the ``hdfs-site.xml`` configuration file on each SQream DB host to set the NameNode Kerberos principals, the location of the Kerberos keytab file, and the principal: - - For example, editing ``/opt/sqream/hdfs/hadoop/etc/hadoop/hdfs-site.xml`` on the first host (``sqreamdb-01``): - - .. code-block:: xml - - - dfs.namenode.kerberos.principal - sqream/sqreamdb-01.piedpiper.com@KRLM.PIEDPIPER.COM - - - dfs.namenode.https.principal - sqream/sqreamdb-01.piedpiper.com@KRLM.PIEDPIPER.COM - - - -.. - - security.keytab.file - /home/sqream/sqreamdb-01.service.keytab - - - security.username - sqream/sqreamdb-01.piedpiper.com@KRLM.PIEDPIPER.CO - - -Test the access --------------------- - -To confirm that Kerberized HDFS is accessible on all SQream DB hosts, run the following command to list a directory: - -.. code-block:: console - - $ hdfs dfs -ls hdfs://hadoop-nn.piedpiper.com:8020 - -Repeat the command on all hosts. -If the command succeeds and you see a directory listing, Kerberized HDFS has been configured correctly and can now be used in SQream DB. - -If an error occured, check your configuration or contact SQream support. - -Testing HDFS access in SQream DB -===================================== - -HDFS access from SQream DB is from :ref:`copy_from` and :ref:`external_tables`. - -* :ref:`Example for an HDFS-stored external table` - -* :ref:`Example for inserting data from a CSV on HDFS` - -Troubelshooting HDFS access -================================== - -``class not found`` error ---------------------------------- - -If you get a ``class not found`` error that looks like this: - - java.lang.ClassNotFoundException: Class org.apache.hadoop.hdfs.DistributedFileSystem not found - -#. Verify that the CLASSPATH and ARROW_LIBHDFS_DIR are set correctly. Read more about :ref:`setting the environment variables` above. - -#. Try restarting SQream DB after setting the environment variables. - diff --git a/guides/features/index.rst b/guides/features/index.rst deleted file mode 100644 index 869b43e6a..000000000 --- a/guides/features/index.rst +++ /dev/null @@ -1,34 +0,0 @@ -.. _features_guides: - -********************************** -Features guides -********************************** - -.. toctree:: - :maxdepth: 8 - :caption: In this section: - :glob: - - access_control - - concurrency_and_locks - concurrency_and_scaling_in_sqream - - metadata_system - chunks_and_extents - compression - data_clustering - delete - time_based_data_management - - external_tables - external_data/index - - - transactions - workload_manager - - python_functions - saved_queries - - viewing_system_objects_as_ddl diff --git a/guides/features/metadata_system.rst b/guides/features/metadata_system.rst deleted file mode 100644 index e0b48dc17..000000000 --- a/guides/features/metadata_system.rst +++ /dev/null @@ -1,71 +0,0 @@ -.. _metadata_system: - -*********************** -Metadata system -*********************** - -SQream DB contains a transparent and automatic system that collects metadata describing each :ref:`chunk`. - -The collected metadata enables effective skipping of chunks and extents when queries are executed. - -How is metadata collected? -============================== - -When data is inserted into SQream DB, the load process splits data into chunks. - -Several parameters are collected and stored for later use, including: - -* Range of values for each column chunk (minimum, maximum) -* The number of values -* Additional information for query optimization - -Data is collected automatically and transparently on every column type. - -.. figure:: /_static/images/chunking.png - :scale: 80 % - - Chunks are collections of rows from a column - -.. figure:: /_static/images/chunking_metadata.png - :scale: 80 % - - Metadata is automatically added to each chunk - - -How is metadata used? -=========================== - -Chunk metadata is collected for identifying column values and potentially skipping accessing them, to reduce unnecessary I/O operations. For example, when a query specifies a filter (e.g. ``WHERE`` or ``JOIN`` condition) on a range of values that spans a fraction of the table values, SQream DB will optimally scan only that fraction of the table chunks. - -Queries that filter on fine-grained date and time ranges will be the most effective, particularly when :ref:`data is timestamped`, and when tables contain a large amount of historical data. - -Why is metadata always on? -============================= - -Metadata collection adds very little overhead to data load. WHen possible, most metadata collection is performed in the GPU. - -Metadata is collected for every chunk, and adds a handful of kilobytes at most per million values, and very few compute cycles. - -At scale, metadata collection is often negligible, resulting in a 0.005% overhead. - -For a 10TB dataset, the metadata storage overhead is estimated at 0.5GB. - -Because SQream DB's metadata collection is so light-weight and often results in effective data skipping, it is always-on. - - - - -.. show the metadata system in action: -.. describe a scenario -.. show a statement which is accelerated via the metadata system -.. do this for a bunch of variants - -.. * where -.. * count -.. * delete support - -.. can easily skip reading chunks and extents when running statements -.. with the right shape - -.. best practice notes - diff --git a/guides/features/time_based_data_management.rst b/guides/features/time_based_data_management.rst deleted file mode 100644 index 49a1f5269..000000000 --- a/guides/features/time_based_data_management.rst +++ /dev/null @@ -1,106 +0,0 @@ -.. _time_based_data_management: - -*************************** -Time based data management -*************************** - -SQream DB's columnar-storage system is well adapted to timestamped data. - -When loading data with natural ordering (sorted by a timestamp), SQream DB organizes and collects metadata in chunks of time. -Natural ordering allows for fast retrieval when performing range queries. - -.. contents:: In this topic: - :local: - - -Timestamped data -=========================== - -Timestamped data usually has some interesting attributes: - -* Data is loaded in a natural order, as it is created - -* Updates are infrequent or non-existent. Any updates are done by inserting a new row relating to a new timestamp - -* Queries on timestamped data is typically on continuous time ranges - -* Inserting and reading data are performed in independently, not in the operation or transaction - -* Timestamped data has a high data volume and accumulates faster than typical OLTP workloads - -Chunking -================= - -Core to handling timestamped data is SQream DB's chunking and metadata system. - -When data is inserted, data is automatically partitioned vertically by column, and horizontally by chunk. - -A chunk can be thought of as an automatic partition that spans several millions of records of one column. -Unlike node-partitioning (or sharding), chunking carries several benefits: - -* Chunks are small enough to allow multiple workers to read them concurrently - -* Chunks are optimized for fast insertion of data - -* Chunks carry metadata, which narrows down their contents for the optimizer - -* Chunks are ideal for data retension as they can be deleted en-masse - -* Chunks are optimized for reading into RAM and the GPU - -* Chunks are compressed individually, which improves compression and data locality - - -Use cases -============ - -Consider a set of data with a timestamp column. - -The timestamp order matches the order of data insertion (i.e. newer data is loaded after older data). -This is common when you insert data in small bulks - every 15 minutes, every hour, every day, etc. - -SQream DB's storage works by appending new data, partitioned into chunks containing millions of values. -As new data is loaded, it is chunked and appended to a table. - -This is particularly useful in many scenarios: - -* You run analytical queries spanning specific date ranges (e.g. the sum of transactions during the summer in 2020 vs. the summer in 2019) - -* You :ref:`delete data` when it is older than X months old - -* Regulations instruct you to keep several years' worth of data, but you're not interested in querying this data all the time - -Best practices for time-based data -========================================= - -Use date and datetime types for columns ------------------------------------------ - -When creating tables with dates or timestamps, using the purpose-built ``DATE`` and ``DATETIME`` types over integer types or ``VARCHAR`` will bring performance and storage footprint improvements, and in many cases huge performance improvements (as well as data integrity benefits). SQream DB stores dates and datetimes very efficiently and can strongly optimize queries using these specific types. - -Ordering ------------ - -Data ordering is an important factor in minimizing storage size and improving query performance. - -Prioritize inserting data based on timestamps. This will likely reduces the number of chunks that SQream DB reads during query execution. - -See our :ref:`data_clustering` guide to see how clustering keys can be defined for optimizing data order. - - -Limit workload by timestamp ------------------------------- - -Grouping by and filtering data based on timestamps will improve performance. - -For example, - -.. code-block:: postgres - - SELECT DATEPART(HOUR, timestamp), - MIN(transaction_amount), - MAX(transaction_amount), - avg(transaction_amount) - FROM transactions - WHERE timestamp BETWEEN (CURRENT_TIMESTAMP AND DATEADD(MONTH,-3,CURRENT_TIMESTAMP)) - GROUP BY 1; diff --git a/guides/index.rst b/guides/index.rst deleted file mode 100644 index 788b76970..000000000 --- a/guides/index.rst +++ /dev/null @@ -1,36 +0,0 @@ -.. _guides: - -*********************** -Guides -*********************** - -This section has concept and features guides, and task focused guides. - -.. rubric:: Recommended guides - -* :ref:`Optimization and best practices in SQream DB` - -* :ref:`Using third party tools` - -* :ref:`Client drivers for SQream DB` - - -Full List of Guides -========================= - -.. toctree:: - :maxdepth: 3 - :glob: - :titlesonly: - - xxqueries - inserting_data - - client_drivers/index - third_party_tools/index - - operations/index - - features/index - - architecture/index diff --git a/guides/migration/avro_foreign_data_format.rst b/guides/migration/avro_foreign_data_format.rst deleted file mode 100644 index 88ad6bf2f..000000000 --- a/guides/migration/avro_foreign_data_format.rst +++ /dev/null @@ -1,352 +0,0 @@ -.. _avro_foreign_data_format: - -************************** -Inserting Data from Avro -************************** -The **Inserting Data from Avro** page describes inserting data from Avro into SQream and includes the following: - -.. contents:: - :local: - :depth: 2 - -Overview -=========== -**Avro** is a well-known data serialization system that relies on schemas. Due to its flexibility and nesting as an efficient data storage method, SQream supports the Avro binary data format as an alternative to JSON. - -Avro Data Types -=========== - -Avro includes the following data types: - -.. contents:: - :local: - :depth: 1 - -Primitive Data Types --------------- -The following table shows the supported **Primitive** data types: - -+-------------+-------------------------------------------+ -| Avro Type | SQream Type | -| +--------+---------------+--------+---------+ -| | Number | Date/Datetime | String | Boolean | -+=============+========+===============+========+=========+ -| ``null`` | ✓ | ✓ | ✓ | ✓ | -+-------------+--------+---------------+--------+---------+ -| ``boolean`` | | | ✓ | ✓ | -+-------------+--------+---------------+--------+---------+ -| ``int`` | ✓ | | ✓ | | -+-------------+--------+---------------+--------+---------+ -| ``long`` | ✓ | | ✓ | | -+-------------+--------+---------------+--------+---------+ -| ``float`` | ✓ | | ✓ | | -+-------------+--------+---------------+--------+---------+ -| ``double`` | ✓ | | ✓ | | -+-------------+--------+---------------+--------+---------+ -| ``bytes`` | | | | | -+-------------+--------+---------------+--------+---------+ -| ``string`` | | ✓ | ✓ | | -+-------------+--------+---------------+--------+---------+ - - - - - - -Complex Data Types --------------- -The following table shows the supported **Complex** data types: - -+------------+-------------------------------------------+ -| | SQream Type | -| +--------+---------------+--------+---------+ -|Avro Type | Number | Date/Datetime | String | Boolean | -+============+========+===============+========+=========+ -| ``record`` | | | | | -+------------+--------+---------------+--------+---------+ -| ``enum`` | | | ✓ | | -+------------+--------+---------------+--------+---------+ -| ``array`` | | | | | -+------------+--------+---------------+--------+---------+ -| ``map`` | | | | | -+------------+--------+---------------+--------+---------+ -| ``union`` | ✓ | ✓ | ✓ | ✓ | -+------------+--------+---------------+--------+---------+ -| ``fixed`` | | | | | -+------------+--------+---------------+--------+---------+ - - -Logical Data Types --------------- -The following table shows the supported **Logical** data types: - -+----------------------------+-------------------------------------------+ -| Avro Type | SQream Type | -| +--------+---------------+--------+---------+ -| | Number | Date/Datetime | String | Boolean | -+============================+========+===============+========+=========+ -| ``decimal`` | ✓ | | ✓ | | -+----------------------------+--------+---------------+--------+---------+ -| ``uuid`` | | | ✓ | | -+----------------------------+--------+---------------+--------+---------+ -| ``date`` | | ✓ | ✓ | | -+----------------------------+--------+---------------+--------+---------+ -| ``time-millis`` | | | | | -+----------------------------+--------+---------------+--------+---------+ -| ``time-micros`` | | | | | -+----------------------------+--------+---------------+--------+---------+ -| ``timestamp-millis`` | | ✓ | ✓ | | -+----------------------------+--------+---------------+--------+---------+ -| ``timestamp-micros`` | | ✓ | ✓ | | -+----------------------------+--------+---------------+--------+---------+ -| ``local-timestamp-millis`` | | | | | -+----------------------------+--------+---------------+--------+---------+ -| ``local-timestamp-micros`` | | | | | -+----------------------------+--------+---------------+--------+---------+ -| ``duration`` | | | | | -+----------------------------+--------+---------------+--------+---------+ - - -Mapping Objects to Rows -=============== -When mapping objects to rows, each Avro object or message must contain one ``record`` type object corresponding to a single row in SQream. The ``record`` fields are **Comment - Must be associated?** associated by name to their target table columns. - -Additional unmapped fields will be ignored. Note that using the JSONPath option overrides this. - -Ingesting Avro Files -==================== -This section describes how to ingest Avro files into SQream and covers the following: - - -.. contents:: - :local: - :depth: 1 - - -Preparing Your Avro Source File ----------- -Prepare your Avro source files according to the following requirements: - -* RFC 4180 standard CSV files, but can also be modified to support non-standard CSVs (with multi-character delimiters, unquoted fields, etc). - - :: - -* Files are encoded with UTF-8 or ASCII. - - :: - -* Field delimiter is an ASCII character or characters. - - :: - -* Record delimiter, also known as a new line separator, is a Unix-style newline (``\n``), DOS-style newline (``\r\n``), or Mac style newline (``\r``). - - :: - -* If a field is quoted, any double quote that appears must be double-quoted (similar to the :ref:`string literals quoting rules`. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. - - :: - -* Fields can be enclosed by double-quotes (optional), or mandatory quotes if they contain one of the following characters: - - * The record delimiter or field delimiter. - - :: - - * A double quote character. - - :: - - * A newline. - -SQream does not support other modes of escaping, such as ``1,"What are \"birds\"?"``. - -``NULL`` values can be marked in the following ways in Avro files: - - * An explicit null marker. For example, ``col1,\N,col3``. - - :: - - * An empty field delimited by the field delimiter. For example, ``col1,,col3``. - - .. note:: If a text field is quoted but contains no content (``""``) it is considered an empty text field and not ``NULL``. - -For more information about standard CSV files, see `RFC 4180 standard CSVs `_. - -Making Avro Files Accessible to Workers ---------------------- -To give workers access to files every node must have the same view of the storage being used. - -The following apply for Avro files to be accessible to workers: - -* For files hosted on NFS, ensure that the mount is accessible from all servers. - -* For HDFS, ensure that SQream servers have access to the HDFS name node with the correct **user-id**. For more information, see :ref:`hdfs`. - -* For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. - -For more information about restricted worker access, see :ref:`workload_manager`. - -Basing Your Table Structure on Inserted Tables ---------------------- -Before loading data, you must build the ``CREATE EXTERNAL TABLE`` to correspond with the file structure of the inserted table. - -The example in this section is based on the source ``nba.parquet`` table shown below: - -.. csv-table:: nba.parquet - :file: nba-t10.csv - :widths: auto - :header-rows: 1 - -The following example shows the correct file structure used to create the ``CREATE EXTERNAL TABLE`` statement based on the **nba.parquet** table: - -.. code-block:: postgres - - CREATE FOREIGN TABLE ext_nba - ( - Name VARCHAR(40), - Team VARCHAR(40), - Number BIGINT, - Position VARCHAR(2), - Age BIGINT, - Height VARCHAR(4), - Weight BIGINT, - College VARCHAR(40), - Salary FLOAT - ) - WRAPPER parquet_fdw - OPTIONS - ( - LOCATION = 's3://sqream-demo-data/nba.parquet' - ); - -.. tip:: - - An exact match must exist between the SQream and Avro types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. - -.. note:: The **nba.parquet** file is stored on S3 at ``s3://sqream-demo-data/nba.parquet``. - -Verifying Your Table Output ---------------------- -Because external tables do not automatically verify the file integrity or structure, you must manually verify that the table output is identical to the original inserted table. - -The following is an example of the output based on the **nba.parquet** table: - -.. code-block:: psql - - t=> SELECT * FROM ext_nba LIMIT 10; - Name | Team | Number | Position | Age | Height | Weight | College | Salary - --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- - Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 - Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 - John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | - R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 - Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 - Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 - Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 - Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 - Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 - Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 - -.. note:: If your table output has errors, verify that the structure of the Avro files correctly corresponds to the external table structure that you created. - -Loading Data into SQream ---------------------- - -Syntax -~~~~~~~~~~~~~~~~~~~~~ -The following is the correct syntax for loading data into SQream: - -.. code-block:: postgres - - CREATE TABLE
AS - SELECT * FROM ; - -The following is an example of loading data into SQream: - -.. code-block:: postgres - - CREATE TABLE nba AS - SELECT * FROM ext_nba; - -For more information about the **CREATE TABLE AS** statement, see :ref:`create_table_as`. - -Examples -~~~~~~~~~~~~~~~~~~~~~ - -This section includes the following examples of loading data into SQream: - -.. contents:: - :local: - :depth: 1 - -Omitting Unsupported Column Types -********************** -When loading data, you can omit columns using the ``NULL as`` argument. You can use this argument to omit unsupported columns from queries that access external tables. By omitting them, these columns will not be called and will avoid generating a "type mismatch" error. - -**Comment - Is "type mismatch" the official name of this error, do the words "type mismatch" appear anywhere, or is this just a description of the error?** - -In the example below, the ``Position`` column is not supported due its type. - -.. code-block:: postgres - - CREATE TABLE nba AS - SELECT Name, Team, Number, NULL as Position, Age, Height, Weight, College, Salary FROM ext_nba; - - -Modifying Data Before Loading -********************** -One of the main reasons for staging data using the ``EXTERNAL TABLE`` argument is to examine and modify table contents before loading it into SQream. - -For example, we can replace **Comment - Convert?** pounds with kilograms using the :ref:`create_table_as` statement - -In the example below, the ``Position`` column is set to the default ``NULL``. - -.. code-block:: postgres - - CREATE TABLE nba AS - SELECT name, team, number, NULL as Position, age, height, (weight / 2.205) as weight, college, salary - FROM ext_nba - ORDER BY weight; - - -Loading a Table from a Directory of Avro Files on HDFS -********************** -The following is an example of loading a table from a directory of Avro files on HDFS: - -.. code-block:: postgres - - CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) - WRAPPER parquet_fdw - OPTIONS - ( - LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet' - ); - - CREATE TABLE users AS SELECT * FROM ext_users; - -For more configuration option examples, see the `CREATE FOREIGN TABLE parameters `_. - -Loading a Table from a Directory of Avro Files on S3 -********************** -The following is an example of loading a table from a directory of Avro files on S3: - -.. code-block:: postgres - - CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) - WRAPPER parquet_fdw - OPTIONS - ( LOCATION = 's3://pp-secret-bucket/users/*.parquet', - AWS_ID = 'our_aws_id', - AWS_SECRET = 'our_aws_secret' - ); - - CREATE TABLE users AS SELECT * FROM ext_users; - - - - - - diff --git a/guides/migration/nba-t10.csv b/guides/migration/nba-t10.csv deleted file mode 100644 index 024530355..000000000 --- a/guides/migration/nba-t10.csv +++ /dev/null @@ -1,10 +0,0 @@ -Name,Team,Number,Position,Age,Height,Weight,College,Salary -Avery Bradley,Boston Celtics,0.0,PG,25.0,6-2,180.0,Texas,7730337.0 -Jae Crowder,Boston Celtics,99.0,SF,25.0,6-6,235.0,Marquette,6796117.0 -John Holland,Boston Celtics,30.0,SG,27.0,6-5,205.0,Boston University, -R.J. Hunter,Boston Celtics,28.0,SG,22.0,6-5,185.0,Georgia State,1148640.0 -Jonas Jerebko,Boston Celtics,8.0,PF,29.0,6-10,231.0,,5000000.0 -Amir Johnson,Boston Celtics,90.0,PF,29.0,6-9,240.0,,12000000.0 -Jordan Mickey,Boston Celtics,55.0,PF,21.0,6-8,235.0,LSU,1170960.0 -Kelly Olynyk,Boston Celtics,41.0,C,25.0,7-0,238.0,Gonzaga,2165160.0 -Terry Rozier,Boston Celtics,12.0,PG,22.0,6-2,190.0,Louisville,1824360.0 diff --git a/guides/operations/configuration.rst b/guides/operations/configuration.rst deleted file mode 100644 index b1e05d54f..000000000 --- a/guides/operations/configuration.rst +++ /dev/null @@ -1,952 +0,0 @@ -.. _configuration: - -************************** -Configuration -************************** - -The **Configuration** page describes SQream’s method for configuring your instance of SQream and includes the following topics: - -.. contents:: - :local: - :depth: 1 - -Current Configuration Method -=================== - - -Overview ------ - - - -Modifications that you make to your configurations are persistent based on whether they are made at the session or cluster level. Persistent configurations are modifications made to attributes that are retained after shutting down your system. - - -Modifying Your Configuration ----- -The **Modifying Your Configuration** section describes the following: - -.. contents:: - :local: - :depth: 1 - - - - - - - - - - -Modifying Your Configuration Using the Worker Configuration File -~~~~~~~~~~~ - -You can modify your configuration using the **worker configuration file (config.json)**. Changes that you make to worker configuration files are persistent. Note that you can only set the attributes in your worker configuration file **before** initializing your SQream worker, and while your worker is active these attributes are read-only. - -The following is an example of a worker configuration file: - -.. code-block:: postgres - - { - “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, - “gpu”: 0, - “licensePath”: “home/test_user/SQream/tests/license.enc”, - “machineIP”: “127.0.0.1”, - “metadataServerIp”: “127.0.0.1”, - “metadataServerPort”: “3105, - “port”: 5000, - “useConfigIP”” true, - “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” - } - -You can access the legacy configuration file from the ``legacyConfigFilePath`` parameter shown above. If all (or most) of your workers require the same flag settings, you can set the ``legacyConfigFilePath`` attribute to the same legacy file. - - - -Modifying Your Configuration Using a Legacy Configuration File -~~~~~~~~~~~ - -You can modify your configuration using a legacy configuration file. - -The Legacy configuration file provides access to the read/write flags used in SQream’s previous configuration method. A link to this file is provided in the **legacyConfigFilePath** parameter in the worker configuration file. - -The following is an example of the legacy configuration file: - - -.. code-block:: postgres - - { - “developerMode”: true, - “reextentUse”: false, - “useClientLog”: true, - “useMetadataServer”” false - } - - - -Session vs Cluster Based Configuration -============================== - -.. contents:: - :local: - :depth: 1 - - - - - -Cluster-Based Configuration --------------- -SQream uses cluster-based configuration, enabling you to centralize configurations for all workers on the cluster. Only flags set to the regular or cluster flag type have access to cluster-based configuration. Configurations made on the cluster level are persistent and stored at the metadata level. The parameter settings in this file are applied globally to all workers connected to it. - -For more information, see the following: - -* `Using SQream SQL `_ - modifying flag attributes from the CLI. -* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. - -For more information on flag-based access to cluster-based configuration, see **Configuration Flag Types** below. - -Session-Based Configuration ----------------- -Session-based configurations are not persistent and are deleted when your session ends. This method enables you to modify all required configurations while avoiding conflicts between flag attributes modified on different devices at different points in time. - -The **SET flag_name** command is used to modify flag attributes. Any modifications you make with the **SET flag_name** command apply only to your open session, and are not saved when it ends - -For example, when the query below has completed executing, the values configured will be restored to its previous setting: - -.. code-block:: console - - set spoolMemoryGB=700; - select * from table a where date='2021-11-11' - -For more information, see the following: - -* `Using SQream SQL `_ - modifying flag attributes from the CLI. -* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. - -Configuration Flag Types -========== -The flag type attribute can be set for each flag and determines its write access as follows: - -* **Regular:** session-based read/write flags that can be stored in the metadata file -* **Cluster:** global cluster-based read/write flags that can be stored in the metadata file -* **Worker:** single worker-based read-only flags that can be stored in the worker configuration file - -The flag type determines which files can be accessed and which commands or commands sets users can run. - -The following table describes the file or command modification rights for each flag type: - -.. list-table:: - :widths: 20 20 20 20 - :header-rows: 1 - - * - **Flag Type** - - **Legacy Configuration File** - - **ALTER SYSTEM SET** - - **Worker Configuration File** - * - :ref:`Regular` - - Can modify - - Can modify - - Cannot modify - * - :ref:`Cluster` - - Cannot modify - - Can modify - - Cannot modify - * - :ref:`Worker` - - Cannot modify - - Cannot modify - - Can modify - -.. _regular_flag_types: - -Regular Flag Types ---------------------- -The following is an example of the correct syntax for running a **Regular** flag type command: - -.. code-block:: console - - SET spoolMemoryGB= 11; - executed - -The following table describes the Regular flag types: - -.. list-table:: - :widths: 2 5 10 - :header-rows: 1 - - * - **Command** - - **Description** - - **Example** - * - ``SET `` - - Used for modifying flag attributes. - - ``SET developerMode=true`` - * - ``SHOW / ALL`` - - Used to preset either a specific flag value or all flag values. - - ``SHOW `` - * - ``SHOW ALL LIKE`` - - Used as a wildcard character for flag names. - - ``SHOW `` - * - ``show_conf_UF`` - - Used to print all flags with the following attributes: - - * Flag name - * Default value - * Is developer mode (Boolean) - * Flag category - * Flag type - - ``rechunkThreshold,90,true,RND,regular`` - * - ``show_conf_extended UF`` - - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. - - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` - ``utility functions names,boolean,true,false`` - * - ``show_md_flag UF`` - - Used to show a specific flag/all flags stored in the metadata file. - - - * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` - * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` - * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` - -.. _cluster_flag_types: - -Cluster Flag Types ---------------------- -The following is an example of the correct syntax for running a **Cluster** flag type command: - -.. code-block:: console - - ALTER SYSTEM RESET useMetadataServer; - executed - -The following table describes the Cluster flag types: - -.. list-table:: - :widths: 1 5 10 - :header-rows: 1 - - * - **Command** - - **Description** - - **Example** - * - ``ALTER SYSTEM SET `` - - Used to storing or modifying flag attributes in the metadata file. - - ``ALTER SYSTEM SET `` - * - ``ALTER SYSTEM RESET `` - - Used to remove a flag or all flag attributes from the metadata file. - - ``ALTER SYSTEM RESET `` - * - ``SHOW / ALL`` - - Used to print the value of a specified value or all flag values. - - ``SHOW `` - * - ``SHOW ALL LIKE`` - - Used as a wildcard character for flag names. - - ``SHOW `` - * - ``show_conf_UF`` - - Used to print all flags with the following attributes: - - * Flag name - * Default value - * Is developer mode (Boolean) - * Flag category - * Flag type - - ``rechunkThreshold,90,true,RND,regular`` - * - ``show_conf_extended UF`` - - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. - - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` - ``utility functions names,boolean,true,false`` - * - ``show_md_flag UF`` - - Used to show a specific flag/all flags stored in the metadata file. - - - * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` - * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` - * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` - -.. _worker_flag_types: - -Worker Flag Types ---------------------- -The following is an example of the correct syntax for running a **Worker** flag type command: - -.. code-block:: console - - SHOW spoolMemoryGB; - -The following table describes the Worker flag types: - -.. list-table:: - :widths: 1 5 10 - :header-rows: 1 - - * - **Command** - - **Description** - - **Example** - * - ``ALTER SYSTEM SET `` - - Used to storing or modifying flag attributes in the metadata file. - - ``ALTER SYSTEM SET `` - * - ``ALTER SYSTEM RESET `` - - Used to remove a flag or all flag attributes from the metadata file. - - ``ALTER SYSTEM RESET `` - * - ``SHOW / ALL`` - - Used to print the value of a specified value or all flag values. - - ``SHOW `` - * - ``SHOW ALL LIKE`` - - Used as a wildcard character for flag names. - - ``SHOW `` - * - ``show_conf_UF`` - - Used to print all flags with the following attributes: - - * Flag name - * Default value - * Is developer mode (Boolean) - * Flag category - * Flag type - - ``rechunkThreshold,90,true,RND,regular`` - * - ``show_conf_extended UF`` - - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. - - - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` - ``utility functions names,boolean,true,false`` - * - ``show_md_flag UF`` - - Used to show a specific flag/all flags stored in the metadata file. - - - * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` - * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` - * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` - -Configuration Commands -========== - - - -The configuration commands are associated with particular flag types based on permissions. - -The following table describes the commands or command sets that can be run based on their flag type. Note that the flag names described in the following table are described in the :ref:`Configuration Roles` section below. - -.. list-table:: - :header-rows: 1 - :widths: 1 2 10 17 - :class: my-class - :name: my-name - - * - Flag Type - - Command - - Description - - Example - * - Regular - - ``SET `` - - Used for modifying flag attributes. - - ``SET developerMode=true`` - * - Cluster - - ``ALTER SYSTEM SET `` - - Used to storing or modifying flag attributes in the metadata file. - - ``ALTER SYSTEM SET `` - * - Cluster - - ``ALTER SYSTEM RESET `` - - Used to remove a flag or all flag attributes from the metadata file. - - ``ALTER SYSTEM RESET `` - * - Regular, Cluster, Worker - - ``SHOW / ALL`` - - Used to print the value of a specified value or all flag values. - - ``SHOW `` - * - Regular, Cluster, Worker - - ``SHOW ALL LIKE`` - - Used as a wildcard character for flag names. - - ``SHOW `` - * - Regular, Cluster, Worker - - ``show_conf_UF`` - - Used to print all flags with the following attributes: - - * Flag name - * Default value - * Is developer mode (Boolean) - * Flag category - * Flag type - - - - - ``rechunkThreshold,90,true,RND,regular`` - * - Regular, Cluster, Worker - - ``show_conf_extended UF`` - - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. - - ``spoolMemoryGB,15,false,generic,regular,Amount of memory (GB)`` - ``the server can use for spooling,”Statement that perform “”group by””,`` - ``“”order by”” or “”join”” operation(s) on large set of data will run`` - ``much faster if given enough spool memory, otherwise disk spooling will`` - ``be used resulting in performance hit.”,uint,,0-5000`` - * - Regular, Cluster, Worker - - ``show_md_flag UF`` - - Used to show a specific flag/all flags stored in the metadata file. - - - * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` - * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` - * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` - - - - - - - -.. _configuration_roles: - -Configuration Roles -=========== -SQream divides flags into the following roles, each with their own set of permissions: - -* **Generic** – Flags that can be modified by standard users on a session basis. -* **Admin** – Flags that can be modified by administrators on a session and cluster basis using the ALTER SYSTEM SET command. - - - -The following table describes the Generic and Admin configuration flags: - -.. list-table:: - :header-rows: 1 - :widths: 1 2 1 15 1 20 - :class: my-class - :name: my-name - - * - Flag Name - - Access Control - - Modification Type - - Description - - Data Type - - Default Value - - * - ``binSizes`` - - Admin - - Regular - - Sets the custom bin size in the cache to enable high granularity bin control. - - string - - - ``16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,`` - ``131072,262144,524288,1048576,2097152,4194304,8388608,16777216,`` - ``33554432,67108864,134217728,268435456,536870912,786432000,107374,`` - ``1824,1342177280,1610612736,1879048192,2147483648,2415919104,`` - ``2684354560,2952790016,3221225472`` - - * - ``checkCudaMemory`` - - Admin - - Regular - - Sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. - - boolean - - ``FALSE`` - - * - ``compilerGetsOnlyUFs`` - - Admin - - Regular - - Sets the runtime to pass only utility functions names to the compiler. - - boolean - - ``FALSE`` - - * - ``copyToRestrictUtf8`` - - Admin - - Regular - - Sets the custom bin size in the cache to enable high granularity bin control. - - boolean - - ``FALSE`` - - * - ``cpuReduceHashtableSize`` - - Admin - - Regular - - Sets the hash table size of the CpuReduce. - - uint - - ``10000`` - - * - ``csvLimitRowLength`` - - Admin - - Cluster - - Sets the maximum supported CSV row length. - - uint - - ``100000`` - - * - ``cudaMemcpyMaxSizeBytes`` - - Admin - - Regular - - Sets the chunk size for copying from CPU to GPU. If set to 0, do not divide. - - uint - - ``0`` - - * - ``CudaMemcpySynchronous`` - - Admin - - Regular - - Indicates if copying from/to GPU is synchronous. - - boolean - - ``FALSE`` - - * - ``cudaMemQuota`` - - Admin - - Worker - - Sets the percentage of total device memory to be used by the instance. - - uint - - ``90`` - - * - ``developerMode`` - - Admin - - Regular - - Enables modifying R&D flags. - - boolean - - ``FALSE`` - - * - ``enableDeviceDebugMessages`` - - Admin - - Regular - - Activates the Nvidia profiler (nvprof) markers. - - boolean - - ``FALSE`` - - * - ``enableLogDebug`` - - Admin - - Regular - - Enables creating and logging in the clientLogger_debug file. - - boolean - - ``TRUE`` - - * - ``enableNvprofMarkers`` - - Admin - - Regular - - Activates the Nvidia profiler (nvprof) markers. - - boolean - - ``FALSE`` - - * - ``endLogMessage`` - - Admin - - Regular - - Appends a string at the end of every log line. - - string - - ``EOM`` - - * - ``extentStorageFileSizeMB`` - - Admin - - Cluster - - Sets the minimum size in mebibytes of extents for table bulk data. - - uint - - ``20`` - - * - ``gatherMemStat`` - - Admin - - Regular - - Monitors all pinned allocations and all **memcopies** to/from device, and prints a report of pinned allocations that were not memcopied to/from the device using the **dump_pinned_misses** utility function. - - boolean - - ``FALSE`` - - * - ``increaseChunkSizeBeforeReduce`` - - Admin - - Regular - - Increases the chunk size to reduce query speed. - - boolean - - ``FALSE`` - - * - ``increaseMemFactors`` - - Admin - - Regular - - Adds rechunker before expensive chunk producer. - - boolean - - ``TRUE`` - - * - ``leveldbWriteBufferSize`` - - Admin - - Regular - - Sets the buffer size. - - uint - - ``524288`` - - * - ``machineIP`` - - Admin - - Worker - - Manual setting of reported IP. - - string - - ``127.0.0.1`` - - - - - * - ``memoryResetTriggerMB`` - - Admin - - Regular - - Sets the size of memory used during a query to trigger aborting the server. - - uint - - ``0`` - - * - ``metadataServerPort`` - - Admin - - Worker - - Sets the port used to connect to the metadata server. SQream recommends using port ranges above 1024† because ports below 1024 are usually reserved, although there are no strict limitations. Any positive number (1 - 65535) can be used. - - uint - - ``3105`` - - * - ``mtRead`` - - Admin - - Regular - - Splits large reads to multiple smaller ones and executes them concurrently. - - boolean - - ``FALSE`` - - * - ``mtReadWorkers`` - - Admin - - Regular - - Sets the number of workers to handle smaller concurrent reads. - - uint - - ``30`` - - * - ``orcImplicitCasts`` - - Admin - - Regular - - Sets the implicit cast in orc files, such as **int** to **tinyint** and vice versa. - - boolean - - ``TRUE`` - - * - ``statementLockTimeout`` - - Admin - - Regular - - Sets the timeout (seconds) for acquiring object locks before executing statements. - - uint - - ``3`` - - * - ``useConfigIP`` - - Admin - - Worker - - Activates the machineIP (true). Setting to false ignores the machineIP and automatically assigns a local network IP. This cannot be activated in a cloud scenario (on-premises only). - - boolean - - ``FALSE`` - - * - ``useLegacyDecimalLiterals`` - - Admin - - Regular - - Interprets decimal literals as **Double** instead of **Numeric**. Used to preserve legacy behavior in existing customers. - - boolean - - ``FALSE`` - - * - ``useLegacyStringLiterals`` - - Admin - - Regular - - Interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. Used to preserve legacy behavior in existing customers. - - boolean - - ``FALSE`` - - * - ``flipJoinOrder`` - - Generic - - Regular - - Reorders join to force equijoins and/or equijoins sorted by table size. - - boolean - - ``FALSE`` - - * - ``limitQueryMemoryGB`` - - Generic - - Worker - - Prevents a query from processing more memory than the flag’s value. - - uint - - ``100000`` - - * - ``logSysLevel`` - - Generic - - Regular - - - Determines the client log level: - 0 - L_SYSTEM, - 1 - L_FATAL, - 2 - L_ERROR, - 3 - L_WARN, - 4 - L_INFO, - 5 - L_DEBUG, - 6 - L_TRACE - - uint - - ``100000`` - - * - ``maxAvgBlobSizeToCompressOnGpu`` - - Generic - - Regular - - Sets the CPU to compress columns with size above (flag’s value) * (row count). - - uint - - ``120`` - - * - ``spoolMemoryGB`` - - Generic - - Regular - - Sets the amount of memory (GB) to be used by the server for spooling. - - uint - - ``8`` - -Showing All Flags in the Catalog Table -======= -SQream uses the **sqream_catalog.parameters** catalog table for showing all flags, providing the scope (default, cluster and session), description, default value and actual value. - -The following is the correct syntax for a catalog table query: - - -.. code-block:: console - - SELECT * FROM sqream_catalog.settings - -The following is an example of a catalog table query: - - -.. code-block:: console - - externalTableBlobEstimate, 100, 100, default, - varcharEncoding, ascii, ascii, default, Changes the expected encoding for Varchar columns - useCrcForTextJoinKeys, true, true, default, - hiveStyleImplicitStringCasts, false, false, default, - -This guide covers the configuration files and the ``SET`` statement. - - - - -Previous Configuration Method -=================== -By default, configuration files are stored in ``/etc/sqream``. - -A very minimal configuration file looks like this: - -.. code-block:: json - - { - "compileFlags": { - }, - "runtimeFlags": { - }, - "runtimeGlobalFlags": { - }, - "server": { - "gpu": 0, - "port": 5000, - "cluster": "/home/sqream/sqream_storage", - "licensePath": "/etc/sqream/license.enc" - } - } - -* Each SQream DB worker (``sqreamd``) has a dedicated configuration file. - -* The configuration file contains four distinct sections, ``compileFlags``, ``runtimeFlags``, ``runtimeGlobalFlags``, and ``server``. - -In the example above, the worker will start on port 5000, and will use GPU #0. - -Frequently Set Parameters ------- -.. todo - list-table:: Compiler flags - :widths: auto - :header-rows: 1 - - * - Name - - Section - - Description - - Default - - Value range - - Example - * - - - - - - - - - - - - -.. list-table:: Server flags - :widths: auto - :header-rows: 1 - - * - Name - - Section - - Description - - Default - - Value range - - Example - * - ``gpu`` - - ``server`` - - Controls the GPU ordinal to use - - ✗ - - 0 to (number of GPUs in the machine -1). Check with ``nvidia-smi -L`` - - ``"gpu": 0`` - * - ``port`` - - ``server`` - - Controls the TCP port to listen on - - ✗ - - 1024 to 65535 - - ``"port" : 5000`` - * - ``ssl_port`` - - ``server`` - - Controls the SSL TCP port to listen on. Must be different from ``port`` - - ✗ - - 1024 to 65535 - - ``"ssl_port" : 5100`` - * - ``cluster`` - - ``server`` - - Specifies the cluster path root - - ✗ - - Valid local system path - - ``"cluster" : "/home/sqream/sqream_storage"`` - * - ``license_path`` - - ``server`` - - Specifies the license file for this worker - - ✗ - - Valid local system path to license file - - ``"license_path" : "/etc/sqream/license.enc"`` - -.. list-table:: Runtime global flags - :widths: auto - :header-rows: 1 - - * - Name - - Section - - Description - - Default - - Value range - - Example - * - ``spoolMemoryGb`` - - ``runtimeGlobalFlags`` - - Modifies RAM allocated for the worker for intermediate results. Statements that use more memory than this setting will spool to disk, which could degrade performance. We recommend not to exceed the amount of RAM in the machine. This setting must be set lower than the ``limitQueryMemoryGB`` setting. - - ``128`` - - 1 to maximum available RAM in gigabytes. - - ``"spoolMemoryGb": 250`` - * - ``limitQueryMemoryGB`` - - ``runtimeGlobalFlags`` - - Modifies the maximum amount of RAM allocated for a query. The recommended value for this is ``total host memory`` / ``sqreamd workers on host``. For example, for a machine with 512GB of RAM and 4 workers, the recommended setting is ``512/4 → 128``. - - ``10000`` - - ``1`` to ``10000`` - - ``"limitQueryMemoryGB" : 128`` - * - ``cudaMemQuota`` - - ``runtimeGlobalFlags`` - - Modifies the maximum amount of GPU RAM allocated for a worker. The recommended value is 99% for a GPU with a single worker, or 49% for a GPU with two workers. - - ``90`` % - - ``1`` to ``99`` - - ``"cudaMemQuota" : 99`` - * - ``showFullExceptionInfo`` - - ``runtimeGlobalFlags`` - - Shows complete error message with debug information. Use this for debugging. - - ``false`` - - ``true`` or ``false`` - - ``"showFullExceptionInfo" : true`` - * - ``initialSubscribedServices`` - - ``runtimeGlobalFlags`` - - Comma separated list of :ref:`service queues` that the worker is subscribed to - - ``"sqream"`` - - Comma separated list of service names, with no spaces. Services that don't exist will be created. - - ``"initialSubscribedServices": "sqream,etl,management"`` - * - ``logClientLevel`` - - ``runtimeGlobalFlags`` - - Used to control which log level should appear in the logs - - ``4`` (``INFO``) - - ``0`` SYSTEM (lowest) - ``4`` INFO (highest). See :ref:`information level table` for explanation about these log levels. - - ``"logClientLevel" : 3`` - * - ``nodeInfoLoggingSec`` - - ``runtimeGlobalFlags`` - - Sets an interval for automatically logging long-running statements' :ref:`show_node_info` output. Output is written as a message type ``200``. - - ``60`` (every minute) - - Positive whole number >=1. - - ``"nodeInfoLoggingSec" : 5`` - * - ``useLogMaxFileSize`` - - ``runtimeGlobalFlags`` - - Defines whether SQream logs should be cycled when they reach ``logMaxFileSizeMB`` size. When ``true``, set the ``logMaxFileSizeMB`` accordingly. - - ``false`` - - ``false`` or ``true`` - - ``"useLogMaxFileSize" : true`` - * - ``logMaxFileSizeMB`` - - ``runtimeGlobalFlags`` - - Sets the size threshold in megabytes after which a new log file will be opened. - - ``20`` - - ``1`` to ``1024`` (1MB to 1GB) - - ``"logMaxFileSizeMB" : 250`` - * - ``logFileRotateTimeFrequency`` - - ``runtimeGlobalFlags`` - - Control frequency of log rotation - - ``never`` - - ``daily``, ``weekly``, ``monthly``, ``never`` - - ``"logClientLevel" : 3`` - * - ``useMetadataServer`` - - ``runtimeGlobalFlags`` - - Specifies if this worker connects to a cluster (``true``) or is standalone (``false``). If set to ``true``, also set ``metadataServerIp`` - - ``true`` - - ``false`` or ``true`` - - ``"useMetadataServer" : true`` - * - ``metadataServerIp`` - - ``runtimeGlobalFlags`` - - Specifies the hostname or IP of the metadata server, when ``useMetadataServer`` is set to ``true``. - - ``127.0.0.1`` - - A valid IP or hostname - - ``"metadataServerIp": "127.0.0.1"`` - * - ``useConfigIP`` - - ``runtimeGlobalFlags`` - - Specifies if the metadata should use a pre-determined hostname or IP to refer to this worker. If set to ``true``, set the ``machineIp`` configuration accordingly. - - ``false`` - automatically derived by the TCP socket - - ``false`` or ``true`` - - ``"useConfigIP" : true`` - * - ``machineIP`` - - ``runtimeGlobalFlags`` - - Specifies the worker's external IP or hostname, when used from a remote network. - - No default - - A valid IP or hostname - - ``"machineIP": "10.0.1.4"`` - * - ``tempPath`` - - ``runtimeGlobalFlags`` - - Specifies an override for the temporary file path on the local machine. Set this to a local path to improve performance for spooling. - - Defaults to the central storage's built-in temporary folder - - A valid path to a folder on the local machine - - ``"tempPath": "/mnt/nvme0/temp"`` - - - -.. list-table:: Runtime flags - :widths: auto - :header-rows: 1 - - * - Name - - Section - - Description - - Default - - Value range - - Example - * - ``insertParsers`` - - ``runtimeFlags`` - - Sets the number of CSV parsing threads launched during bulk load - - 4 - - 1 to 32 - - ``"insertParsers" : 8`` - * - ``insertCompressors`` - - ``runtimeFlags`` - - Sets the number of compressor threads launched during bulk load - - 4 - - 1 to 32 - - ``"insertCompressors" : 8`` - * - ``statementLockTimeout`` - - ``runtimeGlobalFlags`` - - Sets the delay in seconds before SQream DB will stop waiting for a lock and return an error - - 3 - - >=1 - - ``"statementLockTimeout" : 10`` - - -.. list the main configuration options and how they are used - -.. point to the best practices as well - -.. warning:: JSON files can't contain any comments. - -Recommended Configuration File ------ - -.. code-block:: json - - { - "compileFlags":{ - }, - "runtimeFlags":{ - "insertParsers": 16, - "insertCompressors": 8 - }, - "runtimeGlobalFlags":{ - "limitQueryMemoryGB" : 121, - "spoolMemoryGB" : 108, - "cudaMemQuota": 90, - "initialSubscribedServices" : "sqream", - "useMetadataServer": true, - "metadataServerIp": "127.0.0.1", - "useConfigIP": true, - "machineIP": "127.0.0.1" - }, - "server":{ - "gpu":0, - "port":5000, - "ssl_port": 5100, - "cluster":"/home/sqream/sqream_storage", - "licensePath":"/etc/sqream/license.enc" - } - } diff --git a/guides/operations/index.rst b/guides/operations/index.rst deleted file mode 100644 index db6315c91..000000000 --- a/guides/operations/index.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. _operations: - -********************************** -Operations -********************************** - -The guides in this section include information about best practices, monitoring, logging, troubleshooting, and maintaining a SQream DB cluster. - -.. toctree:: - :maxdepth: 8 - :caption: In this section: - :glob: - - optimization_best_practices - xxrecommended_pre-installation_configurations - xxinstalling_monit - xxlaunching_sqream_with_monit - xxinstalling_sqream_with_binary - xxinstalling_sqream_with_kubernetes - xxrunning_sqream_in_a_docker_container - xxmonitoring - monitoring_query_performance - logging - configuration - troubleshooting - information_for_support - creating_or_cloning_a_storage_cluster - xxstarting_and_stopping_the_system - sqream_studio - statement_editor - hardware_guide - security - sqream_studio_5.3.3 diff --git a/guides/operations/installing_monit.rst b/guides/operations/installing_monit.rst deleted file mode 100644 index 85faae964..000000000 --- a/guides/operations/installing_monit.rst +++ /dev/null @@ -1,319 +0,0 @@ -.. _installing_monit: - -********************************************* -Installing Monit -********************************************* - -Getting Started -============================== - -Before installing SQream with Monit, verify that you have followed the required :ref:`recommended pre-installation configurations `. - -The procedures in the **Installing Monit** guide must be performed on each SQream cluster node. - - - - - -.. _back_to_top: - -Overview -============================== - - -Monit is a free open source supervision utility for managing and monitoring Unix and Linux. Monit lets you view system status directly from the command line or from a native HTTP web server. Monit can be used to conduct automatic maintenance and repair, such as executing meaningful causal actions in error situations. - -SQream uses Monit as a watchdog utility, but you can use any other utility that provides the same or similar functionality. - -The **Installing Monit** procedures describes how to install, configure, and start Monit. - -You can install Monit in one of the following ways: - -* :ref:`Installing Monit on CentOS ` -* :ref:`Installing Monit on CentOS offline ` -* :ref:`Installing Monit on Ubuntu ` -* :ref:`Installing Monit on Ubuntu offline ` - - - - - - - -.. _installing-monit-on-centos: - -Installing Monit on CentOS: ------------------------------------- - - - -**To install Monit on CentOS:** - -1. Install Monit as a superuser on CentOS: - - .. code-block:: console - - $ sudo yum install monit - - -.. _installing-monit-on-centos-offline: - - - -Installing Monit on CentOS Offline: ------------------------------------- - - -Installing Monit on CentOS offline can be done in either of the following ways: - -* :ref:`Building Monit from Source Code ` -* :ref:`Building Monit from Pre-Built Binaries ` - - - - -.. _building_monit_from_source_code: - -Building Monit from Source Code -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - -**To build Monit from source code:** - -1. Copy the Monit package for the current version: - - .. code-block:: console - - $ tar zxvf monit-.tar.gz - - The value ``x.y.z`` denotes the version numbers. - -2. Navigate to the directory where you want to store the package: - - .. code-block:: console - - $ cd monit-x.y.z - -3. Configure the files in the package: - - .. code-block:: console - - $ ./configure (use ./configure --help to view available options) - -4. Build and install the package: - - .. code-block:: console - - $ make && make install - -The following are the default storage directories: - -* The Monit package: **/usr/local/bin/** -* The **monit.1 man-file**: **/usr/local/man/man1/** - -5. **Optional** - To change the above default location(s), use the **--prefix** option to ./configure. - -.. - _**Comment - I took this line directly from the external online documentation. Is the "prefix option" referrin gto the "--help" in Step 3? URL: https://mmonit.com/wiki/Monit/Installation** - -6. **Optional** - Create an RPM package for CentOS directly from the source code: - - .. code-block:: console - - $ rpmbuild -tb monit-x.y.z.tar.gz - -.. - _**Comment - Is this an optional or mandatory step?** - - - - -.. _building_monit_from_pre_built_binaries: - -Building Monit from Pre-Built Binaries -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To build Monit from pre-built binaries:** - -1. Copy the Monit package for the current version: - - .. code-block:: console - - $ tar zxvf monit-x.y.z-linux-x64.tar.gz - - The value ``x.y.z`` denotes the version numbers. - -2. Navigate to the directory where you want to store the package: - - .. code-block:: console$ cd monit-x.y.z - -3. Copy the **bin/monit** and **/usr/local/bin/** directories: - - .. code-block:: console - - $ cp bin/monit /usr/local/bin/ - -4. Copy the **conf/monitrc** and **/etc/** directories: - - .. code-block:: console - - $ cp conf/monitrc /etc/ - -.. - _**Comment - please review this procedure.** - -For examples of pre-built Monit binarties, see :ref:`Download Precompiled Binaries`. - -:ref:`Back to top ` - - - -.. _installing-monit-on-ubuntu: - - - -Installing Monit on Ubuntu: ------------------------------------- - - -**To install Monit on Ubuntu:** - -1. Install Monit as a superuser on Ubuntu: - - .. code-block:: console - - $ sudo apt-get install monit - -:ref:`Back to top ` - - - -.. _installing-monit-on-ubuntu-offline: - - -Installing Monit on Ubuntu Offline: -------------------------------------- - - -You can install Monit on Ubuntu when you do not have an internet connection. - -**To install Monit on Ubuntu offline:** - -1. Compress the required file: - - .. code-block:: console - - $ tar zxvf monit--linux-x64.tar.gz - - **NOTICE:** ** denotes the version number. - -2. Navigate to the directory where you want to save the file: - - .. code-block:: console - - $ cd monit-x.y.z - -3. Copy the **bin/monit** directory into the **/usr/local/bin/** directory: - - .. code-block:: console - - $ cp bin/monit /usr/local/bin/ - -4. Copy the **conf/monitrc** directory into the **/etc/** directory: - - .. code-block:: console - - $ cp conf/monitrc /etc/ - -:ref:`Back to top ` - - -Configuring Monit -==================================== - -When the installation is complete, you can configure Monit. You configure Monit by modifying the Monit configuration file, called **monitrc**. This file contains blocks for each service that you want to monitor. - -The following is an example of a service block: - - .. code-block:: console - - $ #SQREAM1-START - $ check process sqream1 with pidfile /var/run/sqream1.pid - $ start program = "/usr/bin/systemctl start sqream1" - $ stop program = "/usr/bin/systemctl stop sqream1" - $ #SQREAM1-END - -For example, if you have 16 services, you can configure this block by copying the entire block 15 times and modifying all service names as required, as shown below: - - .. code-block:: console - - $ #SQREAM2-START - $ check process sqream2 with pidfile /var/run/sqream2.pid - $ start program = "/usr/bin/systemctl start sqream2" - $ stop program = "/usr/bin/systemctl stop sqream2" - $ #SQREAM2-END - -For servers that don't run the **metadataserver** and **serverpicker** commands, you can use the block example above, but comment out the related commands, as shown below: - - .. code-block:: console - - $ #METADATASERVER-START - $ #check process metadataserver with pidfile /var/run/metadataserver.pid - $ #start program = "/usr/bin/systemctl start metadataserver" - $ #stop program = "/usr/bin/systemctl stop metadataserver" - $ #METADATASERVER-END - -**To configure Monit:** - -1. Copy the required block for each required service. -2. Modify all service names in the block. -3. Copy the configured **monitrc** file to the **/etc/monit.d/** directory: - - .. code-block:: console - - $ cp monitrc /etc/monit.d/ - -4. Set file permissions to **600** (full read and write access): - - .. code-block:: console - - $ sudo chmod 600 /etc/monit.d/monitrc - -5. Reload the system to activate the current configurations: - - .. code-block:: console - - $ sudo systemctl daemon-reload - -6. **Optional** - Navigate to the **/etc/sqream** directory and create a symbolic link to the **monitrc** file: - - .. code-block:: console - - $ cd /etc/sqream - $ sudo ln -s /etc/monit.d/monitrc monitrc - -Starting Monit -==================================== - -After configuring Monit, you can start it. - -**To start Monit:** - -1. Start Monit as a super user: - - .. code-block:: console - - $ sudo systemctl start monit - -2. View Monit's service status: - - .. code-block:: console - - $ sudo systemctl status monit - -3. If Monit is functioning correctly, enable the Monit service to start on boot: - - .. code-block:: console - - $ sudo systemctl enable monit diff --git a/guides/operations/installing_sqream_with_binary.rst b/guides/operations/installing_sqream_with_binary.rst deleted file mode 100644 index 246cdff23..000000000 --- a/guides/operations/installing_sqream_with_binary.rst +++ /dev/null @@ -1,278 +0,0 @@ -.. _installing_sqream_with_binary: - -********************************************* -Installing SQream Using Binary Packages -********************************************* -This procedure describes how to install SQream using Binary packages and must be done on all servers. - -**To install SQream using Binary packages:** - -1. Copy the SQream package to the **/home/sqream** directory for the current version: - - .. code-block:: console - - $ tar -xf sqream-db-v<2020.2>.tar.gz - -2. Append the version number to the name of the SQream folder. The version number in the following example is **v2020.2**: - - .. code-block:: console - - $ mv sqream sqream-db-v<2020.2> - -3. Move the new version of the SQream folder to the **/usr/local/** directory: - - .. code-block:: console - - $ sudo mv sqream-db-v<2020.2> /usr/local/ - -4. Change the ownership of the folder to **sqream folder**: - - .. code-block:: console - - $ sudo chown -R sqream:sqream /usr/local/sqream-db-v<2020.2> - -5. Navigate to the **/usr/local/** directory and create a symbolic link to SQream: - - .. code-block:: console - - $ cd /usr/local - $ sudo ln -s sqream-db-v<2020.2> sqream - -6. Verify that the symbolic link that you created points to the folder that you created: - - .. code-block:: console - - $ ls -l - -7. Verify that the symbolic link that you created points to the folder that you created: - - .. code-block:: console - - $ sqream -> sqream-db-v<2020.2> - -8. Create the SQream configuration file destination folders and set their ownership to **sqream**: - - .. code-block:: console - - $ sudo mkdir /etc/sqream - $ sudo chown -R sqream:sqream /etc/sqream - -9. Create the SQream service log destination folders and set their ownership to **sqream**: - - .. code-block:: console - - $ sudo mkdir /var/log/sqream - $ sudo chown -R sqream:sqream /var/log/sqream - -10. Navigate to the **/usr/local/** directory and copy the SQream configuration files from them: - - .. code-block:: console - - $ cd /usr/local/sqream/etc/ - $ cp * /etc/sqream - -The configuration files are **service configuration files**, and the JSON files are **SQream configuration files**, for a total of four files. The number of SQream configuration files and JSON files must be identical. - -**NOTICE** - Verify that the JSON files have been configured correctly and that all required flags have been set to the correct values. - -In each JSON file, the following parameters **must be updated**: - -* instanceId -* machineIP -* metadataServerIp -* spoolMemoryGB -* limitQueryMemoryGB -* gpu -* port -* ssl_port - -Note the following: - -* The value of the **metadataServerIp** parameter must point to the IP that the metadata is running on. -* The value of the **machineIP** parameter must point to the IP of your local machine. - -It would be same on server running metadataserver and different on other server nodes. - -11. **Optional** - To run additional SQream services, copy the required configuration files and create additional JSON files: - - .. code-block:: console - - $ cp sqream2_config.json sqream3_config.json - $ vim sqream3_config.json - -**NOTICE:** A unique **instanceID** must be used in each JSON file. IN the example above, the instanceID **sqream_2** is changed to **sqream_3**. - -12. **Optional** - If you created additional services in **Step 11**, verify that you have also created their additional configuration files: - - .. code-block:: console - - $ cp sqream2-service.conf sqream3-service.conf - $ vim sqream3-service.conf - -13. For each SQream service configuration file, do the following: - - 1. Change the **SERVICE_NAME=sqream2** value to **SERVICE_NAME=sqream3**. - - 2. Change **LOGFILE=/var/log/sqream/sqream2.log** to **LOGFILE=/var/log/sqream/sqream3.log**. - -**NOTE:** If you are running SQream on more than one server, you must configure the ``serverpicker`` and ``metadatserver`` services to start on only one of the servers. If **metadataserver** is running on the first server, the ``metadataServerIP`` value in the second server's /etc/sqream/sqream1_config.json file must point to the IP of the server on which the ``metadataserver`` service is running. - -14. Set up **servicepicker**: - - 1. Do the following: - - .. code-block:: console - - $ vim /etc/sqream/server_picker.conf - - 2. Change the IP **127.0.0.1** to the IP of the server that the **metadataserver** service is running on. - - 3. Change the **CLUSTER** to the value of the cluster path. - -15. Set up your service files: - - .. code-block:: console - - $ cd /usr/local/sqream/service/ - $ cp sqream2.service sqream3.service - $ vim sqream3.service - -16. Increment each **EnvironmentFile=/etc/sqream/sqream2-service.conf** configuration file for each SQream service file, as shown below: - - .. code-block:: console - - $ EnvironmentFile=/etc/sqream/sqream<3>-service.conf - -17. Copy and register your service files into systemd: - - .. code-block:: console - - $ sudo cp metadataserver.service /usr/lib/systemd/system/ - $ sudo cp serverpicker.service /usr/lib/systemd/system/ - $ sudo cp sqream*.service /usr/lib/systemd/system/ - -18. Verify that your service files have been copied into systemd: - - .. code-block:: console - - $ ls -l /usr/lib/systemd/system/sqream* - $ ls -l /usr/lib/systemd/system/metadataserver.service - $ ls -l /usr/lib/systemd/system/serverpicker.service - $ sudo systemctl daemon-reload - -19. Copy the license into the **/etc/license** directory: - - .. code-block:: console - - $ cp license.enc /etc/sqream/ - - -If you have an HDFS environment, see :ref:`Configuring an HDFS Environment for the User sqream `. - - - - - - -Upgrading SQream Version -------------------------- -Upgrading your SQream version requires stopping all running services while you manually upgrade SQream. - -**To upgrade your version of SQream:** - -1. Stop all actively running SQream services. - -**Notice-** All SQream services must remain stopped while the upgrade is in process. Ensuring that SQream services remain stopped depends on the tool being used. - -For an example of stopping actively running SQream services, see :ref:`Launching SQream with Monit `. - - - -2. Verify that SQream has stopped listening on ports **500X**, **510X**, and **310X**: - - .. code-block:: console - - $ sudo netstat -nltp #to make sure sqream stopped listening on 500X, 510X and 310X ports. - -3. Replace the old version ``sqream-db-v2020.2``, with the new version ``sqream-db-v2021.1``: - - .. code-block:: console - - $ cd /home/sqream - $ mkdir tempfolder - $ mv sqream-db-v2021.1.tar.gz tempfolder/ - $ tar -xf sqream-db-v2021.1.tar.gz - $ sudo mv sqream /usr/local/sqream-db-v2021.1 - $ cd /usr/local - $ sudo chown -R sqream:sqream sqream-db-v2021.1 - -4. Remove the symbolic link: - - .. code-block:: console - - $ sudo rm sqream - -5. Create a new symbolic link named "sqream" pointing to the new version: - - .. code-block:: console - - $ sudo ln -s sqream-db-v2021.1 sqream - -6. Verify that the symbolic SQream link points to the real folder: - - .. code-block:: console - - $ ls -l - - The following is an example of the correct output: - - .. code-block:: console - - $ sqream -> sqream-db-v2021.1 - -7. **Optional-** (for major versions) Upgrade your version of SQream storage cluster, as shown in the following example: - - .. code-block:: console - - $ cat /etc/sqream/sqream1_config.json |grep cluster - $ ./upgrade_storage - - The following is an example of the correct output: - - .. code-block:: console - - get_leveldb_version path{} - current storage version 23 - upgrade_v24 - upgrade_storage to 24 - upgrade_storage to 24 - Done - upgrade_v25 - upgrade_storage to 25 - upgrade_storage to 25 - Done - upgrade_v26 - upgrade_storage to 26 - upgrade_storage to 26 - Done - validate_leveldb - ... - upgrade_v37 - upgrade_storage to 37 - upgrade_storage to 37 - Done - validate_leveldb - storage has been upgraded successfully to version 37 - -8. Verify that the latest version has been installed: - - .. code-block:: console - - $ ./sqream sql --username sqream --password sqream --host localhost --databasename master -c "SELECT SHOW_VERSION();" - - The following is an example of the correct output: - - .. code-block:: console - - v2021.1 - 1 row - time: 0.050603s - -For more information, see the `upgrade_storage `_ command line program. - diff --git a/guides/operations/installing_sqream_with_kubernetes.rst b/guides/operations/installing_sqream_with_kubernetes.rst deleted file mode 100644 index 0269b1204..000000000 --- a/guides/operations/installing_sqream_with_kubernetes.rst +++ /dev/null @@ -1,1805 +0,0 @@ -.. _installing_sqream_with_kubernetes: - -********************************************* -Installing SQream with Kubernetes -********************************************* -**Kubernetes**, also known as **k8s**, is a portable open source platform that automates Linux container operations. Kubernetes supports outsourcing data centers to public cloud service providers or can be scaled for web hosting. SQream uses Kubernetes as an orchestration and recovery solution. - -The **Installing SQream with Kubernetes** guide describes the following: - -.. contents:: - :local: - :depth: 1 - -.. _preparing_sqream_environment: - -Preparing the SQream Environment to Launch SQream Using Kubernetes -=============== - -The **Preparing the SQream environment to Launch SQream Using Kubernetes** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Overview --------------- - -A minimum of three servers is required for preparing the SQream environment using Kubernetes. - -Kubernetes uses clusters, which are sets of nodes running containterized applications. A cluster consists of at least two GPU nodes and one additional server without GPU to act as the quorum manager. - -Each server must have the following IP addresses: - -* An IP address located in the management network. -* An additional IP address from the same subnet to function as a floating IP. - -All servers must be mounted in the same shared storage folder. - -The following list shows the server host name format requirements: - -* A maximum of 253 characters. -* Only lowercase alphanumeric characters, such as ``-`` or ``.``. -* Starts and ends with alphanumeric characters. - -Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes` - - -Operating System Requirements ------------------------------- -The required operating system is a version of x86 CentOS/RHEL between 7.6 and 7.9. Regarding PPC64le, the required version is RHEL 7.6. - -Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes` - - -Compute Server Specifications ------------------------------- -Installing SQream with Kubernetes includes the following compute server specifications: - -* **CPU:** 4 cores -* **RAM:** 16GB -* **HD:** 500GB - -Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes` - -.. _set_up_your_hosts: - -Setting Up Your Hosts -=============================== -SQream requires you to set up your hosts. Setting up your hosts requires the following: - -.. contents:: - :local: - :depth: 1 - -Configuring the Hosts File --------------------------------- -**To configure the /etc/hosts file:** - -1. Edit the **/etc/hosts** file: - - .. code-block:: console - - $ sudo vim /etc/hosts - -2. Call your local host: - - .. code-block:: console - - $ 127.0.0.1 localhost - $ - - -Installing the Required Packages ----------------------------------- -The first step in setting up your hosts is to install the required packages. - -**To install the required packages:** - -1. Run the following command based on your operating system: - - * RHEL: - - .. code-block:: postgres - - $ sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm - - * CentOS: - - .. code-block:: postgres - - $ sudo yum install epel-release - $ sudo yum install pciutils openssl-devel python36 python36-pip kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc jq net-tools ntp - -2. Verify that that the required packages were successfully installed. The following is the correct output: - - .. code-block:: postgres - - ntpq --version - jq --version - python3 --version - pip3 --version - rpm -qa |grep kernel-devel-$(uname -r) - rpm -qa |grep kernel-headers-$(uname -r) - gcc --version - -3. Enable the **ntpd (Network Time Protocol daemon)** program on all servers: - - .. code-block:: postgres - - $ sudo systemctl start ntpd - $ sudo systemctl enable ntpd - $ sudo systemctl status ntpd - $ sudo ntpq -p - -Go back to :ref:`Setting Up Your Hosts` - - -Disabling the Linux UI ----------------------------------- -After installing the required packages, you must disable the Linux UI if it has been installed. - -You can disable Linux by running the following command: - - .. code-block:: postgres - - $ sudo systemctl set-default multi-user.target - -Go back to :ref:`Setting Up Your Hosts` - - -Disabling SELinux ----------------------------------- -After disabling the Linux UI you must disable SELinux. - -**To disable SELinux:** - - 1. Run the following command: - - .. code-block:: postgres - - $ sed -i -e s/enforcing/disabled/g /etc/selinux/config - $ sudo reboot - - 2. Reboot the system as a root user: - - .. code-block:: postgres - - $ sudo reboot - -Go back to :ref:`Setting Up Your Hosts` - -Disabling Your Firewall ----------------------------------- -After disabling SELinux, you must disable your firewall by running the following commands: - - .. code-block:: postgres - - $ sudo systemctl stop firewalld - $ sudo systemctl disable firewalld - -Go back to :ref:`Setting Up Your Hosts` - - -Checking the CUDA Version ----------------------------------- -After completing all of the steps above, you must check the CUDA version. - -**To check the CUDA version:** - -1. Check the CUDA version: - - .. code-block:: postgres - - $ nvidia-smi - - The following is an example of the correct output: - - .. code-block:: postgres - - $ +-----------------------------------------------------------------------------+ - $ | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | - $ |-------------------------------+----------------------+----------------------+ - $ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - $ | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - $ |===============================+======================+======================| - $ | 0 GeForce GTX 105... Off | 00000000:01:00.0 Off | N/A | - $ | 32% 38C P0 N/A / 75W | 0MiB / 4039MiB | 0% Default | - $ +-------------------------------+----------------------+----------------------+ - $ - $ +-----------------------------------------------------------------------------+ - $ | Processes: GPU Memory | - $ | GPU PID Type Process name Usage | - $ |=============================================================================| - $ | No running processes found | - $ +-----------------------------------------------------------------------------+ - -In the above output, the CUDA version is **10.1**. - -If the above output is not generated, CUDA has not been installed. To install CUDA, see `Installing the CUDA driver `_. - - -Go back to :ref:`Setting Up Your Hosts` - -.. _install_kubernetes_cluster: - -Installing Your Kubernetes Cluster -=================================== -After setting up your hosts, you must install your Kubernetes cluster. The Kubernetes and SQream software must be installed from the management host, and can be installed on any server in the cluster. - -Installing your Kubernetes cluster requires the following: - -.. contents:: - :local: - :depth: 1 - -Generating and Sharing SSH Keypairs Across All Existing Nodes ------------------------------------- -You can generate and share SSH keypairs across all existing nodes. Sharing SSH keypairs across all nodes enables passwordless access from the management server to all nodes in the cluster. All nodes in the cluster require passwordless access. - -.. note:: You must generate and share an SSH keypair across all nodes even if you are installing the Kubernetes cluster on a single host. - -**To generate and share an SSH keypair:** - -1. Switch to root user access: - - .. code-block:: postgres - - $ sudo su - - -2. Generate an RSA key pair: - - .. code-block:: postgres - - $ ssh-keygen - -The following is an example of the correct output: - - .. code-block:: postgres - - $ ssh-keygen - $ Generating public/private rsa key pair. - $ Enter file in which to save the key (/root/.ssh/id_rsa): - $ Created directory '/root/.ssh'. - $ Enter passphrase (empty for no passphrase): - $ Enter same passphrase again: - $ Your identification has been saved in /root/.ssh/id_rsa. - $ Your public key has been saved in /root/.ssh/id_rsa.pub. - $ The key fingerprint is: - $ SHA256:xxxxxxxxxxxxxxdsdsdffggtt66gfgfg root@localhost.localdomain - $ The key's randomart image is: - $ +---[RSA 2048]----+ - $ | =*. | - $ | .o | - $ | ..o o| - $ | . .oo +.| - $ | = S =...o o| - $ | B + *..o+.| - $ | o * *..o .+| - $ | o * oo.E.o| - $ | . ..+..B.+o| - $ +----[SHA256]-----+ - -The generated file is ``/root/.ssh/id_rsa.pub``. - -3. Copy the public key to all servers in the cluster, including the one that you are running on. - - .. code-block:: postgres - - $ ssh-copy-id -i ~/.ssh/id_rsa.pub root@remote-host - -4. Replace the ``remote host`` with your host IP address. - -Go back to :ref:`Installing Your Kubernetes Cluster` - -Installing and Deploying a Kubernetes Cluster Using Kubespray ------------------------------------- -SQream uses the Kubespray software package to install and deploy Kubernetes clusters. - -**To install and deploy a Kubernetes cluster using Kubespray:** - - -1. Clone Kubernetes: - - 1. Clone the **kubespray.git** repository: - - .. code-block:: postgres - - $ git clone https://github.com/kubernetes-incubator/kubespray.git - - 2. Nagivate to the **kubespray** directory: - - .. code-block:: postgres - - $ cd kubespray - - 3. Install the **requirements.txt** configuration file: - - .. code-block:: postgres - - $ pip3 install -r requirements.txt - -2. Create your SQream inventory directory: - - 1. Run the following command: - - .. code-block:: postgres - - $ cp -rp inventory/sample inventory/sqream - - 2. Replace the **** with the defined cluster node IP address(es). - - .. code-block:: postgres - - $ declare -a IPS=(, ) - - For example, the following replaces ``192.168.0.93`` with ``192.168.0.92``: - - .. code-block:: postgres - - $ declare -a IPS=(host-93,192.168.0.93 host-92,192.168.0.92) - -Note the following: - * Running a declare requires defining a pair (host name and cluster node IP address), as shown in the above example. - * You can define more than one pair. - -3. When the reboot is complete, switch back to the root user: - - .. code-block:: postgres - - $ sudo su - - -4. Navigate to **root/kubespray**: - - .. code-block:: postgres - - $ cd /root/kubespray - -5. Copy ``inventory/sample`` as ``inventory/sqream``: - - .. code-block:: postgres - - $ cp -rfp inventory/sample inventory/sqream - -6. Update the Ansible inventory file with the inventory builder: - - .. code-block:: postgres - - $ declare -a IPS=(, , ,) - -7. In the **kubespray hosts.yml** file, set the node IP's: - - .. code-block:: postgres - - $ CONFIG_FILE=inventory/sqream/hosts.yml python3 contrib/inventory_builder/inventory.py ${IPS[@]} - - If you do not set a specific hostname in declare, the server hostnames will change to ``node1``, ``node2``, etc. To maintain specific hostnames, run declare as in the following example: - - .. code-block:: postgres - - $ declare -a IPS=(eks-rhl-1,192.168.5.81 eks-rhl-2,192.168.5.82 eks-rhl-3,192.168.5.83) - - Note that the declare must contain pairs (hostname,ip). - -:: - -8. Verify that the following have been done: - - * That the **hosts.yml** file is configured correctly. - * That all children are included with their relevant nodes. - -You can save your current server hostname by replacing with your server hostname. - -9. Generate the content output of the **hosts.yml** file. Make sure to include the file's directory: - - .. code-block:: postgres - - $ cat inventory/sqream/hosts.yml - -The hostname can be lowercase and contain ``-`` or ``.`` only, and must be aligned with the server's hostname. - -The following is an example of the correct output. Each host and IP address that you provided in Step 2 should be displayed once: - - .. code-block:: postgres - - $ all: - $ hosts: - $ node1: - $ ansible_host: 192.168.5.81 - $ ip: 192.168.5.81 - $ access_ip: 192.168.5.81 - $ node2: - $ ansible_host: 192.168.5.82 - $ ip: 192.168.5.82 - $ access_ip: 192.168.5.82 - $ node3: - $ ansible_host: 192.168.5.83 - $ ip: 192.168.5.83 - $ access_ip: 192.168.5.83 - $ children: - $ kube-master: - $ hosts: - $ node1: - $ node2: - $ node3: - $ kube-node: - $ hosts: - $ node1: - $ node2: - $ node3: - $ etcd: - $ hosts: - $ node1: - $ node2: - $ node3: - $ k8s-cluster: - $ children: - $ kube-master: - $ kube-node: - $ calico-rr: - $ hosts: {} - -Go back to :ref:`Installing Your Kubernetes Cluster` - -Adjusting Kubespray Deployment Values -------------------------------------- -After downloading and configuring Kubespray, you can adjust your Kubespray deployment values. A script is used to modify how the Kubernetes cluster is deployed, and you must set the cluster name variable before running this script. - -.. note:: The script must be run from the **kubespray** folder. - -**To adjust Kubespray deployment values:** - -1. Add the following export to the local user’s **~/.bashrc** file by replacing the with the user's Virtual IP address: - - .. code-block:: postgres - - $ export VIP_IP= - -2. Logout, log back in, and verify the following: - - .. code-block:: postgres - - $ echo $VIP_IP - -3. Make the following replacements to the **kubespray.settings.sh** file: - - .. code-block:: postgres - - $ cat < kubespray_settings.sh - $ sed -i "/cluster_name: cluster.local/c \cluster_name: cluster.local.$cluster_name" inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml - $ sed -i "/dashboard_enabled/c \dashboard_enabled\: "false"" inventory/sqream/group_vars/k8s-cluster/addons.yml - $ sed -i "/kube_version/c \kube_version\: "v1.18.3"" inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml - $ sed -i "/metrics_server_enabled/c \metrics_server_enabled\: "true"" inventory/sample/group_vars/k8s-cluster/addons.yml - $ echo 'kube_apiserver_node_port_range: "3000-6000"' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml - $ echo 'kube_controller_node_monitor_grace_period: 20s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml - $ echo 'kube_controller_node_monitor_period: 2s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml - $ echo 'kube_controller_pod_eviction_timeout: 30s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml - $ echo 'kubelet_status_update_frequency: 4s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml - $ echo 'ansible ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers - $ EOF - -.. note:: In most cases, the Docker data resides on the system disk. Because Docker requires a high volume of data (images, containers, volumes, etc.), you can change the default Docker data location to prevent the system disk from running out of space. - -4. *Optional* - Change the default Docker data location: - - .. code-block:: postgres - - $ sed -i "/docker_daemon_graph/c \docker_daemon_graph\: """ inventory/sqream/group_vars/all/docker.yml - -5. Make the **kubespray_settings.sh** file executable for your user: - - .. code-block:: postgres - - $ chmod u+x kubespray_settings.sh && ./kubespray_settings.sh - -6. Run the following script: - - .. code-block:: postgres - - $ ./kubespray_settings.sh - -7. Run a playbook on the **inventory/sqream/hosts.yml cluster.yml** file: - - .. code-block:: postgres - - $ ansible-playbook -i inventory/sqream/hosts.yml cluster.yml -v - -The Kubespray installation takes approximately 10 - 15 minutes. - -The following is an example of the correct output: - - .. code-block:: postgres - - $ PLAY RECAP - $ ********************************************************************************************* - $ node-1             : ok=680  changed=133  unreachable=0    failed=0 - $ node-2             : ok=583  changed=113  unreachable=0    failed=0 - $ node-3             : ok=586  changed=115  unreachable=0    failed=0 - $ localhost          : ok=1    changed=0    unreachable=0    failed=0 - -In the event that the output is incorrect, or a failure occurred during the installation, please contact a SQream customer support representative. - -Go back to :ref:`Installing Your Kubernetes Cluster`. - -Checking Your Kubernetes Status -------------------------------- -After adjusting your Kubespray deployment values, you must check your Kubernetes status. - -**To check your Kuberetes status:** - -1. Check the status of the node: - - .. code-block:: postgres - - $ kubectl get nodes - -The following is an example of the correct output: - - .. code-block:: postgres - - $ NAME STATUS ROLES AGE VERSION - $ eks-rhl-1 Ready control-plane,master 29m v1.21.1 - $ eks-rhl-2 Ready control-plane,master 29m v1.21.1 - $ eks-rhl-3 Ready 28m v1.21.1 - -2. Check the status of the pod: - - .. code-block:: postgres - - $ kubectl get pods --all-namespaces - - The following is an example of the correct output: - - .. code-block:: postgres - - $ NAMESPACE NAME READY STATUS RESTARTS AGE - $ kube-system calico-kube-controllers-68dc8bf4d5-n9pbp 1/1 Running 0 160m - $ kube-system calico-node-26cn9 1/1 Running 1 160m - $ kube-system calico-node-kjsgw 1/1 Running 1 160m - $ kube-system calico-node-vqvc5 1/1 Running 1 160m - $ kube-system coredns-58687784f9-54xsp 1/1 Running 0 160m - $ kube-system coredns-58687784f9-g94xb 1/1 Running 0 159m - $ kube-system dns-autoscaler-79599df498-hlw8k 1/1 Running 0 159m - $ kube-system kube-apiserver-k8s-host-1-134 1/1 Running 0 162m - $ kube-system kube-apiserver-k8s-host-194 1/1 Running 0 161m - $ kube-system kube-apiserver-k8s-host-68 1/1 Running 0 161m - $ kube-system kube-controller-manager-k8s-host-1-134 1/1 Running 0 162m - $ kube-system kube-controller-manager-k8s-host-194 1/1 Running 0 161m - $ kube-system kube-controller-manager-k8s-host-68 1/1 Running 0 161m - $ kube-system kube-proxy-5f42q 1/1 Running 0 161m - $ kube-system kube-proxy-bbwvk 1/1 Running 0 161m - $ kube-system kube-proxy-fgcfb 1/1 Running 0 161m - $ kube-system kube-scheduler-k8s-host-1-134 1/1 Running 0 161m - $ kube-system kube-scheduler-k8s-host-194 1/1 Running 0 161m - -Go back to :ref:`Installing Your Kubernetes Cluster` - -Adding a SQream Label to Your Kubernetes Cluster Nodes -------------------------------------------------- -After checking your Kubernetes status, you must add a SQream label on your Kubernetes cluster nodes. - -**To add a SQream label on your Kubernetes cluster nodes:** - -1. Get the cluster node list: - - .. code-block:: postgres - - $ kubectl get nodes - - The following is an example of the correct output: - - .. code-block:: postgres - - $ NAME        STATUS   ROLES    AGE   VERSION - $ eks-rhl-1 Ready control-plane,master 29m v1.21.1 - $ eks-rhl-2 Ready control-plane,master 29m v1.21.1 - $ eks-rhl-3 Ready 28m v1.21.1 - -2. Set the node label, change the ``node-name`` to the node NAME(s) in the above example: - - .. code-block:: postgres - - $ kubectl label nodes cluster=sqream - - The following is an example of the correct output: - - .. code-block:: postgres - - $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-1 cluster=sqream - $ node/eks-rhl-1 labeled - $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-2 cluster=sqream - $ node/eks-rhl-2 labeled - $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-3 cluster=sqream - $ node/eks-rhl-3 labeled - -Go back to :ref:`Installing Your Kubernetes Cluster` - -Copying Your Kubernetes Configuration API File to the Master Cluster Nodes -------------------------------------------------- -After adding a SQream label on your Kubernetes cluster nodes, you must copy your Kubernetes configuration API file to your Master cluster nodes. - -When the Kubernetes cluster installation is complete, an API configuration file is automatically created in the **.kube** folder of the root user. This file enables the **kubectl** command access Kubernetes' internal API service. Following this step lets you run **kubectl** commands from any node in the cluster. - - -.. warning:: You must perform this on the management server only! - -**To copy your Kubernetes configuration API file to your Master cluster nodes:** - -1. Create the **.kube** folder in the **local user** directory: - - .. code-block:: postgres - - $ mkdir /home//.kube - -2. Copy the configuration file from the root user directory to the directory: - - .. code-block:: postgres - - $ sudo cp /root/.kube/config /home//.kube - -3. Change the file owner from **root user** to the : - - .. code-block:: postgres - - $ sudo chown . /home//.kube/config - -4. Create the **.kube** folder in the other nodes located in the directory: - - .. code-block:: postgres - - $ ssh @ mkdir .kube - -5. Copy the configuration file from the management node to the other nodes: - - .. code-block:: postgres - - $ scp /home//.kube/config @:/home//.kube/ - -6. Under local user on each server you copied **.kube** to, run the following command: - - .. code-block:: postgres - - $ sudo usermod -aG docker $USER - -This grants the local user the necessary permissions to run Docker commands. - -Go back to :ref:`Installing Your Kubernetes Cluster` - -Creating an env_file in Your Home Directory -------------------------------------------------- -After copying your Kubernetes configuration API file to your Master cluster nodes, you must create an **env_file** in your home directory, and must set the VIP address as a variable. - -.. warning:: You must perform this on the management server only! - - - -**To create an env_file for local users in the user's home directory:** - -1. Set a variable that includes the VIP IP address: - - .. code-block:: postgres - - $ export VIP_IP= - -.. note:: If you use Kerberos, replace the ``KRB5_SERVER`` value with the IP address of your Kerberos server. - -2. Do one of the following: - - * For local users: - - .. code-block:: postgres - - $ mkdir /home/$USER/.sqream - -3. Make the following replacements to the **kubespray.settings.sh** file, verifying that the ``KRB5_SERVER`` parameter is set to your server IP: - - - .. code-block:: postgres - - $ cat < /home/$USER/.sqream/env_file - SQREAM_K8S_VIP=$VIP_IP - SQREAM_ADMIN_UI_PORT=8080 - SQREAM_DASHBOARD_DATA_COLLECTOR_PORT=8100 - SQREAM_DATABASE_NAME=master - SQREAM_K8S_ADMIN_UI=sqream-admin-ui - SQREAM_K8S_DASHBOARD_DATA_COLLECTOR=dashboard-data-collector - SQREAM_K8S_METADATA=sqream-metadata - SQREAM_K8S_NAMESPACE=sqream - SQREAM_K8S_PICKER=sqream-picker - SQREAM_K8S_PROMETHEUS=prometheus - SQREAM_K8S_REGISTRY_PORT=6000 - SQREAM_METADATA_PORT=3105 - SQREAM_PICKER_PORT=3108 - SQREAM_PROMETHEUS_PORT=9090 - SQREAM_SPOOL_MEMORY_RATIO=0.25 - SQREAM_WORKER_0_PORT=5000 - KRB5CCNAME=FILE:/tmp/tgt - KRB5_SERVER=kdc.sq.com:1 - KRB5_CONFIG_DIR=${ $ SQREAM_MOUNT_DIR}/krb5 - KRB5_CONFIG_FILE=${KRB5_CONFIG_DIR}/krb5.conf - HADOOP_CONFIG_DIR=${ $ SQREAM_MOUNT_DIR}/hadoop - HADOOP_CORE_XML=${HADOOP_CONFIG_DIR}/core-site.xml - HADOOP_HDFS_XML=${HADOOP_CONFIG_DIR}/hdfs-site.xml - EOF - -Go back to :ref:`Installing Your Kubernetes Cluster` - - - - - -Creating a Base Kubernetes Namespace ------------------------------------- -After creating an env_file in the user's home directory, you must create a base Kubernetes namespace. - -You can create a Kubernetes namespace by running the following command: - -.. code-block:: postgres - - $ kubectl create namespace sqream-init - -The following is an example of the correct output: - -.. code-block:: postgres - - $ namespace/sqream-init created - -Go back to :ref:`Installing Your Kubernetes Cluster` - - -Pushing the **env_file** File to the Kubernetes Configmap --------------------------------------- -After creating a base Kubernetes namespace, you must push the **env_file** to the Kubernetes configmap. You must push the **env_file** file to the Kubernetes **configmap** in the **sqream-init** namespace. - -This is done by running the following command: - -.. code-block:: postgres - - $ kubectl create configmap sqream-init -n sqream-init --from-env-file=/home/$USER/.sqream/env_file - -The following is an example of the correct output: - -.. code-block:: postgres - - $ configmap/sqream-init created - - -Go back to :ref:`Installing Your Kubernetes Cluster` - - -Installing the NVIDIA Docker2 Toolkit -------------------------------------- -After pushing the **env_file** file to the Kubernetes configmap, you must install the NVIDIA Docker2 Toolkit. The **NVIDIA Docker2 Toolkit** lets users build and run GPU-accelerated Docker containers, and must be run only on GPU servers. The NVIDIA Docker2 Toolkit includes a container runtime library and utilities that automatically configure containers to leverage NVIDIA GPUs. - - -Installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on CentOS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**To install the NVIDIA Docker2 Toolkit on an x86_64 bit processor on CentOS:** - -1. Add the repository for your distribution: - - .. code-block:: postgres - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ - $ sudo tee /etc/yum.repos.d/nvidia-docker.repo - -2. Install the **nvidia-docker2** package and reload the Docker daemon configuration: - - .. code-block:: postgres - - $ sudo yum install nvidia-docker2 - $ sudo pkill -SIGHUP dockerd - -3. Verify that the **nvidia-docker2** package has been installed correctly: - - .. code-block:: postgres - - $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi - - The following is an example of the correct output: - - .. code-block:: postgres - - $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi - $ Unable to find image 'nvidia/cuda:10.1-base' locally - $ 10.1-base: Pulling from nvidia/cuda - $ d519e2592276: Pull complete - $ d22d2dfcfa9c: Pull complete - $ b3afe92c540b: Pull complete - $ 13a10df09dc1: Pull complete - $ 4f0bc36a7e1d: Pull complete - $ cd710321007d: Pull complete - $ Digest: sha256:635629544b2a2be3781246fdddc55cc1a7d8b352e2ef205ba6122b8404a52123 - $ Status: Downloaded newer image for nvidia/cuda:10.1-base - $ Sun Feb 14 13:27:58 2021 - $ +-----------------------------------------------------------------------------+ - $ | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | - $ |-------------------------------+----------------------+----------------------+ - $ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - $ | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - $ |===============================+======================+======================| - $ | 0 GeForce GTX 105... Off | 00000000:01:00.0 Off | N/A | - $ | 32% 37C P0 N/A / 75W | 0MiB / 4039MiB | 0% Default | - $ +-------------------------------+----------------------+----------------------+ - $ - $ +-----------------------------------------------------------------------------+ - $ | Processes: GPU Memory | - $ | GPU PID Type Process name Usage | - $ |=============================================================================| - $ | No running processes found | - $ +-----------------------------------------------------------------------------+ - -For more information on installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on CentOS, see `NVIDIA Docker Installation - CentOS distributions `_ - -Installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on Ubuntu -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**To install the NVIDIA Docker2 Toolkit on an x86_64 bit processor on Ubuntu:** - -1. Add the repository for your distribution: - - .. code-block:: postgres - - $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \ - $ sudo apt-key add - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \ - $ sudo tee /etc/apt/sources.list.d/nvidia-docker.list - $ sudo apt-get update - -2. Install the **nvidia-docker2** package and reload the Docker daemon configuration: - - .. code-block:: postgres - - $ sudo apt-get install nvidia-docker2 - $ sudo pkill -SIGHUP dockerd - -3. Verify that the nvidia-docker2 package has been installed correctly: - - .. code-block:: postgres - - $ docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi - -For more information on installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on Ubuntu, see `NVIDIA Docker Installation - Ubuntu distributions `_ - -Go back to :ref:`Installing Your Kubernetes Cluster` - -Modifying the Docker Daemon JSON File for GPU and Compute Nodes -------------------------------------- -After installing the NVIDIA Docker2 toolkit, you must modify the Docker daemon JSON file for GPU and Compute nodes. - -Modifying the Docker Daemon JSON File for GPU Nodes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -**To modify the Docker daemon JSON file for GPU nodes:** - -1. Enable GPU and set HTTP access to the local Kubernetes Docker registry. - -.. note:: The Docker daemon JSON file must be modified on all GPU nodes. - -.. note:: Contact your IT department for a virtual IP. - -2. Replace the ``VIP address`` with your assigned VIP address. - -:: - -3. Connect as a root user: - - .. code-block:: postgres - - $ sudo -i - -4. Set a variable that includes the VIP address: - - .. code-block:: postgres - - $ export VIP_IP= - -5. Replace the with the VIP address:  - - .. code-block:: postgres - - $ cat < /etc/docker/daemon.json - $ { - $ "insecure-registries": ["$VIP_IP:6000"], - $ "default-runtime": "nvidia", - $ "runtimes": { - $ "nvidia": { - $ "path": "nvidia-container-runtime", - $ "runtimeArgs": [] - $ } - $ } - $ } - $ EOF - -6. Apply the changes and restart Docker: - - .. code-block:: postgres - - $ systemctl daemon-reload && systemctl restart docker - -7. Exit the root user: - - .. code-block:: postgres - - $ exit - -Go back to :ref:`Installing Your Kubernetes Cluster` - - -Modifying the Docker Daemon JSON File for Compute Nodes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You must follow this procedure only if you have a Compute node. - -**To modify the Docker daemon JSON file for Compute nodes:** - -1. Switch to a root user: - - .. code-block:: postgres - - $ sudo -i - -2. Set a variable that includes a VIP address. - -.. note:: Contact your IT department for a virtual IP. - -3. Replace the ``VIP address`` with your assigned VIP address. - - .. code-block:: postgres - - $ cat < /etc/docker/daemon.json - $ { - $ "insecure-registries": ["$VIP_IP:6000"] - $ } - $ EOF - -4. Restart the services: - - .. code-block:: postgres - - $ systemctl daemon-reload && systemctl restart docker - -5. Exit the root user: - - - .. code-block:: postgres - - $ exit - -Go back to :ref:`Installing Your Kubernetes Cluster` - -Installing the Nvidia-device-plugin Daemonset ----------------------------------------------- -After modifying the Docker daemon JSON file for GPU or Compute Nodes, you must installing the Nvidia-device-plugin daemonset. The Nvidia-device-plugin daemonset is only relevant to GPU nodes. - -**To install the Nvidia-device-plugin daemonset:** - -1. Set ``nvidia.com/gpu`` to ``true`` on all GPU nodes: - -.. code-block:: postgres - - $ kubectl label nodes nvidia.com/gpu=true - -2. Replace the ** with your GPU node name: - - For a complete list of GPU node names, run the ``kubectl get nodes`` command. - - The following is an example of the correct output: - - .. code-block:: postgres - - $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-1 nvidia.com/gpu=true - $ node/eks-rhl-1 labeled - $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-2 nvidia.com/gpu=true - $ node/eks-rhl-2 labeled - $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-3 nvidia.com/gpu=true - $ node/eks-rhl-3 labeled - -Go back to :ref:`Installing Your Kubernetes Cluster` - -Creating an Nvidia Device Plugin ----------------------------------------------- -After installing the Nvidia-device-plugin daemonset, you must create an Nvidia-device-plugin. You can create an Nvidia-device-plugin by running the following command - -.. code-block:: postgres - - $ kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/1.0.0-beta6/nvidia-device-plugin.yml - -If needed, you can check the status of the Nvidia-device-plugin-daemonset pod status: - -.. code-block:: postgres - - $ kubectl get pods -n kube-system -o wide | grep nvidia-device-plugin - -The following is an example of the correct output: - -.. code-block:: postgres - - $ NAME READY STATUS RESTARTS AGE - $ nvidia-device-plugin-daemonset-fxfct 1/1 Running 0 6h1m - $ nvidia-device-plugin-daemonset-jdvxs 1/1 Running 0 6h1m - $ nvidia-device-plugin-daemonset-xpmsv 1/1 Running 0 6h1m - -Go back to :ref:`Installing Your Kubernetes Cluster` - -Checking GPU Resources Allocatable to GPU Nodes -------------------------------------- -After creating an Nvidia Device Plugin, you must check the GPU resources alloctable to the GPU nodes. Each GPU node has records, such as ``nvidia.com/gpu: <#>``. The ``#`` indicates the number of allocatable, or available, GPUs in each node. - -You can output a description of allocatable resources by running the following command: - -.. code-block:: postgres - - $ kubectl describe node | grep -i -A 7 -B 2 allocatable: - -The following is an example of the correct output: - -.. code-block:: postgres - - $ Allocatable: - $ cpu: 3800m - $ ephemeral-storage: 94999346224 - $ hugepages-1Gi: 0 - $ hugepages-2Mi: 0 - $ memory: 15605496Ki - $ nvidia.com/gpu: 1 - $ pods: 110 - -Go back to :ref:`Installing Your Kubernetes Cluster` - -Preparing the WatchDog Monitor ------------------------------- -SQream's deployment includes installing two watchdog services. These services monitor Kuberenetes management and the server's storage network. - -You can enable the storage watchdogs by adding entries in the **/etc/hosts** file on each server: - -.. code-block:: postgres - - $
k8s-node1.storage - $
k8s-node2.storage - $
k8s-node3.storage - -The following is an example of the correct syntax: - -.. code-block:: postgres - - $ 10.0.0.1 k8s-node1.storage - $ 10.0.0.2 k8s-node2.storage - $ 10.0.0.3 k8s-node3.storage - -Go back to :ref:`Installing Your Kubernetes Cluster` - -.. _installing_sqream_software: - -Installing the SQream Software -================================= -Once you've prepared the SQream environment for launching it using Kubernetes, you can begin installing the SQream software. - -The **Installing the SQream Software** section describes the following: - -.. contents:: - :local: - :depth: 1 - - -.. _getting_sqream_package: - -Getting the SQream Package --------------------------------- -The first step in installing the SQream software is getting the SQream package. Please contact the SQream Support team to get the **sqream_k8s-nnn-DBnnn-COnnn-SDnnn-.tar.gz** tarball file. - -This file includes the following values: - -* **sqream_k8s-** - the SQream installer version. -* **DB** - the SQreamDB version. -* **CO** - the SQream console version. -* **SD** - the SQream Acceleration Studio version. -* **arch** - the server architecture. - -You can extract the contents of the tarball by running the following command: - -.. code-block:: postgres - - $ tar -xvf sqream_k8s-1.0.15-DB2020.1.0.2-SD0.7.3-x86_64.tar.gz - $ cd sqream_k8s-1.0.15-DB2020.1.0.2-SD0.7.3-x86_64 - $ ls - -Extracting the contents of the tarball file generates a new folder with the same name as the tarball file. - -The following shows the output of the extracted file: - -.. code-block:: postgres - - drwxrwxr-x. 2 sqream sqream 22 Jan 27 11:39 license - lrwxrwxrwx. 1 sqream sqream 49 Jan 27 11:39 sqream -> .sqream/sqream-sql-v2020.3.1_stable.x86_64/sqream - -rwxrwxr-x. 1 sqream sqream 9465 Jan 27 11:39 sqream-install - -rwxrwxr-x. 1 sqream sqream 12444 Jan 27 11:39 sqream-start - -Go back to :ref:`Installing Your SQream Software` - -Setting Up and Configuring Hadoop --------------------------------- -After getting the SQream package, you can set up and configure Hadoop by configuring the **keytab** and **krb5.conf** files. - -.. note:: You only need to configure the **keytab** and **krb5.conf** files if you use Hadoop with Kerberos authentication. - - -**To set up and configure Hadoop:** - -1. Contact IT for the **keytab** and **krb5.conf** files. - -:: - -2. Copy both files into the respective empty **.hadoop/** and **.krb5/** directories: - -.. code-block:: postgres - - $ cp hdfs.keytab krb5.conf .krb5/ - $ cp core-site.xml hdfs-site.xml .hadoop/ - -The SQream installer automatically copies the above files during the installation process. - -Go back to :ref:`Installing Your SQream Software` - -Starting a Local Docker Image Registry --------------------------------- -After getting the SQream package, or (optionally) setting up and configuring Hadoop, you must start a local Docker image registry. Because Kubernetes is based on Docker, you must start the local Docker image registry on the host's shared folder. This allows all hosts to pull the SQream Docker images. - -**To start a local Docker image registry:** - -1. Create a Docker registry folder: - - .. code-block:: postgres - - $ mkdir /docker-registry/ - -2. Set the ``docker_path`` for the Docker registry folder: - - .. code-block:: postgres - - $ export docker_path= - -3. Apply the **docker-registry** service to the cluster: - - .. code-block:: postgres - - $ cat .k8s/admin/docker_registry.yaml | envsubst | kubectl create -f - - - The following is an example of the correct output: - - .. code-block:: postgres - - namespace/sqream-docker-registry created - configmap/sqream-docker-registry-config created - deployment.apps/sqream-docker-registry created - service/sqream-docker-registry created - -4. Check the pod status of the **docker-registry** service: - - .. code-block:: postgres - - $ kubectl get pods -n sqream-docker-registry - -The following is an example of the correct output: - - .. code-block:: postgres - - NAME READY STATUS RESTARTS AGE - sqream-docker-registry-655889fc57-hmg7h 1/1 Running 0 6h40m - -Go back to :ref:`Installing Your SQream Software` - -Installing the Kubernetes Dashboard --------------------------------- -After starting a local Docker image registry, you must install the Kubernetes dashboard. The Kubernetes dashboard lets you see the Kubernetes cluster, nodes, services, and pod status. - -**To install the Kubernetes dashboard:** - -1. Apply the **k8s-dashboard** service to the cluster: - - .. code-block:: postgres - - $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml - - The following is an example of the correct output: - - .. code-block:: postgres - - namespace/kubernetes-dashboard created - serviceaccount/kubernetes-dashboard created - service/kubernetes-dashboard created - secret/kubernetes-dashboard-certs created - secret/kubernetes-dashboard-csrf created - secret/kubernetes-dashboard-key-holder created - configmap/kubernetes-dashboard-settings created - role.rbac.authorization.k8s.io/kubernetes-dashboard created - clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created - rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created - clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created - deployment.apps/kubernetes-dashboard created - service/dashboard-metrics-scraper created - deployment.apps/dashboard-metrics-scraper created - -2. Grant the user external access to the Kubernetes dashboard: - - .. code-block:: postgres - - $ cat .k8s/admin/kubernetes-dashboard-svc-metallb.yaml | envsubst | kubectl create -f - - - The following is an example of the correct output: - - .. code-block:: postgres - - service/kubernetes-dashboard-nodeport created - -3. Create the ``cluster-admin-sa.yaml`` file: - - .. code-block:: postgres - - $ kubectl create -f .k8s/admin/cluster-admin-sa.yaml - - The following is an example of the correct output: - - .. code-block:: postgres - - clusterrolebinding.rbac.authorization.k8s.io/cluster-admin-sa-cluster-admin created - -4. Check the pod status of the **K8s-dashboard** service: - - .. code-block:: postgres - - $ kubectl get pods -n kubernetes-dashboard - - The following is an example of the correct output: - - .. code-block:: postgres - - NAME READY STATUS RESTARTS AGE - dashboard-metrics-scraper-6b4884c9d5-n8p57 1/1 Running 0 4m32s - kubernetes-dashboard-7b544877d5-qc8b4 1/1 Running 0 4m32s - -5. Obtain the **k8s-dashboard** access token: - - .. code-block:: postgres - - $ kubectl -n kube-system describe secrets cluster-admin-sa-token - - The following is an example of the correct output: - - .. code-block:: postgres - - Name: cluster-admin-sa-token-rbl9p - Namespace: kube-system - Labels: - Annotations: kubernetes.io/service-account.name: cluster-admin-sa - kubernetes.io/service-account.uid: 81866d6d-8ef3-4805-840d-58618235f68d - - Type: kubernetes.io/service-account-token - - Data - ==== - ca.crt: 1025 bytes - namespace: 11 bytes - token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjRMV09qVzFabjhId09oamQzZGFFNmZBeEFzOHp3SlJOZWdtVm5lVTdtSW8ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJjbHVzdGVyLWFkbWluLXNhLXRva2VuLXJibDlwIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImNsdXN0ZXItYWRtaW4tc2EiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI4MTg2NmQ2ZC04ZWYzLTQ4MDUtODQwZC01ODYxODIzNWY2OGQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06Y2x1c3Rlci1hZG1pbi1zYSJ9.mNhp8JMr5y3hQ44QrvRDCMueyjSHSrmqZcoV00ZC7iBzNUqh3n-fB99CvC_GR15ys43jnfsz0tdsTy7VtSc9hm5ENBI-tQ_mwT1Zc7zJrEtgFiA0o_eyfYZOARdhdyFEJg84bzkIxJFPKkBWb4iPWU1Xb7RibuMCjNTarZMZbqzKYfQEcMZWJ5UmfUqp-HahZZR4BNbjSWybs7t6RWdcQZt6sO_rRCDrOeEJlqKKjx4-5jFZB8Du_0kKmnw2YJmmSCEOXrpQCyXIiZJpX08HyDDYfFp8IGzm61arB8HDA9dN_xoWvuz4Cj8klUtTzL9effJJPjHJlZXcEqQc9hE3jw - -6. Navigate to ``https://:5999``. - -:: - -7. Select the **Token** radio button, paste the token from the previous command output, and click **Sign in**. - -The Kubernetes dashboard is displayed. - -Go back to :ref:`Installing Your SQream Software` - -Installing the SQream Prometheus Package --------------------------------- -After installing the Kubernetes dashboard, you must install the SQream Prometheus package. To properly monitor the host and GPU statistics the **exporter service** must be installed on each Kubernetes cluster node. - -This section describes how to install the following: - -* **node_exporter** - collects host data, such as CPU memory usage. -* **nvidia_exporter** - collects GPU utilization data. - - -.. note:: The steps in this section must be done on **all** cluster nodes. - -To install the **sqream-prometheus** package, you must do the following: - -1. :ref:`Install the exporter service ` - -:: - -2. :ref:`Check the exporter service ` - -Go back to :ref:`Installing Your SQream Software` - - -.. _install_exporter_service: - -Installing the Exporter Service -~~~~~~~~~~~~~~~~~~~~~~~~ - -**To install the exporter service:** - -1. Create a user and group that will be used to run the exporter services: - - .. code-block:: console - - $ sudo groupadd --system prometheus && sudo useradd -s /sbin/nologin --system -g prometheus prometheus - -2. Extract the **sqream_exporters_prometheus.0.1.tar.gz** file: - - .. code-block:: console - - $ cd .prometheus - $ tar -xf sqream_exporters_prometheus.0.1.tar.gz - -3. Copy the exporter software files to the **/usr/bin** directory: - - .. code-block:: console - - $ cd sqream_exporters_prometheus.0.1 - $ sudo cp node_exporter/node_exporter /usr/bin/ - $ sudo cp nvidia_exporter/nvidia_exporter /usr/bin/ - -4. Copy the exporters service file to the **/etc/systemd/system/** directory: - - .. code-block:: console - - $ sudo cp services/node_exporter.service /etc/systemd/system/ - $ sudo cp services/nvidia_exporter.service /etc/systemd/system/ - -5. Set the permission and group of the service files: - - .. code-block:: console - - $ sudo chown prometheus:prometheus /usr/bin/node_exporter - $ sudo chmod u+x /usr/bin/node_exporter - $ sudo chown prometheus:prometheus /usr/bin/nvidia_exporter - $ sudo chmod u+x /usr/bin/nvidia_exporter - -6. Reload the services: - - .. code-block:: console - - $ sudo systemctl daemon-reload - -7. Start both services and set them to start when the server is booted up: - - * Node_exporter: - - .. code-block:: console - - $ sudo systemctl start node_exporter && sudo systemctl enable node_exporter - - * Nvidia_exporter: - - .. code-block:: console - - $ sudo systemctl start nvidia_exporter && sudo systemctl enable nvidia_exporter - - - -.. _check_exporter_status: - -Checking the Exporter Status -~~~~~~~~~~~~~~~~~~~~~~~~ -After installing the **exporter** service, you must check its status. - -You can check the exporter status by running the following command: - -.. code-block:: console - - $ sudo systemctl status node_exporter && sudo systemctl status nvidia_exporter - -Go back to :ref:`Installing Your SQream Software` - - -.. _running_sqream_install_service: - -Running the Sqream-install Service -================================ -The **Running the Sqream-install Service** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Installing Your License --------------------------------- -After install the SQream Prometheus package, you must install your license. - -**To install your license:** - -1. Copy your license package to the sqream **/license** folder. - -.. note:: You do not need to untar the license package after copying it to the **/license** folder because the installer script does it automatically. - -The following flags are **mandatory** during your first run: - -.. code-block:: console - - $ sudo ./sqream-install -i -k -m - -.. note:: If you cannot run the script with **sudo**, verify that you have the right permission (**rwx** for the user) on the relevant directories (config, log, volume, and data-in directories). - -Go back to :ref:`Running the SQream_install Service`. - -Changing Your Data Ingest Folder --------------------------------- -After installing your license, you must change your data ingest folder. - -You can change your data ingest folder by running the following command: - -.. code-block:: console - - $ sudo ./sqream-install -d /media/nfs/sqream/data_in - -Go back to :ref:`Running the SQream_install Service`. - -Checking Your System Settings --------------------------------- -After changing your data ingest folder, you must check your system settings. - -The following command shows you all the variables that your SQream system is running with: - -.. code-block:: console - - $ ./sqream-install -s - -After optionally checking your system settings, you can use the **sqream-start** application to control your Kubernetes cluster. - -Go back to :ref:`Running the SQream_install Service`. - -SQream Installation Command Reference --------------------------------- -If needed, you can use the **sqream-install** flag reference for any needed flags by typing: - -.. code-block:: console - - $ ./sqream-install --help - -The following shows the **sqream--install** flag descriptions: - -.. list-table:: - :widths: 22 59 25 - :header-rows: 1 - - * - Flag - - Function - - Note - * - **-i** - - Loads all the software from the hidden **.docker** folder. - - Mandatory - * - **-k** - - Loads the license package from the **/license** directory. - - Mandatory - * - **-m** - - Sets the relative path for all SQream folders under the shared filesystem available from all nodes (sqreamdb, config, logs and data_in). No other flags are required if you use this flag (such as c, v, l or d). - - Mandatory - * - **-c** - - Sets the path where to write/read SQream configuration files from. The default is **/etc/sqream/**. - - Optional - * - **-v** - - Shows the location of the SQream cluster. ``v`` creates a cluster if none exist, and mounts it if does. - - Optional - * - **-l** - - Shows the location of the SQream system startup logs. The logs contain startup and Docker logs. The default is **/var/log/sqream/**. - - Optional - * - **-d** - - Shows the folder containing data that you want to import into or copy from SQream. - - Optional - * - **-n** - - Sets the Kubernetes namespace. The default is **sqream**. - - Optional - * - **-N** - - Deletes a specific Kubernetes namespace and sets the factory default namespace (sqream). - - Optional - * - **-f** - - Overwrite existing folders and all files located in mounted directories. - - Optional - * - **-r** - - Resets the system configuration. This flag is run without any other variables. - - Optional - * - **-s** - - Shows the system settings. - - Optional - * - **-e** - - Sets the Kubernetes cluster's virtual IP address. - - Optional - * - **-h** - - Help, shows all available flags. - - Optional - -Go back to :ref:`Running the SQream_install Service`. - -Controlling Your Kubernetes Cluster Using SQream Flags --------------------------------- -You can control your Kubernetes cluster using SQream flags. - -The following command shows you the available Kubernetes cluster control options: - -.. code-block:: console - - $ ./sqream-start -h - -The following describes the **sqream-start** flags: - -.. list-table:: - :widths: 22 59 25 - :header-rows: 1 - - * - Flag - - Function - - Note - * - **-s** - - Starts the sqream services, starting metadata, server picker, and workers. The number of workers started is based on the number of available GPU’s. - - Mandatory - * - **-p** - - Sets specific ports to the workers services. You must enter the starting port for the sqream-start application to allocate it based on the number of workers. - - - * - **-j** - - Uses an external .json configuration file. The file must be located in the **configuration** directory. - - The workers must each be started individually. - * - **-m** - - Allocates worker spool memory. - - The workers must each be started individually. - * - **-a** - - Starts the SQream Administration dashboard and specifies the listening port. - - - * - **-d** - - Deletes all running SQream services. - - - * - **-h** - - Shows all available flags. - - Help - -Go back to :ref:`Running the SQream_install Service`. - -.. _using_sqream_start_commands: - -Using the sqream-start Commands -======================= -In addition to controlling your Kubernetes cluster using SQream flags, you can control it using **sqream-start** commands. - -The **Using the sqream-start Commands** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Starting Your SQream Services ------------------------- -You can run the **sqream-start** command with the **-s** flag to start SQream services on all available GPU's: - -.. code-block:: console - - $ sudo ./sqream-start -s - -This command starts the SQream metadata, server picker, and sqream workers on all available GPU’s in the cluster. - -The following is an example of the correct output: - -.. code-block:: console - - ./sqream-start -s - Initializing network watchdogs on 3 hosts... - Network watchdogs are up and running - - Initializing 3 worker data collectors ... - Worker data collectors are up and running - - Starting Prometheus ... - Prometheus is available at 192.168.5.100:9090 - - Starting SQream master ... - SQream master is up and running - - Starting up 3 SQream workers ... - All SQream workers are up and running, SQream-DB is available at 192.168.5.100:3108 - All SQream workers are up and running, SQream-DB is available at 192.168.5.100:3108 - - -Go back to :ref:`Using the SQream-start Commands`. - -Starting Your SQream Services in Split Mode ------------------------- -Starting SQream services in split mode refers to running multiple SQream workers on a single GPU. You can do this by running the **sqream-start** command with the **-s** and **-z** flags. In addition, you can define the amount of hosts to run the multiple workers on. In the example below, the command defines to run the multiple workers on three hosts. - -**To start SQream services in split mode:** - -1. Run the following command: - -.. code-block:: console - - $ ./sqream-start -s -z 3 - -This command starts the SQream metadata, server picker, and sqream workers on a single GPU for three hosts: - -The following is an example of the correct output: - -.. code-block:: console - - Initializing network watchdogs on 3 hosts... - Network watchdogs are up and running - - Initializing 3 worker data collectors ... - Worker data collectors are up and running - - Starting Prometheus ... - Prometheus is available at 192.168.5.101:9090 - - Starting SQream master ... - SQream master is up and running - - Starting up 9 SQream workers over <#> available GPUs ... - All SQream workers are up and running, SQream-DB is available at 192.168.5.101:3108 - -2. Verify all pods are properly running in k8s cluster (**STATUS** column): - -.. code-block:: console - - kubectl -n sqream get pods - - NAME READY STATUS RESTARTS AGE - prometheus-bcf877867-kxhld 1/1 Running 0 106s - sqream-metadata-fbcbc989f-6zlkx 1/1 Running 0 103s - sqream-picker-64b8c57ff5-ndfr9 1/1 Running 2 102s - sqream-split-workers-0-1-2-6bdbfbbb86-ml7kn 1/1 Running 0 57s - sqream-split-workers-3-4-5-5cb49d49d7-596n4 1/1 Running 0 57s - sqream-split-workers-6-7-8-6d598f4b68-2n9z5 1/1 Running 0 56s - sqream-workers-start-xj75g 1/1 Running 0 58s - watchdog-network-management-6dnfh 1/1 Running 0 115s - watchdog-network-management-tfd46 1/1 Running 0 115s - watchdog-network-management-xct4d 1/1 Running 0 115s - watchdog-network-storage-lr6v4 1/1 Running 0 116s - watchdog-network-storage-s29h7 1/1 Running 0 116s - watchdog-network-storage-sx9mw 1/1 Running 0 116s - worker-data-collector-62rxs 0/1 Init:0/1 0 54s - worker-data-collector-n8jsv 0/1 Init:0/1 0 55s - worker-data-collector-zp8vf 0/1 Init:0/1 0 54s - -Go back to :ref:`Using the SQream-start Commands`. - -Starting the Sqream Studio UI --------------------------------- -You can run the following command the to start the SQream Studio UI (Editor and Dashboard): - -.. code-block:: console - - $ ./sqream-start -a - -The following is an example of the correct output: - -.. code-block:: console - - $ ./sqream-start -a - Please enter USERNAME: - sqream - Please enter PASSWORD: - ****** - Please enter port value or press ENTER to keep 8080: - - Starting up SQream Admin UI... - SQream admin ui is available at 192.168.5.100:8080 - -Go back to :ref:`Using the SQream-start Commands`. - -Stopping the SQream Services --------------------------------- -You can run the following command to stop all SQream services: - -.. code-block:: console - - $ ./sqream-start -d - -The following is an example of the correct output: - -.. code-block:: console - - $ ./sqream-start -d - $ Cleaning all SQream services in sqream namespace ... - $ All SQream service removed from sqream namespace - -Go back to :ref:`Using the SQream-start Commands`. - -Advanced sqream-start Commands --------------------------------- -Controlling Your SQream Spool Size -~~~~~~~~~~~~~~~~~~~~~~~~ -If you do not specify the SQream spool size, the console automatically distributes the available RAM between all running workers. - -You can define a specific spool size by running the following command: - -.. code-block:: console - - $ ./sqream-start -s -m 4 - -Using a Custom .json File -~~~~~~~~~~~~~~~~~~~~~~~~ -You have the option of using your own .json file for your own custom configurations. Your .json file must be placed within the path mounted in the installation. SQream recommends placing your .json file in the **configuration** folder. - -The SQream console does not validate the integrity of external .json files. - -You can use the following command (using the ``j`` flag) to set the full path of your .json file to the configuration file: - -.. code-block:: console - - $ ./sqream-start -s -f .json - -This command starts one worker with an external configuration file. - -.. note:: The configuration file must be available in the shared configuration folder. - - -Checking the Status of the SQream Services -~~~~~~~~~~~~~~~~~~~~~~~~ -You can show all running SQream services by running the following command: - -.. code-block:: console - - $ kubectl get pods -n -o wide - -This command shows all running services in the cluster and which nodes they are running in. - -Go back to :ref:`Using the SQream-start Commands`. - -Upgrading Your SQream Version -================================ -The **Upgrading Your SQream Version** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Before Upgrading Your System ----------------------------- -Before upgrading your system you must do the following: - -1. Contact SQream support for a new SQream package tarball file. - -:: - -2. Set a maintenance window. - - -.. note:: You must stop the system while upgrading it. - - -Upgrading Your System ----------------------------- -After completing the steps in **Before Upgrading Your System** above, you can upgrade your system. - -**To upgrade your system:** - -1. Extract the contents of the tarball file that you received from SQream support. Make sure to extract the contents to the same directory as in :ref:`getting_sqream_package` and for the same user: - - .. code-block:: console - - $ tar -xvf sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ - $ cd sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ - -2. Start the upgrade process run the following command: - - .. code-block:: console - - $ ./sqream-install -i - -The upgrade process checks if the SQream services are running and will prompt you to stop them. - -3. Do one of the following: - - * Stop the upgrade by writing ``No``. - * Continue the upgrade by writing ``Yes``. - -If you continue upgrading, all running SQream workers (master and editor) are stopped. When all services have been stopped, the new version is loaded. - - -.. note:: SQream periodically upgrades its metadata structure. If an upgrade version includes an upgraded metadata service, an approval request message is displayed. This approval is required to finish the upgrade process. Because SQream supports only specific metadata versions, all SQream services must be upgraded at the same time. - - -4. When SQream has successfully upgraded, load the SQream console and restart your services. - -For questions, contact SQream Support. diff --git a/guides/operations/launching_sqream_with_monit.rst b/guides/operations/launching_sqream_with_monit.rst deleted file mode 100644 index 7a26d5c91..000000000 --- a/guides/operations/launching_sqream_with_monit.rst +++ /dev/null @@ -1,290 +0,0 @@ -.. _launching_sqream_with_monit: - -********************************************* -Launching SQream with Monit -********************************************* -This procedure describes how to launch SQream using Monit. - -Launching SQream -==================================== - -After doing the following, you can launch SQream according to the instructions on this page. - - - -1. :ref:`Installing Monit ` -2. :ref:`Installing SQream with Binary ` - - - - -The following is an example of a working monitrc file configured to monitor the ***metadataserver** and **serverpicker** commands, and **four sqreamd services**. The **monitrc** configuration file is located in the **conf/monitrc** directory. - -Note that the **monitrc** in the following example is configured for eight ``sqreamd`` services, but that only the first four are enabled: - -.. code-block:: console - - $ set daemon 5 # check services at 30 seconds intervals - $ set logfile syslog - $ - $ set httpd port 2812 and - $ use address localhost # only accept connection from localhost - $ allow localhost # allow localhost to connect to the server and - $ allow admin:monit # require user 'admin' with password 'monit' - $ - $ ##set mailserver smtp.gmail.com port 587 - $ ## using tlsv12 - $ #METADATASERVER-START - $ check process metadataserver with pidfile /var/run/metadataserver.pid - $ start program = "/usr/bin/systemctl start metadataserver" - $ stop program = "/usr/bin/systemctl stop metadataserver" - $ #METADATASERVER-END - $ # alert user@domain.com on {nonexist, timeout} - $ # with mail-format { - $ # from: Monit@$HOST - $ # subject: metadataserver $EVENT - $ACTION - $ # message: This is an automate mail, sent from monit. - $ # } - $ #SERVERPICKER-START - $ check process serverpicker with pidfile /var/run/serverpicker.pid - $ start program = "/usr/bin/systemctl start serverpicker" - $ stop program = "/usr/bin/systemctl stop serverpicker" - $ #SERVERPICKER-END - $ # alert user@domain.com on {nonexist, timeout} - $ # with mail-format { - $ # from: Monit@$HOST - $ # subject: serverpicker $EVENT - $ACTION - $ # message: This is an automate mail, sent from monit. - $ # - $ # - $ #SQREAM1-START - $ check process sqream1 with pidfile /var/run/sqream1.pid - $ start program = "/usr/bin/systemctl start sqream1" - $ stop program = "/usr/bin/systemctl stop sqream1" - $ #SQREAM1-END - $ # alert user@domain.com on {nonexist, timeout} - $ # with mail-format { - $ # from: Monit@$HOST - $ # subject: sqream1 $EVENT - $ACTION - $ # message: This is an automate mail, sent from monit. - $ # } - $ #SQREAM2-START - $ check process sqream2 with pidfile /var/run/sqream2.pid - $ start program = "/usr/bin/systemctl start sqream2" - $ #SQREAM2-END - $ # alert user@domain.com on {nonexist, timeout} - $ # with mail-format { - $ # from: Monit@$HOST - $ # subject: sqream1 $EVENT - $ACTION - $ # message: This is an automate mail, sent from monit. - $ # } - $ #SQREAM3-START - $ check process sqream3 with pidfile /var/run/sqream3.pid - $ start program = "/usr/bin/systemctl start sqream3" - $ stop program = "/usr/bin/systemctl stop sqream3" - $ #SQREAM3-END - $ # alert user@domain.com on {nonexist, timeout} - $ # with mail-format { - $ # from: Monit@$HOST - $ # subject: sqream2 $EVENT - $ACTION - $ # message: This is an automate mail, sent from monit. - $ # } - $ #SQREAM4-START - $ check process sqream4 with pidfile /var/run/sqream4.pid - $ start program = "/usr/bin/systemctl start sqream4" - $ stop program = "/usr/bin/systemctl stop sqream4" - $ #SQREAM4-END - $ # alert user@domain.com on {nonexist, timeout} - $ # with mail-format { - $ # from: Monit@$HOST - $ # subject: sqream2 $EVENT - $ACTION - $ # message: This is an automate mail, sent from monit. - $ # } - $ # - $ #SQREAM5-START - $ #check process sqream5 with pidfile /var/run/sqream5.pid - $ #start program = "/usr/bin/systemctl start sqream5" - $ #stop program = "/usr/bin/systemctl stop sqream5" - $ #SQREAM5-END - $ # alert user@domain.com on {nonexist, timeout} - $ # with mail-format { - $ # from: Monit@$HOST - $ # subject: sqream2 $EVENT - $ACTION - $ # message: This is an automate mail, sent from monit. - $ # } - $ # - $ #SQREAM6-START - $ #check process sqream6 with pidfile /var/run/sqream6.pid - $ #start program = "/usr/bin/systemctl start sqream6" - $ #stop program = "/usr/bin/systemctl stop sqream6" - $ #SQREAM6-END - $ # alert user@domain.com on {nonexist, timeout} - $ # with mail-format { - $ # from: Monit@$HOST - $ # subject: sqream2 $EVENT - $ACTION - $ # message: This is an automate mail, sent from monit. - $ # } - $ # - $ #SQREAM7-START - $ #check process sqream7 with pidfile /var/run/sqream7.pid - $ #start program = "/usr/bin/systemctl start sqream7" - $ #stop program = "/usr/bin/systemctl stop sqream7" - $ #SQREAM7-END - $ # with mail-format { - $ # from: Monit@$HOST - $ # subject: sqream2 $EVENT - $ACTION - $ # message: This is an automate mail, sent from monit. - $ # } - $ # - $ #SQREAM8-START - $ #check process sqream8 with pidfile /var/run/sqream8.pid - $ #start program = "/usr/bin/systemctl start sqream8" - $ #stop program = "/usr/bin/systemctl stop sqream8" - $ #SQREAM8-END - $ # alert user@domain.com on {nonexist, timeout} - $ # with mail-format { - $ # from: Monit@$HOST - $ # subject: sqream2 $EVENT - $ACTION - $ # message: This is an automate mail, sent from monit. - $ # } - -Monit Usage Examples -==================================== - -This section shows examples of two methods for stopping the **sqream3** service use Monit's command syntax: - - - -* :ref:`Stopping Monit and SQream separately ` -* :ref:`Stopping SQream using a Monit command ` - -.. _stopping_monit_and_sqream_separately: - -Stopping Monit and SQream Separately -------------------------------------- - -You can stop the Monit service and SQream separately as follows: - -.. code-block:: console - - $ sudo systemctl stop monit - $ sudo systemctl stop sqream3 - -You can restart Monit as follows: - -.. code-block:: console - - $ sudo systemctl start monit - -Restarting Monit automatically restarts the SQream services. - -.. _stopping_sqream_using_a_monit_command: - -Stopping SQream Using a Monit Command -------------------------------------- - -You can stop SQream using a Monit command as follows: - -.. code-block:: console - - $ sudo monit stop sqream3 - -This command stops SQream only (and not Monit). - -You can restart SQream as follows: - -.. code-block:: console - - $ sudo monit start sqream3 - -Monit Command Line Options -------------------------------------- -The **Monit Command Line Options** section describes some of the most commonly used Monit command options. - -You can show the command line options by running: - -.. code-block:: console - - $ monit --help - -.. code-block:: console - - $ start all - Start all services - $ start - Only start the named service - $ stop all - Stop all services - $ stop - Stop the named service - $ restart all - Stop and start all services - $ restart - Only restart the named service - $ monitor all - Enable monitoring of all services - $ monitor - Only enable monitoring of the named service - $ unmonitor all - Disable monitoring of all services - $ unmonitor - Only disable monitoring of the named service - $ reload - Reinitialize monit - $ status [name] - Print full status information for service(s) - $ summary [name] - Print short status information for service(s) - $ report [up|down|..] - Report state of services. See manual for options - $ quit - Kill the monit daemon process - $ validate - Check all services and start if not running - $ procmatch - Test process matching pattern - -Using Monit While Upgrading Your Version of SQream -================================================== - -While upgrading your version of SQream, you can use Monit to avoid conflicts (such as service start). This is done by pausing or stopping all running services while you manually upgrade SQream. When you finish successfully upgrading SQream, you can use Monit to restart all SQream services - -**To use Monit while upgrading your version of SQream:** - -1. Stop all actively running SQream services: - - .. code-block:: console - - $ sudo monit stop all - -2. Verify that SQream has stopped listening on ports **500X**, **510X**, and **310X**: - - .. code-block:: console - - $ sudo netstat -nltp #to make sure sqream stopped listening on 500X, 510X and 310X ports. - - The example below shows the old version ``sqream-db-v2020.2`` being replaced with the new version ``sqream-db-v2025.200``. - - .. code-block:: console - - $ cd /home/sqream - $ mkdir tempfolder - $ mv sqream-db-v2025.200.tar.gz tempfolder/ - $ tar -xf sqream-db-v2025.200.tar.gz - $ sudo mv sqream /usr/local/sqream-db-v2025.200 - $ cd /usr/local - $ sudo chown -R sqream:sqream sqream-db-v2025.200 - $ sudo rm sqream #This only should remove symlink - $ sudo ln -s sqream-db-v2025.200 sqream #this will create new symlink named "sqream" pointing to new version - $ ls -l - - The symbolic SQream link should point to the real folder: - - .. code-block:: console - - $ sqream -> sqream-db-v2025.200 - -4. Restart the SQream services: - - .. code-block:: console - - $ sudo monit start all - -5. Verify that the latest version has been installed: - - .. code-block:: console - - $ SELECT SHOW_VERSION(); - - The correct version is output. - - :: - -6. Restart the UI: - - .. code-block:: console - - $ pm2 start all diff --git a/guides/operations/monitoring.rst b/guides/operations/monitoring.rst deleted file mode 100644 index ab734a61e..000000000 --- a/guides/operations/monitoring.rst +++ /dev/null @@ -1,87 +0,0 @@ -.. _monitoring: - -*********************** -Monitoring -*********************** - -monitoring sqream: - -monitoring alerts -watching processes - -GPU temperature -nvidia-smi - Temp -Temp > 85 -GPU usage -nvidia-smi - GPU-Util -For Information only -Nice to put on graph to track system usage -Processes - sqreamd -ps aux | grep sqreamd -Alert if one or more sqreamd processes are down -Process - metadata -ps aux | grep metadata -Alert if down -Process – server picker -ps aux | grep server_picker -Alert if down -Disk Space – Storage -df -h -Alert if storage usage > 75% -Disk Space – Cluster -du -sh /SQream/sqream_cluster/sqreamdb -For Information only -Nice to put on graph to track full DB growth -Disk Space – leveldb -du -sh -/SQream/sqream_cluster/leveldb -For Information only -Nice to put on graph to track system usage -Disk Space – DB usage -du -sh -/SQream/sqream_cluster/sqreamdb/datab ases/ -For Information only -Nice to put on graph to track specific platform db growth -Server Disk Space -df -h -Alert if disk usage > 75% -Memory Consumption -free –g -Alert if Mem usage > 95% - - -monitoring a running statement -select show_node_info(statement_id); -try to explain how to actually use it (if this is even possible) - -monitoring the activity of the system - - -show_cluster_nodes - -show_conf - -backup_storage? - -show_server_status() - -stop_statement() - - -show_locks - -how do you release locks - -sqream_version - -what else? - -viewing the usage history - link to the logs - - - -.. toctree:: - :maxdepth: 2 - :caption: In this section: - :glob: - diff --git a/guides/operations/running_sqream_in_a_docker_container.rst b/guides/operations/running_sqream_in_a_docker_container.rst deleted file mode 100644 index 11aac5374..000000000 --- a/guides/operations/running_sqream_in_a_docker_container.rst +++ /dev/null @@ -1,1489 +0,0 @@ -.. _running_sqream_in_a_docker_container: - - - -*********************** -Running SQream in a Docker Container -*********************** - - -This document describes how to prepare your machine's environment for installing and running SQream in a Docker container. - -.. contents:: This page describes the following: - :depth: 2 - -Setting Up a Host -==================================== - -Operating System Requirements ------------------------------------- -SQream was tested and verified on the following versions of Linux: - - * x86 CentOS/RHEL 7.6 - 7.9 - * IBM RHEL 7.6 - -SQream recommends installing a clean OS on the host to avoid any installation issues. - -.. warning:: Docker-based installation supports only single host deployment and cannot be used on a multi-node cluster. Installing Docker on a single host you will not be able to scale it to a multi-node cluster. - - -Creating a Local User ----------------- -To run SQream in a Docker container you must create a local user. - -**To create a local user:** - -1. Add a local user: - - .. code-block:: console - - $ useradd -m -U - -2. Set the local user's password: - - .. code-block:: console - - $ passwd - -3. Add the local user to the ``wheel`` group: - - .. code-block:: console - - $ usermod -aG wheel - - You can remove the local user from the ``wheel`` group when you have completed the installation. - -4. Log out and log back in as the local user. - -Setting a Local Language ----------------- -After creating a local user you must set a local language. - -**To set a local language:** - -1. Set the local language: - - .. code-block:: console - - $ sudo localectl set-locale LANG=en_US.UTF-8 - -2. Set the time stamp (time and date) of the locale: - - .. code-block:: console - - $ sudo timedatectl set-timezone Asia/Jerusalem - -You can run the ``timedatectl list-timezones`` command to see your timezone. - -Adding the EPEL Repository ----------------- -After setting a local language you must add the EPEL repository. - -**To add the EPEL repository:** - -1. As a root user, upgrade the **epel-release-latest-7.noarch.rpm** repository: - - 1. RedHat (RHEL 7): - - .. code-block:: console - - $ sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm - - 2. CentOS 7 - - .. code-block:: console - - $ sudo yum install epel-release - -Installing the Required NTP Packages ----------------- -After adding the EPEL repository, you must install the required NTP packages. - -You can install the required NTP packages by running the following command: - -.. code-block:: console - - $ sudo yum install ntp pciutils python36 kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc - -Installing the Recommended Tools ----------------- -After installin gthe required NTP packages you must install the recommended tools. - -SQream recommends installing the following recommended tools: - -.. code-block:: console - - $ sudo yum install bash-completion.noarch vim-enhanced.x86_64 vim-common.x86_64 net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix - -Updating to the Current Version of the Operating System ----------------- -After installing the recommended tools you must update to the current version of the operating system. - -SQream recommends updating to the current version of the operating system. This is not recommended if the nvidia driver has **not been installed.** - - - -Configuring the NTP Package ----------------- -After updating to the current version of the operating system you must configure the NTP package. - -**To configure the NTP package:** - -1. Add your local servers to the NTP configuration. - - :: - -2. Configure the **ntpd** service to begin running when your machine is started: - - .. code-block:: console - - $ sudo systemctl enable ntpd - $ sudo systemctl start ntpd - $ sudo ntpq -p - -Configuring the Performance Profile ----------------- -After configuring the NTP package you must configure the performance profile. - -**To configure the performance profile:** - -1. Switch the active profile: - - .. code-block:: console - - $ sudo tuned-adm profile throughput-performance - -2. Change the multi-user's default run level: - - .. code-block:: console - - $ sudo systemctl set-default multi-user.target - -Configuring Your Security Limits ----------------- -After configuring the performance profile you must configure your security limits. Configuring your security limits refers to configuring the number of open files, processes, etc. - -**To configure your security limits:** - -1. Run the **bash** shell as a super-user: - - .. code-block:: console - - $ sudo bash - -2. Run the following command: - - .. code-block:: console - - $ echo -e "sqream soft nproc 500000\nsqream hard nproc 500000\nsqream soft nofile 500000\nsqream hard nofile 500000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf - -3. Run the following command: - - .. code-block:: console - - $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.zone_reclaim_mode = 0 \n vm.vfs_cache_pressure = 200 \n" >> /etc/sysctl.conf - -Disabling Automatic Bug-Reporting Tools ----------------- -After configuring your security limits you must disable the following automatic bug-reporting tools: - -* ccpp.service -* oops.service -* pstoreoops.service -* vmcore.service -* xorg.service - -You can abort the above but-reporting tools by running the following command: - -.. code-block:: console - - $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done - -Installing the Nvidia CUDA Driver -------------------------------------- - -1. Verify that the Tesla NVIDIA card has been installed and is detected by the system: - - .. code-block:: console - - $ lspci | grep -i nvidia - - The correct output is a list of Nvidia graphic cards. If you do not receive this output, verify that an NVIDIA GPU card has been installed. - -#. Verify that the open-source upstream Nvidia driver is running: - - .. code-block:: console - - $ lsmod | grep nouveau - - No output should be generated. - -#. If you receive any output, do the following: - - 1. Disable the open-source upstream Nvidia driver: - - .. code-block:: console - - $ sudo bash - $ echo "blacklist nouveau" > /etc/modprobe.d/blacklist-nouveau.conf - $ echo "options nouveau modeset=0" >> /etc/modprobe.d/blacklist-nouveau.conf - $ dracut --force - $ modprobe --showconfig | grep nouveau - - 2. Reboot the server and verify that the Nouveau model has not been loaded: - - .. code-block:: console - - $ lsmod | grep nouveau - -#. Check if the Nvidia CUDA driver has already been installed: - - .. code-block:: console - - $ nvidia-smi - - The following is an example of the correct output: - - .. code-block:: console - - nvidia-smi - Wed Oct 30 14:05:42 2019 - +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | - |-------------------------------+----------------------+----------------------+ - | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - |===============================+======================+======================| - | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | - | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | - | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - - +-----------------------------------------------------------------------------+ - | Processes: GPU Memory | - | GPU PID Type Process name Usage | - |=============================================================================| - | No running processes found | - +-----------------------------------------------------------------------------+ - -#. Verify that the installed CUDA version shown in the output above is ``10.1``. - - :: - - -#. Do one of the following: - - :: - - 1. If CUDA version 10.1 has already been installed, skip to Docktime Runtime (Community Edition). - :: - - 2. If CUDA version 10.1 has not been installed yet, continue with Step 7 below. - -#. Do one of the following: - - * Install :ref:`CUDA Driver version 10.1 for x86_64 `. - - :: - - * Install :ref:`CUDA driver version 10.1 for IBM Power9 `. - -.. _CUDA_10.1_x8664: - -Installing the CUDA Driver Version 10.1 for x86_64 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To install the CUDA driver version 10.1 for x86_64:** - -1. Make the following target platform selections: - - :: - - * **Operating system**: Linux - * **Architecture**: x86_64 - * **Distribution**: CentOS - * **Version**: 7 - * **Installer type**: the relevant installer type - -For installer type, SQream recommends selecting **runfile (local)**. The available selections shows only the supported platforms. - -2. Download the base installer for Linux CentOS 7 x86_64: - - .. code-block:: console - - wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm - - -3. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: - - .. code-block:: console - - $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm - $ sudo yum clean all - $ sudo yum install nvidia-driver-latest-dkms - -.. warning:: Verify that the output indicates that driver **418.87** will be installed. - -4. Follow the command line prompts. - - - :: - - -5. Enable the Nvidia service to start at boot and start it: - - .. code-block:: console - - $ sudo systemctl enable nvidia-persistenced.service && sudo systemctl start nvidia-persistenced.service - -6. Create a symbolic link from the **/etc/systemd/system/multi-user.target.wants/nvidia-persistenced.service** file to the **/usr/lib/systemd/system/nvidia-persistenced.service** file. - - :: - -7. Reboot the server. - - :: -8. Verify that the Nvidia driver has been installed and shows all available GPU's: - - .. code-block:: console - - $ nvidia-smi - - The following is the correct output: - - .. code-block:: console - - nvidia-smi - Wed Oct 30 14:05:42 2019 - +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | - |-------------------------------+----------------------+----------------------+ - | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - |===============================+======================+======================| - | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | - | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | - | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - - +-----------------------------------------------------------------------------+ - | Processes: GPU Memory | - | GPU PID Type Process name Usage | - |=============================================================================| - | No running processes found | - +-----------------------------------------------------------------------------+ - -.. _CUDA_10.1_IBMPower9: - -Installing the CUDA Driver Version 10.1 for IBM Power9 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To install the CUDA driver version 10.1 for IBM Power9:** - -1. Download the base installer for Linux CentOS 7 PPC64le: - - .. code-block:: console - - wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm - - -#. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: - - .. code-block:: console - - $ sudo rpm -i cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm - $ sudo yum clean all - $ sudo yum install nvidia-driver-latest-dkms - -.. warning:: Verify that the output indicates that driver **418.87** will be installed. - - - -3. Copy the file to the **/etc/udev/rules.d** directory. - - :: - -4. If you are using RHEL 7 version (7.6 or later), comment out, remove, or change the hot-pluggable memory rule located in file copied to the **/etc/udev/rules.d** directory by running the following command: - - .. code-block:: console - - $ sudo cp /lib/udev/rules.d/40-redhat.rules /etc/udev/rules.d - $ sudo sed -i 's/SUBSYSTEM!="memory",.*GOTO="memory_hotplug_end"/SUBSYSTEM=="*", GOTO="memory_hotplug_end"/' /etc/udev/rules.d/40-redhat.rules - -#. Enable the **nvidia-persisted.service** file: - - .. code-block:: console - - $ sudo systemctl enable nvidia-persistenced.service - -#. Create a symbolic link from the **/etc/systemd/system/multi-user.target.wants/nvidia-persistenced.service** file to the **/usr/lib/systemd/system/nvidia-persistenced.service** file. - - :: - -#. Reboot your system to initialize the above modifications. - - :: - -#. Verify that the Nvidia driver and the **nvidia-persistenced.service** files are running: - - .. code-block:: console - - $ nvidia smi - - The following is the correct output: - - .. code-block:: console - - nvidia-smi - Wed Oct 30 14:05:42 2019 - +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | - |-------------------------------+----------------------+----------------------+ - | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - |===============================+======================+======================| - | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | - | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | - | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - - +-----------------------------------------------------------------------------+ - | Processes: GPU Memory | - | GPU PID Type Process name Usage | - |=============================================================================| - | No running processes found | - +-----------------------------------------------------------------------------+ - -#. Verify that the **nvidia-persistenced** service is running: - - .. code-block:: console - - $ systemctl status nvidia-persistenced - - The following is the correct output: - - .. code-block:: console - - root@gpudb ~]systemctl status nvidia-persistenced - nvidia-persistenced.service - NVIDIA Persistence Daemon - Loaded: loaded (/usr/lib/systemd/system/nvidia-persistenced.service; enabled; vendor preset: disabled) - Active: active (running) since Tue 2019-10-15 21:43:19 KST; 11min ago - Process: 8257 ExecStart=/usr/bin/nvidia-persistenced --verbose (code=exited, status=0/SUCCESS) - Main PID: 8265 (nvidia-persiste) - Tasks: 1 - Memory: 21.0M - CGroup: /system.slice/nvidia-persistenced.service - └─8265 /usr/bin/nvidia-persistenced --verbose - -Installing the Docker Engine (Community Edition) -======================= -After installing the Nvidia CUDA driver you must install the Docker engine. - -This section describes how to install the Docker engine using the following processors: - -* :ref:`Using x86_64 processor on CentOS ` -* :ref:`Using x86_64 processor on Ubuntu ` -* :ref:`Using IBM Power9 (PPC64le) processor ` - - -.. _dockerx8664centos: - -Installing the Docker Engine Using an x86_64 Processor on CentOS ---------------------------------- -The x86_64 processor supports installing the **Docker Community Edition (CE)** versions 18.03 and higher. - -For more information on installing the Docker Engine CE on an x86_64 processor, see `Install Docker Engine on CentOS `_ - - - -.. _dockerx8664ubuntu: - -Installing the Docker Engine Using an x86_64 Processor on Ubuntu ------------------------------------------------------ - - -The x86_64 processor supports installing the **Docker Community Edition (CE)** versions 18.03 and higher. - -For more information on installing the Docker Engine CE on an x86_64 processor, see `Install Docker Engine on Ubuntu `_ - -.. _docker_ibmpower9: - -Installing the Docker Engine on an IBM Power9 Processor ----------------------------------------- -The x86_64 processor only supports installing the **Docker Community Edition (CE)** version 18.03. - - -**To install the Docker Engine on an IBM Power9 processor:** - -You can install the Docker Engine on an IBM Power9 processor by running the following command: - -.. code-block:: console - - $ wget - $ http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm - $ wget - $ http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - $ yum install -y container-selinux-2.9-4.el7.noarch.rpm - $ docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - - - -For more information on installing the Docker Engine CE on an IBM Power9 processor, see `Install Docker Engine on Ubuntu `_. - -Docker Post-Installation -================================= -After installing the Docker engine you must configure Docker on your local machine. - -**To configure Docker on your local machine:** - -1. Enable Docker to start on boot: - - .. code-block:: console - - $ sudo systemctl enable docker && sudo systemctl start docker - -2. Enable managing Docker as a non-root user: - - .. code-block:: console - - $ sudo usermod -aG docker $USER - -3. Log out and log back in via SSH. This causes Docker to re-evaluate your group membership. - - :: - -4. Verify that you can run the following Docker command as a non-root user (without ``sudo``): - - .. code-block:: console - - $ docker run hello-world - -If you can run the above Docker command as a non-root user, the following occur: - -* Docker downloads a test image and runs it in a container. -* When the container runs, it prints an informational message and exits. - -For more information on installing the Docker Post-Installation, see `Docker Post-Installation `_. - -Installing the Nvidia Docker2 ToolKit -========================================== -After configuring Docker on your local machine you must install the Nvidia Docker2 ToolKit. The NVIDIA Docker2 Toolkit lets you build and run GPU-accelerated Docker containers. The Toolkit includes a container runtime library and related utilities for automatically configuring containers to leverage NVIDIA GPU's. - -This section describes the following: - -* :ref:`Installing the NVIDIA Docker2 Toolkit on an x86_64 processor. ` -* :ref:`Installing the NVIDIA Docker2 Toolkit on a PPC64le processor. ` - -.. _install_nvidia_docker2_toolkit_x8664_processor: - -Installing the NVIDIA Docker2 Toolkit on an x86_64 Processor ----------------------------------------- - -This section describes the following: - -* :ref:`Installing the NVIDIA Docker2 Toolkit on a CentOS operating system ` - -* :ref:`Installing the NVIDIA Docker2 Toolkit on an Ubuntu operating system ` - -.. _install_nvidia_docker2_toolkit_centos: - -Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To install the NVIDIA Docker2 Toolkit on a CentOS operating system:** - -1. Install the repository for your distribution: - - .. code-block:: console - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L - $ https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ - $ sudo tee /etc/yum.repos.d/nvidia-docker.repo - -2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: - - .. code-block:: console - - $ sudo yum install nvidia-docker2 - $ sudo pkill -SIGHUP dockerd - -3. Do one of the following: - - * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 `. - * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 `. - -.. _step_4_centos: - -4. Do the following: - - 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: - - - .. code-block:: console - - https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: - [Errno -1] repomd.xml signature could not be verified for nvidia-docker - - 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. - -.. _step_5_centos: - -5. Verify that the NVIDIA-Docker run has been installed correctly: - - .. code-block:: console - - $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi - -For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on a CentOS operating system ` - - -.. _install_nvidia_docker2_toolkit_ubuntu: - -Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To install the NVIDIA Docker2 Toolkit on an Ubuntu operating system:** - -1. Install the repository for your distribution: - - .. code-block:: console - - $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \ - $ sudo apt-key add - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L - $ https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \ - $ sudo tee /etc/apt/sources.list.d/nvidia-docker.list - $ sudo apt-get update - -2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: - - .. code-block:: console - - $ sudo apt-get install nvidia-docker2 - $ sudo pkill -SIGHUP dockerd -3. Do one of the following: - * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 `. - * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 `. - - .. _step_4_ubuntu: - -4. Do the following: - - 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: - - .. code-block:: console - - https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: - [Errno -1] repomd.xml signature could not be verified for nvidia-docker - - 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. - -.. _step_5_ubuntu: - -5. Verify that the NVIDIA-Docker run has been installed correctly: - - .. code-block:: console - - $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi - -For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on an Ubuntu operating system ` - -.. _install_nvidia_docker2_toolkit_ppc64le_processor: - -Installing the NVIDIA Docker2 Toolkit on a PPC64le Processor --------------------------------------- - -This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL operating system: - -**To install the NVIDIA Docker2 Toolkit on an IBM RHEL operating system:** - -1. Import the repository and install the ``libnvidia-container`` and the ``nvidia-container-runtime`` containers. - - .. code-block:: console - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ - sudo tee /etc/yum.repos.d/nvidia-docker.repo - $ sudo yum install -y libnvidia-container* - -2. Do one of the following: - - * If you received an error when installing the containers, skip to :ref:`Step 3 `. - * If you successfully installed the containers, skip to :ref:`Step 4 `. - -.. _step_3_installing_nvidia_docker2_toolkit_ppc64le_processor: - -3. Do the following: - - 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the containers: - - .. code-block:: console - - https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: - [Errno -1] repomd.xml signature could not be verified for nvidia-docker - - 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. - - :: - - 3. Install the ``libnvidia-container`` container. - - .. code-block:: console - - $ sudo yum install -y libnvidia-container* - - .. _step_4_installing_nvidia_docker2_toolkit_ppc64le_processor: - -4. Install the ``nvidia-container-runtime`` container: - - .. code-block:: console - - $ sudo yum install -y nvidia-container-runtime* - -5. Add ``nvidia runtime`` to the Docker daemon: - - .. code-block:: console - - $ sudo mkdir -p /etc/systemd/system/docker.service.d/ - $ sudo vi /etc/systemd/system/docker.service.d/override.conf - - $ [Service] - $ ExecStart= - $ ExecStart=/usr/bin/dockerd - -6. Restart Docker: - - .. code-block:: console - - $ sudo systemctl daemon-reload - $ sudo systemctl restart docker - -7. Verify that the NVIDIA-Docker run has been installed correctly: - - .. code-block:: console - - $ docker run --runtime=nvidia --rm nvidia/cuda-ppc64le nvidia-smi - -.. _accessing_hadoop_kubernetes_configuration_files: - -Accessing the Hadoop and Kubernetes Configuration Files --------------------------------------- -The information this section is optional and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, contact your IT department for access to the following configuration files: - -* Hadoop configuration files: - - * core-site.xml - * hdfs-site.xml - - :: - -* Kubernetes files: - - * Configuration file - krb.conf - * Kubernetes Hadoop client certificate - hdfs.keytab - -Once you have the above files, you must copy them into the correct folders in your working directory. - -For more information about the correct directory to copy the above files into, see the :ref:`Installing the SQream Software ` section below. - -For related information, see the following sections: - -* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. -* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. - -.. _installing_sqream_software: - -Installing the SQream Software -============================== - -Preparing Your Local Environment -------------------------- -After installing the Nvidia Docker2 toolKit you must prepare your local environment. - -.. note:: You must install the SQream software under a *sqream* and not a *root* user. - -The Linux user preparing the local environment must have **read/write** access to the following directories for the SQream software to correctly read and write the required resources: - -* **Log directory** - default: /var/log/sqream/ -* **Configuration directory** - default: /etc/sqream/ -* **Cluster directory** - the location where SQream writes its DB system, such as */mnt/sqreamdb* -* **Ingest directory** - the location where the required data is loaded, such as */mnt/data_source/* - -.. _download_sqream_software: - -Deploying the SQream Software -------------------------- -After preparing your local environment you must deploy the SQream software. Deploying the SQream software requires you to access and extract the required files and to place them in the correct directory. - -**To deploy the SQream software:** - -1. Contact the SQream Support team for access to the **sqream_installer-nnn-DBnnn-COnnn-EDnnn-.tar.gz** file. - -The **sqream_installer-nnn-DBnnn-COnnn-EDnnn-.tar.gz** file includes the following parameter values: - -* **sqream_installer-nnn** - sqream installer version -* **DBnnn** - SQreamDB version -* **COnnn** - SQream console version -* **EDnnn** - SQream editor version -* **arch** - server arch (applicable to X86.64 and ppc64le) - -2. Extract the tarball file: - - .. code-block:: console - - $ tar -xvf sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz - -When the tarball file has been extracted, a new folder will be created. The new folder is automatically given the name of the tarball file: - - .. code-block:: console - - drwxrwxr-x 9 sqream sqream 4096 Aug 11 11:51 sqream_istaller-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64/ - -rw-rw-r-- 1 sqream sqream 3130398797 Aug 11 11:20 sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz - -3. Change the directory to the new folder that you created in the previous step. - -:: - -4. Verify that the folder you just created contains all of the required files. - - .. code-block:: console - - $ ls -la - - The following is an example of the files included in the new folder: - - .. code-block:: console - - drwxrwxr-x. 10 sqream sqream 198 Jun 3 17:57 . - drwx------. 25 sqream sqream 4096 Jun 7 18:11 .. - drwxrwxr-x. 2 sqream sqream 226 Jun 7 18:09 .docker - drwxrwxr-x. 2 sqream sqream 64 Jun 3 12:55 .hadoop - drwxrwxr-x. 2 sqream sqream 4096 May 31 14:18 .install - drwxrwxr-x. 2 sqream sqream 39 Jun 3 12:53 .krb5 - drwxrwxr-x. 2 sqream sqream 22 May 31 14:18 license - drwxrwxr-x. 2 sqream sqream 82 May 31 14:18 .sqream - -rwxrwxr-x. 1 sqream sqream 1712 May 31 14:18 sqream-console - -rwxrwxr-x. 1 sqream sqream 4608 May 31 14:18 sqream-install - -For information relevant to Hadoop users, see the following sections: - -* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. -* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. -* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. - -.. _configure_hadoop_kubernetes_configuration_files: - -Configuring the Hadoop and Kubernetes Configuration Files ------------------------------ -The information in this section is optional and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, you must copy the Hadoop and Kubernetes files into the correct folders in your working directory as shown below: - -* .hadoop/core-site.xml -* .hadoop/hdfs-site.xml -* .krb5/krb5.conf -* .krb5/hdfs.keytab - -For related information, see the following sections: - -* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. -* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. - -Configuring the SQream Software -------------------------------- -After deploying the SQream software, and optionally configuring the Hadoop and Kubernetes configuration files, you must configure the SQream software. - -Configuring the SQream software requires you to do the following: - -* Configure your local environment -* Understand the ``sqream-install`` flags -* Install your SQream license -* Validate your SQream icense -* Change your data ingest folder - -Configuring Your Local Environment -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've downloaded the SQream software, you can begin configuring your local environment. The following commands must be run (as **sudo**) from the same directory that you located your packages. - -For example, you may have saved your packages in **/home/sqream/sqream-console-package/**. - -The following table shows the flags that you can use to configure your local directory: - -.. list-table:: - :widths: 10 50 40 - :header-rows: 1 - - * - Flag - - Function - - Note - * - **-i** - - Loads all software from the hidden folder **.docker**. - - Mandatory - * - **-k** - - Loads all license packages from the **/license** directory. - - Mandatory - * - **-f** - - Overwrites existing folders. **Note** Using ``-f`` overwrites **all files** located in mounted directories. - - Mandatory - * - **-c** - - Defines the origin path for writing/reading SQream configuration files. The default location is ``/etc/sqream/``. - - If you are installing the Docker version on a server that already works with SQream, do not use the default path. - * - **-v** - - The SQream cluster location. If a cluster does not exist yet, ``-v`` creates one. If a cluster already exists, ``-v`` mounts it. - - Mandatory - * - **-l** - - SQream system startup logs location, including startup logs and docker logs. The default location is ``/var/log/sqream/``. - - - * - **-d** - - The directory containing customer data to be imported and/or copied to SQream. - - - * - **-s** - - Shows system settings. - - - * - **-r** - - Resets the system configuration. This value is run without any other variables. - - Mandatory - * - **-h** - - Help. Shows the available flags. - - Mandatory - * - **-K** - - Runs license validation - - - * - **-e** - - Used for inserting your RKrb5 server DNS name. For more information on setting your Kerberos configuration parameters, see :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. - - - * - **-p** - - Used for inserting your Kerberos user name. For more information on setting your Kerberos configuration parameters, see :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. - - - - -Installing Your License -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've configured your local environment, you must install your license by copying it into the SQream installation package folder located in the **./license** folder: - -.. code-block:: console - - $ sudo ./sqream-install -k - -You do not need to extract this folder after uploading into the **./license**. - - -Validating Your License -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You can copy your license package into the SQream console folder located in the **/license** folder by running the following command: - -.. code-block:: console - - $ sudo ./sqream-install -K - -The following mandatory flags must be used in the first run: - -.. code-block:: console - - $ sudo ./sqream-install -i -k -v - -The following is an example of the correct command syntax: - -.. code-block:: console - - $ sudo ./sqream-install -i -k -c /etc/sqream -v /home/sqream/sqreamdb -l /var/log/sqream -d /home/sqream/data_ingest - -.. _setting_hadoop_kubernetes_connectivity_parameters: - -Setting the Hadoop and Kubernetes Connectivity Parameters -------------------------------- -The information in this section is optional, and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, you must set their connectivity parameters. - -The following is the correct syntax when setting the Hadoop and Kubernetes connectivity parameters: - -.. code-block:: console - - $ sudo ./sqream-install -p -e : - -The following is an example of setting the Hadoop and Kubernetes connectivity parameters: - -.. code-block:: console - - $ sudo ./sqream-install -p -e kdc.sq.com:<192.168.1.111> - -For related information, see the following sections: - -* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. -* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. - -Modifying Your Data Ingest Folder -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've validated your license, you can modify your data ingest folder after the first run by running the following command: - -.. code-block:: console - - $ sudo ./sqream-install -d /home/sqream/data_in - -Configuring Your Network for Docker -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've modified your data ingest folder (if needed), you must validate that the server network and Docker network that you are setting up do not overlap. - -**To configure your network for Docker:** - -1. To verify that your server network and Docker network do not overlap, run the following command: - -.. code-block:: console - - $ ifconfig | grep 172. - -2. Do one of the following: - - * If running the above command output no results, continue the installation process. - * If running the above command output results, run the following command: - - .. code-block:: console - - $ ifconfig | grep 192.168. - - -Checking and Verifying Your System Settings -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've configured your network for Docker, you can check and verify your system settings. - -Running the following command shows you all the variables used by your SQream system: - -.. code-block:: console - - $ ./sqream-install -s - -The following is an example of the correct output: - -.. code-block:: console - - SQREAM_CONSOLE_TAG=1.5.4 - SQREAM_TAG=2019.2.1 - SQREAM_EDITOR_TAG=3.0.0 - license_worker_0=f0:cc: - license_worker_1=26:91: - license_worker_2=20:26: - license_worker_3=00:36: - SQREAM_VOLUME=/media/sqreamdb - SQREAM_DATA_INGEST=/media/sqreamdb/data_in - SQREAM_CONFIG_DIR=/etc/sqream/ - LICENSE_VALID=true - SQREAM_LOG_DIR=/var/log/sqream/ - SQREAM_USER=sqream - SQREAM_HOME=/home/sqream - SQREAM_ENV_PATH=/home/sqream/.sqream/env_file - PROCESSOR=x86_64 - METADATA_PORT=3105 - PICKER_PORT=3108 - NUM_OF_GPUS=2 - CUDA_VERSION=10.1 - NVIDIA_SMI_PATH=/usr/bin/nvidia-smi - DOCKER_PATH=/usr/bin/docker - NVIDIA_DRIVER=418 - SQREAM_MODE=single_host - -Using the SQream Console -========================= -After configuring the SQream software and veriying your system settings you can begin using the SQream console. - -SQream Console - Basic Commands ---------------------------------- -The SQream console offers the following basic commands: - -* :ref:`Starting your SQream console ` -* :ref:`Starting Metadata and Picker ` -* :ref:`Starting the running services ` -* :ref:`Listing the running services ` -* :ref:`Stopping the running services ` -* :ref:`Using the SQream editor ` -* :ref:`Using the SQream Client ` - -.. _starting_sqream_console: - -Starting Your SQream Console -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can start your SQream console by running the following command: - -.. code-block:: console - - $ ./sqream-console - -.. _starting_metadata_and_picker: - -Starting the SQream Master -~~~~~~~~~~~~~~~~~ - -**To listen to metadata and picker:** - -1. Start the metadata server (default port 3105) and picker (default port 3108) by running the following command: - - .. code-block:: console - - $ sqream master --start - - The following is the correct output: - - .. code-block:: console - - sqream-console> sqream master --start - starting master server in single_host mode ... - sqream_single_host_master is up and listening on ports: 3105,3108 - - -2. *Optional* - Change the metadata and server picker ports by adding ``-p `` and ``-m ``: - - .. code-block:: console - - $ sqream-console>sqream master --start -p 4105 -m 43108 - $ starting master server in single_host mode ... - $ sqream_single_host_master is up and listening on ports: 4105,4108 - - - -.. _starting_running_services: - -Starting SQream Workers -~~~~~~~~~~~~~~~~~ - - -When starting SQream workers, setting the ```` value sets how many workers to start. Leaving the ```` value unspecified runs all of the available resources. - - -.. code-block:: console - - $ sqream worker --start - - The following is an example of expected output when setting the ```` value to ``2``: - - .. code-block:: console - - sqream-console>sqream worker --start 2 - started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 - started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 - - -.. _listing_running_services: - -Listing the Running Services -~~~~~~~~~~~~~~~~~ - -You can list running SQream services to look for container names and ID's by running the following command: - -.. code-block:: console - - $ sqream master --list - -The following is an example of the expected output: - -.. code-block:: console - - sqream-console>sqream master --list - container name: sqream_single_host_worker_0, container id: c919e8fb78c8 - container name: sqream_single_host_master, container id: ea7eef80e038-- - - -.. _stopping_running_services: - -Stopping the Running Services -~~~~~~~~~~~~~~~~~ - -You can stop running services either for a single SQream worker, or all SQream services for both master and worker. - -The following is the command for stopping a running service for a single SQream worker: - -.. code-block:: console - - $ sqream worker --stop - -The following is an example of expected output when stopping a running service for a single SQream worker: - -.. code-block:: console - - sqream worker stop - stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 - - -You can stop all running SQream services (both master and worker) by running the following command: - -.. code-block:: console - - $ sqream-console>sqream master --stop --all - -The following is an example of expected output when stopping all running services: - -.. code-block:: console - - sqream-console>sqream master --stop --all - stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 - stopped container sqream_single_host_master, id: 55cb7e38eb22 - - -.. _using_sqream_editor: - -Using SQream Studio -~~~~~~~~~~~~~~~~~ -SQream Studio is an SQL statement editor. - -**To start SQream Studio:** - -1. Run the following command: - - .. code-block:: console - - $ sqream studio --start - -The following is an example of the expected output: - - .. code-block:: console - - SQream Acceleration Studio is available at http://192.168.1.62:8080 - -2. Click the ``http://192.168.1.62:8080`` link shown in the CLI. - - -**To stop SQream Studio:** - -You can stop your SQream Studio by running the following command: - -.. code-block:: console - - $ sqream studio --stop - -The following is an example of the expected output: - -.. code-block:: console - - sqream_admin stopped - - -.. _using_sqream_client: - -Using the SQream Client -~~~~~~~~~~~~~~~~~ - - -You can use the embedded SQream Client on the following nodes: - -* Master node -* Worker node - - -When using the SQream Client on the Master node, the following default settings are used: - -* **Default port**: 3108. You can change the default port using the ``-p`` variable. -* **Default database**: master. You can change the default database using the ``-d`` variable. - -The following is an example: - -.. code-block:: console - - $ sqream client --master -u sqream -w sqream - - -When using the SQream Client on a Worker node (or nodes), you should use the ``-p`` variable for Worker ports. The default database is ``master``, but you can use the ``-d`` variable to change databases. - -The following is an example: - -.. code-block:: console - - $ sqream client --worker -p 5000 -u sqream -w sqream - - -Moving from Docker Installation to Standard On-Premises Installation ------------------------------------------------ - -Because Docker creates all files and directories on the host at the **root** level, you must grant ownership of the SQream storage folder to the working directory user. - -SQream Console - Advanced Commands ------------------------------ - -The SQream console offers the following advanced commands: - - -* :ref:`Controlling the spool size ` -* :ref:`Splitting a GPU ` -* :ref:`Splitting a GPU and setting the spool size ` -* :ref:`Using a custom configuration file ` -* :ref:`Clustering your Docker environment ` - - - - -.. _controlling_spool_size: - -Controlling the Spool Size -~~~~~~~~~~~~~~~~~~ - -From the console you can define a spool size value. - -The following example shows the spool size being set to ``50``: - -.. code-block:: console - - $ sqream-console>sqream worker --start 2 -m 50 - - -If you don't define the SQream spool size, the SQream console automatically distributes the available RAM between all running workers. - -.. _splitting_gpu: - -Splitting a GPU -~~~~~~~~~~~~~~~~~~ - -You can start more than one sqreamd on a single GPU by splitting it. - - -The following example shows the GPU being split into **two** sqreamd's on the GPU in **slot 0**: - -.. code-block:: console - - $ sqream-console>sqream worker --start 2 -g 0 - -.. _splitting_gpu_setting_spool_size: - -Splitting GPU and Setting the Spool Size -~~~~~~~~~~~~~~~~~~ - -You can simultaneously split a GPU and set the spool size by appending the ``-m`` flag: - -.. code-block:: console - - $ sqream-console>sqream worker --start 2 -g 0 -m 50 - -.. note:: The console does not validate whether the user-defined spool size is available. Before setting the spool size, verify that the requested resources are available. - -.. _using_custom_configuration_file: - -Using a Custom Configuration File -~~~~~~~~~~~~~~~~~~ - -SQream lets you use your own external custom configuration json files. You must place these json files in the path mounted in the installation. SQream recommends placing the json file in the Configuration folder. - -The SQream console does not validate the integrity of your external configuration files. - -When using your custom configuration file, you can use the ``-j`` flag to define the full path to the Configuration file, as in the example below: - -.. code-block:: console - - $ sqream-console>sqream worker --start 1 -j /etc/sqream/configfile.json - -.. note:: To start more than one sqream daemon, you must provide files for each daemon, as in the example below: - -.. code-block:: console - - $ sqream worker --start 2 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json - -.. note:: To split a specific GPU, you must also list the GPU flag, as in the example below: - -.. code-block:: console - - $ sqream worker --start 2 -g 0 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json - -.. _clustering_docker_environment: - -Clustering Your Docker Environment -~~~~~~~~~~~~~~~~~~ - -SQream lets you connect to a remote Master node to start Docker in Distributed mode. If you have already connected to a Slave node server in Distributed mode, the **sqream Master** and **Client** commands are only available on the Master node. - -.. code-block:: console - - $ --master-host - $ sqream-console>sqream worker --start 1 --master-host 192.168.0.1020 - -Checking the Status of SQream Services ---------------------------- -SQream lets you check the status of SQream services from the following locations: - -* :ref:`From the Sqream console ` -* :ref:`From outside the Sqream console ` - -.. _inside_sqream_console: - -Checking the Status of SQream Services from the SQream Console -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -From the SQream console, you can check the status of SQream services by running the following command: - -.. code-block:: console - - $ sqream-console>sqream master --list - -The following is an example of the expected output: - -.. code-block:: console - - $ sqream-console>sqream master --list - $ checking 3 sqream services: - $ sqream_single_host_worker_1 up, listens on port: 5001 allocated gpu: 1 - $ sqream_single_host_worker_0 up, listens on port: 5000 allocated gpu: 1 - $ sqream_single_host_master up listens on ports: 3105,3108 - -.. _outside_sqream_console: - -Checking the Status of SQream Services from Outside the SQream Console -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -From outside the Sqream Console, you can check the status of SQream services by running the following commands: - -.. code-block:: console - - $ sqream-status - $ NAMES STATUS PORTS - $ sqream_single_host_worker_1 Up 3 minutes 0.0.0.0:5001->5001/tcp - $ sqream_single_host_worker_0 Up 3 minutes 0.0.0.0:5000->5000/tcp - $ sqream_single_host_master Up 3 minutes 0.0.0.0:3105->3105/tcp, 0.0.0.0:3108->3108/tcp - $ sqream_editor_3.0.0 Up 3 hours (healthy) 0.0.0.0:3000->3000/tcp - -Upgrading Your SQream System ----------------------------- -This section describes how to upgrade your SQream system. - -**To upgrade your SQream system:** - -1. Contact the SQream Support team for access to the new SQream package tarball file. - - :: - -2. Set a maintenance window to enable stopping the system while upgrading it. - - :: - -3. Extract the following tarball file received from the SQream Support team, under it with the same user and in the same folder that you used while :ref:`Downloading the SQream Software <_download_sqream_software>`. - - - .. code-block:: console - - $ tar -xvf sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ - -4. Navigate to the new folder created as a result of extracting the tarball file: - - .. code-block:: console - - $ cd sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ - -5. Initiate the upgrade process: - - .. code-block:: console - - $ ./sqream-install -i - - Initiating the upgrade process checks if any SQream services are running. If any services are running, you will be prompted to stop them. - -6. Do one of the following: - - * Select **Yes** to stop all running SQream workers (Master and Editor) and continue the upgrade process. - * Select **No** to stop the upgrade process. - - SQream periodically upgrades the metadata structure. If an upgrade version includes a change to the metadata structure, you will be prompted with an approval request message. Your approval is required to finish the upgrade process. - - Because SQream supports only certain metadata versions, all SQream services must be upgraded at the same time. - -7. When the upgrade is complete, load the SQream console and restart your services. - - For assistance, contact SQream Support. diff --git a/guides/operations/sqream_studio.rst b/guides/operations/sqream_studio.rst deleted file mode 100644 index 0dd41aa34..000000000 --- a/guides/operations/sqream_studio.rst +++ /dev/null @@ -1,578 +0,0 @@ -.. _sqream_studio: - -**************************** -SQream Acceleration Studio -**************************** - -The studio is a web-based client for use with SQream DB. - -It can be used to run statements, manage roles and permissions, and manage a SQream DB cluster. - -.. contents:: In this topic: - :local: - - -Setting up and starting the studio -==================================================== - -The studio is included with all :ref:`dockerized installations of SQream DB`. - -.. todo: How to start it? -.. You can start the studio using :ref:`sqream-console`: -.. .. code-block:: console -.. -.. $ ./sqream-console -.. sqream-console> sqream editor --start -.. access sqream statement editor through Chrome http://192.168.0.100:3000 - -When starting the studio, it listens on the local machine, on port 8080. - -Logging in -=================== - -Open a browser to the host, on port 8080. (e.g. If the machine is ``196.168.0.100``, navigate to http://192.168.0.100:8080) . - -Fill in your login details for SQream DB. These are the same credentials you might use when using :ref:`sqream sql` or JDBC. - -.. image:: /_static/images/studio_login.png - -Your user level in SQream DB changes what you see. - -* ``SUPERUSER`` levels have full access to the studio, including the :ref:`Dashboard`. - -* All users have access to the :ref:`Editor`, and can only see databases they have permissions for. - -.. _studio_editor: - -Statement editor -================= - -Familiarizing yourself with the editor ------------------------------------------ - -The editor is built up of main panes. - -.. image:: /_static/images/studio_editor_familiarize.png - -* :ref:`Toolbar` - used to select the active database you want to work on, limit the number of rows, save query, etc. - -* :ref:`Statement area` - The statement area is a multi-tab text editor where you write SQL statements. Each tab can connect to a different database. - -* :ref:`Results` - Results from a query will populate here. This is where you can copy or save query results, or show query execution details. - -* :ref:`Database tree` - contains a heirarchy tree of databases, views, tables, and columns. Can be used to navigate and perform some table operations. - -See more about each pane below: - -Navigation and user information -------------------------------------- - -The user information menu is located on the bottom left portion of the screen |icon-user|. - -.. image:: /_static/images/studio_user_info.png - - -The menu contains information about the currently signed-in user, as well as version information. - -You can sign out of the current user at any point, by selecting :kbd:`Logout` in the user menu. - - -.. _studio_editor_toolbar: - -Toolbar -------------- - -In the toolbar, you can perform the folllowing operations (from left to right): - -.. image:: /_static/images/studio_editor_toolbar.png - -* Database dropdown - Select the database you want to the statements to run on. - -* Queue - specify which service queue the statement should run in - -* :kbd:`⯈ Execute` / :kbd:`STOP` - Use the :kbd:`⯈ EXECUTE` button to execute the statement in the Editor pane. When a statement is running, the button changes to :kbd:`STOP`, and can be used to :ref:`stop the active statement`. - -* :kbd:`Format SQL` - Reformats and reindents the statement - -* :kbd:`Download query` - save query text to your computer - -* :kbd:`Open query` - load query text from your computer - -* Max. Rows - By default, the editor will only fetch the first 1000 rows. Click the number to edit. Click outside the number area to save. Setting a higher limit can slow down your browser if the result set is very large. This number is limited to 100000 results (To see more results, consider saving the results to a file or a table with :ref:`create_table_as`). - -.. _studio_editor_statement_area: - -Statement area ----------------- - -The multi-tabbed statement area is where you write queries and statements. - -.. image:: /_static/images/studio_editor_statement.png - - -Select the database you wish to use in the toolbar, and then write and execute statements. - -A new tab can be opened for each statement. Tabs can be used to separate statements to different databases. Clicking the |icon-plus| will open a new tab with a default name of SQL + a running number. - -Multiple statements can be written in the same tab, separated by semicolons (``;``). - -If too many tabs are open, pagination controls will appear. Click |icon-left| or |icon-right| to scroll through the tab listings. -Rename a tab by double clicking it's name. - -Close a tab by clicking |icon-close| - -To close all tabs, click :kbd:`Close all`, to the right of the tabs. - - -.. tip:: If this is your first time with SQream DB, see our :ref:`first steps guide`. - -.. Keyboard shortcuts -.. ^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. :kbd:`Ctrl` +: kbd:`Enter` - Execute all queries in the statement area, or just the highlighted part of the query. - -.. :kbd:`Ctrl` + :kbd:`Space` - Auto-complete the current keyword - -.. :kbd:`Ctrl` + :kbd:`↑` - Switch to next tab. - -.. :kbd:`Ctrl` + :kbd:`↓` - Switch to previous tab - -.. _studio_editor_results: - - -Formatting your SQL -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The |icon-format-sql| button can be used to automatically indent and reformat your SQL statements. - -Saving statements -^^^^^^^^^^^^^^^^^^^^^ - -The |icon-download-query| saves the tab contents to your computer. - -Loading SQL to a tab -^^^^^^^^^^^^^^^^^^^^^^^ - -The |icon-open-query| button loads a local file from your computer into a new editor tab. - -Executing SQL statements -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Clicking |icon-execute| will execute statements from the active tab. - -The button has three modes, which can be selected with the dropdown arrow :kbd:`ᐯ` - -* Execute statements – executes the statements where the cursor is located. -* Execute selected – executes the exact highlighted text. This mode is good for executing a subquery or other part of a large query (as long as it is a valid SQL). -* Execute all – executes all statements in the active tab, regardless of any selection - -When a statement is running, the button changes to :kbd:`STOP`, and can be used to :ref:`stop the active statement`. - -Results -------------- - -The results pane shows query results and execution information. By default, only the first 10000 results are returned (modify via the :ref:`studio_editor_toolbar`). - -.. image:: /_static/images/studio_editor_results.png - -By default, executing several statements together will open a separate results tab for each statement. - -Statements will be executed serially. Any failed statement will cancel subsequent statements. - -If the |keep-tabs| switch is on, new statements will create new tabs. When off, existing result will be cleared. - -If too many result tabs are open, pagination controls will appear. Click |icon-left| or |icon-right| to scroll through the tab listings. - -Close a tab by clicking |icon-close| - -To close all tabs, click :kbd:`Close all`, to the right of the tabs. - -.. contents:: In this topic: - :local: - - -Sorting results -^^^^^^^^^^^^^^^^^^^^^^ - -After the results have appeared, sort them by clicking the column name. - -Viewing execution information -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -During query execution the time elapsed is tracked in seconds. - -The :kbd:`Show Execution Details` button opens the query's :ref:`execution plan`, for monitoring purposes. - -Saving results to a file or clipboard -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Query results can be saved to a clipboard (for pasting into another text editor) or a local file. - -.. _studio_editor_db_tree: - -Database tree ---------------- - -The database tree shows the database objects (e.g. tables, columns, views), as well as some metadata like row counts. - -It also contains a few predefined catalog queries for execution. - -.. image:: /_static/images/studio_editor_db_tree.png - -Each level contains a context menu relevant to that object, accessible via a right-click. - -.. contents:: In this topic: - :local: - -System Queries -^^^^^^^^^^^^^^^^^^^^^^^ - -The studio editor comes with several predefined catalog queries that are useful for analysis of table compression rates, users and permissions, etc. - -Clicking on the :kbd:`System queries` tab in the Tree section will show a list of pre-defined system queries. - -Clicking on an item will paste the query into the editing area. - - -Filtering (searching) for objects -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Clicking the |icon-filter| filter icon by columns or tables opens an editable field that can be used for searching. - -To remove the filter, click the icon again or select ❌. - -Copying object names -^^^^^^^^^^^^^^^^^^^^^^^^^ - -Clicking the |icon-copy| icon will copy the object name - -Generating SELECT statements -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Clicking the |icon-select| icon will generate a :ref:`select` query for the selected table in the editing area. - -Generating an INSERT statement -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Clicking the :kbd:`Insert statement` option under the :kbd:`⋮` menu generates an :ref:`insert` statement for the selected table in the editing area. - -Generating a DELETE statement -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Clicking the :kbd:`Delete statement` option under the :kbd:`⋮` menu generates a :ref:`delete` statement for the selected table in the editing area. - -Generating a CREATE TABLE AS statement -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Clicking the :kbd:`Create table as` option under the :kbd:`⋮` menu generates a :ref:`create_table_as` statement for the selected table in the editing area. - -Renaming a table -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Clicking the :kbd:`Rename table` option under the :kbd:`⋮` menu generates an :ref:`alter_table` statement for renaming the selected table in the editing area. - - -Adding columns to table -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Clicking the :kbd:`Add column` option under the :kbd:`⋮` menu generates an :ref:`alter_table` statement for adding columns to the selected table in the editing area. - -Truncate a table -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Clicking the :kbd:`Truncate table` option under the :kbd:`⋮` menu generates a :ref:`truncate` statement for the selected table in the -editing area. - - -Dropping an object -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Clicking the :kbd:`Drop table`, :kbd:`Drop view`, or :kbd:`Drop function` option under the :kbd:`⋮` menu generates a ``DROP`` statement for the selected object in the editing area. - - -Generating DDL statements -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Clicking the :kbd:`Table DDL`, :kbd:`View DDL`, or :kbd:`Function function` option under the :kbd:`⋮` menu generates a DDL statement for the selected object in the editing area. - -To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. -See also :ref:`seeing_system_objects_as_sql`. - -The DDL optimizer -^^^^^^^^^^^^^^^^^^^^^^^^^ - -The DDL optimizer tab analyzes database tables and recommends possible optimizations, per the :ref:`sql_best_practices` guide. - -Using the DDL optimizer ---------------------------- - -Navigate to the DDL optimizer module by selecting :kbd:`DDL Optimizer` from the :kbd:`⋮` ("More") menu. - -.. image:: /_static/images/studio_ddl_optimizer.png - -* ``Rows`` - number of rows to scan for analysis. Defaults to 1,000,000 - -* ``Buffer Size`` - overhead threshold to use when analyzing ``VARCHAR`` fields. Defaults to 10%. - -* ``Optimize NULLs`` - attempt to figure out field nullability. - -Click :kbd:`Run Optimizer` to start the optimization process. - -Analyzing the results ----------------------------- - -When results are produced, a :kbd:`Generate CREATE statement` button will appear. -Clicking the button creates a new tab with an optimized :ref:`create_table` statement, and an :ref:`insert` statement to copy the data to the new table. - - -.. _studio_dashboard: - -Administration Dashboard -============================== - -If you signed in with a ``SUPERUSER`` role, you can enter the administration dashboard. - -Enter the administration dashboard by clicking the |icon-dashboard| icon in the navigation bar. - - - -Familiarizing yourself with the dashboard ---------------------------------------------- - -.. image:: /_static/images/studio_dashboard_familiarize.png - -The main dashboard screen contains two main panes: - -* - :ref:`Data storage pane` - monitor the SQream DB cluster's storage - - - can be expanded to :ref:`drill down into database storage` - -* - :ref:`Worker pane` - monitor system health - - - the worker pane used to monitor workers and :ref:`service queues` in the cluster. - -.. _administration_storage_pane: - -Data storage pane ------------------------ - -The left section of the Admin Dashboard shows you the status of your system's storage as a donut. - -.. image:: /_static/images/studio_dashboard_storage.png - -Storage is displayed broken up into four components: - -* Data – Storage occupied by databases in SQream DB - -* Free – Free storage space - -* - Deleted – Storage that is temporarily occupied but hasn't been reclaimed (see our :ref:`delete guide` to understand how data deletion works). - - (This value is estimated and may not be accurate) - -* Other – Storage used by other applications. On a dedicated SQream DB cluster, this should be close to zero. - -.. _administration_storage_database: - -Database storage -^^^^^^^^^^^^^^^^^^^^^^^^ - -Expanding the storage pane (|icon-expand|) will show a breakdown of how much storage is used by each database in the cluster. - -.. image:: /_static/images/studio_dashboard_storage_breakdown.png - -This can be used to drill down into each database's storage footprint. - -Databases are displayed in a table, containing the following information: -* Database name -* Raw storage size – the estimated size of raw data (uncompressed) in the database -* Storage size – the physical size of the compressed data -* Ratio – effective compression ratio -* Deleted data – storage that is temporarily occupied but hasn't been reclaimed (see our :ref:`delete guide` to understand how data deletion works). (This value is estimated and may not be accurate) - -Below the table, a graph shows the database storage trends. - -By default, the graph shows the total storage for all databases. Clicking a database in the table will filter to show just that database. - -The scale of the presented information can be controlled by changing the timeframe in the scale dropdown (|icon-scale|). - -.. _administration_worker_pane: - -Service and workers pane --------------------------- - -This pane shows the cluster status in workers and their :ref:`service queues`. - -.. _administration_services: - -Services -^^^^^^^^^^^ - -The services bar shows the defined :ref:`service queues`. - -Services are used to divide workers and associate (subscribe) workers to services. - -Each service queue contains the following details: -* Service name -* A graph of load over time (statements in that queue) -* Currently processed queries of the Service / total queries for that service in the system (including queued queries) - -Creating new service queues -******************************** - -Click the |icon-add| button above the service list. Type the service queue name and associate new workers to the service queue. - -.. note:: if you choose not to associate a worker with the new service, it will not be created. - -Associating a worker with an existing service -********************************************** - -Clicking on the |icon-add-worker| icon on a service name is used to attach workers to a service. - -Clicking on a service queue in the services bar will display the list of workers in the main pane. - -.. image:: /_static/images/studio_dashboard_services.png - -In this mode, the :kbd:`⋮` icon (more menu) can be used to detach a worker from a service. - -You can select a Worker from the list that is available to process queries of the relevant Service and by clicking on the button of that Worker that Worker will be associated with the Service. After that the page will go back to its normal layout and you will be able to click the Service and see the Worker associated with the Service. -Other Services associated with that Worker will remain associated to it. - - -.. _administration_workers: - -Workers -^^^^^^^^^^^^^ - -The worker pane shows each worker (``sqreamd``) running in the cluster. - -Each worker has a status bar that represents the status over time. The scale of the presented information can be controlled by changing the timeframe in the scale dropdown (|icon-scale|). - -The status bar is divided into 20 equal sections, showing the most dominant activity in that slice. Hover over the status bar sections to see the activity: - -* Idle – worker is idle and available for statements -* Compiling – Compiling a statement, in preparation for execution -* Executing – executing a statement after compilation -* Stopped – worker was stopped (either deliberately or due to a fault) -* Waiting – worker was waiting on an object locked by another worker - -Show host resources -***************************** - -Clicking the |icon-expand-down| button below each host will expand to show the host resource utilization. - -.. image:: /_static/images/studio_worker_activity.png - -The host resource utilization includes information about: - -* CPU utilization -* Memory utilization -* GPU utilization - -Graphs show resource utilization over time. Current values are shown on the right. - -Hover over the graph line to see the activity at a given time. - - -Active queries -****************** - -Clicking the |icon-expand-down| button on a worker will expand to show the active statements running. - -Each statement has a statement ID, status, service queue, elapsed time, execution time, and estimated completion status. - -Each statement can be stopped or expanded to show its execution plan and progress (:ref:`show_node_info`). - -.. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst - :start-line: 67 - :end-line: 84 - -Control worker status (start, stop, restart) -**************************************************** - -In some cases, it may be useful to stop or restart workers for maintenance. - -Each Worker line has a :kbd:`⋮` menu (more menu). This menu allows stopping, starting, or restarting workers. - -When a worker is stopped, it has a gray background and its status is "Stopped". - - - - -.. |icon-user| image:: /_static/images/studio_icon_user.png - :align: middle - -.. |icon-editor| image:: /_static/images/studio_icon_editor.png - :align: middle - -.. |icon-copy| image:: /_static/images/studio_icon_copy.png - :align: middle - -.. |icon-select| image:: /_static/images/studio_icon_select.png - :align: middle - -.. |icon-dots| image:: /_static/images/studio_icon_dots.png - :align: middle - -.. |icon-filter| image:: /_static/images/studio_icon_filter.png - :align: middle - -.. |icon-ddl-edit| image:: /_static/images/studio_icon_ddl_edit.png - :align: middle - -.. |icon-run-optimizer| image:: /_static/images/studio_icon_run_optimizer.png - :align: middle - -.. |icon-generate-create-statement| image:: /_static/images/studio_icon_generate_create_statement.png - :align: middle - -.. |icon-plus| image:: /_static/images/studio_icon_plus.png - :align: middle - -.. |icon-close| image:: /_static/images/studio_icon_close.png - :align: middle - -.. |icon-left| image:: /_static/images/studio_icon_left.png - :align: middle - -.. |icon-right| image:: /_static/images/studio_icon_right.png - :align: middle - -.. |icon-format-sql| image:: /_static/images/studio_icon_format.png - :align: middle - -.. |icon-download-query| image:: /_static/images/studio_icon_download_query.png - :align: middle - -.. |icon-open-query| image:: /_static/images/studio_icon_open_query.png - :align: middle - -.. |icon-execute| image:: /_static/images/studio_icon_execute.png - :align: middle - -.. |icon-stop| image:: /_static/images/studio_icon_stop.png - :align: middle - -.. |icon-dashboard| image:: /_static/images/studio_icon_dashboard.png - :align: middle - -.. |icon-expand| image:: /_static/images/studio_icon_expand.png - :align: middle - -.. |icon-scale| image:: /_static/images/studio_icon_scale.png - :align: middle - -.. |icon-expand-down| image:: /_static/images/studio_icon_expand_down.png - :align: middle - -.. |icon-add| image:: /_static/images/studio_icon_add.png - :align: middle - -.. |icon-add-worker| image:: /_static/images/studio_icon_add_worker.png - :align: middle - -.. |keep-tabs| image:: /_static/images/studio_keep_tabs.png - :align: middle \ No newline at end of file diff --git a/guides/operations/starting_and_stopping_the_system.rst b/guides/operations/starting_and_stopping_the_system.rst deleted file mode 100644 index 62dbb6d72..000000000 --- a/guides/operations/starting_and_stopping_the_system.rst +++ /dev/null @@ -1,21 +0,0 @@ -.. _running_and_stopping_the_system: - -**************************************** -running_and_stopping_the_system -**************************************** - -how do you run sqream with the various methods: - -monit - -pacemaker - -docker - -k8s - -from command line - -how do you check it's running/view it's status/check you can use it - -how do you stop it diff --git a/guides/operations/statement_editor.rst b/guides/operations/statement_editor.rst deleted file mode 100644 index 55c29def1..000000000 --- a/guides/operations/statement_editor.rst +++ /dev/null @@ -1,290 +0,0 @@ -.. _statement_editor: - -***************************************** -Using the statement editor (deprecated) -***************************************** - -The statement editor is a web-based client for use with SQream DB. It can be used to run statements, and manage roles and permissions. - -.. note:: The statement editor is deprecated from SQream DB v2020.2. It is replaced by :ref:`SQream Studio` - -.. contents:: In this topic: - :local: - -Setting up and starting the statement editor -==================================================== - -.. note:: We recommend using Google Chrome or Chrome-based browsers to access the statement editor. - -The statement editor is included with all :ref:`dockerized installations of SQream DB`. - -You can start the editor using :ref:`sqream-console`: - - -.. code-block:: console - - $ ./sqream-console - sqream-console> sqream editor --start - access sqream statement editor through Chrome http://192.168.0.100:3000 - -When starting the editor, it listens on the local machine, on port 3000. - -Logging in -=================== - -Open a browser to the host, on port 3000. If the machine is ``196.168.0.100``, navigate to http://192.168.0.100:3000 . - -Fill in your login details for SQream DB. These are the same credentials you might use when using :ref:`sqream sql` or JDBC. - -.. image:: /_static/images/statement_editor_login.png - -.. tip:: - * If using a :ref:`load balancer`, select the ``Server picker`` box and make sure to use the correct port (usually ``3108``). If connecting directly to a worker, make sure to untick the box and use the correct port, usually ``5000`` and up. - * If this is your first time using SQream DB, use database name ``master``. - * When using SQream DB on AWS, the initial password is the EC2 instance ID. - -Familiarizing yourself with the editor -============================================== - -The editor is built up of main panes. - -.. image:: /_static/images/statement_editor_main.png - -* :ref:`Toolbar` - used to select the active database you want to work on, limit the number of rows, save query results, control tab behavior, and more. - -* :ref:`Statement area` - The statement area is a multi-tab text editor where you write SQL statements. Each tab can connect to a different database. - -* :ref:`Results` - Results from a query will populate here. - -* :ref:`Database tree` - contains a heirarchy tree of databases, views, tables, and columns. Can be used to navigate and perform some table operations. - -See more about each pane below: - -.. _editor_toolbar: - -Toolbar -------------- - -.. image:: /_static/images/statement_editor_toolbar.png - -In the toolbar, you can perform the folllowing operations (from left to right): - -* Toggle Database Tree - Click •••​ to show or hide the Database Tree pane. - -* Database dropdown - Select the database you want to the statements to run on. - -* :kbd:`⯈ RUN` / :kbd:`◼ STOP` - Use the :kbd:`⯈ RUN` button to execute the statement in the Editor pane. When a statement is running, the button changes to :kbd:`◼ STOP`, and can be used to :ref:`stop the active statement`. - -* :kbd:`SQL` - Reformats and reindents the statement - -* Max. Rows - By default, the editor will only fetch the first 1000 rows. Click the number to edit. Click outside the number area to save. Setting a higher limit can slow down your browser if the result set is very large. - -* 💾 (Save) - Save the query text to a file. - -* 📃 (Load) - Load query text from a file. - -* ⋮ (more) - - - * Append new results - When checked, every statement executed will open a new Results tab. If unchecked, the Results tab is reused and overwritten with every new statement. - -.. _editor_statement_area: - -Statement area ----------------- - -.. image:: /_static/images/statement_editor_editor.png - -The multi-tabbed statement area is where you write queries and statements. - -Select the database you wish to use in the toolbar, and then write and execute statements. - -* A new tab can be opened for each statement. Tabs can be used to separate statements to different databases. - -* Multiple statements can be written in the same tab, separated by semicolons. - -* When multiple statements exist in the tab, clicking :kbd:`Run` executes all statements in the tab, or only the selected statements. - -.. tip:: If this is your first time with SQream DB, see our :ref:`first steps guide`. - -Keyboard shortcuts -^^^^^^^^^^^^^^^^^^^^^^^^^ - -:kbd:`Ctrl` +: kbd:`Enter` - Execute all queries in the statement area, or just the highlighted part of the query. - -:kbd:`Ctrl` + :kbd:`Space` - Auto-complete the current keyword - -:kbd:`Ctrl` + :kbd:`↑` - Switch to next tab. - -:kbd:`Ctrl` + :kbd:`↓` - Switch to previous tab - -.. _editor_results: - -Results -------------- - -The results pane shows query results and execution information. By default, only the first 1000 results are returned (modify via the :ref:`editor_toolbar`). - -A context menu, accessible via a right click on the results tab, enables: - -* Renaming the tab name -* Show the SQL query text -* Reload results -* Close the current tab -* Close all result tabs - -Sorting results -^^^^^^^^^^^^^^^^^^^^^^ - -After the results have appeared, sort them by clicking the column name. - -Viewing execution information -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -During query execution the time elapsed is tracked in seconds. - -.. image:: /_static/images/statement_editor_statistics.png - -The :kbd:`SHOW STATISTICS` button opens the query's :ref:`execution plan`, for monitoring purposes. - -Saving results to a file or clipboard -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. image:: /_static/images/statement_editor_save.png - -Query results can be saved to a clipboard (for pasting into another text editor) or a local file. - -.. _editor_db_tree: - -Database tree ---------------- - -The database tree shows the database objects (e.g. tables, columns, views), as well as some metadata like row counts. - -It also contains a few predefined catalog queries for execution. - -.. image:: /_static/images/statement_editor_db_tree.png - -Each level contains a context menu relevant to that object, accessible via a right-click. - -Database -^^^^^^^^^^^^^ - -* :ref:`Copy the database DDL` to the clipboard - -Schema -^^^^^^^^^^ - -* Drop the schema (copies statement to the clipboard) - -Table -^^^^^^^^^^ - -* Show row count in the database tree - -* :ref:`Copy the create table script` to the clipboard - -* Copy :ref:`select` to clipboard - -* Copy :ref:`insert` to clipboard - -* Copy :ref:`delete` to clipboard - -* Rename table - Copy :ref:`rename_table` to clipboard - -* Create table LIKE - Copy :ref:`create_table_as` to clipboard - -* Add column - Copy :ref:`add_column` to clipboard - -* Truncate table - Copy :ref:`truncate` to clipboard - -* Drop table - Copy :ref:`drop_table` to pclipboard - -* Create a table - Add a new table by running a statement, or alternatively use the **Add new** link near the **TABLES** group. - -Create a table -^^^^^^^^^^^^^^^^^^^^ - -Creating a new table is also possible using the wizard which can guide you with creating a table. - -Refer to the :ref:`create_table` reference for information about creating a table (e.g. able parameters like default values, identity, etc.). - -.. image:: /_static/images/statement_editor_add_table.png - -Fill in the table name, and add a new row for each table column. - -If a table by the same name exists, check **Create or Replace table** to overwrite it. - -Click :kbd:`EXEC` to create the table. - -Catalog views -^^^^^^^^^^^^^^^^^^^ - -To see :ref:`catalog views`, click the catalog view name in the tree. The editor will run a query on that view. - -.. image:: /_static/images/statement_editor_view_catalog.png - -Predefined queries -^^^^^^^^^^^^^^^^^^^^^^^ - -The editor comes with several predefined catalog queries that are useful for analysis of table compression rates, users and permissions, etc. - -.. image:: /_static/images/statement_editor_predefined_queries.png - -Notifications -=================== - -Desktop notificaitons lets you receive a notification when a statement is completed. - -You can minimize the browser or switch to other tabs, and still recieve a notification when the query is done. - -.. image:: /_static/images/statement_editor_notifications.png - -Enable the desktop notification through the **Allow Desktop Notification** from the menu options. - -DDL optimizer -================== - -The DDL optimizer tab analyzes database tables and recommends possible optimizations, per the :ref:`sql_best_practices` guide. - -Using the DDL optimizer ---------------------------- - -Navigate to the DDL optimizer module by selecting it from the :kbd:`⋮` ("More") menu. - -.. image:: /_static/images/statement_editor_ddl_optimizer.png - -* ``Database`` and ``Table`` - select the database and desired table to optimize -* ``Rows`` is the number to scan for analysis. Defaults to 1,000,000 - -* ``Buffer Size`` - overhead threshold to use when analyzing ``VARCHAR`` fields. Defaults to 10%. - -* ``Optimize NULLs`` - attempt to figure out field nullability. - -Click ``EXECUTE`` to start the optimization process. - -Analyzing the results ----------------------------- - -The analysis process shows results for each row. - -.. image:: /_static/images/statement_editor_ddl_optimizer_results.png - -The results are displayed in two tabs: - -* **OPTIMIZED COLUMNS** - review the system recommendation to: - - #. decrease the length of ``VARCHAR`` fields - - #. remove the ``NULL`` option - -* **OPTIMIZED DDL** - The recommended :ref:`create_table` statement - -Analyzing the DDL culminates in four possible actions: - -* :kbd:`COPY DDL TO CLIPBOARD` - Copies the optimized :ref:`create_table` to the clipboard - -* :kbd:`CREATE A NEW TABLE` - Creates the new table structure with ``_new`` appended to the table name. No data is populated - -* :kbd:`CREATE AND INSERT INTO EXISTING DATA` - Create a new table in same database and schema as the original table and populates the data - -* **Back** - go back to the statement editor and abandon any recommendations diff --git a/guides/operations/troubleshooting.rst b/guides/operations/troubleshooting.rst deleted file mode 100644 index 7eed4c757..000000000 --- a/guides/operations/troubleshooting.rst +++ /dev/null @@ -1,163 +0,0 @@ -.. _troubleshooting: - -*********************** -Troubleshooting -*********************** - -.. contents:: In this topic: - :local: - -Follow this checklist if you find that the performance is slower than you expect. - -.. list-table:: Troubleshooting checklist - :widths: auto - :header-rows: 1 - - * - Step - - Description - - Results - * - 1 - - A single query is slow - - - If a query isn't performing as you expect, follow the :ref:`Query best practices` part of the :ref:`sql_best_practices` guide. - - If all queries are slow, continue to step 2. - * - 2 - - All queries on a specific table are slow - - - #. If all queries on a specific table aren't performing as you expect, follow the :ref:`Table design best practices` part of the :ref:`sql_best_practices` guide. - #. Check for active delete predicates in the table. Consult the :ref:`delete_guide` guide for more information. - - If the problem spans all tables, continue to step 3. - * - 3 - - Check that all workers are up - - - Use ``SELECT show_cluster_nodes();`` to list the active cluster workers. - - If the worker list is incomplete, follow the :ref:`cluster troubleshooting` section below. - - If all workers are up, continue to step 4. - * - 4 - - Check that all workers are performing well - - - #. Identify if a specific worker is slower than others by running the same query on different workers. (e.g. by connecting directly to the worker or through a service queue) - #. If a specific worker is slower than others, investigate performance issues on the host using standard monitoring tools (e.g. ``top``). - #. Restart SQream DB workers on the problematic host. - - If all workers are performing well, continue to step 5. - * - 5 - - Check if the workload is balanced across all workers - - - #. Run the same query several times and check that it appears across multiple workers (use ``SELECT show_server_status()`` to monitor) - #. If some workers have a heavier workload, check the service queue usage. Refer to the :ref:`workload_manager` guide. - - If the workload is balanced, continue to step 6. - * - 6 - - Check if there are long running statements - - - #. Identify any currently running statements (use ``SELECT show_server_status()`` to monitor) - #. If there are more statements than available resources, some statements may be in an ``In queue`` mode. - #. If there is a statement that has been running for too long and is blocking the queue, consider stopping it (use ``SELECT stop_statement()``). - - If the statement does not stop correctly, contact SQream support. - - If there are no long running statements or this does not help, continue to step 7. - * - 7 - - Check if there are active locks - - - #. Use ``SELECT show_locks()`` to list any outstanding locks. - #. If a statement is locking some objects, consider waiting for that statement to end or stop it. - #. If after a statement is completed the locks don't free up, refer to the :ref:`concurrency_and_locks` guide. - - If performance does not improve after the locks are released, continue to step 8. - * - 8 - - Check free memory across hosts - - - #. Check free memory across the hosts by running ``$ free -th`` from the terminal. - #. If the machine has less than 5% free memory, consider **lowering** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. Refer to the :ref:`configuration` guide. - #. If the machine has a lot of free memory, consider **increasing** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. - - If performance does not improve, contact SQream support for more help. - - - -Troubleshooting common issues -====================================== - -.. _cluster_troubleshooting: - -Troubleshoot cluster setup and configuration ------------------------------------------------------ - -#. Note any errors - Make a note of any error you see, or check the :ref:`logs` for errors you might have missed. - -#. If SQream DB can't start, start SQream DB on a new storage cluster, with default settings. If it still can't start, there could be a driver or hardware issue. :ref:`Contact SQream support`. - -#. Reproduce the issue with a standalone SQream DB - starting up a temporary, standalone SQream DB can isolate the issue to a configuration issue, network issue, or similar. - -#. Reproduce on a minimal example - Start a standalone SQream DB on a clean storage cluster and try to replicate the issue if possible. - - -Troubleshoot connectivity issues ------------------------------------ - -#. Verify the correct login credentials - username, password, and database name. - -#. Verify the host name and port - -#. Try connecting directly to a SQream DB worker, rather than via the load balancer - -#. Verify that the driver version you're using is supported by the SQream DB version. Driver versions often get updated together with major SQream DB releases. - -#. Try connecting directly with :ref:`the built in SQL client`. If you can connect with the local SQL client, check network availability and firewall settings. - -Troubleshoot query performance ------------------------------------- - -#. Use :ref:`show_node_info` to examine which building blocks consume time in a statement. If the query has finished, but the results are not yet materialized in the client, it could point to a problem in the application's data buffering or a network throughput issue.. - -#. If a problem occurs through a 3\ :sup:`rd` party client, try reproducing it directly with :ref:`the built in SQL client`. If the performance is better in the local client, it could point to a problem in the application or network connection. - -#. Consult the :ref:`sql_best_practices` guide to learn how to optimize queries and table structures. - - -Troubleshoot query behavior ---------------------------------- - -#. Consult the :ref:`sql` reference to verify if a statement or syntax behaves correctly. SQream DB may have some differences in behavior when compared to other databases. - -#. If a problem occurs through a 3\ :sup:`rd` party client, try reproducing it directly with :ref:`the built in SQL client`. If the problem still occurs, file an issue with SQream support. - -File an issue with SQream support ------------------------------------- - -To file an issue, follow our :ref:`information_for_support` guide. - -Examining logs -======================== - -See the :ref:`collecting_logs` section of the :ref:`information_for_support` guide for information about collecting logs for support. - - -Start a temporary SQream DB for testing -=============================================== - -Starting a SQream DB temporarily (not as part of a cluster, with default settings) can be helpful in identifying configuration issues. - -Example: - -.. code-block:: console - - $ sqreamd /home/rhendricks/raviga_database 0 5000 /home/sqream/.sqream/license.enc - -.. tip:: - - * Using ``nohup`` and ``&`` sends SQream DB to run in the background. - - * - It is safe to stop SQream DB at any time using ``kill``. No partial data or data corruption should occur when using this method to stop the process. - - .. code-block:: console - - $ kill -9 $SQREAM_PID - diff --git a/guides/queries.rst b/guides/queries.rst deleted file mode 100644 index 24a4e589d..000000000 --- a/guides/queries.rst +++ /dev/null @@ -1,10 +0,0 @@ -.. _queries: - -********************************** -Queries -********************************** - -go through all the query features in sqream and give examples and -state what we do that's interesting, or less usual, and maybe what we -don't do that's common in other products/ limitations - diff --git a/guides/third_party_tools/talend.rst b/guides/third_party_tools/talend.rst deleted file mode 100644 index 2b678d1a1..000000000 --- a/guides/third_party_tools/talend.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. _talend: - -************************* -Connecting to Talend -************************* - -You can use Talend to read data from a SQream DB cluster, and load data into SQream DB. This tutorial is a guide that will show you how to connect Talend to SQream DB. - - -.. contents:: In this topic: - :local: diff --git a/index.rst b/index.rst index a4e314eaf..3d044ee2f 100644 --- a/index.rst +++ b/index.rst @@ -4,13 +4,13 @@ SQream DB Documentation ************************* -For SQream DB |latest_version|. +For SQream DB Version Version 2020.3.2.1. .. only:: html .. tip:: Want to read this offline? - `Download the documentation as a single PDF `_ . + `Download the documentation as a single PDF `_ . .. only:: pdf or latex @@ -20,7 +20,7 @@ SQream DB is a columnar analytic SQL database management system. SQream DB supports regular SQL including :ref:`a substantial amount of ANSI SQL`, uses :ref:`serializable transactions`, and :ref:`scales horizontally` for concurrent statements. -Even a `basic SQream DB machine `_ can support tens to hundreds of terabytes of data. +Even a :ref:`basic SQream DB machine` can support tens to hundreds of terabytes of data. SQream DB easily plugs in to third-party tools like :ref:`Tableau` comes with standard SQL client drivers, including :ref:`JDBC`, :ref:`ODBC`, and :ref:`Python DB-API`. @@ -47,7 +47,7 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau`_ + :ref:`setup` :ref:`Best practices` @@ -56,10 +56,10 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` - :ref:`2020.2<2020.2>` + :ref:`2020.2<2020.2>` :ref:`2020.1<2020.1>` @@ -72,9 +72,9 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau`_ - :ref:`information_for_support` + `Gathering Information for SQream Support `_ @@ -96,12 +96,18 @@ If you're looking for an older version of the documentation, versions 1.10 throu :titlesonly: :hidden: - first_steps - xxfeatures_tour - guides/index + getting_started/index installation_guides/index + data_ingestion_guides/index + third_party_tools/index + feature_guides/index + operational_guides/index + sqream_studio_5.4.3/index + architecture/index + configuration_guides/index reference/index releases/index + troubleshooting/index glossary .. diff --git a/guides/operations/creating_or_cloning_a_storage_cluster.rst b/operational_guides/creating_or_cloning_a_storage_cluster.rst similarity index 85% rename from guides/operations/creating_or_cloning_a_storage_cluster.rst rename to operational_guides/creating_or_cloning_a_storage_cluster.rst index 0ff7fe294..d9cd711ea 100644 --- a/guides/operations/creating_or_cloning_a_storage_cluster.rst +++ b/operational_guides/creating_or_cloning_a_storage_cluster.rst @@ -1,9 +1,21 @@ .. _creating_or_cloning_a_storage_cluster: **************************************** -Creating or cloning a storage cluster +Creating or Cloning Storage Clusters **************************************** + +1. *Install and configure MC (Management Console)* +#. *Prepare the Hosts* +#. *Create the private key file and copy it to your local machine* +#. *Run the Cluster Installation Wizard* - **It may be worthwhile to develop this.** +#. *Validate the hosts and create the cluster* +#. *Create a new database on the cluster* + +*Note that Vertica's "Management Console" corresponds to our SQream Console - confirm.* + +*Note also that each item in the list above links to a different area of their documentation and is unorganized. Verify whether the above steps are located in order on a page in our documentation.* + When SQream DB is installed, it comes with a default storage cluster. This guide will help if you need a fresh storage cluster or a separate copy of an existing storage cluster. Creating a new storage cluster diff --git a/operational_guides/exporting_data.rst b/operational_guides/exporting_data.rst new file mode 100644 index 000000000..18a90cc64 --- /dev/null +++ b/operational_guides/exporting_data.rst @@ -0,0 +1,15 @@ +.. _exporting_data: + +*********************** +Exporting Data +*********************** +You can export data from SQream, which you may want to do for the following reasons: + + +* To use data in external tables. See `Working with External Data `_. +* To share data with other clients or consumers with different systems. +* To copy data into another SQream cluster. + +SQream provides the following methods for exporting data: + +* Copying data from a SQream database table or query to another file - See `COPY TO `_. \ No newline at end of file diff --git a/guides/features/external_data/index.rst b/operational_guides/external_data.rst similarity index 74% rename from guides/features/external_data/index.rst rename to operational_guides/external_data.rst index c5bbd2597..98d157ab2 100644 --- a/guides/features/external_data/index.rst +++ b/operational_guides/external_data.rst @@ -1,15 +1,14 @@ .. _external_data: ********************************** -Working with external data +Working with External Data ********************************** SQream DB supports external data sources for use with :ref:`external_tables`, :ref:`copy_from`, and :ref:`copy_to`. .. toctree:: - :maxdepth: 2 - :caption: In this section: - :glob: + :maxdepth: 1 + :titlesonly: s3 hdfs diff --git a/guides/features/external_tables.rst b/operational_guides/external_tables.rst similarity index 66% rename from guides/features/external_tables.rst rename to operational_guides/external_tables.rst index b3b566083..005dc961f 100644 --- a/guides/features/external_tables.rst +++ b/operational_guides/external_tables.rst @@ -1,103 +1,56 @@ .. _external_tables: -************************** -Foreign Tables -************************** - -Foreign tables can be used to run queries directly on data without inserting it into SQream DB first. - -SQream DB supports read only foreign tables, so you can query from foreign tables, but you cannot insert to them, or run deletes or updates on them. - -Running queries directly on foreign (external) data is most effectively used for things like one off querying. If you will be repeatedly querying data, the performance will usually be better if you insert the data into SQream DB first. - -Although foreign tables can be used without inserting data into SQream DB, one of their main use cases is to help with the insertion process. An insert select statement on an foreign table can be used to insert data into SQream using the full power of the query engine to perform ETL. - +*********************** +External Tables +*********************** +External tables can be used to run queries directly on data without inserting it into SQream DB first. +SQream DB supports read only external tables, so you can query from external tables, but you cannot insert to them, or run deletes or updates on them. +Running queries directly on external data is most effectively used for things like one off querying. If you will be repeatedly querying data, the performance will usually be better if you insert the data into SQream DB first. +Although external tables can be used without inserting data into SQream DB, one of their main use cases is to help with the insertion process. An insert select statement on an external table can be used to insert data into SQream using the full power of the query engine to perform ETL. .. contents:: In this topic: :local: What kind of data is supported? ===================================== +SQream DB supports external tables over: -SQream DB uses foreign data wrappers (FDW) to abstract external sources. - -SQream DB supports these FDWs: - -* text files (e.g. CSV, PSV, TSV) via the ``csv_fdw`` -* ORC via the ``orc_fdw`` -* Parquet via the ``parquet_fdw`` +* text files (e.g. CSV, PSV, TSV) +* ORC +* Parquet What kind of data staging is supported? ============================================ - SQream DB can stage data from: * a local filesystem (e.g. ``/mnt/storage/....``) * :ref:`s3` buckets (e.g. ``s3://pp-secret-bucket/users/*.parquet``) * :ref:`hdfs` (e.g. ``hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv``) -Using foreign tables - a practical example +Using external tables - a practical example ============================================== - -Use an foreign table to stage data before loading from CSV, Parquet or ORC files. +Use an external table to stage data before loading from CSV, Parquet or ORC files. Planning for data staging -------------------------------- - For the following examples, we will want to interact with a CSV file. Here's a peek at the table contents: .. csv-table:: nba.csv + :file: nba-t10.csv :widths: auto :header-rows: 1 The file is stored on :ref:`s3`, at ``s3://sqream-demo-data/nba_players.csv``. - We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_TABLE`` statement. -Creating the foreign table ------------------------------------- - -Based on the source file structure, we we :ref:`create a foreign table` with the appropriate structure, and point it to the file. - -The file format in this case is CSV, with a DOS newline (``\r\n``). - -Here's how the table would be created from S3 and HDFS: - -From S3 -^^^^^^^^^^ - - -.. code-block:: postgres - - CREATE FOREIGN TABLE nba - ( - Name varchar(40), - Team varchar(40), - Number tinyint, - Position varchar(2), - Age tinyint, - Height varchar(4), - Weight real, - College varchar(40), - Salary float - ) - WRAPPER csv_fdw -- Text file - OPTIONS - ( LOCATION = 's3://sqream-demo-data/nba_players.csv', - RECORD_DELIMITER = '\r\n'; -- DOS delimited file - ) - ; - -.. _hdfs_external_table_demo: - -From HDFS -^^^^^^^^^^^^^^ - +Creating the external table +----------------------------- +Based on the source file structure, we we :ref:`create an external table` with the appropriate structure, and point it to the file. .. code-block:: postgres - CREATE FOREIGN TABLE nba + CREATE EXTERNAL TABLE nba ( Name varchar(40), Team varchar(40), @@ -109,20 +62,16 @@ From HDFS College varchar(40), Salary float ) - WRAPPER csv_fdw -- Text file - OPTIONS - ( - LOCATION = 'hdfs://hadoop-nn.piedpiper.com:8020/demo-data/nba_players.csv', - RECORD_DELIMITER = '\r\n'; -- DOS delimited file - ) - ; - - + USING FORMAT CSV -- Text file + WITH PATH 's3://sqream-demo-data/nba_players.csv' + RECORD DELIMITER '\r\n'; -- DOS delimited file -Querying foreign tables +The file format in this case is CSV, and it is stored as an :ref:`s3` object (if the path is on :ref:`hdfs`, change the URI accordingly). +We also took note that the record delimiter was a DOS newline (``\r\n``). +Querying external tables ------------------------------ -Let's peek at the data from the foreign table: +Let's peek at the data from the external table: .. code-block:: psql @@ -142,9 +91,7 @@ Let's peek at the data from the foreign table: Modifying data from staging ------------------------------- - One of the main reasons for staging data is to examine the contents and modify them before loading them. - Assume we are unhappy with weight being in pounds, because we want to use kilograms instead. We can apply the transformation as part of a query: .. code-block:: psql @@ -152,6 +99,7 @@ Assume we are unhappy with weight being in pounds, because we want to use kilogr t=> SELECT name, team, number, position, age, height, (weight / 2.205) as weight, college, salary . FROM nba . ORDER BY weight; + name | team | number | position | age | height | weight | college | salary -------------------------+------------------------+--------+----------+-----+--------+----------+-----------------------+--------- Nikola Pekovic | Minnesota Timberwolves | 14 | C | 30 | 6-11 | 139.229 | | 12100000 @@ -165,14 +113,14 @@ Assume we are unhappy with weight being in pounds, because we want to use kilogr Cristiano Felicio | Chicago Bulls | 6 | PF | 23 | 6-10 | 124.7166 | | 525093 [...] -Now, if we're happy with the results, we can convert the staged foreign table to a standard table +Now, if we're happy with the results, we can convert the staged external table to a standard table -Converting a foreign table to a standard database table +Converting an external table to a standard database table --------------------------------------------------------------- -:ref:`create_table_as` can be used to materialize a foreign table into a regular table. +:ref:`create_table_as` can be used to materialize an external table into a regular table. -.. tip:: If you intend to use the table multiple times, convert the foreign table to a standard table. +.. tip:: If you intend to use the table multiple times, convert the external table to a standard table. .. code-block:: psql @@ -182,6 +130,7 @@ Converting a foreign table to a standard database table . ORDER BY weight; executed t=> SELECT * FROM real_nba LIMIT 5; + name | team | number | position | age | height | weight | college | salary -----------------+------------------------+--------+----------+-----+--------+----------+-------------+--------- Nikola Pekovic | Minnesota Timberwolves | 14 | C | 30 | 6-11 | 139.229 | | 12100000 @@ -190,15 +139,12 @@ Converting a foreign table to a standard database table Jusuf Nurkic | Denver Nuggets | 23 | C | 21 | 7-0 | 126.9841 | | 1842000 Andre Drummond | Detroit Pistons | 0 | C | 22 | 6-11 | 126.5306 | Connecticut | 3272091 - Error handling and limitations ================================== - -* Error handling in foreign tables is limited. Any error that occurs during source data parsing will result in the statement aborting. +* Error handling in external tables is limited. Any error that occurs during source data parsing will result in the statement aborting. * - Foreign tables are logical and do not contain any data, their structure is not verified or enforced until a query uses the table. - + External tables are logical and do not contain any data, their structure is not verified or enforced until a query uses the table. For example, a CSV with the wrong delimiter may cause a query to fail, even though the table has been created successfully: .. code-block:: psql @@ -206,5 +152,4 @@ Error handling and limitations t=> SELECT * FROM nba; master=> select * from nba; Record delimiter mismatch during CSV parsing. User defined line delimiter \n does not match the first delimiter \r\n found in s3://sqream-demo-data/nba.csv - -* Since the data for a foreign table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against a foreign table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. +* Since the data for an external table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against an external table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. diff --git a/guides/operations/hardware_guide.rst b/operational_guides/hardware_guide.rst similarity index 100% rename from guides/operations/hardware_guide.rst rename to operational_guides/hardware_guide.rst diff --git a/operational_guides/hdfs.rst b/operational_guides/hdfs.rst new file mode 100644 index 000000000..274926e36 --- /dev/null +++ b/operational_guides/hdfs.rst @@ -0,0 +1,252 @@ +.. _hdfs: + +.. _back_to_top_hdfs: + +Using SQream in an HDFS Environment +======================================= + +.. _configuring_an_hdfs_environment_for_the_user_sqream: + +Configuring an HDFS Environment for the User **sqream** +---------------------------------------------------------- + +This section describes how to configure an HDFS environment for the user **sqream** and is only relevant for users with an HDFS environment. + +**To configure an HDFS environment for the user sqream:** + +1. Open your **bash_profile** configuration file for editing: + + .. code-block:: console + + $ vim /home/sqream/.bash_profile + +.. + Comment: - see below; do we want to be a bit more specific on what changes we're talking about? + + .. code-block:: console + + $ #PATH=$PATH:$HOME/.local/bin:$HOME/bin + + $ #export PATH + + $ # PS1 + $ #MYIP=$(curl -s -XGET "http://ip-api.com/json" | python -c 'import json,sys; jstr=json.load(sys.stdin); print jstr["query"]') + $ #PS1="\[\e[01;32m\]\D{%F %T} \[\e[01;33m\]\u@\[\e[01;36m\]$MYIP \[\e[01;31m\]\w\[\e[37;36m\]\$ \[\e[1;37m\]" + + $ SQREAM_HOME=/usr/local/sqream + $ export SQREAM_HOME + + $ export JAVA_HOME=${SQREAM_HOME}/hdfs/jdk + $ export HADOOP_INSTALL=${SQREAM_HOME}/hdfs/hadoop + $ export CLASSPATH=`${HADOOP_INSTALL}/bin/hadoop classpath --glob` + $ export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native + $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${SQREAM_HOME}/lib:$HADOOP_COMMON_LIB_NATIVE_DIR + + + $ PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin + $ export PATH + +3. Verify that the edits have been made: + + .. code-block:: console + + source /home/sqream/.bash_profile + +4. Check if you can access Hadoop from your machine: + + .. code-block:: console + + $ hadoop fs -ls hdfs://:8020/ + +.. + Comment: - + **NOTICE:** If you cannot access Hadoop from your machine because it uses Kerberos, see `Connecting a SQream Server to Cloudera Hadoop with Kerberos `_ + + +5. Verify that an HDFS environment exists for SQream services: + + .. code-block:: console + + $ ls -l /etc/sqream/sqream_env.sh + +.. _step_6: + + +6. If an HDFS environment does not exist for SQream services, create one (sqream_env.sh): + + .. code-block:: console + + $ #!/bin/bash + + $ SQREAM_HOME=/usr/local/sqream + $ export SQREAM_HOME + + $ export JAVA_HOME=${SQREAM_HOME}/hdfs/jdk + $ export HADOOP_INSTALL=${SQREAM_HOME}/hdfs/hadoop + $ export CLASSPATH=`${HADOOP_INSTALL}/bin/hadoop classpath --glob` + $ export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native + $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${SQREAM_HOME}/lib:$HADOOP_COMMON_LIB_NATIVE_DIR + + + $ PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin + $ export PATH + +:ref:`Back to top ` + + +.. _authenticate_hadoop_servers_that_require_kerberos: + +Authenticating Hadoop Servers that Require Kerberos +--------------------------------------------------- + +If your Hadoop server requires Kerberos authentication, do the following: + +1. Create a principal for the user **sqream**. + + .. code-block:: console + + $ kadmin -p root/admin@SQ.COM + $ addprinc sqream@SQ.COM + +2. If you do not know yor Kerberos root credentials, connect to the Kerberos server as a root user with ssh and run **kadmin.local**: + + .. code-block:: console + + $ kadmin.local + + Running **kadmin.local** does not require a password. + +3. If a password is not required, change your password to **sqream@SQ.COM**. + + .. code-block:: console + + $ change_password sqream@SQ.COM + +4. Connect to the hadoop name node using ssh: + + .. code-block:: console + + $ cd /var/run/cloudera-scm-agent/process + +5. Check the most recently modified content of the directory above: + + .. code-block:: console + + $ ls -lrt + +5. Look for a recently updated folder containing the text **hdfs**. + +The following is an example of the correct folder name: + + .. code-block:: console + + cd -hdfs- + + This folder should contain a file named **hdfs.keytab** or another similar .keytab file. + + + +.. + Comment: - Does "something" need to be replaced with "file name" + + +6. Copy the .keytab file to user **sqream's** Home directory on the remote machines that you are planning to use Hadoop on. + +7. Copy the following files to the **sqream sqream@server:/hdfs/hadoop/etc/hadoop:** directory: + + * core-site.xml + * hdfs-site.xml + +8. Connect to the sqream server and verify that the .keytab file's owner is a user sqream and is granted the correct permissions: + + .. code-block:: console + + $ sudo chown sqream:sqream /home/sqream/hdfs.keytab + $ sudo chmod 600 /home/sqream/hdfs.keytab + +9. Log into the sqream server. + +10. Log in as the user **sqream**. + +11. Navigate to the Home directory and check the name of a Kerberos principal represented by the following .keytab file: + + .. code-block:: console + + $ klist -kt hdfs.keytab + + The following is an example of the correct output: + + .. code-block:: console + + $ sqream@Host-121 ~ $ klist -kt hdfs.keytab + $ Keytab name: FILE:hdfs.keytab + $ KVNO Timestamp Principal + $ ---- ------------------- ------------------------------------------------------ + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + +12. Verify that the hdfs service named **hdfs/nn1@SQ.COM** is shown in the generated output above. + +13. Run the following: + + .. code-block:: console + + $ kinit -kt hdfs.keytab hdfs/nn1@SQ.COM + + 13. Check the output: + + .. code-block:: console + + $ klist + + The following is an example of the correct output: + + .. code-block:: console + + $ Ticket cache: FILE:/tmp/krb5cc_1000 + $ Default principal: sqream@SQ.COM + $ + $ Valid starting Expires Service principal + $ 09/16/2020 13:44:18 09/17/2020 13:44:18 krbtgt/SQ.COM@SQ.COM + +14. List the files located at the defined server name or IP address: + + .. code-block:: console + + $ hadoop fs -ls hdfs://:8020/ + +15. Do one of the following: + + * If the list below is output, continue with Step 16. + * If the list is not output, verify that your environment has been set up correctly. + +If any of the following are empty, verify that you followed :ref:`Step 6 ` in the **Configuring an HDFS Environment for the User sqream** section above correctly: + + .. code-block:: console + + $ echo $JAVA_HOME + $ echo $SQREAM_HOME + $ echo $CLASSPATH + $ echo $HADOOP_COMMON_LIB_NATIVE_DIR + $ echo $LD_LIBRARY_PATH + $ echo $PATH + +16. Verify that you copied the correct keytab file. + +17. Review this procedure to verify that you have followed each step. + +:ref:`Back to top ` \ No newline at end of file diff --git a/operational_guides/index.rst b/operational_guides/index.rst new file mode 100644 index 000000000..783e571b1 --- /dev/null +++ b/operational_guides/index.rst @@ -0,0 +1,26 @@ +.. _operational_guides: + +********************************** +Operational Guides +********************************** +The **Operational Guides** section describes processes that SQream users can manage to affect the way their system operates, such as creating storage clusters and monitoring query performance. + +This section summarizes the following operational guides: + +.. toctree:: + :maxdepth: 1 + :glob: + :titlesonly: + + + access_control + creating_or_cloning_a_storage_cluster + external_data + exporting_data + logging + monitoring_query_performance + security + saved_queries + seeing_system_objects_as_ddl + configuration + hardware_guide \ No newline at end of file diff --git a/guides/operations/logging.rst b/operational_guides/logging.rst similarity index 99% rename from guides/operations/logging.rst rename to operational_guides/logging.rst index 29a743668..a40e08601 100644 --- a/guides/operations/logging.rst +++ b/operational_guides/logging.rst @@ -158,7 +158,7 @@ The log is a CSV, with several fields. * - ``1000`` - ``SYSTEM`` - Worker startup message - - ``"Server Start Time - 2019-12-30 21:18:31, SQream ver{v2020.1}"`` + - ``"Server Start Time - 2019-12-30 21:18:31, SQream ver{v2020.2}"`` * - ``1002`` - ``SYSTEM`` - ``Metadata`` @@ -374,12 +374,12 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas OPTIONS ( LOCATION = '/home/rhendricks/sqream_storage/logs/**/sqream*.log', - DELIMITER = '|', + DELIMITER = '|' CONTINUE_ON_ERROR = true ) ; -For more information, see `Loading Logs with Foreign Tables `_. +For more information, see `Loading Logs with Foreign Tables `_. diff --git a/guides/operations/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst similarity index 97% rename from guides/operations/monitoring_query_performance.rst rename to operational_guides/monitoring_query_performance.rst index 53815b78b..d6d60dbe4 100644 --- a/guides/operations/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -1,34 +1,24 @@ .. _monitoring_query_performance: ********************************* -Monitoring query performance +Monitoring Query Performance ********************************* - -When analyzing options for query tuning, the first step is to analyze the query plan and execution. - +When analyzing options for query tuning, the first step is to analyze the query plan and execution. The query plan and execution details explains how SQream DB processes a query and where time is spent. - This document details how to analyze query performance with execution plans. - This guide focuses specifically on identifying bottlenecks and possible optimization techniques to improve query performance. - Performance tuning options for each query are different. You should adapt the recommendations and tips for your own workloads. - See also our :ref:`sql_best_practices` guide for more information about data loading considerations and other best practices. .. contents:: In this section: :local: -Setting up the system for monitoring +Setting Up the System for Monitoring ================================================= - By default, SQream DB logs execution details for every statement that runs for more than 60 seconds. If you want to see the execution details for a currently running statement, see :ref:`using_show_node_info` below. - - -Adjusting the logging frequency +Adjusting the Logging Frequency --------------------------------------- - To adjust the frequency of logging for statements, you may want to reduce the interval from 60 seconds down to, say, 5 or 10 seconds. Modify the configuration files and set the ``nodeInfoLoggingSec`` parameter as you see fit: @@ -46,18 +36,14 @@ say, 5 or 10 seconds. Modify the configuration files and set the ``nodeInfoLoggi "server":{ } } - After restarting the SQream DB cluster, the execution plan details will be logged to the :ref:`standard SQream DB logs directory`, as a message of type ``200``. - You can see these messages with a text viewer or with queries on the log :ref:`external_tables`. -Reading execution plans with a foreign table +Reading Execution Plans with a Foreign Table ----------------------------------------------------- - First, create a foreign table for the logs .. code-block:: postgres - CREATE FOREIGN TABLE logs ( start_marker VARCHAR(4), @@ -83,12 +69,10 @@ First, create a foreign table for the logs DELIMITER = '|' ) ; - Once you've defined the foreign table, you can run queries to observe the previously logged execution plans. This is recommended over looking at the raw logs. .. code-block:: psql - t=> SELECT message . FROM logs . WHERE message_type_id = 200 @@ -117,17 +101,13 @@ This is recommended over looking at the raw logs. .. _using_show_node_info: -The ``SHOW_NODE_INFO`` command +Using the ``SHOW_NODE_INFO`` Command ===================================== - The :ref:`show_node_info` command returns a snapshot of the current query plan, similar to ``EXPLAIN ANALYZE`` from other databases. - The :ref:`show_node_info` result, just like the periodically-logged execution plans described above, are an at-the-moment view of the compiler's execution plan and runtime statistics for the specified statement. - To inspect a currently running statement, execute the ``show_node_info`` utility function in a SQL client like :ref:`sqream sql`, the :ref:`SQream Studio Editor`, or any other :ref:`third party SQL terminal`. - In this example, we inspect a statement with statement ID of 176. The command looks like this: .. code-block:: psql @@ -147,17 +127,13 @@ In this example, we inspect a statement with statement ID of 176. The command lo 176 | 10 | CpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 9 | | | | 0 176 | 11 | ReadTable | 457 | 1 | 457 | 2019-12-25 23:53:13 | 10 | 4MB | | public.nba | 0.0004 -Understanding the query execution plan output +Understanding the Query Execution Plan Output ================================================== - Both :ref:`show_node_info` and the logged execution plans represents the query plan as a graph hierarchy, with data separated into different columns. - Each row represents a single logical database operation, which is also called a **node** or **chunk producer**. A node reports several metrics during query execution, such as how much data it has read and written, how many chunks and rows, and how much time has elapsed. - Consider the example show_node_info presented above. The source node with ID #11 (``ReadTable``), has a parent node ID #10 (``CpuDecompress``). If we were to draw this out in a graph, it'd look like this: - .. figure:: /_static/images/show_node_info_graph.png :height: 70em :align: center @@ -175,8 +151,6 @@ The last node, also called the sink, has a parent node ID of -1, meaning it has rankdir=tb; ranksep=0.95; node[shape=box3d, width=3.0, height=0.6, fontname="Consolas", fillcolor=SteelBlue2, style=filled]; - - PushToNetworkQueue [shape=house, fillcolor=SeaGreen1, style=filled]; ReadTable->CpuDecompress; @@ -195,7 +169,6 @@ The last node, also called the sink, has a parent node ID of -1, meaning it has DeferredGather->ReorderInput4; ReorderInput4->Rechunk2; Rechunk2->PushToNetworkQueue; - Rechunk2[label="Rechunk"]; ReorderInput4[label="ReorderInput"]; ReorderInput3[label="ReorderInput"]; @@ -204,24 +177,19 @@ The last node, also called the sink, has a parent node ID of -1, meaning it has GpuTransform3[label="GpuTransform"]; ReadTable [shape=house, style=filled, fillcolor=SeaGreen4]; - } - - When using :ref:`show_node_info`, a tabular representation of the currently running statement execution is presented. - See the examples below to understand how the query execution plan is instrumental in identifying bottlenecks and optimizing long-running statements. -Information presented in the execution plan +Information Presented in the Execution Plan ---------------------------------------------------- .. include:: /reference/sql/sql_statements/monitoring_commands/show_node_info.rst :start-line: 47 :end-line: 78 -Commonly seen nodes +Commonly Seen Nodes ---------------------- - .. list-table:: Node types :widths: auto :header-rows: 1 @@ -325,34 +293,26 @@ Commonly seen nodes .. tip:: The full list of nodes appears in the :ref:`Node types table`, as part of the :ref:`show_node_info` reference. - Examples ================== - In general, looking at the top three longest running nodes (as is detailed in the ``timeSum`` column) can indicate the biggest bottlenecks. - In the following examples you will learn how to identify and solve some common issues. .. contents:: In this section: :local: -1. Spooling to disk +1. Spooling to Disk ----------------------- - When there is not enough RAM to process a statement, SQream DB will spill over data to the ``temp`` folder in the storage disk. While this ensures that a statement can always finish processing, it can slow down the processing significantly. - It's worth identifying these statements, to figure out if the cluster is configured correctly, as well as potentially reduce the statement size. - You can identify a statement that spools to disk by looking at the ``write`` column in the execution details. A node that spools will have a value, shown in megabytes in the ``write`` column. - Common nodes that write spools include ``Join`` or ``LoopJoin``. -Identifying the offending nodes +Identifying the Offending Nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - #. Run a query. @@ -376,7 +336,6 @@ Identifying the offending nodes WHERE o_orderdate BETWEEN '1995-01-01' AND '1996-12-31') AS all_nations GROUP BY o_year ORDER BY o_year; - #. Observe the execution information by using the foreign table, or use ``show_node_info`` @@ -429,34 +388,27 @@ Identifying the offending nodes : 150,LoopJoin ,182369485,10,18236948,2020-09-04 18:31:47,149,12860MB,12860MB,inner,23.62 [...] : 199,ReadTable ,20000000,1,20000000,2020-09-04 18:30:33,198,0MB,,public.part,0.83 - Because of the relatively low amount of RAM in the machine and because the data set is rather large at around 10TB, SQream DB needs to spool. The total spool used by this query is around 20GB (1915MB + 2191MB + 3064MB + 12860MB). -Common solutions for reducing spool +Common Solutions for Reducing Spool ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * Increase the amount of spool memory available for the workers, as a proportion of the maximum statement memory. When the amount of spool memory is increased, SQream DB may not need to write to disk. This setting is called ``spoolMemoryGB``. Refer to the :ref:`configuration` guide. - * Reduce the amount of **workers** per host, and increase the amount of spool available to the (now reduced amount of) active workers. This may reduce the amount of concurrent statements, but will improve performance for heavy statements. - -2. Queries with large result sets +2. Queries with Large Result Sets ------------------------------------ - When queries have large result sets, you may see a node called ``DeferredGather``. - This gathering occurs when the result set is assembled, in preparation for sending it to the client. -Identifying the offending nodes +Identifying the Offending Nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - #. Run a query. @@ -483,7 +435,6 @@ Identifying the offending nodes WHERE r_name = 'AMERICA' AND o_orderdate BETWEEN '1995-01-01' AND '1996-12-31' AND high_selectivity(p_type = 'ECONOMY BURNISHED NICKEL'); - #. Observe the execution information by using the foreign table, or use ``show_node_info`` @@ -508,12 +459,10 @@ Identifying the offending nodes 494 | 194 | DeferredGather | 133241 | 20 | 6662 | 2020-09-04 19:07:03 | 193 | | | | 0.41 [...] 494 | 221 | ReadTable | 20000000 | 20 | 1000000 | 2020-09-04 19:07:01 | 220 | 20MB | | public.part | 0.1 - When you see ``DeferredGather`` operations taking more than a few seconds, that's a sign that you're selecting too much data. In this case, the DeferredGather with node ID 166 took over 21 seconds. #. Modify the statement to see the difference - Altering the select clause to be more restrictive will reduce the deferred gather time back to a few milliseconds. .. code-block:: postgres @@ -523,38 +472,29 @@ Identifying the offending nodes n2.n_name as nation FROM ... -Common solutions for reducing gather time +Common Solutions for Reducing Gather Time ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * Reduce the effect of the preparation time. Avoid selecting unnecessary columns (``SELECT * FROM...``), or reduce the result set size by using more filters. - .. `` - -3. Inefficient filtering +3. Inefficient Filtering -------------------------------- - When running statements, SQream DB tries to avoid reading data that is not needed for the statement by :ref:`skipping chunks`. - If statements do not include efficient filtering, SQream DB will read a lot of data off disk. In some cases, you need the data and there's nothing to do about it. However, if most of it gets pruned further down the line, it may be efficient to skip reading the data altogether by using the :ref:`metadata`. -Identifying the situation +Identifying the Situation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - We consider the filtering to be inefficient when the ``Filter`` node shows that the number of rows processed is less than a third of the rows passed into it by the ``ReadTable`` node. - For example: - #. Run a query. In this example, we execute a modified query from the TPC-H benchmark. Our ``lineitem`` table contains 600,037,902 rows. - .. code-block:: postgres SELECT o_year, @@ -576,7 +516,6 @@ For example: AND high_selectivity(p_type = 'ECONOMY BURNISHED NICKEL')) AS all_nations GROUP BY o_year ORDER BY o_year; - #. Observe the execution information by using the foreign table, or use ``show_node_info`` @@ -614,7 +553,6 @@ For example: 559 | 214 | Rechunk | 20000000 | 20 | 1000000 | 2020-09-07 11:11:57 | 213 | | | | 0 559 | 215 | CpuDecompress | 20000000 | 20 | 1000000 | 2020-09-07 11:11:57 | 214 | | | | 0 559 | 216 | ReadTable | 20000000 | 20 | 1000000 | 2020-09-07 11:11:57 | 215 | 20MB | | public.part | 0 - * The ``Filter`` on line 9 has processed 12,007,447 rows, but the output of ``ReadTable`` on ``public.lineitem`` @@ -627,7 +565,6 @@ For example: of the data, but the entire table was read. However, this table is small enough that we can ignore it. #. Modify the statement to see the difference - Altering the statement to have a ``WHERE`` condition on the clustered ``l_orderkey`` column of the ``lineitem`` table will help SQream DB skip reading the data. .. code-block:: postgres @@ -671,37 +608,27 @@ For example: 586 | 197 | CpuDecompress | 494927872 | 8 | 61865984 | 2020-09-07 13:20:44 | 196 | | | | 0 586 | 198 | ReadTable | 494927872 | 8 | 61865984 | 2020-09-07 13:20:44 | 197 | 6595MB | | public.lineitem | 0.09 [...] - - In this example, the filter processed 494,621,593 rows, while the output of ``ReadTable`` on ``public.lineitem`` was 494,927,872 rows. This means that it has filtered out all but 0.01% (:math:`1 - \dfrac{494621593}{494927872} = 0.01\%`) of the data that was read. The metadata skipping has performed very well, and has pre-filtered the data for us by pruning unnecessary chunks. -Common solutions for improving filtering +Common Solutions for Improving Filtering ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * Use :ref:`clustering keys and naturally ordered data` in your filters. - * Avoid full table scans when possible - -4. Joins with ``varchar`` keys +4. Joins with ``varchar`` Keys ----------------------------------- - Joins on long text keys, such as ``varchar(100)`` do not perform as well as numeric data types or very short text keys. - -Identifying the situation +Identifying the Situation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - When a join is inefficient, you may note that a query spends a lot of time on the ``Join`` node. - For example, consider these two table structures: .. code-block:: postgres - CREATE TABLE t_a ( amt FLOAT NOT NULL, @@ -711,14 +638,12 @@ For example, consider these two table structures: flag VARCHAR(10) NOT NULL, fk VARCHAR(50) NOT NULL ); - CREATE TABLE t_b ( id VARCHAR(50) NOT NULL prob FLOAT NOT NULL, j INT NOT NULL, ); - #. Run a query. @@ -731,7 +656,6 @@ For example, consider these two table structures: FROM t_a JOIN t_b ON (t_a.fk = t_b.id) GROUP BY t_a.country_code - #. Observe the execution information by using the foreign table, or use ``show_node_info`` @@ -760,12 +684,9 @@ For example, consider these two table structures: 5 | 41 | CpuDecompress | 10000000 | 2 | 5000000 | 2020-09-08 18:26:09 | 40 | | | | 0 5 | 42 | ReadTable | 10000000 | 2 | 5000000 | 2020-09-08 18:26:09 | 41 | 14MB | | public.t_a | 0 - -Improving query performance +Improving Query Performance ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * In general, try to avoid ``VARCHAR`` as a join key. As a rule of thumb, ``BIGINT`` works best as a join key. - * Convert text values on-the-fly before running the query. For example, the :ref:`crc64` function takes a text input and returns a ``BIGINT`` hash. @@ -779,7 +700,6 @@ Improving query performance FROM t_a JOIN t_b ON (crc64_join(t_a.fk) = crc64_join(t_b.id)) GROUP BY t_a.country_code - The execution below has been shortened, but note the highlighted rows for ``Join``. The ``Join`` node went from taking nearly 70 seconds, to just 6.67 seconds for joining 1.5 billion records. @@ -804,23 +724,16 @@ Improving query performance * You can map some text values to numeric types by using a dimension table. Then, reconcile the values when you need them by joining the dimension table. - 5. Sorting on big ``VARCHAR`` fields --------------------------------------- - In general, SQream DB automatically inserts a ``Sort`` node which arranges the data prior to reductions and aggregations. - When running a ``GROUP BY`` on large ``VARCHAR`` fields, you may see nodes for ``Sort`` and ``Reduce`` taking a long time. - -Identifying the situation +Identifying the Situation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - When running a statement, inspect it with :ref:`show_node_info`. If you see ``Sort`` and ``Reduce`` among your top five longest running nodes, there is a potential issue. - For example: - #. Run a query to test it out. @@ -876,7 +789,6 @@ For example: 30 | 10 | Rechunk | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 9 | | | | 0 30 | 11 | CpuDecompress | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 10 | | | | 0 30 | 12 | ReadTable | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 11 | 520MB | | public.t_inefficient | 0.05 - #. We can look to see if there's any shrinking we can do on the ``GROUP BY`` key .. code-block:: psql @@ -885,14 +797,11 @@ For example: max --- 3 - With a maximum string length of just 3 characters, our ``VARCHAR(100)`` is way oversized. - #. We can recreate the table with a more restrictive ``VARCHAR(3)``, and can examine the difference in performance: .. code-block:: psql - t=> CREATE TABLE t_efficient . AS SELECT i, . amt, @@ -918,36 +827,28 @@ For example: This time, the entire query took just 4.75 seconds, or just about 91% faster. -Improving sort performance on text keys +Improving Sort Performance on Text Keys ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - When using VARCHAR, ensure that the maximum length defined in the table structure is as small as necessary. For example, if you're storing phone numbers, don't define the field as ``VARCHAR(255)``, as that affects sort performance. You can run a query to get the maximum column length (e.g. ``MAX(LEN(a_column))``), and potentially modify the table structure. - .. _high_selectivity_data_opt: -6. High selectivity data +6. High Selectivity Data -------------------------- - Selectivity is the ratio of cardinality to the number of records of a chunk. We define selectivity as :math:`\frac{\text{Distinct values}}{\text{Total number of records in a chunk}}` - SQream DB has a hint called ``HIGH_SELECTIVITY``, which is a function you can wrap a condition in. - The hint signals to SQream DB that the result of the condition will be very sparse, and that it should attempt to rechunk the results into fewer, fuller chunks. - .. note:: SQream DB doesn't do this automatically because it adds a significant overhead on naturally ordered and well-clustered data, which is the more common scenario. -Identifying the situation +Identifying the Situation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - This is easily identifiable - when the amount of average of rows in a chunk is small, following a ``Filter`` operation. - Consider this execution plan: .. code-block:: psql @@ -959,34 +860,25 @@ Consider this execution plan: 30 | 38 | Filter | 18160 | 74 | 245 | 2020-09-10 12:17:09 | 37 | | | | 0.012 [...] 30 | 44 | ReadTable | 77000000 | 74 | 1040540 | 2020-09-10 12:17:09 | 43 | 277MB | | public.dim | 0.058 - - The table was read entirely - 77 million rows into 74 chunks. - The filter node reduced the output to just 18,160 relevant rows, but they're distributed across the original 74 chunks. All of these rows could fit in one single chunk, instead of spanning 74 rather sparse chunks. -Improving performance with high selectivity hints +Improving Performance with High Selectivity Hints ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * Use when there's a ``WHERE`` condition on an :ref:`unclustered column`, and when you expect the filter to cut out more than 60% of the result set. - * Use when the data is uniformly distributed or random - 7. Performance of unsorted data in joins ------------------------------------------ - When data is not well-clustered or naturally ordered, a join operation can take a long time. -Identifying the situation +Identifying the Situation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - When running a statement, inspect it with :ref:`show_node_info`. If you see ``Join`` and ``DeferredGather`` among your top five longest running nodes, there is a potential issue. - In this case, we're also interested in the number of chunks produced by these nodes. Consider this execution plan: @@ -1009,23 +901,18 @@ Consider this execution plan: 30 | 38 | Filter | 18160 | 74 | 245 | 2020-09-10 12:17:09 | 37 | | | | 0.012 [...] 30 | 44 | ReadTable | 77000000 | 74 | 1040540 | 2020-09-10 12:17:09 | 43 | 277MB | | public.dim | 0.058 - * ``Join`` is the node that matches rows from both table relations. * ``DeferredGather`` gathers the required column chunks to decompress - Pay special attention to the volume of data removed by the ``Filter`` node. The table was read entirely - 77 million rows into 74 chunks. - The filter node reduced the output to just 18,160 relevant rows, but they're distributed across the original 74 chunks. All of these rows could fit in one single chunk, instead of spanning 74 rather sparse chunks. -Improving join performance when data is sparse +Improving Join Performance when Data is Sparse ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - You can tell SQream DB to reduce the amount of chunks involved, if you know that the filter is going to be quite agressive by using the :ref:`HIGH_SELECTIVITY` hint described :ref:`above`. This forces the compiler to rechunk the data into fewer chunks. - To tell SQream DB to rechunk the data, wrap a condition (or several) in the ``HIGH_SELECTIVITY`` hint: .. code-block:: postgres @@ -1047,26 +934,20 @@ To tell SQream DB to rechunk the data, wrap a condition (or several) in the ``HI AND EnterpriseID=1150 AND MSISDN='9724871140341'; - -8. Manual join reordering +8. Manual Join Reordering -------------------------------- - When joining multiple tables, you may wish to change the join order to join the smallest tables first. Identifying the situation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - When joining more than two tables, the ``Join`` nodes will be the most time-consuming nodes. -Changing the join order +Changing the Join Order ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Always prefer to join the smallest tables first. - .. note:: We consider small tables to be tables that only retain a small amount of rows after conditions are applied. This bears no direct relation to the amount of total rows in the table. - Changing the join order can reduce the query runtime significantly. In the examples below, we reduce the time from 27.3 seconds to just 6.4 seconds. @@ -1077,7 +958,6 @@ from 27.3 seconds to just 6.4 seconds. SELECT SUM(l_extendedprice / 100.0*(1 - l_discount / 100.0)) AS revenue, c_nationkey FROM lineitem --6B Rows, ~183GB - JOIN orders --1.5B Rows, ~55GB ON l_orderkey = o_orderkey JOIN customer --150M Rows, ~12GB @@ -1097,7 +977,6 @@ from 27.3 seconds to just 6.4 seconds. SELECT SUM(l_extendedprice / 100.0*(1 - l_discount / 100.0)) AS revenue, c_nationkey FROM orders --1.5B Rows, ~55GB - JOIN customer --150M Rows, ~12GB ON c_custkey = o_custkey JOIN lineitem --6B Rows, ~183GB @@ -1110,9 +989,6 @@ from 27.3 seconds to just 6.4 seconds. AND l_shipdate <= dateadd(DAY,122,'1994-01-01') GROUP BY c_nationkey - - -Further reading +Further Reading ================== - See our :ref:`sql_best_practices` guide for more information about query optimization and data loading considerations. \ No newline at end of file diff --git a/guides/operations/optimization_best_practices.rst b/operational_guides/optimization_best_practices.rst similarity index 55% rename from guides/operations/optimization_best_practices.rst rename to operational_guides/optimization_best_practices.rst index 2ee93dbe0..1cc0ca01e 100644 --- a/guides/operations/optimization_best_practices.rst +++ b/operational_guides/optimization_best_practices.rst @@ -4,7 +4,7 @@ Optimization and Best Practices ********************************** -This topic explains some best practices of working with SQream. +This topic explains some best practices of working with SQream DB. See also our :ref:`monitoring_query_performance` guide for more information. @@ -13,16 +13,16 @@ See also our :ref:`monitoring_query_performance` guide for more information. .. _table_design_best_practices: -Table Design +Table design ============== This section describes best practices and guidelines for designing tables. -Using Date and Datetime Types for Columns +Use date and datetime types for columns ----------------------------------------- -When creating tables with dates or timestamps, using the purpose-built ``DATE`` and ``DATETIME`` types over integer types or ``VARCHAR`` will bring performance and storage footprint improvements, and in many cases huge performance improvements (as well as data integrity benefits). SQream stores dates and datetimes very efficiently and can strongly optimize queries using these specific types. +When creating tables with dates or timestamps, using the purpose-built ``DATE`` and ``DATETIME`` types over integer types or ``VARCHAR`` will bring performance and storage footprint improvements, and in many cases huge performance improvements (as well as data integrity benefits). SQream DB stores dates and datetimes very efficiently and can strongly optimize queries using these specific types. -Shortening VARCHAR Length +Reduce varchar length to a minimum -------------------------------------- With the ``VARCHAR`` type, the length has a direct effect on query performance. @@ -31,23 +31,23 @@ If the size of your column is predictable, by defining an appropriate column len * Data loading issues can be identified more quickly -* SQream can reserve less memory for decompression operations +* SQream DB can reserve less memory for decompression operations * Third-party tools that expect a data size are less likely to over-allocate memory -Avoiding Flattening or Denormalizing Data +Don't flatten or denormalize data ----------------------------------- -SQream executes JOIN operations very effectively. It is almost always better to JOIN tables at query-time rather than flatten/denormalize your tables. +SQream DB executes JOIN operations very effectively. It is almost always better to JOIN tables at query-time rather than flatten/denormalize your tables. This will also reduce storage size and reduce row-lengths. We highly suggest using ``INT`` or ``BIGINT`` as join keys, rather than a text/string type. -Converting Foreign Tables to Native Tables +Convert foreign tables to native tables ------------------------------------------- -SQream's native storage is heavily optimized for analytic workloads. It is always faster for querying than other formats, even columnar ones such as Parquet. It also enables the use of additional metadata to help speed up queries, in some cases by many orders of magnitude. +SQream DB's native storage is heavily optimized for analytic workloads. It is always faster for querying than other formats, even columnar ones such as Parquet. It also enables the use of additional metadata to help speed up queries, in some cases by many orders of magnitude. You can improve the performance of all operations by converting :ref:`foreign tables` into native tables by using the :ref:`create_table_as` syntax. @@ -59,46 +59,52 @@ For example, The one situation when this wouldn't be as useful is when data will be only queried once. -Leverating Column Data Information +Use information about the column data to your advantage ------------------------------------------------------------- Knowing the data types and their ranges can help design a better table. -Identifying Relevance of Setting NULL or NOT NULL Values +Set ``NULL`` or ``NOT NULL`` when relevant ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For example, if a value cannot be omitted (or ``NULL``), you must specify a ``NOT NULL`` constraint on the columns. +For example, if a value can't be missing (or ``NULL``), specify a ``NOT NULL`` constraint on the columns. -In addition to saving data storage, specifying ``NOT NULL`` informs the query compiler that a column cannot have a ``NULL`` value, which can improve query performance. +Not only does specifying ``NOT NULL`` save on data storage, it lets the query compiler know that a column cannot have a ``NULL`` value, which can improve query performance. -Shortening VARCHAR Length +Keep VARCHAR lengths to a minimum ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Although long strings do not affect storage, they require a lot of memory while queries are being run. If a column's string length is less than 50 characters, specify ``VARCHAR(50)`` rather than an arbitrarily large number. +While it won't make a big difference in storage, large strings allocate a lot of memory at query time. -Sorting Data +If a column's string length never exceeds 50 characters, specify ``VARCHAR(50)`` rather than an arbitrarily large number. + + +Sorting ============== -Sorting data is an important factor in minimizing storage size and improving query performance for the following reasons: -* Minimizing storage saves on physical resources and increases performance by reducing overall disk I/O. Prioritize the sorting of low-cardinality columns. This reduces the number of chunks and extents that SQream reads during query execution. +Data sorting is an important factor in minimizing storage size and improving query performance. -* Where possible, sort columns with the lowest cardinality first. Avoid sorting ``VARCHAR`` and ``TEXT`` columns with lengths exceeding 50 characters. +* Minimizing storage saves on physical resources and increases performance by reducing overall disk I/O. Prioritize the sorting of low-cardinality columns. This reduces the number of chunks and extents that SQream DB reads during query execution. + +* Where possible, sort columns with the lowest cardinality first. Avoid sorting ``VARCHAR`` and ``TEXT/NVARCHAR`` columns with lengths exceeding 50 characters. * For longer-running queries that run on a regular basis, performance can be improved by sorting data based on the ``WHERE`` and ``GROUP BY`` parameters. Data can be sorted during insert by using :ref:`external_tables` or by using :ref:`create_table_as`. .. _query_best_practices: -Best Practices for Writing SQL Queries +Query best practices ===================== This section describes best practices for writing SQL queries. -Reducing Data Sets Before Joining Tables +Reduce data sets before joining tables ----------------------------------------- Reducing the input to a ``JOIN`` clause can increase performance. -Some queries benefit from retreiving a reduced dataset as a subquery prior to a join, as shown in the following example: +Some queries benefit from retreiving a reduced dataset as a subquery prior to a join. + +For example, .. code-block:: postgres @@ -107,7 +113,7 @@ Some queries benefit from retreiving a reduced dataset as a subquery prior to a WHERE p_date BETWEEN '2018-07-01' AND '2018-07-31' GROUP BY 1; -This can be rewritten as follows: +Can be rewritten as .. code-block:: postgres @@ -119,11 +125,13 @@ This can be rewritten as follows: group by 2) AS fact ON dim.store_id=fact.store_id; -Using an ANSI JOIN +Prefer the ANSI JOIN ---------------------------- -SQream prefers the ANSI JOIN syntax. -In some cases ANSI JOINs performs better than the non-ANSI variety, as shown in the following example: +SQream DB prefers the ANSI JOIN syntax. +In some cases, the ANSI JOIN performs better than the non-ANSI variety. + +For example, this ANSI JOIN example will perform better: .. code-block:: postgres :caption: ANSI JOIN will perform better @@ -135,7 +143,7 @@ In some cases ANSI JOINs performs better than the non-ANSI variety, as shown in JOIN "Customers" as c ON s.c_id = c.id AND c.id = 20301125; -SQream supports the following non-ANSI JOIN, but does not recommend using it: +This non-ANSI JOIN is supported, but not recommended: .. code-block:: postgres :caption: Non-ANSI JOIN may not perform well @@ -150,16 +158,19 @@ SQream supports the following non-ANSI JOIN, but does not recommend using it: .. _high_selectivity: -Using a High Selectivity Hint +Use the high selectivity hint -------------------------------- -**Selectivity** is the ratio of cardinality to the number of records of a chunk. Selectivity is defined as ``:math:`\frac{\text{Distinct values}}{\text{Total number of records in a chunk}}```. +Selectivity is the ratio of cardinality to the number of records of a chunk. We define selectivity as :math:`\frac{\text{Distinct values}}{\text{Total number of records in a chunk}}` -SQream employees a hint function called ``HIGH_SELECTIVITY``, which is a function that can be used for wrapping a condition. The hint signals to SQream that the result of the condition is very sparse and to rechunk the results into fewer, fuller chunks. +SQream DB has a hint function called ``HIGH_SELECTIVITY``, which is a function you can wrap a condition in. -SQream recommends using the high selectivity hint when you expect a predicate to filter out most values, such as when data is dispersed over many chunks, indicating that the data has not been optimally clustered. +The hint signals to SQream DB that the result of the condition will be very sparse, and that it should attempt to rechunk +the results into fewer, fuller chunks. -The following example shows data that is not clustered optimally: +Use the high selectivity hint when you expect a predicate to filter out most values. For example, when the data is dispersed over lots of chunks (meaning that the data is :ref:`not well-clustered`). + +For example, .. code-block:: postgres @@ -167,19 +178,19 @@ The following example shows data that is not clustered optimally: WHERE HIGH_SELECTIVITY(p_date = '2018-07-01') GROUP BY 1; -This hint tells the query compiler that the ``WHERE`` condition is expected to filter out more than 60% of values. While it does not affect query results, using it correctly can improve query performance. - -.. tip:: The ``HIGH_SELECTIVITY()`` hint function can only be used as part of the ``WHERE`` clause and cannot be used in equijoin conditions, cases, or in the select list. +This hint tells the query compiler that the ``WHERE`` condition is expected to filter out more than 60% of values. It never affects the query results, but when used correctly can improve query performance. -For more information about identifying scenarios for the high selectivity hint, see the :ref:`Monitoring Query Performance Guide`. +.. tip:: The ``HIGH_SELECTIVITY()`` hint function can only be used as part of the ``WHERE`` clause. It can't be used in equijoin conditions, cases, or in the select list. -For more information about optimal data clustering, see :ref:`not well-clustered`). +Read more about identifying the scenarios for the high selectivity hint in our :ref:`Monitoring query performance guide`. -Casting Smaller Types to Avoid Aggregate Overflow +Cast smaller types to avoid overflow in aggregates ------------------------------------------------------ When using an ``INT`` or smaller type, the ``SUM`` and ``COUNT`` operations return a value of the same type. -To avoid overflow on large results, cast the column up to a larger type, as shown in the following example: +To avoid overflow on large results, cast the column up to a larger type. + +For example .. code-block:: postgres @@ -187,13 +198,13 @@ To avoid overflow on large results, cast the column up to a larger type, as show GROUP BY 1; -Preferring ``COUNT(*)`` and ``COUNT`` on Non-Nullable Columns +Prefer ``COUNT(*)`` and ``COUNT`` on non-nullable columns ------------------------------------------------------------ -SQream optimizes ``COUNT(*)`` queries very strongly. This also applies to ``COUNT(column_name)`` on non-nullable columns. Using ``COUNT(column_name)`` on a nullable column operate quickly, but much slower than the previous variations. +SQream DB optimizes ``COUNT(*)`` queries very strongly. This also applies to ``COUNT(column_name)`` on non-nullable columns. Using ``COUNT(column_name)`` on a nullable column will operate quickly, but much slower than the previous variations. -Returning Only Required Columns +Return only required columns ------------------------------- Returning only the columns you need to client programs can improve overall query performance. @@ -201,10 +212,10 @@ This also reduces the overall result set, which can improve performance in third SQream is able to optimize out unneeded columns very strongly due to its columnar storage. -Using Saved Queries to Reduce Recurring Compilation Duration +Use saved queries to reduce recurring compilation time ------------------------------------------------------- -:ref:`saved_queries` are compiled when they are created. The query plan is saved in SQream's metadata for later re-use. +:ref:`saved_queries` are compiled when they are created. The query plan is saved in SQream DB's metadata for later re-use. Because the query plan is saved, they can be used to reduce compilation overhead, especially with very complex queries, such as queries with lots of values in an :ref:`IN` predicate. @@ -212,9 +223,10 @@ When executed, the saved query plan is recalled and executed on the up-to-date d See how to use saved queries in the :ref:`saved queries guide`. -Pre-Filtering to Reduce JOIN Complexity +Pre-filter to reduce :ref:`JOIN` complexity -------------------------------------------------------- -The following is the correct syntax for pre-filtering to reduce JOIN complexity by filtering and reducing table sizes before joining them: + +Filter and reduce table sizes prior to joining on them .. code-block:: postgres @@ -225,7 +237,7 @@ The following is the correct syntax for pre-filtering to reduce JOIN complexity WHERE p_date BETWEEN '2019-07-01' AND '2019-07-31' GROUP BY store_name; -The example above can be rewritten as follows: +Can be rewritten as: .. code-block:: postgres @@ -237,25 +249,27 @@ The example above can be rewritten as follows: FROM fact WHERE p_date BETWEEN '2019-07-01' AND '2019-07-31' GROUP BY store_id) AS fact ON dim.store_id = fact.store_id; - -For more information about reducing JOIN complexity, see :ref:`JOIN`. .. _data_loading_considerations: -Data Loading Considerations +Data loading considerations ================================= -Enabling and Using Natural Data Sorting +Allow and use natural sorting on data ---------------------------------------- -Tabular data is often naturally ordered along a dimension, such as a timestamp or area. This natural order is a major factor for query performance during later stages, as data that is naturally sorted can be more easily compressed and analyzed with SQream's metadata collection. +Very often, tabular data is already naturally ordered along a dimension such as a timestamp or area. + +This natural order is a major factor for query performance later on, as data that is naturally sorted can be more easily compressed and analyzed with SQream DB's metadata collection. -For example, when data is sorted by timestamp, filtering on this timestamp is more effective than filtering on an unordered column. Natural ordering can also be used for effective **DELETE** operations. +For example, when data is sorted by timestamp, filtering on this timestamp is more effective than filtering on an unordered column. -For more information about Delete operations, see :ref:`delete operations`. +Natural ordering can also be used for effective :ref:`delete` operations. -Further Reading and Monitoring Query Performance +Further reading and monitoring query performance ======================================================= -For more information about built-in monitoring utilities, see the :ref:`monitoring_query_performance` guide. The Monitoring Query Performance Guide also gives concerete examples for improving query performance. + +Read our :ref:`monitoring_query_performance` guide to learn how to use the built in monitoring utilities. +The guide also gives concerete examples for improving query performance. diff --git a/guides/features/external_data/s3.rst b/operational_guides/s3.rst similarity index 100% rename from guides/features/external_data/s3.rst rename to operational_guides/s3.rst diff --git a/guides/features/saved_queries.rst b/operational_guides/saved_queries.rst similarity index 98% rename from guides/features/saved_queries.rst rename to operational_guides/saved_queries.rst index 23f47647b..d554b4dc8 100644 --- a/guides/features/saved_queries.rst +++ b/operational_guides/saved_queries.rst @@ -1,10 +1,10 @@ .. _saved_queries: *********************** -Saved queries +Saved Queries *********************** -Saved queries can be used to reuse a query plan for a query to eliminate compilation times for repeated queries. They also provide a way to implement 'parameterized views'. +Saved queries can be used to reuse a query plan for a query to eliminate compilation times for repeated queries. They also provide a way to implement 'parameterized views'. How saved queries work ========================== diff --git a/guides/operations/security.rst b/operational_guides/security.rst similarity index 95% rename from guides/operations/security.rst rename to operational_guides/security.rst index 7cda38a7d..598c40196 100644 --- a/guides/operations/security.rst +++ b/operational_guides/security.rst @@ -47,9 +47,6 @@ After creating a second ``SUPERUSER`` role, remove or change the default credent No database user should ever use the default ``SUPERUSER`` role in a production environment. -If you don't change the user role itself, change the password of the default ``SUPERUSER``. See the :ref:`change password` section of our :ref:`access control` guide. - - Create distinct user roles -------------------------------- @@ -81,7 +78,6 @@ Follow these recommendations to strengthen passwords: * Mix letters and numbers * Include non-alphanumeric characters (except ``"`` and ``'``) - Use TLS/SSL when possible ---------------------------- diff --git a/guides/features/viewing_system_objects_as_ddl.rst b/operational_guides/viewing_system_objects_as_ddl.rst similarity index 97% rename from guides/features/viewing_system_objects_as_ddl.rst rename to operational_guides/viewing_system_objects_as_ddl.rst index ce1fc59b3..fe4649c3b 100644 --- a/guides/features/viewing_system_objects_as_ddl.rst +++ b/operational_guides/viewing_system_objects_as_ddl.rst @@ -1,7 +1,7 @@ -.. _seeing_system_objects_as_sql: +.. _viewing_system_objects_as_ddl: ******************************** -Seeing system objects as DDL +Seeing System Objects as DDL ******************************** Dump specific objects @@ -10,7 +10,7 @@ Dump specific objects Tables ---------- -See :ref:`get_ddl` for more information. +See :ref:`get_ddl` for more information. .. rubric:: Examples diff --git a/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst b/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst new file mode 100644 index 000000000..3fcac7861 --- /dev/null +++ b/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst @@ -0,0 +1,23 @@ +.. _configuring_your_instance_of_sqream: + +**************************** +Configuring Your Instance of SQreams +**************************** +The **Configuration** section lets you edit parameters from one centralized location. While you can edit these parameters from the **worker configuration file (config.json)** or from your CLI, you can also modify them in Studio in an easy-to-use format. + +Configuring your instance of SQream in Studio is session-based, which enables you to edit parameters per session on your own device. +Because session-based configurations are not persistent and are deleted when your session ends, you can edit your required parameters while avoiding conflicts between parameters edited on different devices at different points in time. + +Editing Your Parameters +------------------------------- +When configuring your instance of SQream in Studio you can edit parameters for the **Generic** and **Admin** parameters only. + +Studio includes two types of parameters: toggle switches, such as **flipJoinOrder**, and text fields, such as **logSysLevel**. After editing a parameter, you can reset each one to its previous value or to its default value individually, or revert all parameters to their default setting simultaneously. Note that you must click **Save** to save your configurations. + +You can hover over the **information** icon located on each parameter to read a short description of its behavior. + +Exporting and Importing Configuration Files +------------------------- +You can also export and import your configuration settings into a .json file. This allows you to easily edit your parameters and to share this file with other users if required. + +For more information about configuring your instance of SQream, see :ref:`Configuration`. \ No newline at end of file diff --git a/sqream_studio_5.4.3/creating_assigning_and_managing_roles_and_permissions.rst b/sqream_studio_5.4.3/creating_assigning_and_managing_roles_and_permissions.rst new file mode 100644 index 000000000..9f0f7f39a --- /dev/null +++ b/sqream_studio_5.4.3/creating_assigning_and_managing_roles_and_permissions.rst @@ -0,0 +1,98 @@ +.. _creating_assigning_and_managing_roles_and_permissions: + +.. _roles_5.4.3: + +**************************** +Creating, Assigning, and Managing Roles and Permissions +**************************** +The **Creating, Assigning, and Managing Roles and Permissions** describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +--------------- +In the **Roles** area you can create and assign roles and manage user permissions. + +The **Type** column displays one of the following assigned role types: + +.. list-table:: + :widths: 15 75 + :header-rows: 1 + + * - Role Type + - Description + * - Groups + - Roles with no users. + * - Enabled users + - Users with log-in permissions and a password. + * - Disabled users + - Users with log-in permissions and with a disabled password. An admin may disable a user's password permissions to temporary disable access to the system. + +.. note:: If you disable a password, when you enable it you have to create a new one. + +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` + + +Viewing Information About a Role +-------------------- +Clicking a role in the roles table displays the following information: + + * **Parent Roles** - displays the parent roles of the selected role. Roles inherit all roles assigned to the parent. + + :: + + * **Members** - displays all members that the role has been assigned to. The arrow indicates the roles that the role has inherited. Hovering over a member displays the roles that the role is inherited from. + + :: + + * **Permissions** - displays the role's permissions. The arrow indicates the permissions that the role has inherited. Hovering over a permission displays the roles that the permission is inherited from. + +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` + + +Creating a New Role +-------------------- +You can create a new role by clicking **New Role**. + + + +An admin creates a **user** by granting login permissions and a password to a role. Each role is defined by a set of permissions. An admin can also group several roles together to form a **group** to manage them simultaneously. For example, permissions can be granted to or revoked on a group level. + +Clicking **New Role** lets you do the following: + + * Add and assign a role name (required) + * Enable or disable log-in permissions for the role. + * Set a password. + * Assign or delete parent roles. + * Add or delete permissions. + * Grant the selected user with superuser permissions. + +From the New Role panel you view directly and indirectly (or inherited) granted permissions. Disabled permissions have no connect permissions for the referenced database and are displayed in gray text. You can add or remove permissions from the **Add permissions** field. From the New Role panel you can also search and scroll through the permissions. In the **Search** field you can use the **and** operator to search for strings that fulfill multiple criteria. + +When adding a new role, you must select the **Enable login for this role** and **Has password** check boxes. + +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` + +Editing a Role +-------------------- +Once you've created a role, clicking the **Edit Role** button lets you do the following: + + * Edit the role name. + * Enable or disable log-in permissions. + * Set a password. + * Assign or delete parent roles. + * Assign a role **administrator** permissions. + * Add or delete permissions. + * Grant the selected user with superuser permissions. + +From the Edit Role panel you view directly and indirectly (or inherited) granted permissions. Disabled permissions have no connect permissions for the referenced database and are displayed in gray text. You can add or remove permissions from the **Add permissions** field. From the Edit Role panel you can also search and scroll through the permissions. In the **Search** field you can use the **and** operator to search for strings that fulfill multiple criteria. + +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` + +Deleting a Role +----------------- +Clicking the **delete** icon displays a confirmation message with the amount of users and groups that will be impacted by deleting the role. + +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` \ No newline at end of file diff --git a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst new file mode 100644 index 000000000..65863ab6c --- /dev/null +++ b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst @@ -0,0 +1,416 @@ +.. _executing_statements_and_running_queries_from_the_editor: + +.. _editor_top_5.4.3: + +**************************** +Executing Statements and Running Queries from the Editor +**************************** +The **Editor** is used for the following: + +* Selecting an active database and executing queries. +* Performing statement-related operations and showing metadata. +* Executing pre-defined queries. +* Writing queries and statements and viewing query results. + +The following is a brief description of the Editor panels: + + +.. list-table:: + :widths: 10 34 56 + :header-rows: 1 + + * - No. + - Element + - Description + * - 1 + - :ref:`Toolbar` + - Used to select the active database you want to work on, limit the number of rows, save query, etc. + * - 2 + - :ref:`Database Tree and System Queries panel` + - Shows a hierarchy tree of databases, views, tables, and columns + * - 3 + - :ref:`Statement panel` + - Used for writing queries and statements + * - 4 + - :ref:`Results panel` + - Shows query results and execution information. + + + +.. _top_5.4.3: + +.. _studio_5.4.3_editor_toolbar: + +Executing Statements from the Toolbar +================ +You can access the following from the Toolbar pane: + +* **Database dropdown list** - select a database that you want to run statements on. + + :: + +* **Service dropdown list** - select a service that you want to run statements on. The options in the service dropdown menu depend on the database you select from the **Database** dropdown list. + + :: + +* **Execute** - lets you set which statements to execute. The **Execute** button toggles between **Execute** and **Stop**, and can be used to stop an active statement before it completes: + + * **Statements** - executes the statement at the location of the cursor. + * **Selected** - executes only the highlighted text. This mode should be used when executing subqueries or sections of large queries (as long as they are valid SQLs). + * **All** - executes all statements in a selected tab. + +* **Format SQL** - Lets you reformat and reindent statements. + + :: + +* **Download query** - Lets you download query text to your computer. + + :: + +* **Open query** - Lets you upload query text from your computer. + + :: + +* **Max Rows** - By default, the Editor fetches only the first 10,000 rows. You can modify this number by selecting an option from the **Max Rows** dropdown list. Note that setting a higher number may slow down your browser if the result is very large. This number is limited to 100,000 results. To see a higher number, you can save the results in a file or a table using the :ref:`create_table_as` command. + + +For more information on stopping active statements, see the :ref:`STOP_STATEMENT` command. + +:ref:`Back to Executing Statements and Running Queries from the Editor` + + +.. _studio_5.4.3_editor_db_tree: + +Performing Statement-Related Operations from the Database Tree +================ +From the Database Tree you can perform statement-related operations and show metadata (such as a number indicating the amount of rows in the table). + + + + + +The database object functions are used to perform the following: + +* The **SELECT** statement - copies the selected table's **columns** into the Statement panel as ``SELECT`` parameters. + + :: + +* The **copy** feature |icon-copy| - copies the selected table's **name** into the Statement panel. + + :: + +* The **additional operations** |icon-dots| - displays the following additional options: + + + + + +.. list-table:: + :widths: 30 70 + :header-rows: 1 + + * - Function + - Description + * - Insert statement + - Generates an `INSERT `_ statement for the selected table in the editing area. + * - Delete statement + - Generates a `DELETE `_ statement for the selected table in the editing area. + * - Create Table As statement + - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. + * - Rename statement + - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. + * - Adding column statement + - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. + * - Truncate table statement + - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. + * - Drop table statement + - Generates a ``DROP`` statement for the selected object in the editing area. + * - Table DDL + - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL `_. + * - DDL Optimizer + - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. + +Optimizing Database Tables Using the DDL Optimizer +----------------------- +The **DDL Optimizer** tab analyzes database tables and recommends possible optimizations according to SQream's best practices. + +As described in the previous table, you can access the DDL Optimizer by clicking the **additional options icon** and selecting **DDL Optimizer**. + +The following table describes the DDL Optimizer screen: + +.. list-table:: + :widths: 15 75 + :header-rows: 1 + + * - Element + - Description + * - Column area + - Shows the column **names** and **column types** from the selected table. You can scroll down or to the right/left for long column lists. + * - Optimization area + - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``VARCHAR`` fields), and the default percent buffer to add to ``VARCHAR`` lengths (10%). Attempts to determine field nullability. + * - Run Optimizer + - Starts the optimization process. + +Clicking **Run Optimizer** adds a tab to the Statement panel showing the optimized results of the selected object. + +For more information, see `Optimization and Best Practices `_. + +Executing Pre-Defined Queries from the System Queries Panel +--------------- +The **System Queries** panel lets you execute predefined queries and includes the following system query types: + +* **Catalog queries** - used for analyzing table compression rates, users and permissions, etc. + + :: + +* **Admin queries** - queries related to available (describe the functionality in a general way). Queries useful for SQream database management. + +Clicking an item pastes the query into the Statement pane, and you can undo a previous operation by pressing **Ctrl + Z**. + +.. _studio_5.4.3_editor_statement_area: + +Writing Statements and Queries from the Statement Panel +============== +The multi-tabbed statement area is used for writing queries and statements, and is used in tandem with the toolbar. When writing and executing statements, you must first select a database from the **Database** dropdown menu in the toolbar. When you execute a statement, it passes through a series of statuses until completed. Knowing the status helps you with statement maintenance, and the statuses are shown in the **Results panel**. + +The auto-complete feature assists you when writing statements by suggesting statement options. + +The following table shows the statement statuses: + +.. list-table:: + :widths: 45 160 + :header-rows: 1 + + * - Status + - Description + * - Pending + - The statement is pending. + * - In queue + - The statement is waiting for execution. + * - Initializing + - The statement has entered execution checks. + * - Executing + - The statement is executing. + * - Statement stopped + - The statement has been stopped. + +You can add and name new tabs for each statement that you need to execute, and Studio preserves your created tabs when you switch between databases. You can add new tabs by clicking |icon-plus| , which creates a new tab to the right with a default name of SQL and an increasing number. This helps you keep track of your statements. + +You can also rename the default tab name by double-clicking it and typing a new name and write multiple statements in tandem in the same tab by separating them with semicolons (``;``).If too many tabs to fit into the Statement Pane are open at the same time, the tab arrows are displayed. You can scroll through the tabs by clicking |icon-left| or |icon-right|, and close tabs by clicking |icon-close|. You can also close all tabs at once by clicking **Close all** located to the right of the tabs. + +.. tip:: If this is your first time using SQream, see `Getting Started `_. + + +.. Keyboard shortcuts +.. ^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. :kbd:`Ctrl` +: kbd:`Enter` - Execute all queries in the statement area, or just the highlighted part of the query. + +.. :kbd:`Ctrl` + :kbd:`Space` - Auto-complete the current keyword + +.. :kbd:`Ctrl` + :kbd:`↑` - Switch to next tab. + +.. :kbd:`Ctrl` + :kbd:`↓` - Switch to previous tab + +.. _studio_editor_results_5.4.3: + +:ref:`Back to Executing Statements and Running Queries from the Editor` + +.. _studio_5.4.3_editor_results: + +.. _results_panel_5.4.3: + +Viewing Statement and Query Results from the Results Panel +============== +The results panel shows statement and query results. By default, only the first 10,000 results are returned, although you can modify this from the :ref:`studio_editor_toolbar`, as described above. By default, executing several statements together opens a separate results tab for each statement. Executing statements together executes them serially, and any failed statement cancels all subsequent executions. + +.. image:: /_static/images/results_panel.png + +The following is a brief description of the Results panel views highlighted in the figure above: + +.. list-table:: + :widths: 45 160 + :header-rows: 1 + + * - Element + - Description + * - :ref:`Results view` + - Lets you view search query results. + * - :ref:`Execution Details view` + - Lets you analyze your query for troubleshooting and optimization purposes. + * - :ref:`SQL view` + - Lets you see the SQL view. + + +.. _results_view_5.4.3: + +:ref:`Back to Executing Statements and Running Queries from the Editor` + +Searching Query Results in the Results View +---------------- +The **Results view** lets you view search query results. + +From this view you can also do the following: + +* View the amount of time (in seconds) taken for a query to finish executing. +* Switch and scroll between tabs. +* Close all tabs at once. +* Enable keeping tabs by selecting **Keep tabs**. +* Sort column results. + +Saving Results to the Clipboard +^^^^^^^^^^^^ +The **Save results to clipboard** function lets you save your results to the clipboard to paste into another text editor or into Excel for further analysis. + +.. _save_results_to_local_file_5.4.3: + +Saving Results to a Local File +^^^^^^^^^^^^ +The **Save results to local file** functions lets you save your search query results to a local file. Clicking **Save results to local file** downloads the contents of the Results panel to an Excel sheet. You can then use copy and paste this content into other editors as needed. + +In the Results view you can also run parallel statements, as described in **Running Parallel Statements** below. + +.. _running_parallel_statements_5.4.3: + +Running Parallel Statements +^^^^^^^^^^^^ +While Studio's default functionality is to open a new tab for each executed statement, Studio supports running parallel statements in one statement tab. Running parallel statements requires using macros and is useful for advanced users. + +The following shows the syntax for running parallel statements: + +.. code-block:: console + + $ @@ parallel + $ $$ + $ select 1; + $ select 2; + $ select 3; + $ $$ + + +:ref:`Back to Viewing Statement and Query Results from the Results Panel` + +.. _execution_details_view_5.4.3: + +.. _execution_tree_5.4.3: + +Execution Details View +-------------- +The **Execution Details View** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +^^^^^^^^^^^^ +Clicking **Execution Details View** displays the **Execution Tree**, which is a chronological tree of processes that occurred to execute your queries. The purpose of the Execution Tree is to analyze all aspects of your query for troubleshooting and optimization purposes, such as resolving queries with an exceptionally long runtime. + +.. note:: The **Execution Details View** button is enabled only when a query takes longer than five seconds. + +From this screen you can scroll in, out, and around the execution tree with the mouse to analyze all aspects of your query. You can navigate around the execution tree by dragging or by using the mini-map in the bottom right corner. + +.. image:: /_static/images/execution_tree_1.png + +You can also search for query data by pressing **Ctrl+F** or clicking the search icon |icon-search| in the search field in the top right corner and typing text. + +.. image:: /_static/images/search_field.png + +Pressing **Enter** takes you directly to the next result matching your search criteria, and pressing **Shift + Enter** takes you directly to the previous result. You can also search next and previous results using the up and down arrows. + +.. |icon-search| image:: /_static/images/studio_icon_search.png + :align: middle + +The nodes are color-coded based on the following: + +* **Slow nodes** - red +* **In progress nodes** - yellow +* **Completed nodes** - green +* **Pending nodes** - white +* **Currently selected node** - blue +* **Search result node** - purple (in the mini-map) + +The execution tree displays the same information as shown in the plain view in tree format. + +The Execution Tree tracks each phase of your query in real time as a vertical tree of nodes. Each node refers to an operation that occurred on the GPU or CPU. When a phase is completed, the next branch begins to its right until the entire query is complete. Joins are displayed as two parallel branches merged together in a node called **Join**, as shown in the figure above. The nodes are connected by a line indicating the number of rows passed from one node to the next. The width of the line indicates the amount of rows on a logarithmic scale. + +Each node displays a number displaying its **node ID**, its **type**, **table name** (if relevant), **status**, and **runtime**. The nodes are color-coded for easy identification. Green nodes indicate **completed nodes**, yellow indicates **nodes in progress**, and red indicates **slowest nodes**, typically joins, as shown below: + +.. image:: /_static/images/nodes.png + +Viewing Query Statistics +^^^^^^^^^^^^ +The following statistical information is displayed in the top left corner, as shown in the figure above: + +* **Query Statistics**: + + * **Elapsed** - the total time taken for the query to complete. + * **Result rows** - the amount of rows fetched. + * **Running nodes completion** + * **Total query completion** - the amount of the total execution tree that was executed (nodes marked green). + +* **Slowest Nodes** information is displayed in the top right corner in red text. Clicking the slowest node centers automatically on that node in the execution tree. + +You can also view the following **Node Statistics** in the top right corner for each individual node by clicking a node: + +.. list-table:: + :widths: 45 160 + :header-rows: 1 + + * - Element + - Description + * - Node type + - Shows the node type. + * - Status + - Shows the execution status. + * - Time + - The total time taken to execute. + * - Rows + - Shows the number of produced rows passed to the next node. + * - Chunks + - Shows number of produced chunks. + * - Average rows per chunk + - Shows the number of average rows per chunk. + * - Table (for **ReadTable** and joins only) + - Shows the table name. + * - Write (for joins only) + - Shows the total date size written to the disk. + * - Read (for **ReadTable** and joins only) + - Shows the total data size read from the disk. + +Note that you can scroll the Node Statistics table. You can also download the execution plan table in .csv format by clicking the download arrow |icon-download| in the upper-right corner. + +.. |icon-download| image:: /_static/images/studio_icon_download.png + :align: middle + +Using the Plain View +^^^^^^^^^^^^ +You can use the **Plain View** instead of viewing the execution tree by clicking **Plain View** |icon-plain| in the top right corner. The plain view displays the same information as shown in the execution tree in table format. + +.. |icon-plain| image:: /_static/images/studio_icon_plain.png + :align: middle + + + + +The plain view lets you view a query’s execution plan for monitoring purposes and highlights rows based on how long they ran relative to the entire query. + +This can be seen in the **timeSum** column as follows: + +* **Rows highlighted red** - longest runtime +* **Rows highlighted orange** - medium runtime +* **Rows highlighted yellow** - shortest runtime + +:ref:`Back to Viewing Statement and Query Results from the Results Panel` + +.. _sql_view_5.4.3: + +Viewing Wrapped Strings in the SQL View +------------------ +The SQL View panel allows you to more easily view certain queries, such as a long string that appears on one line. The SQL View makes it easier to see by wrapping it so that you can see the entire string at once. It also reformats and organizes query syntax entered in the Statement panel for more easily locating particular segments of your queries. The SQL View is identical to the **Format SQL** feature in the Toolbar, allowing you to retain your originally constructed query while viewing a more intuitively structured snapshot of it. + +.. _save_results_to_clipboard_5.4.3: + +:ref:`Back to Viewing Statement and Query Results from the Results Panel` + +:ref:`Back to Executing Statements and Running Queries from the Editor` diff --git a/sqream_studio_5.4.3/getting_started.rst b/sqream_studio_5.4.3/getting_started.rst new file mode 100644 index 000000000..7f401f5fa --- /dev/null +++ b/sqream_studio_5.4.3/getting_started.rst @@ -0,0 +1,61 @@ +.. _getting_started: + +**************************** +Getting Started with SQream Acceleration Studio 5.4.3 +**************************** +Setting Up and Starting Studio +---------------- +Studio is included with all `dockerized installations of SQream DB `_. When starting Studio, it listens on the local machine on port 8080. + +Logging In to Studio +--------------- +**To log in to SQream Studio:** + +1. Open a browser to the host on **port 8080**. + + For example, if your machine IP address is ``192.168.0.100``, insert the IP address into the browser as shown below: + + .. code-block:: console + + $ http://192.168.0.100:8080 + +2. Fill in your SQream DB login credentials. These are the same credentials used for :ref:`sqream sql` or JDBC. + + When you sign in, the License Warning is displayed. + +Navigating Studio's Main Features +------------- +When you log in, you are automatically taken to the **Editor** screen. The Studio's main functions are displayed in the **Navigation** pane on the left side of the screen. + +From here you can navigate between the main areas of the Studio: + +.. list-table:: + :widths: 10 90 + :header-rows: 1 + + * - Element + - Description + * - :ref:`Dashboard` + - Lets you monitor system health and manage queues and workers. + * - :ref:`Editor` + - Lets you select databases, perform statement operations, and write and execute queries. + * - :ref:`Logs` + - Lets you view usage logs. + * - :ref:`Roles` + - Lets you create users and manage user permissions. + * - :ref:`Configuration` + - Lets you configure your instance of SQream. + +By clicking the user icon, you can also use it for logging out and viewing the following: + +* User information +* Connection type +* SQream version +* SQream Studio version +* License expiration date +* License storage capacity +* Log out + +.. _back_to_dashboard_5.4.3: + +.. _studio_dashboard_5.4.3: diff --git a/sqream_studio_5.4.3/index.rst b/sqream_studio_5.4.3/index.rst new file mode 100644 index 000000000..023fa265a --- /dev/null +++ b/sqream_studio_5.4.3/index.rst @@ -0,0 +1,19 @@ +.. _sqream_studio_5.4.3: + +********************************** +SQream Acceleration Studio 5.4.3 +********************************** +The SQream Acceleration Studio is a web-based client for use with SQream. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQream clusters. + +This section describes how to use the SQream Accleration Studio version 5.4.3: + +.. toctree:: + :maxdepth: 1 + :glob: + + getting_started + monitoring_workers_and_services_from_the_dashboard + executing_statements_and_running_queries_from_the_editor + viewing_logs + creating_assigning_and_managing_roles_and_permissions + configuring_your_instance_of_sqream \ No newline at end of file diff --git a/sqream_studio_5.4.3/monitoring_workers_and_services_from_the_dashboard.rst b/sqream_studio_5.4.3/monitoring_workers_and_services_from_the_dashboard.rst new file mode 100644 index 000000000..993b11761 --- /dev/null +++ b/sqream_studio_5.4.3/monitoring_workers_and_services_from_the_dashboard.rst @@ -0,0 +1,265 @@ +.. _monitoring_workers_and_services_from_the_dashboard: + +.. _back_to_dashboard_5.4.3: + +**************************** +Monitoring Workers and Services from the Dashboard +**************************** +The **Dashboard** is used for the following: + +* Monitoring system health. +* Viewing, monitoring, and adding defined service queues. +* Viewing and managing worker status and add workers. + +The following is an image of the Dashboard: + +.. image:: /_static/images/dashboard.png + +You can only access the Dashboard if you signed in with a ``SUPERUSER`` role. + +The following is a brief description of the Dashboard panels: + +.. list-table:: + :widths: 10 25 65 + :header-rows: 1 + + * - No. + - Element + - Description + * - 1 + - :ref:`Services panel` + - Used for viewing and monitoring the defined service queues. + * - 2 + - :ref:`Workers panel` + - Monitors system health and shows each Sqreamd worker running in the cluster. + * - 3 + - :ref:`License information` + - Shows the remaining amount of days left on your license. + + +.. _data_storage_panel_5.4.3: + + + +:ref:`Back to Monitoring Workers and Services from the Dashboard` + +.. _services_panel_5.4.3: + +Subscribing to Workers from the Services Panel +-------------------------- +Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined `service queues `_. + + + +The following is a brief description of each pane: + +.. list-table:: + :widths: 10 90 + :header-rows: 1 + + * - No. + - Description + * - 1 + - Adds a worker to the selected service. + * - 2 + - Shows the service name. + * - 3 + - Shows a trend graph of queued statements loaded over time. + * - 4 + - Adds a service. + * - 5 + - Shows the currently processed queries belonging to the service/total queries for that service in the system (including queued queries). + +Adding A Service +^^^^^^^^^^^^^^^^^^^^^ +You can add a service by clicking **+ Add** and defining the service name. + +.. note:: If you do not associate a worker with the new service, it will not be created. + +You can manage workers from the **Workers** panel. For more information about managing workers, see the following: + +* :ref:`Managing Workers from the Workers Panel` +* `Workers `_ + +:ref:`Back to Monitoring Workers and Services from the Dashboard` + +.. _workers_panel_5.4.3: + +Managing Workers from the Workers Panel +------------ +From the **Workers** panel you can do the following: + +* :ref:`View workers ` +* :ref:`Add a worker to a service` +* :ref:`View a worker's active query information` +* :ref:`View a worker's execution plan` + +.. _view_workers_5.4.3: + +Viewing Workers +^^^^^^^^ +The **Worker** panel shows each worker (``sqreamd``) running in the cluster. Each worker has a status bar that represents the status over time. The status bar is divided into 20 equal segments, showing the most dominant activity in that segment. + +From the **Scale** dropdown menu you can set the time scale of the displayed information +You can hover over segments in the status bar to see the date and time corresponding to each activity type: + +* **Idle** – the worker is idle and available for statements. +* **Compiling** – the worker is compiling a statement and is preparing for execution. +* **Executing** – the worker is executing a statement after compilation. +* **Stopped** – the worker was stopped (either deliberately or due to an error). +* **Waiting** – the worker was waiting on an object locked by another worker. + +.. _add_worker_to_service_5.4.3: + +Adding A Worker to A Service +^^^^^^^^^^^^^^^^^^^^^ +You can add a worker to a service by clicking the **add** button. + + + +Clicking the **add** button shows the selected service's workers. You can add the selected worker to the service by clicking **Add Worker**. Adding a worker to a service does not break associations already made between that worker and other services. + + +.. _view_worker_query_information_5.4.3: + +Viewing A Worker's Active Query Information +^^^^^^^^^^^^^^^^^^^^^ +You can view a worker's active query information by clicking **Queries**, which displays them in the selected service. + + +Each statement shows the **query ID**, **status**, **service queue**, **elapsed time**, **execution time**, and **estimated completion status**. In addition, each statement can be stopped or expanded to show its execution plan and progress. For more information on viewing a statement's execution plan and progress, see :ref:`Viewing a Worker's Execution Plan ` below. + +Viewing A Worker's Host Utilization +^^^^^^^^^^^^^^^^^^^^^ + +While viewing a worker's query information, clicking the **down arrow** expands to show the host resource utilization. + + + +The graphs show the resource utilization trends over time, and the **CPU memory** and **utilization** and the **GPU utilization** values on the right. You can hover over the graph to see more information about the activity at any point on the graph. + +Error notifications related to statements are displayed, and you can hover over them for more information about the error. + + +.. _view_worker_execution_plan_5.4.3: + +Viewing a Worker's Execution Plan +^^^^^^^^^^^^^^^^^^^^^ + +Clicking the ellipsis in a service shows the following additional options: + +* **Stop Query** - stops the query. +* **Show Execution Plan** - shows the execution plan as a table. The columns in the **Show Execution Plan** table can be sorted. + +For more information on the current query plan, see `SHOW_NODE_INFO `_. For more information on checking active sessions across the cluster, see `SHOW_SERVER_STATUS `_. + +.. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst + :start-line: 67 + :end-line: 84 + +Managing Worker Status +^^^^^^^^^^^^^^^^^^^^^ + +In some cases you may want to stop or restart workers for maintenance purposes. Each Worker line has a :kbd:`⋮` menu used for stopping, starting, or restarting workers. + + +Starting or restarting workers terminates all queries related to that worker. When you stop a worker, its background turns gray. + + + + +.. |icon-user| image:: /_static/images/studio_icon_user.png + :align: middle + +.. |icon-dots| image:: /_static/images/studio_icon_dots.png + :align: middle + +.. |icon-editor| image:: /_static/images/studio_icon_editor.png + :align: middle + +.. |icon-copy| image:: /_static/images/studio_icon_copy.png + :align: middle + +.. |icon-select| image:: /_static/images/studio_icon_select.png + :align: middle + +.. |icon-dots| image:: /_static/images/studio_icon_dots.png + :align: middle + +.. |icon-filter| image:: /_static/images/studio_icon_filter.png + :align: middle + +.. |icon-ddl-edit| image:: /_static/images/studio_icon_ddl_edit.png + :align: middle + +.. |icon-run-optimizer| image:: /_static/images/studio_icon_run_optimizer.png + :align: middle + +.. |icon-generate-create-statement| image:: /_static/images/studio_icon_generate_create_statement.png + :align: middle + +.. |icon-plus| image:: /_static/images/studio_icon_plus.png + :align: middle + +.. |icon-close| image:: /_static/images/studio_icon_close.png + :align: middle + +.. |icon-left| image:: /_static/images/studio_icon_left.png + :align: middle + +.. |icon-right| image:: /_static/images/studio_icon_right.png + :align: middle + +.. |icon-format-sql| image:: /_static/images/studio_icon_format.png + :align: middle + +.. |icon-download-query| image:: /_static/images/studio_icon_download_query.png + :align: middle + +.. |icon-open-query| image:: /_static/images/studio_icon_open_query.png + :align: middle + +.. |icon-execute| image:: /_static/images/studio_icon_execute.png + :align: middle + +.. |icon-stop| image:: /_static/images/studio_icon_stop.png + :align: middle + +.. |icon-dashboard| image:: /_static/images/studio_icon_dashboard.png + :align: middle + +.. |icon-expand| image:: /_static/images/studio_icon_expand.png + :align: middle + +.. |icon-scale| image:: /_static/images/studio_icon_scale.png + :align: middle + +.. |icon-expand-down| image:: /_static/images/studio_icon_expand_down.png + :align: middle + +.. |icon-add| image:: /_static/images/studio_icon_add.png + :align: middle + +.. |icon-add-worker| image:: /_static/images/studio_icon_add_worker.png + :align: middle + +.. |keep-tabs| image:: /_static/images/studio_keep_tabs.png + :align: middle + +:ref:`Back to Monitoring Workers and Services from the Dashboard` + + + +.. _license_information_5.4.3: + +License Information +---------------------- +The license information section shows the following: + + * The amount of time in days remaining on the license. + * The license storage capacity. + +.. image:: /_static/images/license_storage_capacity.png + + +:ref:`Back to Monitoring Workers and Services from the Dashboard` diff --git a/sqream_studio_5.4.3/viewing_logs.rst b/sqream_studio_5.4.3/viewing_logs.rst new file mode 100644 index 000000000..7f98bea5e --- /dev/null +++ b/sqream_studio_5.4.3/viewing_logs.rst @@ -0,0 +1,122 @@ +.. _viewing_logs: + +.. _logs_top_5.4.3: + +**************************** +Viewing Logs +**************************** +The **Logs** screen is used for viewing logs and includes the following elements: + +.. list-table:: + :widths: 15 75 + :header-rows: 1 + + * - Element + - Description + * - :ref:`Filter area` + - Lets you filter the data shown in the table. + * - :ref:`Query tab` + - Shows basic query information logs, such as query number and the time the query was run. + * - :ref:`Session tab` + - Shows basic session information logs, such as session ID and user name. + * - :ref:`System tab` + - Shows all system logs. + * - :ref:`Log lines tab` + - Shows the total amount of log lines. + + +.. _filter_5.4.3: + +Filtering Table Data +------------- +From the Logs tab, from the **FILTERS** area you can also apply the **TIMESPAN**, **ONLY ERRORS**, and additional filters (**Add**). The **Timespan** filter lets you select a timespan. The **Only Errors** toggle button lets you show all queries, or only queries that generated errors. The **Add** button lets you add additional filters to the data shown in the table. The **Filter** button applies the selected filter(s). + +Other filters require you to select an item from a dropdown menu: + +* INFO +* WARNING +* ERROR +* FATAL +* SYSTEM + +You can also export a record of all of your currently filtered logs in Excel format by clicking **Download** located above the Filter area. + +.. _queries_5.4.3: + +:ref:`Back to Viewing Logs` + + +Viewing Query Logs +---------- +The **QUERIES** log area shows basic query information, such as query number and the time the query was run. The number next to the title indicates the amount of queries that have been run. + +From the Queries area you can see and sort by the following: + +* Query ID +* Start time +* Query +* Compilation duration +* Execution duration +* Total duration +* Details (execution details, error details, successful query details) + +In the Queries table, you can click on the **Statement ID** and **Query** items to set them as your filters. In the **Details** column you can also access additional details by clicking one of the **Details** options for a more detailed explanation of the query. + +:ref:`Back to Viewing Logs` + +.. _sessions_5.4.3: + +Viewing Session Logs +---------- +The **SESSIONS** tab shows the sessions log table and is used for viewing activity that has occurred during your sessions. The number at the top indicates the amount of sessions that have occurred. + +From here you can see and sort by the following: + +* Timestamp +* Connection ID +* Username +* Client IP +* Login (Success or Failed) +* Duration (of session) +* Configuration Changes + +In the Sessions table, you can click on the **Timestamp**, **Connection ID**, and **Username** items to set them as your filters. + +:ref:`Back to Viewing Logs` + +.. _system_5.4.3: + +Viewing System Logs +---------- +The **SYSTEM** tab shows the system log table and is used for viewing all system logs. The number at the top indicates the amount of sessions that have occurred. Because system logs occur less frequently than queries and sessions, you may need to increase the filter timespan for the table to display any system logs. + +From here you can see and sort by the following: + +* Timestamp +* Log type +* Message + +In the Systems table, you can click on the **Timestamp** and **Log type** items to set them as your filters. In the **Message** column, you can also click on an item to show more information about the message. + +:ref:`Back to Viewing Logs` + +.. _log_lines_5.4.3: + +Viewing All Log Lines +---------- +The **LOG LINES** tab is used for viewing the total amount of log lines in a table. From here users can view a more granular breakdown of log information collected by Studio. The other tabs (QUERIES, SESSIONS, and SYSTEM) show a filtered form of the raw log lines. For example, the QUERIES tab shows an aggregation of several log lines. + +From here you can see and sort by the following: + +* Timestamp +* Message level +* Worker hostname +* Worker port +* Connection ID +* Database name +* User name +* Statement ID + +In the **LOG LINES** table, you can click on any of the items to set them as your filters. + +:ref:`Back to Viewing Logs` \ No newline at end of file diff --git a/guides/client_drivers/cpp/connect_test.cpp b/third_party_tools/client_drivers/cpp/connect_test.cpp similarity index 100% rename from guides/client_drivers/cpp/connect_test.cpp rename to third_party_tools/client_drivers/cpp/connect_test.cpp diff --git a/guides/client_drivers/cpp/index.rst b/third_party_tools/client_drivers/cpp/index.rst similarity index 100% rename from guides/client_drivers/cpp/index.rst rename to third_party_tools/client_drivers/cpp/index.rst diff --git a/guides/client_drivers/cpp/insert_test.cpp b/third_party_tools/client_drivers/cpp/insert_test.cpp similarity index 100% rename from guides/client_drivers/cpp/insert_test.cpp rename to third_party_tools/client_drivers/cpp/insert_test.cpp diff --git a/third_party_tools/client_drivers/index.rst b/third_party_tools/client_drivers/index.rst new file mode 100644 index 000000000..7ae1894f4 --- /dev/null +++ b/third_party_tools/client_drivers/index.rst @@ -0,0 +1,113 @@ +.. _client_drivers: + +************************************ +Client Drivers for |latest_version| +************************************ + + + +The guides on this page describe how to use the Sqream DB client drivers and client applications with Sqream DB. + +Client Driver Downloads +============================= + +All Operating Systems +--------------------------- +The following are applicable to all operating systems: + +.. _jdbc: + +* **JDBC** - recommended installation via ``mvn``: + + * `JDBC .jar file `_ - sqream-jdbc-4.4.0 (.jar) + * `JDBC driver `_ + + +.. _python: + +* **Python** - Recommended installation via ``pip``: + + * `Python .tar file `_ - pysqream v3.1.3 (.tar.gz) + * `Python driver `_ + + +.. _nodejs: + +* **Node.JS** - Recommended installation via ``npm``: + + * `Node.JS `_ - sqream-v4.2.4 (.tar.gz) + * `Node.JS driver `_ + + +.. _tableau_connector: + +* **Tableau**: + + * `Tableau connector `_ - SQreamDB (.taco) + * `Tableau manual installation `_ + + + + +Windows +-------------- +The following are applicable to Windows: + + +* **JDBC installer** - `SQream_JDBC_Driver_v2020.2.0.exe `_ - Windows installer for JDBC driver, with Tableau connector. + + :: + +* **ODBC installer** - SQream Drivers v2020.2.0, with Tableau customizations. Please contact your `Sqream represenative `_ for this installer. + + For more information on installing and configuring ODBC on Windows, see :ref:`Install and configure ODBC on Windows `. + + +* **Net driver** - `SQream .Net driver v3.0.2 `_ + + + +Linux +-------------- +The following are applicable to Linux: + +* `SQream SQL (x86_64) `_ - sqream-sql-v2020.1.1_stable.x86_64.tar.gz +* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for Intel-based machines + + :: + +* `SQream SQL*(IBM POWER9) `_ - sqream-sql-v2020.1.1_stable.ppc64le.tar.gz +* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for IBM POWER9-based machines + + :: + +* `ODBC Installer `_ - sqream_odbc_4.0.0_x86_64_linux.tar.gz +* :ref:`Linux installer for ODBC`. Please contact your SQream representative for this installer. + + :: + + +* C++ connector - `libsqream-4.0 `_ +* `C++ shared object library `_ + + +.. toctree:: + :maxdepth: 4 + :caption: Client Driver Documentation: + :titlesonly: + + jdbc/index + python/index + nodejs/index + odbc/index + cpp/index + + + +.. rubric:: Need help? + +If you couldn't find what you're looking for, we're always happy to help. Visit `SQream's support portal `_ for additional support. + +.. rubric:: Looking for older drivers? + +If you're looking for an older version of SQream DB drivers, versions 1.10 through 2019.2.1 are available at https://sqream.com/product/client-drivers/ . diff --git a/guides/client_drivers/jdbc/index.rst b/third_party_tools/client_drivers/jdbc/index.rst similarity index 77% rename from guides/client_drivers/jdbc/index.rst rename to third_party_tools/client_drivers/jdbc/index.rst index 423754c1a..07e384e89 100644 --- a/guides/client_drivers/jdbc/index.rst +++ b/third_party_tools/client_drivers/jdbc/index.rst @@ -12,25 +12,25 @@ The JDBC driver requires Java 1.8 or newer. .. contents:: In this topic: :local: -Installing the JDBC Driver +Installing the JDBC driver ================================== Prerequisites ---------------- -The SQream JDBC driver requires Java 1.8 or newer. We recommend either Oracle Java or OpenJDK. +The SQream DB JDBC driver requires Java 1.8 or newer. We recommend either Oracle Java or OpenJDK. **Oracle Java** -To download and install Java 8 from Oracle for your platform, see `Java Downloads for All Operating Systems `_. - +Download and install Java 8 from Oracle for your platform +https://www.java.com/en/download/manual.jsp **OpenJDK** -For Linux and BSD, see `How to download and install prebuilt OpenJDK packages `_. +For Linux and BSD, see https://openjdk.java.net/install/ -For Windows, SQream recommends `Zulu 8 `_. +For Windows, SQream recommends Zulu 8 https://www.azul.com/downloads/zulu-community/?&version=java-8-lts&architecture=x86-64-bit&package=jdk .. _get_jdbc_jar: @@ -40,7 +40,7 @@ Getting the JAR file The JDBC driver is provided as a zipped JAR file, available for download from the :ref:`client drivers download page`. This JAR file can integrate into your Java-based applications or projects. -Extract the ZIP Archive +Extract the zip archive ------------------------- Extract the JAR file from the zip archive @@ -68,10 +68,10 @@ An alternative method is to pass ``-classpath`` to the Java executable: $ java -classpath .:/home/sqream/sqream-jdbc-4.3.0.jar my_java_app -Connect to SQream DB with a JDBC Application +Connect to SQream DB with a JDBC application ============================================== -Driver Class +Driver class -------------- Use ``com.sqream.jdbc.SQDriver`` as the driver class in the JDBC application. @@ -79,19 +79,16 @@ Use ``com.sqream.jdbc.SQDriver`` as the driver class in the JDBC application. .. _connection_string: -Connection String +Connection string -------------------- -JDBC drivers rely on a connection string. -The following is the correct syntax for writing a connection string: +JDBC drivers rely on a connection string. Use the following syntax for SQream DB .. code-block:: text jdbc:Sqream:///;user=;password=sqream;[; ...] - -If you receive an error when saving large quantities of data as files, see `Troubleshooting - Error Saving Large Quantities of Data as Files `_. -Connection Parameters +Connection parameters ^^^^^^^^^^^^^^^^^^^^^^^^ .. list-table:: @@ -131,7 +128,7 @@ Connection Parameters - ``true`` - Connect via load balancer (use only if exists, and check port). -Connection String Examples +Connection string examples ^^^^^^^^^^^^^^^^^^^^^^^^^^^ For a SQream DB cluster with load balancer and no service queues, with SSL @@ -153,7 +150,7 @@ For a SQream DB cluster with load balancer and a specific service queue named `` jdbc:Sqream://sqream.mynetwork.co:3108/raviga;user=rhendricks;password=Tr0ub4dor&3;cluster=true;service=etl -Sample Java Program +Sample Java program -------------------- Download this file by right clicking and saving to your computer :download:`sample.java `. @@ -162,3 +159,4 @@ Download this file by right clicking and saving to your computer :download:`samp :language: java :caption: JDBC application sample :linenos: + diff --git a/guides/client_drivers/jdbc/sample.java b/third_party_tools/client_drivers/jdbc/sample.java similarity index 100% rename from guides/client_drivers/jdbc/sample.java rename to third_party_tools/client_drivers/jdbc/sample.java diff --git a/guides/client_drivers/nodejs/index.rst b/third_party_tools/client_drivers/nodejs/index.rst similarity index 100% rename from guides/client_drivers/nodejs/index.rst rename to third_party_tools/client_drivers/nodejs/index.rst diff --git a/guides/client_drivers/nodejs/sample.js b/third_party_tools/client_drivers/nodejs/sample.js similarity index 100% rename from guides/client_drivers/nodejs/sample.js rename to third_party_tools/client_drivers/nodejs/sample.js diff --git a/guides/client_drivers/odbc/index.rst b/third_party_tools/client_drivers/odbc/index.rst similarity index 100% rename from guides/client_drivers/odbc/index.rst rename to third_party_tools/client_drivers/odbc/index.rst diff --git a/guides/client_drivers/odbc/install_configure_odbc_linux.rst b/third_party_tools/client_drivers/odbc/install_configure_odbc_linux.rst similarity index 100% rename from guides/client_drivers/odbc/install_configure_odbc_linux.rst rename to third_party_tools/client_drivers/odbc/install_configure_odbc_linux.rst diff --git a/guides/client_drivers/odbc/install_configure_odbc_windows.rst b/third_party_tools/client_drivers/odbc/install_configure_odbc_windows.rst similarity index 91% rename from guides/client_drivers/odbc/install_configure_odbc_windows.rst rename to third_party_tools/client_drivers/odbc/install_configure_odbc_windows.rst index ee51dc5c9..4972e3057 100644 --- a/guides/client_drivers/odbc/install_configure_odbc_windows.rst +++ b/third_party_tools/client_drivers/odbc/install_configure_odbc_windows.rst @@ -1,10 +1,10 @@ .. _install_odbc_windows: **************************************** -Install and configure ODBC on Windows +Install and Configure ODBC on Windows **************************************** -The ODBC driver for Windows is provided as a self-contained installer. +The ODBC driver for Windows is provided as a self-contained installer. This tutorial shows you how to install and configure ODBC on Windows. @@ -12,7 +12,7 @@ This tutorial shows you how to install and configure ODBC on Windows. :local: :depth: 2 -Installing the ODBC driver +Installing the ODBC Driver ================================== Prerequisites @@ -23,12 +23,9 @@ Prerequisites Visual Studio 2015 Redistributables ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The ODBC driver requires Microsoft's Visual Studio 2015 Redistributable packages installed. +To install the ODBC driver you must first install Microsoft's **Visual C++ Redistributable for Visual Studio 2015**. To install Visual C++ Redistributable for Visual Studio 2015, see the `Install Instructions `_. -Follow the instructions for download and installation on Microsoft's website https://www.microsoft.com/en-us/download/details.aspx?id=48145 - - -Administrator privileges +Administrator Privileges ^^^^^^^^^^^^^^^^^^^^^^^^^^^ The SQream DB ODBC driver requires administrator privileges on your computer to add the DSNs (data source names). @@ -43,7 +40,7 @@ Install the driver by following the on-screen instructions in the easy-to-follow .. note:: The installer will install the driver in ``C:\Program Files\SQream Technologies\ODBC Driver`` by default. This path is changable during the installation. -2. Selecting components +2. Selecting Components ^^^^^^^^^^^^^^^^^^^^^^^^^^ The installer includes additional components, like JDBC and Tableau customizations. @@ -87,7 +84,7 @@ ODBC driver configurations are done via DSNs. Each DSN represents one SQream DB -Connection parameters +Connection Parameters ----------------------- .. list-table:: @@ -134,4 +131,4 @@ After installing the ODBC driver, you may experience the following error: code 126: The specified module could not be found. (c:\Program Files\SQream Technologies\ODBC Driver\sqreamOdbc64.dll) -This is an issue with the Visual Studio Redistributable packages. Verify you've correctly installed them, as described in the :ref:`Visual Studio 2015 Redistributables ` section above. \ No newline at end of file +This is an issue with the Visual Studio Redistributable packages. Verify you've correctly installed them, as described in the :ref:`Visual Studio 2015 Redistributables ` section above. diff --git a/guides/client_drivers/python/api-reference.rst b/third_party_tools/client_drivers/python/api-reference.rst similarity index 100% rename from guides/client_drivers/python/api-reference.rst rename to third_party_tools/client_drivers/python/api-reference.rst diff --git a/guides/client_drivers/python/index.rst b/third_party_tools/client_drivers/python/index.rst similarity index 99% rename from guides/client_drivers/python/index.rst rename to third_party_tools/client_drivers/python/index.rst index 8f4117cc6..c2f5911b3 100644 --- a/guides/client_drivers/python/index.rst +++ b/third_party_tools/client_drivers/python/index.rst @@ -352,7 +352,6 @@ This example loads 10,000 rows of dummy data to a SQream DB instance # Create a table for loading create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s varchar(12), ss text, dt date, dtt datetime)' - con.execute(create) # After creating the table, we can load data into it with the INSERT command diff --git a/guides/features/nba-t10.csv b/third_party_tools/client_drivers/python/nba-t10.csv similarity index 100% rename from guides/features/nba-t10.csv rename to third_party_tools/client_drivers/python/nba-t10.csv diff --git a/guides/client_drivers/python/test.py b/third_party_tools/client_drivers/python/test.py similarity index 100% rename from guides/client_drivers/python/test.py rename to third_party_tools/client_drivers/python/test.py diff --git a/guides/third_party_tools/connect.sas b/third_party_tools/client_platforms/connect.sas similarity index 100% rename from guides/third_party_tools/connect.sas rename to third_party_tools/client_platforms/connect.sas diff --git a/guides/third_party_tools/index.rst b/third_party_tools/client_platforms/index.rst similarity index 92% rename from guides/third_party_tools/index.rst rename to third_party_tools/client_platforms/index.rst index a3335d463..6b354524b 100644 --- a/guides/third_party_tools/index.rst +++ b/third_party_tools/client_platforms/index.rst @@ -1,10 +1,10 @@ -.. _third_party_tools: +.. _client_platforms: ************************************ -Third party tools +Client Platforms ************************************ -These topics explain how to install and connect a variety of third party tools. +These topics explain how to install and connect a variety of third party tools. Browse the articles below, in the sidebar, or use the search to find the information you need. @@ -24,6 +24,8 @@ If you are looking for a tool that is not listed, SQream and our partners can he sql_workbench tableau + pentaho + microstrategy r php xxspotfire diff --git a/third_party_tools/client_platforms/microstrategy.rst b/third_party_tools/client_platforms/microstrategy.rst new file mode 100644 index 000000000..6cad19be2 --- /dev/null +++ b/third_party_tools/client_platforms/microstrategy.rst @@ -0,0 +1,185 @@ +.. _microstrategy: + + +************************* +Connect to SQream Using MicroStrategy +************************* + +.. _ms_top: + +Overview +--------------- +This document is a Quick Start Guide that describes how to install MicroStrategy and connect a datasource to the MicroStrategy dasbhoard for analysis. + + + +The **Connecting to SQream Using MicroStrategy** page describes the following: + + +.. contents:: + :local: + + + + + + +What is MicroStrategy? +================ +MicroStrategy is a Business Intelligence software offering a wide variety of data analytics capabilities. SQream uses the MicroStrategy connector for reading and loading data into SQream. + +MicroStrategy provides the following: + +* Data discovery +* Advanced analytics +* Data visualization +* Embedded BI +* Banded reports and statements + + +For more information about Microstrategy, see `MicroStrategy `_. + + + +:ref:`Back to Overview ` + + + + + +Connecting a Data Source +======================= + +1. Activate the **MicroStrategy Desktop** app. The app displays the Dossiers panel to the right. + + :: + +2. Download the most current version of the `SQream JDBC driver `_. + + :: + +3. Click **Dossiers** and **New Dossier**. The **Untitled Dossier** panel is displayed. + + :: + +4. Click **New Data**. + + :: + +5. From the **Data Sources** panel, select **Databases** to access data from tables. The **Select Import Options** panel is displayed. + + :: + +6. Select one of the following: + + * Build a Query + * Type a Query + * Select Tables + + :: + +7. Click **Next**. + + :: + +8. In the Data Source panel, do the following: + + 1. From the **Database** dropdown menu, select **Generic**. The **Host Name**, **Port Number**, and **Database Name** fields are removed from the panel. + + :: + + 2. In the **Version** dropdown menu, verify that **Generic DBMS** is selected. + + :: + + 3. Click **Show Connection String**. + + :: + + 4. Select the **Edit connection string** checkbox. + + :: + + 5. From the **Driver** dropdown menu, select a driver for one of the following connectors: + + * **JDBC** - The SQream driver is not integrated with MicroStrategy and does not appear in the dropdown menu. However, to proceed, you must select an item, and in the next step you must specify the path to the SQream driver that you installed on your machine. + * **ODBC** - SQreamDB ODBC + + :: + + 6. In the **Connection String** text box, type the relevant connection string and path to the JDBC jar file using the following syntax: + + .. code-block:: console + + $ jdbc:Sqream:///;user=;password=sqream;[; ...] + + The following example shows the correct syntax for the JDBC connector: + + .. code-block:: console + + jdbc;MSTR_JDBC_JAR_FOLDER=C:\path\to\jdbc\folder;DRIVER=;URL={jdbc:Sqream:///;user=;password=;[; ...];} + + The following example shows the correct syntax for the ODBC connector: + + .. code-block:: console + + odbc:Driver={SqreamODBCDriver};DSN={SQreamDB ODBC};Server=;Port=;Database=;User=;Password=;Cluster=; + + For more information about the available **connection parameters** and other examples, see `Connection Parameters `_. + + 7. In the **User** and **Password** fields, fill out your user name and password. + + :: + + 8. In the **Data Source Name** field, type **SQreamDB**. + + :: + + 9. Click **Save**. The SQreamDB that you picked in the Data Source panel is displayed. + + +9. In the **Namespace** menu, select a namespace. The tables files are displayed. + + :: + +10. Drag and drop the tables into the panel on the right in your required order. + + :: + +11. **Recommended** - Click **Prepare Data** to customize your data for analysis. + + :: + +12. Click **Finish**. + + :: + +13. From the **Data Access Mode** dialog box, select one of the following: + + + * Connect Live + * Import as an In-memory Dataset + +Your populated dashboard is displayed and is ready for data discovery and analytics. + + + + + + +.. _supported_sqream_drivers: + +:ref:`Back to Overview ` + +Supported SQream Drivers +================ + +The following list shows the supported SQream drivers and versions: + +* **JDBC** - Version 4.3.3 and higher. +* **ODBC** - Version 4.0.0. + + +.. _supported_tools_and_operating_systems: + +:ref:`Back to Overview ` diff --git a/guides/third_party_tools/odbc-sqream.tdc b/third_party_tools/client_platforms/odbc-sqream.tdc similarity index 100% rename from guides/third_party_tools/odbc-sqream.tdc rename to third_party_tools/client_platforms/odbc-sqream.tdc diff --git a/third_party_tools/client_platforms/pentaho.rst b/third_party_tools/client_platforms/pentaho.rst new file mode 100644 index 000000000..998a7db22 --- /dev/null +++ b/third_party_tools/client_platforms/pentaho.rst @@ -0,0 +1,288 @@ +.. _pentaho_data_integration: + + +************************* +Connect to SQream Using Pentaho Data Integration +************************* + +.. _pentaho_top: + +Overview +========= +This document is a Quick Start Guide that describes how to install Pentaho, create a transformation, and define your output. + +The Connecting to SQream Using Pentaho page describes the following: + +* :ref:`Installing Pentaho ` +* :ref:`Installing and setting up the JDBC driver ` +* :ref:`Creating a transformation ` +* :ref:`Defining your output ` +* :ref:`Importing your data ` + + +.. _install_pentaho: + +Installing Pentaho +~~~~~~~~~~~~~~~~~ +To install PDI, see the `Pentaho Community Edition (CE) Installation Guide `_. + +The **Pentaho Community Edition (CE) Installation Guide** describes how to do the following: + +* Downloading the PDI software. +* Installing the **JRE (Java Runtime Environment)** and **JDK (Java Development Kit)**. +* Setting up the JRE and JDK environment variables for PDI. + +:ref:`Back to Overview ` + +.. _install_set_up_jdbc_driver: + +Installing and Setting Up the JDBC Driver +~~~~~~~~~~~~~~~~~ +After installing Pentaho you must install and set up the JDBC driver. This section explains how to set up the JDBC driver using Pentaho. These instructions use Spoon, the graphical transformation and job designer associated with the PDI suite. + +You can install the driver by copying and pasting the SQream JDBC .jar file into your **/design-tools/data-integration/lib** directory. + +**NOTE:** Contact your SQream license account manager for the JDBC .jar file. + +:ref:`Back to Overview ` + +.. _create_transformation: + +Creating a Transformation +~~~~~~~~~~~~~~~~~~ + +After installing Pentaho you can create a transformation. + +**To create a transformation:** + +1. Use the CLI to open the PDI client for your operating system (Windows): + + .. code-block:: console + + $ spoon.bat + +2. Open the spoon.bat file from its folder location. + +.. image:: /_static/images/third_party_connectors/pentaho/spoon_bat_file.png + +3. In the **View** tab, right-click **Transformations** and click **New**. + +.. image:: /_static/images/third_party_connectors/pentaho/pentaho_1.png + +A new transformation tab is created. + +.. image:: /_static/images/third_party_connectors/pentaho/pentaho_2.png + +4. In the **Design** tab, click **Input** to show its file contents. + +.. image:: /_static/images/third_party_connectors/pentaho/pentaho_3.png + +5. Drag and drop the **CSV file input** item to the new transformation tab that you created. + +.. image:: /_static/images/third_party_connectors/pentaho/pentaho_4.png + +6. Double-click **CSV file input**. The **CSV file input** panel is displayed. + +.. image:: /_static/images/third_party_connectors/pentaho/pentaho_5.png + +7. In the **Step name** field, type a name. + +.. image:: /_static/images/third_party_connectors/pentaho/pentaho_6.png + +8. To the right of the **Filename** field, click **Browse**. + +.. image:: /_static/images/third_party_connectors/pentaho/pentaho_select_file.png + +9. Select the file that you want to read from and click **OK**. + +.. image:: /_static/images/third_party_connectors/pentaho/add_csv_file.png + +10. In the CSV file input window, click **Get Fields**. + +.. image:: /_static/images/third_party_connectors/pentaho/get_fields.png + +11. In the **Sample data** window, enter the number of lines you want to sample and click **OK**. The default setting is **100**. + +.. image:: /_static/images/third_party_connectors/pentaho/number_of_lines_to_sample.png + +The tool reads the file and suggests the field name and type. + +.. image:: /_static/images/third_party_connectors/pentaho/suggested_field_name_and_type.png + +12. In the CSV file input window, click **Preview**. + +.. image:: /_static/images/third_party_connectors/pentaho/preview.png + +13. In the **Preview size** window, enter the number of rows you want to preview and click **OK**. The default setting is **1000**. + +.. image:: /_static/images/third_party_connectors/pentaho/number_of_rows_to_preview.png + +14. Verify that the preview data is correct and click **Close**. + +.. image:: /_static/images/third_party_connectors/pentaho/examine.png + +15. Click **OK** in the **CSV file input** window. + +:ref:`Back to Overview ` + +.. _define_output: + +Defining Your Output +----------------- +After creating your transformation you must define your output. + +**To define your output:** + +1. In the **Design** tab, click **Output**. + +.. image:: /_static/images/third_party_connectors/pentaho/design_output.png + + The Output folder is opened. + +2. Drag and drop **Table output** item to the Transformation window. + +.. image:: /_static/images/third_party_connectors/pentaho/table_output.png + +3. Double-click **Table output** to open the **Table output** dialog box. + +:: + +4. From the **Table output** dialog box, type a **Step name** and click **New** to create a new connection. Your **steps** are the building blocks of a transformation, such as file input or a table output. + +.. image:: /_static/images/third_party_connectors/pentaho/rename_table_output.png + +The **Database Connection** window is displayed with the **General** tab selected by default. + +.. image:: /_static/images/third_party_connectors/pentaho/database_connection_window.png + +5. Enter or select the following information in the Database Connection window and click **Test**. + +.. image:: /_static/images/third_party_connectors/pentaho/pentaho_fillout_database_connection_window.png + +The following table shows and describes the information that you need to fill out in the Database Connection window: + +.. list-table:: + :widths: 6 31 73 + :header-rows: 1 + + * - No. + - Element Name + - Description + * - 1 + - Connection name + - Enter a name that uniquely describes your connection, such as **sampledata**. + * - 2 + - Connection type + - Select **Generic database**. + * - 3 + - Access + - Select **Native (JDBC)**. + * - 4 + - Custom connection URL + - Insert **jdbc:Sqream:///;user=;password=;[; ...];**. The IP is a node in your SQream cluster and is the name or schema of the database you want to connect to. Verify that you have not used any leading or trailing spaces. + * - 5 + - Custom driver class name + - Insert **com.sqream.jdbc.SQDriver**. Verify that you have not used any leading or trailing spaces. + * - 6 + - Username + - Your SQreamdb username. If you leave this blank, you will be prompted to provide it when you connect. + * - 7 + - Password + - Your password. If you leave this blank, you will be prompted to provide it when you connect. + +The following message is displayed: + +.. image:: /_static/images/third_party_connectors/pentaho/connection_tested_successfully_2.png + +6. Click **OK** in the window above, in the Database Connection window, and Table Output window. + +:ref:`Back to Overview ` + +.. _import_data: + +Importing Data +----------------- +After defining your output you can begin importing your data. + +For more information about backing up users, permissions, or schedules, see `Backup and Restore Pentaho Repositories `_ + +**To import data:** + +1. Double-click the **Table output** connection that you just created. + +.. image:: /_static/images/third_party_connectors/pentaho/table_output.png + +2. To the right of the **Target schema** field, click **Browse** and select a schema name. + +.. image:: /_static/images/third_party_connectors/pentaho/select_schema_name.png + +3. Click **OK**. The selected schema name is displayed in the **Target schema** field. + +.. image:: /_static/images/third_party_connectors/pentaho/selected_target_schema.png + +4. Create a new hop connection between the **CSV file input** and **Table output** steps: + + 1. On the CSV file input step item, click the **new hop connection** icon. + + .. image:: /_static/images/third_party_connectors/pentaho/csv_file_input_options.png + + + + 2. Drag an arrow from the **CSV file input** step item to the **Table output** step item. + + .. image:: /_static/images/third_party_connectors/pentaho/csv_file_input_options_2.png + + + 3. Release the mouse button. The following options are displayed. + + 4. Select **Main output of step**. + +.. image:: /_static/images/third_party_connectors/pentaho/main_output_of_step.png + +:: + +5. Double-click **Table output** to open the **Table output** dialog box. + +:: + +6. In the **Target table** field, define a target table name. + + .. image:: /_static/images/third_party_connectors/pentaho/target_table_name.png + +:: + +7. Click **SQL** to open the **Simple SQL editor.** + + .. image:: /_static/images/third_party_connectors/pentaho/sql_editor.png + +:: + +8. In the **Simple SQL editor**, click **Execute**. + + .. image:: /_static/images/third_party_connectors/pentaho/execute_sql_statements.png + + The system processes and displays the results of the SQL statements. + + .. image:: /_static/images/third_party_connectors/pentaho/sql_statement_results_2.png + +:: + +9. Close all open dialog boxes. + +:: + +10. Click the play button to execute the transformation. + + .. image:: /_static/images/third_party_connectors/pentaho/execute_transformation.png + +:: + +The **Run Options** dialog box is displayed. + + .. image:: /_static/images/third_party_connectors/pentaho/run_options_dialog_box.png + +11. Click **Run**. The **Execution Results** are displayed. + + .. image:: /_static/images/third_party_connectors/pentaho/execution_results_2.png + +:ref:`Back to Overview ` diff --git a/guides/third_party_tools/php.rst b/third_party_tools/client_platforms/php.rst similarity index 96% rename from guides/third_party_tools/php.rst rename to third_party_tools/client_platforms/php.rst index a04aa981a..16dc89fe3 100644 --- a/guides/third_party_tools/php.rst +++ b/third_party_tools/client_platforms/php.rst @@ -1,12 +1,12 @@ .. _php: ***************************** -Connecting with PHP +Connect to SQream Using PHP ***************************** You can use PHP to interact with a SQream DB cluster. -This tutorial is a guide that will show you how to connect a PHP application to SQream DB. +This tutorial is a guide that will show you how to connect a PHP application to SQream DB. .. contents:: In this topic: :local: diff --git a/guides/third_party_tools/r.rst b/third_party_tools/client_platforms/r.rst similarity index 98% rename from guides/third_party_tools/r.rst rename to third_party_tools/client_platforms/r.rst index 7d9e7659f..c84bf901b 100644 --- a/guides/third_party_tools/r.rst +++ b/third_party_tools/client_platforms/r.rst @@ -1,12 +1,12 @@ .. _r: ***************************** -Connecting with R +Connect to SQream Using R ***************************** You can use R to interact with a SQream DB cluster. -This tutorial is a guide that will show you how to connect R to SQream DB. +This tutorial is a guide that will show you how to connect R to SQream DB. .. contents:: In this topic: :local: @@ -148,4 +148,4 @@ A full example 3 3 91 22356 3 4 4 84 17232 4 5 5 13 14315 5 - > close(ch) \ No newline at end of file + > close(ch) diff --git a/guides/third_party_tools/sas_viya.rst b/third_party_tools/client_platforms/sas_viya.rst similarity index 98% rename from guides/third_party_tools/sas_viya.rst rename to third_party_tools/client_platforms/sas_viya.rst index 50f79c28b..744d4b771 100644 --- a/guides/third_party_tools/sas_viya.rst +++ b/third_party_tools/client_platforms/sas_viya.rst @@ -1,10 +1,10 @@ .. _connect_to_sas_viya: ************************* -Connecting to SAS Viya +Connect to SQream Using SAS Viya ************************* -You can use SAS Viya to connect to a SQream DB cluster. This tutorial is a guide that will show you how to connect to SAS Viya. +You can use SAS Viya to connect to a SQream DB cluster. This tutorial is a guide that will show you how to connect to SAS Viya. .. contents:: In this topic: :local: diff --git a/guides/third_party_tools/sql_workbench.rst b/third_party_tools/client_platforms/sql_workbench.rst similarity index 97% rename from guides/third_party_tools/sql_workbench.rst rename to third_party_tools/client_platforms/sql_workbench.rst index 5329527e8..16265ebd4 100644 --- a/guides/third_party_tools/sql_workbench.rst +++ b/third_party_tools/client_platforms/sql_workbench.rst @@ -1,10 +1,10 @@ .. _connect_to_sql_workbench: ***************************** -Connecting to SQL Workbench +Connect to SQream Using SQL Workbench ***************************** -You can use SQL Workbench to interact with a SQream DB cluster. SQL Workbench/J is a free SQL query tool, and is designed to run on any JRE-enabled environment. +You can use SQL Workbench to interact with a SQream DB cluster. SQL Workbench/J is a free SQL query tool, and is designed to run on any JRE-enabled environment. This tutorial is a guide that will show you how to connect SQL Workbench to SQream DB. @@ -132,4 +132,4 @@ If you installed SQL Workbench manually, you can set a customization to help SQL workbench.db.sqreamdb.schema.retrieve.change.catalog=true -#. Save the file and restart SQL Workbench \ No newline at end of file +#. Save the file and restart SQL Workbench diff --git a/guides/third_party_tools/tableau.rst b/third_party_tools/client_platforms/tableau.rst similarity index 95% rename from guides/third_party_tools/tableau.rst rename to third_party_tools/client_platforms/tableau.rst index aa8a44b31..c74c2e9b1 100644 --- a/guides/third_party_tools/tableau.rst +++ b/third_party_tools/client_platforms/tableau.rst @@ -6,7 +6,7 @@ Connecting to SQream Using Tableau Overview ===================== -SQream's Tableau connector plugin, based on standard JDBC, enables storing and fast querying large volumes of data. +SQream's Tableau connector plugin, based on standard JDBC, enables storing and fast querying large volumes of data. The **Connecting to SQream Using Tableau** page is a Quick Start Guide that describes how install Tableau and the JDBC and ODBC drivers and connect to SQream using the JDBC and ODBC drivers for data analysis. It also describes using best practices and troubleshoot issues that may occur while installing Tableau. SQream supports both Tableau Desktop and Tableau Server on Windows, MacOS, and Linux distributions. @@ -48,8 +48,7 @@ If you are using Windows, after installing the Tableau Desktop application you c :: -#. Download the most current version of the `SQream JDBC driver `_. - +#. Download the most current version of the `SQream JDBC driver `_. :: @@ -417,16 +416,6 @@ Creating a Separate Service for Tableau ~~~~~~~~~~~~~~~~~~~ SQream recommends creating a separate service for Tableau with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. -Error Saving Large Quantities of Data as Files -~~~~~~~~~~~~~~~~~~~ -An **FAB9A2C5** error can when saving large quantities of data as files. If you receive this error when writing a connection string, add the ``fetchSize`` parameter to ``1``, as shown below: - -.. code-block:: text - - jdbc:Sqream:///;user=;password=sqream;[; fetchSize=1...] - -For more information on troubleshooting error **FAB9A2C5**, see the `Tableau Knowledge Base `_. - Troubleshooting Workbook Performance Before Deploying to the Tableau Server ~~~~~~~~~~~~~~~~~~~ Tableau has a built-in `performance recorder `_ that shows how time is being spent. If you're seeing slow performance, this could be the result of a misconfiguration such as setting concurrency too low. diff --git a/third_party_tools/client_platforms/talend.rst b/third_party_tools/client_platforms/talend.rst new file mode 100644 index 000000000..2a4d2658a --- /dev/null +++ b/third_party_tools/client_platforms/talend.rst @@ -0,0 +1,204 @@ +.. _talend: + +************************* +Connecting to SQream Using Talend +************************* + +.. _top: + +Overview +================= + +This page describes how to use Talend to interact with a SQream DB cluster. The Talend connector is used for reading data from a SQream DB cluster and loading data into SQream DB. + +In addition, this page provides a viability report on Talend's comptability with SQream DB for stakeholders. + +It includes the following: + +* :ref:`A Quick Start guide ` +* :ref:`Information about supported SQream drivers ` +* :ref:`Supported data sources ` and :ref:`tool and operating system versions ` +* :ref:`A description of known issues ` +* :ref:`Related links ` + + +About Talend +================= +Talend is an open-source data integration platform. It provides various software and services for Big Data integration and management, enterprise application integration, data quality and cloud storage. + +For more information about Talend, see `Talend `_. + + +.. _quickstart_guide: + +Quick Start Guide +======================= + +Creating a New Metadata JDBC DB Connection +------------- +**To create a new metadata JDBC DB connection:** + +1. In the **Repository** panel, nagivate to **Metadata** and right-click **Db connections**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_1.png + +2. Select **Create connection**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_2.png + +3. In the **Name** field, type a name. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_3.png + +The name cannot contain spaces. + +4. In the **Purpose** field, type a purpose and click **Next**. You cannot go to the next step until you define both a Name and a Purpose. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_4.png + +5. In the **DB Type** field, select **JDBC**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_5.png + +6. In the **JDBC URL** field, type the relevant connection string. + + For connection string examples, see `Connection Strings `_. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_6.png + +7. In the **Drivers** field, click the **Add** button. + + The **"newLine** entry is added. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_7.png + +8. One the **"newLine** entry, click the ellipsis. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_8.png + +The **Module** window is displayed. + +9. From the Module window, select **Artifact repository(local m2/nexus)** and select **Install a new module**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_9.png + +10. Click the ellipsis. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_9.5.png + +Your hard drive is displayed. + +11. Navigate to a **JDBC jar file** (such as **sqream-jdbc-4.4.0.jar**)and click **Open**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_10.png + +12. Click **Detect the module install status**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_11.5.png + +13. Click **OK**. + +The JDBC that you selected is displayed in the **Driver** field. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_12.png + +14. Click **Select class name**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_13.png + +15. Click **Test connection**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_14.png + +If a driver class is not found (for example, you didn't select a JDBC jar file), the following error message is displayed: + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_15.png + +After creating a new metadata JDBC DB connection, you can do the following: + + * Use your new metadata connection. + * Drag it to the **job** screen. + * Build Talend components. + +For more information on loading data from JSON files to the Talend Open Studio, see `How to Load Data from JSON Files in Talend `_. + +:ref:`Back to top ` + +.. _supported_sqream_drivers: + +Supported SQream Drivers +================ + +The following list shows the supported SQream drivers and versions: + +* **JDBC** - Version 4.3.3 and higher. +* **ODBC** - Version 4.0.0. This version requires a Bridge to connect. For more information on the required Bridge, see `Connecting Talend on Windows to an ODBC Database `_. + +:ref:`Back to top ` + + +.. _supported_data_sources: + +Supported Data Sources +============================ +Talend Cloud connectors let you create reusable connections with a wide variety of systems and environments, such as those shown below. This lets you access and read records of a range of diverse data. + +* **Connections:** Connections are environments or systems for storing datasets, including databases, file systems, distributed systems and platforms. Because these systems are reusable, you only need to establish connectivity with them once. + +* **Datasets:** Datasets include database tables, file names, topics (Kafka), queues (JMS) and file paths (HDFS). For more information on the complete list of connectors and datasets that Talend supports, see `Introducing Talend Connectors `_. + +:ref:`Back to top ` + + +.. _supported_tools_os_sys_versions: + +Supported Tool and Operating System Versions +====================== +Talend was tested using the following: + +* Talend version 7.4.1M6 +* Windows 10 +* SQream version 2021.1 +* JDBC version + + + + +:ref:`Back to top ` + + +.. _known_issues: + +Known Issues +=========================== +The the list below describes the following known issues as of 6/1/2021: + +* Schemas not displayed for tables with identical names. + +:ref:`Back to top ` + + +.. _related_links: + +Related Links +=============== +The following is a list of links relevant to the Talend connector: + +* `Talend Home page `_ +* `Talend Community page `_ +* `Talend BugTracker `_ + + +Download Links +================== +The following is a list of download links relevant to the Talend connector: + +* `Talend Open Studio for Big Data `_ +* `Latest version of SQream JDBC `_ + +:ref:`Back to top ` + + + +.. contents:: In this topic: + :local: diff --git a/guides/third_party_tools/test.php b/third_party_tools/client_platforms/test.php similarity index 100% rename from guides/third_party_tools/test.php rename to third_party_tools/client_platforms/test.php diff --git a/third_party_tools/connectivity_ecosystem.jpg b/third_party_tools/connectivity_ecosystem.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8bcb05369699c8f8b21f6e6c00e926156116de71 GIT binary patch literal 149570 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 literal 0 HcmV?d00001 diff --git a/third_party_tools/index.rst b/third_party_tools/index.rst new file mode 100644 index 000000000..818a1dc5a --- /dev/null +++ b/third_party_tools/index.rst @@ -0,0 +1,18 @@ +.. _third_party_tools: + +************************* +Third Party Tools +************************* +SQream supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualiztion tools and utilities. The tools described on this page have been tested and approved for use with SQream. Most third party tools that work through JDBC, ODBC, and Python should work. + +This section provides information about the following third party tools: + +.. toctree:: + :maxdepth: 2 + :glob: + :titlesonly: + + client_platforms/index + client_drivers/index + +If you need a tool that SQream does not support, contact SQream Support or your SQream account manager for more information. \ No newline at end of file diff --git a/troubleshooting/core_dumping_related_issues.rst b/troubleshooting/core_dumping_related_issues.rst new file mode 100644 index 000000000..ace7c8787 --- /dev/null +++ b/troubleshooting/core_dumping_related_issues.rst @@ -0,0 +1,58 @@ +.. _core_dumping_related_issues: + +*********************** +Core Dumping Related Issues +*********************** + +The **Core Dumping Related Issues** page describes the troubleshooting procedure to be followed if all parameters have been configured correctly, but the cores have not been created. + +**To troubleshoot core dumping:** + +1. Reboot the server. + +2. Verify that you have folder permissions: + + .. code-block:: console + + $ sudo chmod -R 777 /tmp/core_dumps + +3. Verify that the limits have been set correctly: + + .. code-block:: console + + $ ulimit -c + + If all parameters have been configured correctly, the correct output is: + + .. code-block:: console + + $ unlimited + +4. If all parameters have been configured correctly, but running **ulimit -c** outputs **0**, run the following: + + .. code-block:: console + + $ sudo vim /etc/profile + +5. Search for line and tag it with the **hash** symbol: + + .. code-block:: console + + $ ulimit -S -c 0 > /dev/null 2>&1 + + +6. If the line is not found in **/etc/profile** directory, do the following: + + a. Run the following command: + + .. code-block:: console + + $ sudo vim /etc/init.d/functions + + b. Search for the following: + + .. code-block:: console + + $ ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 + + c. If the line is found, tag it with the **hash** symbol and reboot the server. diff --git a/troubleshooting/examining_logs.rst b/troubleshooting/examining_logs.rst new file mode 100644 index 000000000..9b5a5fb79 --- /dev/null +++ b/troubleshooting/examining_logs.rst @@ -0,0 +1,6 @@ +.. _examining_logs: + +*********************** +Examining Logs +*********************** +See the :ref:`collecting_logs` section of the :ref:`information_for_support` guide for information about collecting logs for support. \ No newline at end of file diff --git a/troubleshooting/identifying_configuration_issues.rst b/troubleshooting/identifying_configuration_issues.rst new file mode 100644 index 000000000..25708cda6 --- /dev/null +++ b/troubleshooting/identifying_configuration_issues.rst @@ -0,0 +1,32 @@ +.. _identifying_configuration_issues: + +*********************** +Identifying Configuration Issues +*********************** + +The **Troubleshooting Common Issues** page describes how to troubleshoot the following common issues: + +.. toctree:: + :maxdepth: 2 + :glob: + :titlesonly: + + +Starting a SQream DB temporarily (not as part of a cluster, with default settings) can be helpful in identifying configuration issues. + +Example: + +.. code-block:: console + + $ sqreamd /home/rhendricks/raviga_database 0 5000 /home/sqream/.sqream/license.enc + +.. tip:: + + * Using ``nohup`` and ``&`` sends SQream DB to run in the background. + + * + It is safe to stop SQream DB at any time using ``kill``. No partial data or data corruption should occur when using this method to stop the process. + + .. code-block:: console + + $ kill -9 $SQREAM_PID \ No newline at end of file diff --git a/troubleshooting/index.rst b/troubleshooting/index.rst new file mode 100644 index 000000000..efbcdd412 --- /dev/null +++ b/troubleshooting/index.rst @@ -0,0 +1,25 @@ +.. _troubleshooting: + +*********************** +Troubleshooting +*********************** + +The **Troubleshooting** page describes solutions to the following issues: + +.. toctree:: + :maxdepth: 1 + :glob: + + remedying_slow_queries + resolving_common_issues + examining_logs + identifying_configuration_issues + lock_related_issues + sas_viya_related_issues + tableau_related_issues + solving_code_126_odbc_errors + log_related_issues + node_js_related_issues + core_dumping_related_issues + sqream_sql_installation_related_issues + information_for_support \ No newline at end of file diff --git a/guides/operations/information_for_support.rst b/troubleshooting/information_for_support.rst similarity index 93% rename from guides/operations/information_for_support.rst rename to troubleshooting/information_for_support.rst index 62f79b227..16dcb4174 100644 --- a/guides/operations/information_for_support.rst +++ b/troubleshooting/information_for_support.rst @@ -1,7 +1,7 @@ .. _information_for_support: ******************************************* -Gathering information for SQream support +Gathering Information for SQream Support ******************************************* .. What do we want to look into a performance issue @@ -12,7 +12,7 @@ Gathering information for SQream support `SQream Support `_ is ready to answer any questions, and help solve any issues with SQream DB. -Getting support and reporting bugs +Getting Support and Reporting Bugs ======================================= When contacting `SQream Support `_, we recommend reporting the following information: @@ -28,7 +28,7 @@ When possible, please attach as many of the following: * :ref:`Log files` * Screen captures if relevant -How SQream debugs issues +How SQream Debugs Issues =================================== Reproduce @@ -65,7 +65,7 @@ Your SQream account manager will keep you up-to-date about the status of the iss .. _reproducible_statement: -Collecting a reproducible example of a problematic statement +Collecting a Reproducible Example of a Problematic Statement =============================================================== SQream DB contains an SQL utility that can help SQream support reproduce a problem with a query or statement. @@ -107,7 +107,7 @@ Example .. _collecting_logs: -Collecting logs and metadata database +Collecting Logs and Metadata Database ============================================= SQream DB comes bundled with a data collection utility and an SQL utility intended for collecting logs and additional information that can help SQream support drill down into possible issues. @@ -132,7 +132,8 @@ Write an archive to ``/home/rhendricks``, containing log files and metadata data ; -Using the command line utility: +Using the Command Line Utility: +============================================= .. code-block:: console diff --git a/troubleshooting/lock_related_issues.rst b/troubleshooting/lock_related_issues.rst new file mode 100644 index 000000000..1a15858ec --- /dev/null +++ b/troubleshooting/lock_related_issues.rst @@ -0,0 +1,29 @@ +.. _lock_related_issues: + +*********************** +Lock Related Issues +*********************** +Sometimes, a rare situation can occur where a lock is never freed. + +The workflow for troubleshooting locks is: + +#. Identify which statement has obtained locks +#. Understand if the statement is itself stuck, or waiting for another statement +#. Try to abort the offending statement +#. Force the stale locks to be removed + +For example, we will assume that the statement from the previous example is stuck (statement #\ ``287``). We can attempt to abort it using :ref:`stop_statement`: + +.. code-block:: psql + + t=> SELECT STOP_STATEMENT(287); + executed + +If the locks still appear in the :ref:`show_locks` utility, we can force remove the stale locks: + +.. code-block:: psql + + t=> SELECT RELEASE_DEFUNCT_LOCKS(); + executed + +.. warning:: This operation can cause some statements to fail on the specific worker on which they are queued. This is intended as a "last resort" to solve stale locks. \ No newline at end of file diff --git a/troubleshooting/log_related_issues.rst b/troubleshooting/log_related_issues.rst new file mode 100644 index 000000000..a260f59d5 --- /dev/null +++ b/troubleshooting/log_related_issues.rst @@ -0,0 +1,133 @@ +.. _log_related_issues: + +*********************** +Log Related Issues +*********************** +The **Log Related Issues** page describes how to resolve the following common issues: + +.. toctree:: + :maxdepth: 2 + :glob: + :titlesonly: + +Loading Logs with Foreign Tables +--------------------------------------- +Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a database administrator can access the logs using the :ref:`external_tables` concept through SQream DB. + +.. code-block:: postgres + + CREATE FOREIGN TABLE logs + ( + start_marker VARCHAR(4), + row_id BIGINT, + timestamp DATETIME, + message_level TEXT, + thread_id TEXT, + worker_hostname TEXT, + worker_port INT, + connection_id INT, + database_name TEXT, + user_name TEXT, + statement_id INT, + service_name TEXT, + message_type_id INT, + message TEXT, + end_message VARCHAR(5) + ) + WRAPPER csv_fdw + OPTIONS + ( + LOCATION = '/home/rhendricks/sqream_storage/logs/**/sqream*.log', + DELIMITER = '|', + CONTINUE_ON_ERROR = true + ) + ; + +For more information, see `Loading Logs with Foreign Tables `_. + + + + + +Counting Message Types +------------------------------ + +.. code-block:: psql + + t=> SELECT message_type_id, COUNT(*) FROM logs GROUP BY 1; + message_type_id | count + ----------------+---------- + 0 | 9 + 1 | 5578 + 4 | 2319 + 10 | 2788 + 20 | 549 + 30 | 411 + 31 | 1720 + 32 | 1720 + 100 | 2592 + 101 | 2598 + 110 | 2571 + 200 | 11 + 500 | 136 + 1000 | 19 + 1003 | 19 + 1004 | 19 + 1010 | 5 + +Finding Fatal Errors +---------------------- + +.. code-block:: psql + + t=> SELECT message FROM logs WHERE message_type_id=1010; + Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/leveldb/LOCK: Resource temporarily unavailable + Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/leveldb/LOCK: Resource temporarily unavailable + Mismatch in storage version, upgrade is needed,Storage version: 25, Server version is: 26 + Mismatch in storage version, upgrade is needed,Storage version: 25, Server version is: 26 + Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/LOCK: Resource temporarily unavailable + +Countng Error Events Within a Certain Timeframe +--------------------------------------------------- + +.. code-block:: psql + + t=> SELECT message_type_id, + . COUNT(*) + . FROM logs + . WHERE message_type_id IN (1010,500) + . AND timestamp BETWEEN '2019-12-20' AND '2020-01-01' + . GROUP BY 1; + message_type_id | count + ----------------+------ + 500 | 18 + 1010 | 3 + + +.. _tracing_errors: + +Tracing Errors to Find Offending Statements +------------------------------------------------- + +If we know an error occured, but don't know which statement caused it, we can find it using the connection ID and statement ID. + +.. code-block:: psql + + t=> SELECT connection_id, statement_id, message + . FROM logs + . WHERE message_level = 'ERROR' + . AND timestamp BETWEEN '2020-01-01' AND '2020-01-06'; + connection_id | statement_id | message + --------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------ + 79 | 67 | Column type mismatch, expected UByte, got INT64 on column Number, file name: /home/sqream/nba.parquet + +Use the ``connection_id`` and ``statement_id`` to narrow down the results. + +.. code-block:: psql + + t=> SELECT database_name, message FROM logs + . WHERE connection_id=79 AND statement_id=67 AND message_type_id=1; + database_name | message + --------------+-------------------------- + master | Query before parsing + master | SELECT * FROM nba_parquet \ No newline at end of file diff --git a/troubleshooting/node_js_related_issues.rst b/troubleshooting/node_js_related_issues.rst new file mode 100644 index 000000000..b3b95b2ed --- /dev/null +++ b/troubleshooting/node_js_related_issues.rst @@ -0,0 +1,54 @@ +.. _node_js_related_issues: + +*********************** +Node.js Related Issues +*********************** +The **Node.js Related Issues** page describes how to resolve the following common issues: + +.. toctree:: + :maxdepth: 2 + :glob: + :titlesonly: + +Preventing Heap Out of Memory Errors +-------------------------------------------- + +Some workloads may cause Node.JS to fail with the error: + +.. code-block:: none + + FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory + +To prevent this error, modify the heap size configuration by setting the ``--max-old-space-size`` run flag. + +For example, set the space size to 2GB: + +.. code-block:: console + + $ node --max-old-space-size=2048 my-application.js + +Providing Support for BIGINT Data Type +------------------------ + +The Node.JS connector supports fetching ``BIGINT`` values from SQream DB. However, some applications may encounter an error when trying to serialize those values. + +The error that appears is: +.. code-block:: none + + TypeError: Do not know how to serialize a BigInt + +This is because JSON specification do not support BIGINT values, even when supported by Javascript engines. + +To resolve this issue, objects with BIGINT values should be converted to string before serializing, and converted back after deserializing. + +For example: + +.. code-block:: javascript + + const rows = [{test: 1n}] + const json = JSON.stringify(rows, , (key, value) => + typeof value === 'bigint' + ? value.toString() + : value // return everything else unchanged + )); + console.log(json); // [{"test": "1"}] \ No newline at end of file diff --git a/troubleshooting/remedying_slow_queries.rst b/troubleshooting/remedying_slow_queries.rst new file mode 100644 index 000000000..8a109f0c0 --- /dev/null +++ b/troubleshooting/remedying_slow_queries.rst @@ -0,0 +1,79 @@ +.. _remedying_slow_queries: + +*********************** +Remedying Slow Queries +*********************** + +The **Remedying Slow Queries** page describes how to troubleshoot the causes of slow queries. + +The following table is a checklist you can use to identify the cause of your slow queries: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Step + - Description + - Results + * - 1 + - A single query is slow + - + If a query isn't performing as you expect, follow the :ref:`Query best practices` part of the :ref:`sql_best_practices` guide. + + If all queries are slow, continue to step 2. + * - 2 + - All queries on a specific table are slow + - + #. If all queries on a specific table aren't performing as you expect, follow the :ref:`Table design best practices` part of the :ref:`sql_best_practices` guide. + #. Check for active delete predicates in the table. Consult the :ref:`delete_guide` guide for more information. + + If the problem spans all tables, continue to step 3. + * - 3 + - Check that all workers are up + - + Use ``SELECT show_cluster_nodes();`` to list the active cluster workers. + + If the worker list is incomplete, follow the :ref:`cluster troubleshooting` section below. + + If all workers are up, continue to step 4. + * - 4 + - Check that all workers are performing well + - + #. Identify if a specific worker is slower than others by running the same query on different workers. (e.g. by connecting directly to the worker or through a service queue) + #. If a specific worker is slower than others, investigate performance issues on the host using standard monitoring tools (e.g. ``top``). + #. Restart SQream DB workers on the problematic host. + + If all workers are performing well, continue to step 5. + * - 5 + - Check if the workload is balanced across all workers + - + #. Run the same query several times and check that it appears across multiple workers (use ``SELECT show_server_status()`` to monitor) + #. If some workers have a heavier workload, check the service queue usage. Refer to the :ref:`workload_manager` guide. + + If the workload is balanced, continue to step 6. + * - 6 + - Check if there are long running statements + - + #. Identify any currently running statements (use ``SELECT show_server_status()`` to monitor) + #. If there are more statements than available resources, some statements may be in an ``In queue`` mode. + #. If there is a statement that has been running for too long and is blocking the queue, consider stopping it (use ``SELECT stop_statement()``). + + If the statement does not stop correctly, contact SQream support. + + If there are no long running statements or this does not help, continue to step 7. + * - 7 + - Check if there are active locks + - + #. Use ``SELECT show_locks()`` to list any outstanding locks. + #. If a statement is locking some objects, consider waiting for that statement to end or stop it. + #. If after a statement is completed the locks don't free up, refer to the :ref:`concurrency_and_locks` guide. + + If performance does not improve after the locks are released, continue to step 8. + * - 8 + - Check free memory across hosts + - + #. Check free memory across the hosts by running ``$ free -th`` from the terminal. + #. If the machine has less than 5% free memory, consider **lowering** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. Refer to the :ref:`configuration` guide. + #. If the machine has a lot of free memory, consider **increasing** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. + + If performance does not improve, contact SQream support for more help. \ No newline at end of file diff --git a/troubleshooting/resolving_common_issues.rst b/troubleshooting/resolving_common_issues.rst new file mode 100644 index 000000000..fd90472d3 --- /dev/null +++ b/troubleshooting/resolving_common_issues.rst @@ -0,0 +1,60 @@ +.. _resolving_common_issues: + +*********************** +Resolving Common Issues +*********************** + +The **Resolving Common Issues** page describes how to resolve the following common issues: + +.. toctree:: + :maxdepth: 2 + :glob: + :titlesonly: + + +Troubleshooting Cluster Setup and Configuration +----------------------------------------------------- + +#. Note any errors - Make a note of any error you see, or check the :ref:`logs` for errors you might have missed. + +#. If SQream DB can't start, start SQream DB on a new storage cluster, with default settings. If it still can't start, there could be a driver or hardware issue. :ref:`Contact SQream support`. + +#. Reproduce the issue with a standalone SQream DB - starting up a temporary, standalone SQream DB can isolate the issue to a configuration issue, network issue, or similar. + +#. Reproduce on a minimal example - Start a standalone SQream DB on a clean storage cluster and try to replicate the issue if possible. + + +Troubleshooting Connectivity Issues +----------------------------------- + +#. Verify the correct login credentials - username, password, and database name. + +#. Verify the host name and port + +#. Try connecting directly to a SQream DB worker, rather than via the load balancer + +#. Verify that the driver version you're using is supported by the SQream DB version. Driver versions often get updated together with major SQream DB releases. + +#. Try connecting directly with :ref:`the built in SQL client`. If you can connect with the local SQL client, check network availability and firewall settings. + +Troubleshooting Query Performance +------------------------------------ + +#. Use :ref:`show_node_info` to examine which building blocks consume time in a statement. If the query has finished, but the results are not yet materialized in the client, it could point to a problem in the application's data buffering or a network throughput issue.. + +#. If a problem occurs through a 3\ :sup:`rd` party client, try reproducing it directly with :ref:`the built in SQL client`. If the performance is better in the local client, it could point to a problem in the application or network connection. + +#. Consult the :ref:`sql_best_practices` guide to learn how to optimize queries and table structures. + + +Troubleshooting Query Behavior +--------------------------------- + +#. Consult the :ref:`sql` reference to verify if a statement or syntax behaves correctly. SQream DB may have some differences in behavior when compared to other databases. + +#. If a problem occurs through a 3\ :sup:`rd` party client, try reproducing it directly with :ref:`the built in SQL client`. If the problem still occurs, file an issue with SQream support. + +File an issue with SQream support +------------------------------------ + +To file an issue, follow our :ref:`information_for_support` guide. \ No newline at end of file diff --git a/troubleshooting/sas_viya_related_issues.rst b/troubleshooting/sas_viya_related_issues.rst new file mode 100644 index 000000000..6661dec95 --- /dev/null +++ b/troubleshooting/sas_viya_related_issues.rst @@ -0,0 +1,55 @@ +.. _sas_viya_related_issues: + +*********************** +SAS Viya Related Issues +*********************** + +This section describes the following best practices and troubleshooting procedures when connecting to SQream using SAS Viya: + +.. contents:: + :local: + +Inserting Only Required Data +------ +When using Tableau, SQream recommends using only data that you need, as described below: + +* Insert only the data sources you need into SAS Viya, excluding tables that don’t require analysis. + + :: + + +* To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQream database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyze and increases query performance. + + +Creating a Separate Service for SAS Viya +------ +SQream recommends creating a separate service for SAS Viya with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. + +Locating the SQream JDBC Driver +------ +In some cases, SAS Viya cannot locate the SQream JDBC driver, generating the following error message: + +.. code-block:: text + + java.lang.ClassNotFoundException: com.sqream.jdbc.SQDriver + +**To locate the SQream JDBC driver:** + +1. Verify that you have placed the JDBC driver in a directory that SAS Viya can access. + + :: + + +2. Verify that the classpath in your SAS program is correct, and that SAS Viya can access the file that it references. + + :: + + +3. Restart SAS Viya. + +For more troubleshooting assistance, see the `SQream Support Portal `_. + + +Supporting TEXT +------ +In SAS Viya versions lower than 4.0, casting ``TEXT`` to ``CHAR`` changes the size to 1,024, such as when creating a table including a ``TEXT`` column. This is resolved by casting ``TEXT`` into ``CHAR`` when using the JDBC driver. diff --git a/troubleshooting/solving_code_126_odbc_errors.rst b/troubleshooting/solving_code_126_odbc_errors.rst new file mode 100644 index 000000000..2e652b113 --- /dev/null +++ b/troubleshooting/solving_code_126_odbc_errors.rst @@ -0,0 +1,14 @@ +.. _solving_code_126_odbc_errors: + +*********************** +Solving "Code 126" ODBC Errors +*********************** +After installing the ODBC driver, you may experience the following error: + +.. code-block:: none + + The setup routines for the SQreamDriver64 ODBC driver could not be loaded due to system error + code 126: The specified module could not be found. + (c:\Program Files\SQream Technologies\ODBC Driver\sqreamOdbc64.dll) + +This is an issue with the Visual Studio Redistributable packages. Verify you've correctly installed them, as described in the :ref:`Visual Studio 2015 Redistributables ` section above. diff --git a/troubleshooting/sqream_sql_installation_related_issues.rst b/troubleshooting/sqream_sql_installation_related_issues.rst new file mode 100644 index 000000000..8225a2f18 --- /dev/null +++ b/troubleshooting/sqream_sql_installation_related_issues.rst @@ -0,0 +1,33 @@ +.. _sqream_sql_installation_related_issues: + +*********************** +SQream SQL Installation Related Issues +*********************** + +The **SQream SQL Installation Related Issues** page describes how to resolve SQream SQL installation related issues. + +Upon running sqream sql for the first time, you may get an error ``error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory``. + +Solving this error requires installing the ncruses or libtinfo libraries, depending on your operating system. + +* Ubuntu: + + #. Install ``libtinfo``: + + ``$ sudo apt-get install -y libtinfo`` + #. Depending on your Ubuntu version, you may need to create a symbolic link to the newer libtinfo that was installed. + + For example, if ``libtinfo`` was installed as ``/lib/x86_64-linux-gnu/libtinfo.so.6.2``: + + ``$ sudo ln -s /lib/x86_64-linux-gnu/libtinfo.so.6.2 /lib/x86_64-linux-gnu/libtinfo.so.5`` + +* CentOS / RHEL: + + #. Install ``ncurses``: + + ``$ sudo yum install -y ncurses-libs`` + #. Depending on your RHEL version, you may need to create a symbolic link to the newer libtinfo that was installed. + + For example, if ``libtinfo`` was installed as ``/usr/lib64/libtinfo.so.6``: + + ``$ sudo ln -s /usr/lib64/libtinfo.so.6 /usr/lib64/libtinfo.so.5`` \ No newline at end of file diff --git a/troubleshooting/tableau_related_issues.rst b/troubleshooting/tableau_related_issues.rst new file mode 100644 index 000000000..99b4a04dd --- /dev/null +++ b/troubleshooting/tableau_related_issues.rst @@ -0,0 +1,73 @@ +.. _tableau_related_issues: + +*********************** +Tableau Related Issues +*********************** +This section describes the following best practices and troubleshooting procedures when connecting to Tableau: + +.. contents:: + :local: + +Inserting Only Required Data +~~~~~~~~~~~~~~~~~~ +When using Tableau, SQream recommends using only data that you need, as described below: + +* Insert only the data sources you need into Tableau, excluding tables that don't require analysis. + + :: + +* To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQream database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyze and increases query performance. + +Using Tableau's Table Query Syntax +~~~~~~~~~~~~~~~~~~~ +Dragging your desired tables into the main area in Tableau builds queries based on its own syntax. This helps ensure increased performance, while using views or custom SQL may degrade performance. In addition, SQream recommends using the :ref:`create_view` to create pre-optimized views, which your datasources point to. + +Creating a Separate Service for Tableau +~~~~~~~~~~~~~~~~~~~ +SQream recommends creating a separate service for Tableau with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. + +Error Saving Large Quantities of Data as Files +~~~~~~~~~~~~~~~~~~~ +An **FAB9A2C5** error can when saving large quantities of data as files. If you receive this error when writing a connection string, add the ``fetchSize`` parameter to ``1``, as shown below: + +.. code-block:: text + + jdbc:Sqream:///;user=;password=sqream;[; fetchSize=1...] + +For more information on troubleshooting error **FAB9A2C5**, see the `Tableau Knowledge Base `_. + +Troubleshooting Workbook Performance Before Deploying to the Tableau Server +~~~~~~~~~~~~~~~~~~~ +Tableau has a built-in `performance recorder `_ that shows how time is being spent. If you're seeing slow performance, this could be the result of a misconfiguration such as setting concurrency too low. + +Use the Tableau Performance Recorder for viewing the performance of queries run by Tableau. You can use this information to identify queries that can be optimized by using views. + +Troubleshooting Error Codes +~~~~~~~~~~~~~~~~~~~ +Tableau may be unable to locate the SQream JDBC driver. The following message is displayed when Tableau cannot locate the driver: + +.. code-block:: console + + Error Code: 37CE01A3, No suitable driver installed or the URL is incorrect + +**To troubleshoot error codes:** + +If Tableau cannot locate the SQream JDBC driver, do the following: + + 1. Verify that the JDBC driver is located in the correct directory: + + * **Tableau Desktop on Windows:** *C:\Program Files\Tableau\Drivers* + * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* + * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* + + 2. Find the file path for the JDBC driver and add it to the Java classpath: + + * **For Linux** - ``export CLASSPATH=;$CLASSPATH`` + + :: + + * **For Windows** - add an environment variable for the classpath: + + + +If you experience issues after restarting Tableau, see the `SQream support portal `_. From 68c847ff7ca55e7567612591fa38f7c9ab175b1b Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 20 Feb 2022 11:26:54 +0200 Subject: [PATCH 185/300] Update executing_statements_and_running_queries_from_the_editor.rst Added icon syntax to make icon images appear. --- ...ts_and_running_queries_from_the_editor.rst | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst index 65863ab6c..3be680e9b 100644 --- a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst @@ -414,3 +414,81 @@ The SQL View panel allows you to more easily view certain queries, such as a lon :ref:`Back to Viewing Statement and Query Results from the Results Panel` :ref:`Back to Executing Statements and Running Queries from the Editor` + +.. |icon-user| image:: /_static/images/studio_icon_user.png + :align: middle + +.. |icon-dots| image:: /_static/images/studio_icon_dots.png + :align: middle + +.. |icon-editor| image:: /_static/images/studio_icon_editor.png + :align: middle + +.. |icon-copy| image:: /_static/images/studio_icon_copy.png + :align: middle + +.. |icon-select| image:: /_static/images/studio_icon_select.png + :align: middle + +.. |icon-dots| image:: /_static/images/studio_icon_dots.png + :align: middle + +.. |icon-filter| image:: /_static/images/studio_icon_filter.png + :align: middle + +.. |icon-ddl-edit| image:: /_static/images/studio_icon_ddl_edit.png + :align: middle + +.. |icon-run-optimizer| image:: /_static/images/studio_icon_run_optimizer.png + :align: middle + +.. |icon-generate-create-statement| image:: /_static/images/studio_icon_generate_create_statement.png + :align: middle + +.. |icon-plus| image:: /_static/images/studio_icon_plus.png + :align: middle + +.. |icon-close| image:: /_static/images/studio_icon_close.png + :align: middle + +.. |icon-left| image:: /_static/images/studio_icon_left.png + :align: middle + +.. |icon-right| image:: /_static/images/studio_icon_right.png + :align: middle + +.. |icon-format-sql| image:: /_static/images/studio_icon_format.png + :align: middle + +.. |icon-download-query| image:: /_static/images/studio_icon_download_query.png + :align: middle + +.. |icon-open-query| image:: /_static/images/studio_icon_open_query.png + :align: middle + +.. |icon-execute| image:: /_static/images/studio_icon_execute.png + :align: middle + +.. |icon-stop| image:: /_static/images/studio_icon_stop.png + :align: middle + +.. |icon-dashboard| image:: /_static/images/studio_icon_dashboard.png + :align: middle + +.. |icon-expand| image:: /_static/images/studio_icon_expand.png + :align: middle + +.. |icon-scale| image:: /_static/images/studio_icon_scale.png + :align: middle + +.. |icon-expand-down| image:: /_static/images/studio_icon_expand_down.png + :align: middle + +.. |icon-add| image:: /_static/images/studio_icon_add.png + :align: middle + +.. |icon-add-worker| image:: /_static/images/studio_icon_add_worker.png + :align: middle + +.. |keep-tabs| image:: /_static/images/studio_keep_tabs.png + :align: middle From cb04765dd63025be728afd4fe15744569be9cd1c Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 20 Feb 2022 12:00:59 +0200 Subject: [PATCH 186/300] Update creating_or_cloning_a_storage_cluster.rst --- .../creating_or_cloning_a_storage_cluster.rst | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/operational_guides/creating_or_cloning_a_storage_cluster.rst b/operational_guides/creating_or_cloning_a_storage_cluster.rst index d9cd711ea..0406bda77 100644 --- a/operational_guides/creating_or_cloning_a_storage_cluster.rst +++ b/operational_guides/creating_or_cloning_a_storage_cluster.rst @@ -3,19 +3,6 @@ **************************************** Creating or Cloning Storage Clusters **************************************** - - -1. *Install and configure MC (Management Console)* -#. *Prepare the Hosts* -#. *Create the private key file and copy it to your local machine* -#. *Run the Cluster Installation Wizard* - **It may be worthwhile to develop this.** -#. *Validate the hosts and create the cluster* -#. *Create a new database on the cluster* - -*Note that Vertica's "Management Console" corresponds to our SQream Console - confirm.* - -*Note also that each item in the list above links to a different area of their documentation and is unorganized. Verify whether the above steps are located in order on a page in our documentation.* - When SQream DB is installed, it comes with a default storage cluster. This guide will help if you need a fresh storage cluster or a separate copy of an existing storage cluster. Creating a new storage cluster From ba959c9fa36ca6a13e91fc7fee7fd51ec111f6a5 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 20 Feb 2022 18:42:45 +0200 Subject: [PATCH 187/300] Updated Updated: Links to Branch 2020.3.2.1 Replaced JDBC link 4.4.0 with 4.5.3 (Client Drivers page) --- _static/images/TPD_33.png | Bin 0 -> 38530 bytes _static/images/dashboard.png | Bin 0 -> 149169 bytes _static/images/execution_tree_1.png | Bin 0 -> 110949 bytes _static/images/search_field.png | Bin 0 -> 35853 bytes _static/images/studio_icon_close.png | Bin 215 -> 208 bytes _static/images/studio_icon_copy.png | Bin 421 -> 390 bytes _static/images/studio_icon_ddl_edit.png | Bin 551 -> 518 bytes _static/images/studio_icon_dots.png | Bin 353 -> 327 bytes _static/images/studio_icon_left.png | Bin 271 -> 250 bytes _static/images/studio_icon_plain.png | Bin 0 -> 285 bytes _static/images/studio_icon_right.png | Bin 262 -> 250 bytes _static/images/studio_icon_search.png | Bin 0 -> 415 bytes feature_guides/workload_manager.rst | 10 ++-- .../executing_statements_in_sqream.rst | 4 +- getting_started/installing_sqream.rst | 6 +-- ...eparing_your_machine_to_install_sqream.rst | 2 +- glossary.rst | 46 +++++++++--------- index.rst | 8 +-- ...lling_prometheus_using_binary_packages.rst | 12 ++--- .../installing_sqream_with_binary.rst | 4 +- operational_guides/exporting_data.rst | 4 +- operational_guides/index.rst | 1 + ...l.rst => seeing_system_objects_as_ddl.rst} | 6 +-- .../configuring_your_instance_of_sqream.rst | 2 +- ...ts_and_running_queries_from_the_editor.rst | 22 ++++----- sqream_studio_5.4.3/getting_started.rst | 2 +- ...orkers_and_services_from_the_dashboard.rst | 10 ++-- third_party_tools/client_drivers/index.rst | 16 +++--- .../client_drivers/nodejs/index.rst | 6 +-- .../client_platforms/sql_workbench.rst | 4 +- .../client_platforms/tableau.rst | 7 ++- 31 files changed, 82 insertions(+), 90 deletions(-) create mode 100644 _static/images/TPD_33.png create mode 100644 _static/images/dashboard.png create mode 100644 _static/images/execution_tree_1.png create mode 100644 _static/images/search_field.png create mode 100644 _static/images/studio_icon_plain.png create mode 100644 _static/images/studio_icon_search.png rename operational_guides/{viewing_system_objects_as_ddl.rst => seeing_system_objects_as_ddl.rst} (97%) diff --git a/_static/images/TPD_33.png b/_static/images/TPD_33.png new file mode 100644 index 0000000000000000000000000000000000000000..f3235acc1e16ed8f0f5d0badcabf5cf98c7c5bad GIT binary patch literal 38530 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

choa+z`qt!6z9A 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 +FxbA>4^q>wD6s$!Kj`{iFWk; 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 HN@xNA-#i-> literal 0 HcmV?d00001 diff --git a/_static/images/execution_tree_1.png b/_static/images/execution_tree_1.png new file mode 100644 index 0000000000000000000000000000000000000000..66ae30bbb315008fa9b41b5d19675bf1e0b84c08 GIT binary patch literal 110949 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 z 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 TOuYOY`14RkS-MQhIPm`f(0+d@ literal 0 HcmV?d00001 diff --git a/_static/images/search_field.png b/_static/images/search_field.png new file mode 100644 index 0000000000000000000000000000000000000000..9fe94bb4b7ec4273f87bd54b897442f086ebac47 GIT binary patch literal 35853 zcmZsD1y~hW^S6r9AR*Eq(v5To2ugQ@G}0+8EsekhE+O3@4FUqvBHi7kba&@>E^fU0 zf4+U(-AC{BoHIT1n;AaI%Zi~P6CmHacMnZM{Egzhdk=r!yLTUo_yGI~B3BR+_}_hd zMKR%f#eGEU;5QFVgk*&7-75`8xzc|GevkBCT*Lm}J@jVSzxUg1at-g@3(1gpBc%L6 zXZzaBfk@3@^;2J=-na9f z_=Ap?$WOPoSLl5ZLN4p2M?SBvKD;|8z1b+a+3?cC3()`bD-P$4O2<4KYBS59Up;mj zT3YT$YYNuZ*5BxvVzWe9|M`r$=jTr!7725TzrT!Ho^f<~DkdVLK#u?KfkvL5DFmH= zorl_7_$90`pW_OG)+f@9w%gu$iH}S z^^y(ckoWrVc~aC&K>FVVho-iNjF&MzN-n6?uax=u^XEUWT|MU8`{>*ZLlFXg9Q}XTuZ(oFc6>Z~`sDT0b ze~3M^cNnXRz6=kvla#V_K!=jr19<_56$eL)^5W$~dFS$k4q20}*;{#R=p^IxBJiTUdsMiob93#kS= zG8POR^&e?iT~@TFvJV-QwzReN_4gNa7fVY^KYaA)_~azN+d}63dzOEN#lyQfOp{kI zTd`|V-6*HV%%aZsl{4qt8@0wKj$8#u-&kJIO4J_jXH!s8FBa77*MNiVY;9lg^YfFD z39)tN<>hUTmyC~%1&hc%z|HKgGVD9>0J9RW-HD!s3%>|D$Vbg>s9E;w%FyHHSm+ z4`46r8PG<#yu6$x&B)Yz-hzWD1FeE%qJls@xCK6603xpLiiu;7Yy&aV7G3c z<#$;5Ry>p(bwAek`E!RDDFq-kOJa!oz_i=V&qwYeliK97n;yJMN=gXmL?6!>85nX^ zNCN*OIxQ{ll)#&qE!H)Ux-UutOY5l&8;)$ILhnE{-?< zC1e#w$j##Kk}whhM@qeF>I(Evf!_so@4wv1t<{jJ3=@5xz^0>X3x`J@jJQw)E{X3QPelX(4a?Bz}@T^86Js(0c5q zxLIK_{;vkXYzIAV>36xwGe}PHLoH;ar_10e4aCm4{!24j+LzgPuSfu|kht)E{e1Ic zPW)dRZ~->-q`I*rtAUgIIT3*i9}{Oz;Tx@$grwM7tSDvJ^+J$0df_+w>dD7_qXlaJ zG1~cj^-mJ{fXJ?{ZtSSY5q}(0Ls!u@cvFh*?2AvENF7y&y0*1c^!q{0&MHErs1O+PsIzT z!fa9g)%usbn}@s`*6wTuKM!5rBRfp~=K(NR5-`bGZMXbCUJV!u?61UGVgH9AtBxbH zEYnnfB)q@P0Q`F$L%7KogdD2+u=gF%N&Mqe%yO&06p=K0O!k8}ypk6SfyaJ~55^4&QuX#g)VzG;{A7&nT3gPEbN#C~Oq z=g%uFk8@2-t5r-Qd=7I}Y#U|`(64;8SBp5r&Bn&Ijf{*)q;i&3E1gfsa)bBRJ+pht zq55%*ghsCR?(PN#26lFK=H|$f>r7D###i)zSTI@h8y~NkMU!W*?f38BP$+b8 zP=SWhU9lspRw7>p|MoAAR+@geXl3acdpxrLyE!nNgx~e*?1iD7fq`)1=PZc}+dnE> zj?-+<9H8$`d3}BTnB*lM9^Oaku+Y%Z@NhX98C%(*#y`<5t_UyX!wb|!dY7xSQikr? z+1dK~dS74PpA?R2Rp3%Dq(73c)LM%`Z9bFN3*Fw{cB-u}D3D^4uyv$owmKgFqX5R; zk5)Cg_Z4wL%&c_Uqwh9lPv|vH?4^=E7|ayQ%*>36ib{$&8h<$|ZgT38npV`TC@*hX zF*$;HrocjjiUv1=7LOs^Q7POo4wqGIecTV%%+m8&PSRD>SXReVLBdQ##nI#4J9`T$ zO|jZu{g@qPxF>Fy3Q@mJdPKk`OpQiO>A|_>dNBc+}!V(neR+ZO+7tz;;Bx1 ze>J~D#6t}571B4YX|mRI5ThgWvm|XP5rWA`Ao_cYVVt3=wWq#>hKr+>cGRG$Ih&^C z(?H7{(F<~cJg5(PV&@}aU< zS{_dW%e%edM%=ztCfM8CIix9$_b4T4*LX+7lr70q`C&BPH+ie5#s!lGsidKUrKP)p z-P;;gGL5%78k*yJmYCxeQxxFHPe>B8C439D-^~owxCU7grw{G!P7Af9C_{0MU-GiR z6ux@ApC~gZZW8P2)CMeS8Jh%uJ0U_^roXR~nTfWfIM0TaGjV#l&}oijJ@&ggDh2X2dr$4fWpv16seX2T5E&6#H1w~O5q@{S0L!L z;bK3vrDo;jWO_l%LC#i{misLuzcRgZ!hA)^=_*DlmWh8*JW!gwr|omykppq=2nYG5 zcW6nZ((5+0Y9-H%*ko&gJXwXi=RJfyOt+_KkIy;d-3}GSmn@T&C0shWNi$Pc8UnLy z(F;mB4#moepn$x=h{VVYxR@H_mP_^R2RXfDweP1W@l9RVIknG^BGnQo$XayMK#*Px zsm39}#KgfSd<^N4XD`!oQK#n^3b!5Zs6@}uFD~epk{y+4-SH zFF&Igl&$@iE^6mg`d}QJtR)AQ-Ytds5N4mED?r|v z8-<;-z;l2_;cjKEV)~-9$ar#uDsdX8S-E9s&UX;`mLoma^je)i8ABjRee+XVqlm9O8~>b{?5C0~8$Woid`6 zdeM+xS^XG!$uq-1k?O0_75SZPzdus;TP1K=>VP($g*2YQ1?)Hd8fd*=NYWK5=TA^Q z3lvzr2KV-X-EYTLNqdnRi=hyFM`H0+arg(mM-q|AV3xxbUH4T!4h{};oaQs-_iGFH+Vp#PBvMg0hEfNv_1}KZAuy8@ry%$e)UjZ{ z3bWeK50AtQB40^LI(=MvB4(E#ovyMvXL(66+fS?t8Y)E{hM7Xu(4mnp zGc4y1qO|N$Vtm|_w>@! zF_z>P*;rbeS#6qD@f1d4HxBDXCP+sz27Q4(m`$Z7wkE)TD$6eIEkqgkc=J_uG5$Vs z*fge-&>6AYo2*6IEPmE5OyYOppDN}d&Og|ql(LSb#hk)eMKl!Y)Rbw}YB<@=sA!uh zh|4Zoh))r!n0OWdS3<~dJ}ma16R=}Z&j;1~0AeEPY>11{)Yr#^DwH~7M=G(E*`owY z(VLrZqV@KE;Vf?*(~s4Q-V6CNFqCIWN&icY>;jIQqbhPpg8{`2`VQ`ZJTb-IMh z7`=2^^THFk87Lp0HdQAda7O~cXXP>w!%F)P6qg1I3k#8vk*sWND9Ffk^z?}d2~*S4 zloA{3>+74FZfASH2L=Yd(uc- z$g(Y{zQ5mo=ltq?aEJu;`D}-fWmC$MUs~~bv^kw5ZT}RxT)xNGf+guf-{VO=WXq*f zJ;y;m4b{z^VbM^c=OTy>{GKqqj9&2ln~EvLZUlwj8O_|N_?3s66zU?MhARb|rXW5( zesy&@FQSw#B9$(b6fYGOFNcRNhuJPz z*)Ge<5$p~xP>|gYQCx@EqUrVC8N^&tvz139>_w||a5#2J3BB#@$}Uo^-HJ$uCcz%f z1TvLBuN@JeN0T06;?tbsmEL|@-U^@UC!Nn0#hvLHCLu5?UO^ZznXeI-Ok6&_ySg-$ z`A#oVQMK}bXuQkZ#3R$rtYF$N%PEk8BNAi59^?(HJ;vZo=GoSaV&zA)9YzIcK8 z5fN$e6b?I} z%&4fSFc_>&7rn6FdyP**Qe0S6VrE*%#ZLHEn$e2bI7H?}C$){ahI!vFgVk@;J%874B~cv;e8E2EV{)L5?9P3mWqk+MJf^VxY(IhD=SgshnD5_uGbV-3}-`GZNh=j zV8tL1S_xx(eEb>pSNm1jUW(rlUZ>7pr@J?^jcf#v3}d(lfmf%uH}kiFw|k_V-4wes z)lt#W4+H%ci&9%*&l%|0s`I(Zh+HTO4o;Y=5%o=P9htJm+`V#Oa5kgoh}`d_3AaH* zac-fOjMoUuFv!b)YtG)mNR{*9FmUq(R6=AexFF>943WF^R=c0G-ryicjSvAjD`?l> zV4|O|dfluJbo8=HsLy!AA^7A}!J1)6v(<$Uw(bl3Q3bJaJ@7FJq(_!L(PC?2bSQUg|Q>YXE?eW2I)&!bt};L0&@EG%W#0^^8DPTz({e zLXjY0o$>nQ}T^tvLfw7HST$2=s!_uwL-ijPc*PgavxRt34+yq=|*8O)JeMk=`t zgq@5B6Lg*#T2jkR7VDG;&X-bC@Rr$U57|{$>Tq(_3L1$?i|0R{vgH#Y_lqb(1wsEa zNoNWIRW%g-(+`q)_d}W40uH@MKIa`GLPDk3aW)K2fxH+E{WK`ZfD9I~v6O~b@BDOk zfyHKGXz$7iXMxA$G&$g=T$|I@_iMY4{9Bd$OhPW+h7x(oO7!@lk(;!9F#2{ur3L6? zEf3hMhxT;AK~Td(gM%R{HOa+C-7VLO3R#yGh{E>H51cpyA>r~FyEq^E6 z?dXUMmde^7$Xj1;ewzpN!yxqs*nm{Hq46dHL3~OI2|hlOvy22lfI7VuRaI2tdyQ$j zt`Qyw1O{?I{Ca<~VLoYDK~z0HJ#}_)I6697+ltlL{blmxDJDKXHeqaBbOJP9Q(pP4 zg39!Op(TglF6`B9)bFlWz5@SzOv|?(uc%O(0foTljY>m+U9kV-%q~xMAETq+Y~C*3 zo;BZIrQXha9f^4z>E3jEoi7UBq~0#c30&9X(`A?yK zOeDMxYqwX4jY#1^xrK%7@x5gXD3GM&WZ*M=UZ?PSOc_)-sWTv;lU#KclvGw!<>cge z?Ox8yNyyYY@9Kz%v`+8V*{|*W-ru*aa5hecgVf=W{I220B8X2nHFPnO;Ro7ZJAqF0 zEt%isF?y+3JI(GD4TGXCabAz;Tf;eMtHOOCz0^hwKzg~tg4i0c-?}G$(n>)^6)d(@_lg_pHmB$3u1juRxtL^~c*&wR%#E)P-~5|K>r{&tZ^({;v;mu1uA#zyRc_uL zThPW`golD%S$iA2RF;I-Jx)!8t-GzprmyZc+EU@9i3S+S{<`q)Ut9L;QAsl5T zjkk+(0vh=+v~8~5t*W`%>-u+~*NyJ&rmp9vCT(7x`#@hnD>`I}-eX4Y>lDIZBfI_{d0ZH|nBq)BVt9 zJcRO^o-^@=<82#KKF_+`+_hHRij3Z3=7tYPYtV`O#zsLl`U0R6wK-yu6t+0@VgRbv+nydq+n7%UOISnDO` zlb;`$n3$YA57E6*?6LQ3u)u|<>SiU_`mo8!K2T{lKfAPKC~RP0sQd(dSWVY$`zW4` zv8ZU`q1)g|-hVM8Tah!_EF&5y^s$odo#xNyaqdTO~)jB2mxaUC!%_m{+jx6< zlSN6Rj;=2A3M39K2+-7n5&U8Oz-W-z({7bn%hcLh)Mc3fz{>Pph^`;$7xZ|YuDDgx z;Tca!xmj3QeGZnEmbe1Zd5FT!&(DDY327W29O}m`1iU>>8C+S&mYP}~WKkSUw07PJ zIg2<`4Pw1w+q-a7Fuo#(NvLrlUG%wF7!jsg6>Dh!qd=xrG7ol;?Ji)#Dk~fu9Djd* zr&?`O3ZJNRZ}0m_ODJqaBqTdu)jvi&z)aeB%{@Ie^?n0gM&2SG?Gt$Yn{Io^NP>*C zG!d^mUOfjp=L+r*8bi>CTRIIuyXy<>lqvQSC^A8P-26vp<+{+D(SM zO*h1J-uZ>_xQWmC=1P(s%O5xcrtfxqFR!e%i0EQR#ffw#-UDIAOc3+7h|jorHi;BX z?O@E#mC|&Lh~EML6=R_U<`DK<0vvBSpjy#Zjf8X!P#v%oeQg)yU1~#Gc&bpd8^&uEnpBxP;K=Z z=J@WAME4gX;;CUU)qP*Z957i1%Y3hJU_e&`o_Us>2^xXRLJJZsf&Bk`aAM9*e-&Q9{-Bp2NO8dezgx22LBwowAYb) zp&71^XN=Om?tlzoU}VH00O^^Vt7|T_0gzCxEquqs9fHYGd)@1zb^wm~E9vN@#Kgp; zrs}Gyg6_)r)KrZ!IquV^xlm0`a0iIRO8;|5mP%w`0BJ$v8SF`hNwOxcuC5@&2?^bI zFKcL+Gh~&Bbhy2_77HhVKp--5asW?MAg{9fmn)_O>+b3o zWuVtMD$2?uQiyza1#@j z=Z==lcj^MW?aUV6md~e>CUW*H&5n?B6+4K`b z&iMKK`R@zWRbh1^8J^%=^@D_>p6ow6Ux(;>gSg4$eMd@3AYm9B-%$ zo-K7o?N%=jq`!Wf2$7hJ`auHVl4lVBh5(#+FYeo<$C=owy!7M8y&gX<(F@63=rko8 zisxE{4`^=>)5k?+!MqFMe$HF1ar06s1L3l{0WB3xT}2(FsGhD~x$YiWSt&VjS%{ou zn3Qx)VgzD=yYK_DmfDsU+MwI--pD_bRTH~onRBwT(jp?_J^+{z)GjmMZQ()&2M6Wf zs9{s$GHC??W092=uwMy{V5h*7v6-P^ViIt^ad&sG%bjV7{tSY8OiXO7nyTv9$Oup) zLWn4LRU3>HjWY$^d1c8BGtZG?_2ta1{`xeaBL#ncMZIWJ#Q89s`>0li#IE^ z`wuBo9>PN-)-S##fC4F|;y4>e#h=os`jJRP=g}6?nW4F;u_SNDk5n(=4%dk21avH= zVXR0cz_wqq1--{$Px1>2e0_ZTQ}}R6NWxm{>guqmWq;r)i1xS3CH+wQFtxwf zUS3wN@JR)f9=MR-Nw`cpPY&Q|MdT-bjnpWrsUf&oT3Y(Oss#U3RZVX@{f+=l8FF%R zV2Me=M=>x{*M4gPDa5Z=JDW%cZSRqeSYvZfomK6db}447Y?x3;_Q$6NT^@VY6-A;( zS>jNcnHCq@Fq9NC=H)UlF!nPub<#5gC;~j(XY1<0)j74_hvdRK_lWq!SZFdzh=q=a zwZDH%baW7_;a10BW@%}u0j8_V+5p-2=M5PQbRi)j;lzBEHuDX@1-{c9#Orff?ITvs z*axPtmSkF|Z{~uPo7rh-Zeg*xw)XK=SJ}+$ELxzS`p)$ReH;bRkOv(r*$d2E6Fb5f zoShMa3eS`CRnV!DkFC zD(XwuBgFjk;|7>F+(BP2hUQAkO1M}6if!tTcieVk)Rgs#xSQO}40Et=@_{_2WQoz+ z=e>5_@Z;k%NY=lq->mH3SW`xR8W|nEUao2wHDt-{ZoKu-a5+!C9ls5Bb#!?Y58Q>p z=}t+*jjOS-=m?lRaKB={^^q*Z;;2b8k}z98JF98rpCE_SeP}$;Q)^naqiRqMclvaY z(wEd$O5(u(lFP9shatDhsfz8Ajfeb~(DC9q?MSWWeEoVmb*+?hXZ$Pn?+0lY*tEp% zWG4Ef9aj#ML3LGZxM&Ry#@Pbqx>xmf10!Lx&0+E`YdT~C@EixN`&Y#sA-#^ViJO89 zeOLtN?_JGp9Bm^e_iW9=YDF_{^sFYmP-{`;e;DXHuilbi9|Y>(_e#W@dpQx#i4+zl z820@n_2&c61bk+Qz*yyRgc#fKhG{A+92xSZu}Qq3HmjU?JH`7fN`~wMt85+KE<|#0C*z2cPD-otr2(Y@DPT>a;t!sT2Im5B+r|EV&RM6}8Im@fV(YM9ZGzBYKXuM!)m1(M4@KZ*z-?`~piYtKg63(r?ltoKYlY#lu@jI^+b^vR zu9__k3}8@T>y9ovf+FF(q|dTF`oL-NOlUaA&UJf@KU#{Uo4Q7-4c9mgiqWm<0l{co z_vblFkKmUfR|xM4C0l+Lr>TXwRRr;vSeU!Fo`TOarp<6-=Vg4fSD!KVX)Yxm3a5R} zQ9P@UBM>l_qQM#dS$urzEVfL`iWBSAGeO#J$MKHJbRn|9*~QG#%1XDzOu>FRUkL-8 zt$i-aNp*jC2wZ)xg#DD{uCv*+YZ&j;svoG=C#k+CW^Hb$=Cm>)#j{sv{)*~daiYmC z9ks;x7Kcc-DWqgiZ)$0s$Hguc`OtPM#ar0xV$y`8q5`DU%MQHy-11GAr@N%Q?q}_S z=bim?ZjV{*e*J1HEq%eAHEMo6ia>gG)XR0cHS5O6BF{}|*yEv!QAs;vX<)E$G+A!5 zGjU)3$8);hX5QZ36XRly*W20Mv5lYz_pNf;d1-sFbaeEs)AHt6jC30mg4`*b1!m=w zpLd=Rxa<#QgYl5GkF5as_6o>kKAAjH_u!6Q`I!wTaO#>Nx;~jBK1IX{)V&7r+;{6hN1Fp_=hZLEUEG*osIUI z{#oW!4dn)-zV-BBexvu|_uwoEYMG~i8S#xOA=i&ED12BE3wwe#m=4TkRW8e+sL6&n zPb8c;_lfo=POeLWTqtu`Rm$LnBE+4W-?5`5942D-ZN0bA1t=4d)?3Kdq`*Xv@(K+MNCc56I^grg^gga^m ztnU|D5%+$n1d#XOcEXw8!?^yA4nzlfF6PGq0b2F09K2M3Zzb?q$rqK~tYv5}**b2Fy`(kEmjG*EoKxz7PYLV9|7ZeWi7Ys)ZJ9};#1 z-}6^LTJqb;$w62Xv&n6dE#f4kn{`HZdvZa5Lktn2!4G9R+0iZ?(Kz&HdH5 zJxRWVMheF`_*%n-=c&D&{orFxOoI4?&tvAS>3hGL;6hPS?=Ke@7sIeOK3-mQQl1A< zZ_s$#so;I@CqVl4`TfjQm6czKl_GEJR|}`ue)Kp#9yk3(SPtDO%b{HczR$$9ODzNX z+CIv3fOn9dz;uw{*_5h*!W%USh`U+caokv}x#8-Bc)q2t^c*4Sbxsn+VzZ|e=g`TA z+~dKImzIXIvC%u~E5+H*MI$V=?Hp6gRtV zmZitX$4Ev~)-FeDm<$Eg*^ibJrlzhD&_f{*T3+X+pyBnT#KgqZ)GBp`OYMY*+Ake1 zj<%u@bY>tS!>AaET&WL|ynl@o6(5%Ej311dVqqcq3o z*3MTjq3KFpll7S}?cnR{Vz}6u{7Ai$98~%DFnDOyZWl9{_(Bnz)Bl`4kZbqqTHj= zD_sye)oly7$@%)xX1+d8d-kFob9_KgOw|W>7t(?^Iw(LbOb+^k#0rC;4DE1w#U}Bw zaXDX3KtU2@W0_a&kj=OEI+mIPAE%>Dvrv_v^LbrXc^x!fG5e6-tcjH|G*gfXYinzx z6ss4F!OgqFLB35|vb?sWl$~SG^fk|j&wcZ|YqS6$aeKM%+QXR(pa%4qGFKSdx6k{h z^9IDXE{2x7D;yo)iv&fDB?5y^GfR{ue?en8F);A{VrvpW4pxi~`&Qkf;$*T{qSjA>Hx?6-w_w-($N)x*`Vg!?3k*k5xGemUtRchbwB-~dtDJJ)Tq zW~``luji<4lXM!zV76-h4j_eRSCo`dV=pU9fT6W+>`_k;Qz`r`?=1*gzh^~@YBA&Y zGpseTw%!4FnA!R|O|73T87m#K-U}LTZYBW|4pV!cXZKd%n0?|I>KhzfT`xc?xQ~Qn z8tU4CSNNFo*eB$z|N5t;r4?Z(`5&@_x74YgbR;v#O;VDQ1jNMJPB}CvkT>^(zGu*Ijh6{p!u&%@(?b4w#rM;-1D+_ z9v>n)Vwx-n(yzoHB%m&2hxi3Hiwu%5?sqB;4?Sx({kmFEqBnk)@{2DD3iY-@X+!Uw z^ZNC10;;wE70vf}Nj)HbMp3A!ZOq9rmk=?NQ0G90Rk|(sjD3g%XIoq*79gk*+kRib zf6-n?NhHqjynGpIf3f{kyn9vG{eHGWEG{l+zB+sCKWZS{ zj~s&~S9@-EYOS8c@}dyLj>Q<#+q0r%zT5R=XFGd)e?{R(u^ug96Os=-k2fC+z6s>A znN_ru{M<_JG@t^8K?Sg;7;2Sd$bU;UUY@bDMbQ<<)pO70@P%`Y`qW z{6lf7CDq8Ret}z})Q1-PI7aSvMfUD}KQ_l(wG$FVgFWXwcKK0nuXV44*IvA(%E`J~ zi&0~FZel`BbTII{d7xW0YJJ;z4zq7PMxMM%fokPyn4*1kMTZr0J=pQ~{^g|o$uA5y z2UK=NCI>SxnqbYL1gg+!v~BiSj55y;#Zb7%qyWk+K)Jy>?g`!BFU%BW)nr5o35hzi zzj1J+Z}Y({+N**d{}7t4K0F~L3yV`1dmE4eRS6cA1a^u@=2r-pAidyDusXAW-)TOy z6bvQ^G-&~p5IgDbUs|nUQ!inM-9*Cz!w`aw6JL)V;#!iWhsD(@x_&td6}{^h2_x<^ zk(e90h_w2L;0o2ySB?$-#?Rk?y=?cbJy~j%yqi=3Jj&YD^ z-iV3BL3C;MLlux!W zIt_>iJuk#s4)pc4-QRyN^-a3J10#keC+my3^UjOVDuAa|N?D49Pcl84u<@T<#9At} ztj&Wj8h+QcFie<`G;vS+P*VNV`z{B_H zet-Y#mr&D-swx83zt5$XohsIH1f6LLSkEvkk~Qy(tdD5Ibn;U|0Ly^0=UO)jczAge zVq!)?W#jlnt%|7t3I+sucz6KRl98f61^`>*+7{21!fV%vYuT*mq=k;osBXHfDc8=4 zEz8Z1qP)Zr9ZaSaM2cTP5JV(vdG~T$ynIqiTN~mNAsS?0WMm|6Y6_Y@7T5O7<^blw zDRGL6kAH!Os-)CaJBi;G0zkrP$}tpNtA!UudFzUv=~@bu<6K>BPfcoD%_?4#w<=Q* zMFL+1c-+6QMgBX``8hdUiEbc2a@5xLCU7f0M8WX=ZY_Pl#{(GnPdjLJZxw>tV_B)gUpc(>1ayWah+i*!08;@pM`w)uT6BsJzkYyt2@<`FFT1$zZgJ9`t)YXy- z=|ZroDMg7Xr5}cHP!$-2^CSvqA97k_8B`#~gl-}u*Qm6FsB2H4la~6Bi&?dYX@;eK z1p_kt9&N5SKCrIxUJXCRh$o-0OS6~(7SRwiahHZxg=ApEwLj2K%`i~qX}_t5ok+n( z#9w9rdfWSpAHG0wnK7O7-@WsH9jvD?{_#U%H*)L)%UC!|wc@GbM^nWJw9J8ZIL40~ z7lXn|+bJial!)UsfLbXle&IIM_8p#Js7gpC?$U-%H9LL~p$D84t^>H?-O=e>pF~|G z^Yg>4h3=-LP7^+NTli1mM;OkQT++2hHTf|x%%q++XuRXD^!HTM%U_TJW6 zLPV}sbwYGu5C4}hQeWG*h?ZqLem*zCDl2_xDtFcjj=J!e>&F zF$k;C(LArfOo=L)nzDpSFu!EQaU@klk?}a2q$U31-=!<;S0Kv3Ek?B}&_ktE*KIvu3Onm<)0H zM{M~MRP4pA=pxbY%$^x|$-8%1vRIp#cXufZY1w}LRE)hqtQU&R7+LygW6kmf?dhwZ zB-6alBDzBOpG9y64wH2kUy`jyfOjBj*xadp`J}kgbY=FJ3`Lb@6?nppn&%dxm?F+o zyh+44(5??waTCni^b|j}(7;K#u9v&BH!?6i5WYBRX&C6}rl_e> zB>6kRr`M4ft6#y|)j=Y20m2!W5$4o+-a@iW{UA?9c!&(fg|cGcJvdBEP1izZYr!(j z3AfJf02{<1InRd6yud=4_~_Z%n{mc{j8;7DTVBq4y zA^;Cd5FQzU0d;BVpbNLt9e&p%@#xrIP#=S#>eN)VSp1SNt2fu$y6*cM7A4*wl^vd+ zFDc&B(J}V`SUqKS_Tu8=#zA*k1-l}@%)IQ#*jWDaHQRxhV*3SRb{lt}?|v#1nYFLX z+u32V3mV^-C(rrv1q%z?KZAjZ2}}#DF0Z1ny=hu^sCmnn3hMQv(9p?A4afL>9ni57 zoUiECWBC>66RoCv1+WzWux^+$FK3Tcy=Bz0x{PgOgJ{_`?978}^N`oF(_YUq1*u`o z<@WM#6_+^BQ~`2{7Q zL_MD3NYVj2E)LGlneGQ8d1=4&l2$=l*rCm*@Z&jhL{Hhl0l?p<0y6F&E`W42V7385 z8mQiKs+)LhWoqeuT7Nn>Qwpc6Ad2Scp3|RF55^C|Z5m&Evy6<4Fe~Ut4r0aBOm-M?U@_{y zF?b!<^P@QsMrsnjGx|J}V-q7NYVM#6muS+LAMTlKuCIHGdRDtR8yGxq=m*F#>CFmP zEZhUV@Q%{O_H-}P(77}hgDDLs-cmBpr#l3nQuG5BB8`vEN5^$D=}+Mix0JUY(b6#Z zDQ2+pQLlm~?*uMg=?O?8Cs_&Bd4=ZDN5)1ArmE0|R%>RV9BH_%l%`@VckU1V7wGqL zUy_oLSaZY!g_29ATzDgR7TlJBCD?U{%k+wQmJt)} z=BWQhdXd!g0NY`0?p{-lolW`ekNa0ggGDSVhVS3MN9h&akRA4TpyVb7Cc9Kr96@Vl zy^BUeBRC`kCH7&=#zw42)$pqK-HJevwdunkauq)HJCDYRVk=u_4DnOwspThM1=|)c zN=p|AfPR2{)1Ut*Jm?&no13c^LlG|mBYqvR(r~LQ5wEm%cJ?}si?~0&ytvq_$ggqL zfcX6~J8G=IV$WGW`0ht4f|K01sS0Qe2R`jKkFdRaQkFkhKocP9(hY0J2cp-Hr z?lC+mAt}l0AFo)5P$ju~wnMq4E68JDX`CT8W)7vrSO;(mBBCN@gg>#^%FBQT$}=(2 zm#Y`;JlbAqMP4}jdplN=psHg;{JSsT39pBuyIygM^7X=+jVOkO2iwoDqa;%>( znL#IBxPPyRz9jc!%I_!FF1QuNZ^&bHMuJl>cf79Ewoqc$&Ou50v_3ub22@?fCMKW~ zJ8?h8L3IM7JEY`5K_>PW4OFYsVTjOu{~|Yqf|GE=kaw|sWc$ZxXclJ(buqrb_2lsg z;ByICVOoMXsRcAX>7tqF`OXXyDypAnR(4LaN=yEYw>PkDJ=S>8aKpyJk`D_DE6y!M zMMV6ey3o)C@Z2_PinRMa4=zC44n7t1a7Cy=Q)F^-at(iJWqH45EJn=bcYCbvMv93q z!(~u%jOo&l*w&Bh2PL{*#}(tCC@al9zPe%d92}YoCLki|q@@MZN;sAaTU&43xMw$Q z>byC@$duMa5b@R8tyMpX`4ZjNPT4D^(&_Duplc>TLXiFjJeXPsRB&QG=7^l6@)i}Q z9ep(a>DI!~NF|2q`i1}%qj>}^2_`H*OVCO;rc4*L7D>>QF%X{I_0>1{TJswl_E|)) z4=iS0X_14(_T{-)NbkJo<+hrR%kr?CAdd5Q5+NH>(qT1G$>7D5fJbMjhoY2<=^pO zH}7nA*VFlIPrnfD@#EX3$DV1E#)^uHZ{HFmjE;_aoc#_g)=X|c-JU)Lt;&M~JNDP_ z9Ckj%8hpho+ev)&hweupb8X)@fv{J83#KM^i3IQ*Sf5Sdwl#2dB?xH`C%v8Q_dH3Q zzgh_tywVpH4KO9os0%e3XCnJ-Tz>x3A4OQG`RC8HG|*xO!#N^oM|Qh&^``fT>mAl3 z4`hcj#enS$UN zjS=Yb^D@xU38zk+Oq9NR{ra^j3@v^O4-X&QH~tj0vU8&FlIre`2pMmf+`*WHJlXt! zIB-oK9`(EfqX;^&iHVmR1tkp!UG$(!j3bc8Z?FpCniH3jdQCWpXFD!#n!Yn9t~}QW zx)-PO?P}3Bb9G4lEi2-ZlEK!@7AWu`WSb30FaskqRJzMUy~f1z4t2m3gFJWRJg*dC*{X4el-V13| zRW5g!{$iAAfUyn1uv7~QQ!5K*CMGb%sUWuH+%&-Q3RQ{g{h#lAy8F(p1;s~$<<-^N z#-wH&AFzn!a98d|6v5wR<5|#*F>2GQDLT3s2PY?4S=nH*tP5)v*mhM@8VmcZUKQaK zv&Eg!6!~&1z;faE?F{GxB~39aZEYcaeFX&t7Z(?QHQ$@A&n?q@O*&ose=ldfpU${$ z083QB>pTxCe*$zjc3+%4Irl(jD{|Pt-eF=(r^VE=v$ykZ8{u(Ndt2Z*T3{XCX>;ry zBi~_|fFbHO=EZnXCr50w@@jr&YB2;l$KH+rGC^-iSk@W=5leCebT)>X5KOv+n|_O* zIw&i@+j9C4cExHMd3U=*3oQbmwi~n$lKYr42FJ|%x_j={g%)`Fa5F3xtz&jr^Y*rO zUGF&eClgNT73DR|(C4gN%Fg+-&OzjYB-?q8YM1j9yFfW+$Rp$6lZ1I72TZ8{Rtf)S ztBFs2n>UFw@akcXHdZB4_LhT^2p7uGR zM9jW-LM)UGL8Ea!e?vP;EBS)wyoI8|jmqqfpnYDLt(3z3gpVgEf&VR>zLIleZ!Khk#QgRd<7gtWP@fcYd!|jIeV;!$W$f?(U$mcOt1s*{` zFEGJHUD9x|5=I=$q??kEfOY&fWn6D^Zl*k777Ps<8<{kMu93PM=yLu3t*;=+&3)Fo zGrP6{Kt9j{AKZEbsgDE$D#Iafv&)b(^t<{P>l~$Ex)Fp6?WU*1wF4_q3d^~LpY!vV z6W#(u2HF!qMU!o5sY*rHyWJ)7RhVi!vR0yIo;vS(?oU>X@t8x=(8-CDpZuMk-Yae6 zF-8#KbUm&e-Q4)P!1{Qq`-Pd8mtdFC@-i6T1MrH5y86doA|hg$SW}fC_nBOG*YRCF z{tSg;5)dG(X^rlDb5LiPFbCsl!RqqrA2yE69Q;AzSp2OJH6~n4^jDPWNnKk8Y5yWr zl-KScD1eqWn}$XHjtH*KUbRm8hy#>tpXYhG>U2y{$*w2Oh04*2`<@=)M@EyjymsVTr7YUcf= zChIDI$^mTd-RSk@skR48cTQ2!_S*j98G2@@4Y5`+0M6$efh57W^j z+`?i7!?I2qt}4kdoO##&ROefy_wM{qMd^Kl__%0xF#L&>m!DtbvN^W4Mzb-^$1B<0 zCI6Af(8MJ3eixV+06B&fbBEzK(ECs3cb3(D--#Codi^T{WNS&eM1M{B;)HY@5-?0B z*8J+4atf6BnoeT@!F=+SW}_k{_U`3k1ZF6Wui2%AnkdD>|ClH;z$jw)n9?=}UjWF} z%`%BxK*2}fQc$yhoQ6uk@P7e{7y?3Y}~=oum=MK;gtH zBK_Y3Qmu50SXp2>&h<-lRF2lxTUD~r5jwer7vP5hSXc12VmoV5t=|+9Z&wMz6sjX( z@*c#GCfF6QqRW)Qn4D4q>ya^~#$^%;TV|tDhBxTWn_>=by1c~@^pR6V(Aq1J@ARB zL|;CRoXRe$dwqwO>KF}kV69-_;83RY1Kbpu$2q2eYcCTqQktb^|;t2YauaMAHKavQGn!MJEf5gZY~GcGU&qY&RmN0OoI zL7!Ae+M<#dY3Ni_e!ZQiVX}(hD=gEFjFlA^xHS2A7v?HHh=5fr3-Hr6&b-ouC~Q3yd>J1WD!?W~rHFB001Vt;!*jFC&yp1%lYr0MTqae`(cW+{ zqevZ>ge4ZRWtuB)7#jV?g`;B|QA{`^I%b=O?sI{K;kaXwU7(1|--|^+N$MWKa)>(s zc(b*;av%|O4!{mYb((l_q3Rsj&`Qag=+bS)+1uv$h99^zy_%R%5DEQp|KOPDU~|)UtXG014uBLKISt$a|Ao5 z)QZz;RL)iqk_6cP>c64pQq5eI(m3N1i@ zz-9m;0fAyH7}Ew#rRn(cEutf%kVjE?=+qy501+)bZHn*s>Up)iqGiE?odK zQbc^7GsfkgL}-XkLil$+Y!(4btaJ)J4=O;g*>Jr>K#TiC;?MI731I>OK~6YupcPDY zg3$wj2T;0dsiYZV&^hW?qoSjOO@!DcJ#{Uu7K6angUQuYfH8>|YP%G2POq1nm>3(& zw~>_UD%kwL(%w3*s&;$#wv$jK7bVglUD8sEl9cWS0Z~#)co3u)jg(4v2}lbH($d`} zp`;)vg2)+bq5Jndd+&4J_k4~Y{{!ZlYtB2yJ;wLC1~&qilK;kvCJ@!(E&ID76Q8*% zRvUtmSs9E7Z51ith+*jx_>*BBZ{743<>RC0#`Pi~A=sUmIoyEn{?}$ukVwG$t*%sw zMt&&j4KgGN=SRX`&tAv(Xbr02S7Z6BtBorkgmhoUhx(|LoBF{M1`1Jo@t7$dJl5|J zhwKHv{J_lg3#yGSZ+3@4ThV658*&aCg#u2T!euKTS0uumglF`dj?wJPIuGytr6irq z;c%Pu?AmuDj>|pX+n=*HP*Xgmc{Tg+Y(Z)j+ZDeX+AAZ-&B+;zsZ~VmqSpiaH|dc& zDK543d*Z}K5)$u!oj#v(hq+HiOApFDkYc)Y`SRu8ILISS5q*u?Vo1h4dk)rMV3N_2opJx%( zuQ^2Gdu0R`kp9Q_g2JSj-xNnefj$jOTflQc=Fy|?faC9?X|UDRYrCZb7eC_F(0XDe z{XG0$|2^CLo8=x8ui<)qFGb2=^1RGt-W?Sm|0j@OjydM(ZmNFsHiamchhPCf{MLLwD3gG%QF|bw6IhY zG6{O)@^`mOepr8Z=3~XFOHJW7a8c}TmXBLnUREi}D;oAxx{MYIq^1W})Dl5fqNNRF zCYwK2m_1(t8xqKUM+g`5fB^ z54>%b6&2RGQJ&LMg^9wVc>WByV2zWN8N{q#9->pS0%#Uwi+i{vJWrIZhRLmwQ*JjSf)3M2MBc^bYc}Ud zky;$0(fGgJT867-OYLTzrhy8Th zQG6q?Uk=NPWS-IV_CC@y^k(^W(gwk}Qc}3)ly>uFmT%pgqY%T_uPcJj=`6x9mVpAF zDwiY)OEaGtq+%g)X;2Wkhh?&Y7q$;VGOgq{p?=zLkGG-HNX+?C8j<^Lj*ubR!fN$J z?B->=i*udb?J98z_eqXdLtY^KF^gA1T-+mJ2ARpz?Y0yDxI!F{gN=o;u@4_5=kbDJ zOY_pk%)ra*_U+qHZWe23fTFIa{G>)VEFPe0f~BZ@WXAQhduCF@lhCTS=?0U`%MWk$ zq5*)j^Bk-oCD{u)0x)d`GS6qX*bywBvg_+9P*a=L5_c@V7K`kisH=W^f>MlxCud~Z zXtU7vGUzSPm>&8(*~EmK{glET)PI67akH+SkGf(C*m&4=)3OpjsJiOW)&z-xebB_*ZEQJ7H8+||3KbG4}egSYcZS|Nlq>$Tth%qYjQRA z%X`QQuC3Wt-B>e$G^H@0qrzllcNFB4UcN+%(nZV0)0ZhW^n4opJWw+xb9HYTjq3u2 z@$uI$ubWvJS&euzk2mWm>$Wd7sp`E=d=c&VtMMrSK0o)aClvqOYn{);lOHfHu_}uM zIC5xuI;`V7E(LlR>(zLYm=iO4ZCLp#)&u7DX0%Zkvt9ogRR(=+r_bYFii(bIzImgm zw5CRf`!=kgD%7DRwY45bMkxga1)1eTw!G<&t*uuU7HBSk8xZ)SMbWrzl_D+1)YLUM zMIYYoBxNH_@4L|B_XUWtG!8G9w)HO$IUFxsMui1keI%b|0hH_qYnuI5gICpB=od%x zl$DN#&Khws6Q8JDoD){x%)OcO#s5;&Kt3lDV!&qGjCNaA$o<=#-=i=V&ro;caw+)ZfoPabjGO_Tv{vQ9^ZgS z0?r;zLT(;!m;d?L24!-jTwE%et)<*RlBGgHNvQ;hA_aMglj|YDA$@mpe~9D(SOj2P$3h2h&2{b59ODA0Uw}u$+}#dX}T00*L|$96SMNLdwW^ia&{HA05@= zAWZ-X0sv2RLGCh)uPM*Eex5FVOBh!;Zd(DkT$2^I^)whqNDQV>ECS@%+gwz{8nd-q z)+0(p)T^Uksa>>wOOF>FwEk-nhaiI9k#4p$3p*(|vcPJ1DwlzUrOSIeh5VMKlM}bz z*+m$n+uPfKTc*s;o)Iyze0)m(=QqQnT~K-9jiieoDWheeP^w~~qX5Z(p~vAa1P6PS z!XAF(_ckwxEkaoG)GV0DE9KlSm{VPih2?#e(4SH81$vC$URwm+=5?GCTPC=+Pdk7o z8Vsy@`{n(i)b*F>z#Su`!o2pP$k5{Dtu`5_J6PNX`UW;JN7M|=UyIJWgN@a(FzR^q zpIq`e;Nj&7k`EK^oSjWMP%qGhO6mW6W6TZ>DiOYrw?~JQ^No{@jRi`nlXh>ij)MNN zjan~Md}y4X-}(7-baJh?a|g6UY@9+|sGe|@f(|;gKpfI_GRL85bscBzD|P|F{4&lN zb0?Q`)T*uDO8>rgIu>bqVHT2;cv)(w2#EA(nwHuzJ z%_q>S2+!@9?H_zMT30Z@!z)Fh313U^R<^m;<&cT-CxVce0N&n4%-WSZ45ept zUr5!^M{4zBDqrb*S2#sl{u=9fM4V_<+zs9G`@&-6U;g9eES^_Si`y^RaQyzkk}x)D z;Q4?=wnxWo#EEmG+%AT%bIEHTive|>S*LQndWR~PD&@Kr>=oOpT9eW&;FHC#9Dt})Ds(UuB5jerGmiW62~ z+=QVqaJL>0MV6Q(={p=`0ENim6MYqUAvbE|tQX|Jj{3H~Zp6DrMt&6k!pieo|3Fbm zpDA{1MXLmZA^R|S4$F{618FoZbG^w#xLoPijrMU{8YY{A&F^s|~gBC}%7Mi15}=TCJ6`O?{I+pfKTwpv%t z(0Q}_duQm{Y6qL!O=J6qcJnUYcW2g!*{t>N(=9DI^_M$zliD1$zPo!gQ24={nDEQY zyd4kjw<}PA~&R+CX$~?6;(S|mON4LPQnS)TlG$FS$^8rI-%(CAEgE%o zd9-!LO*9z_>73t5gX(ooVNucf24CGu9OCAkC);5O1TFhrR1-fge~VCNTq=rr$w)x( zVTi{e`YPh{+AD!|Jnqup6x=a@G}yKt-#l~V1*K#MFFRX1Le3@KS+0-KAHNn`UFv74 zkO;U>#5N}JVBGX$M(EAlDoKZX8MfBx$7z$_-x$(3CFH^uwfIJF36=uoBg#r4$5Nf8 z!AtyN$wh(MP34&T`kyS(L{M}EvnF{ZHQB|Wur;#Wj5~l{p}I<|>!2PaVD>wI(zbuk z?C#y@fzN70!}zvgii2nUwI8D+(4h4ll7rpr2QOq8`I{r7>EqO8Ab(dPWw-iJBtMe# zc*szEtVXilyh)5|fz2I`!wr0P@e|{O`bvc0N}Au%*?C9C>eG+QM1$rJFcH`&tKRFG z3nd|yj~9sK7Gu%gY?GHzF;9^q_Gtec*vo`k9Z`M~;N{tHQW>-yig)B3ZjmwE1!I}) z%<^4uDLCAVR_cB!n62UV8{}NfJJg6jw0lEME&q5zS|U0va-DF@I&O+v^FDHAvE`tBH>{GGk}<9v1ezh>=##t zKtAyF=~?bxZoIJIXY1tTpMLy0Jb+-;WC@U!Yc?dJknwN(^vOzJpB$`ehVc$|jo_h4 ztCk82w$8cNhb_2I1nl?ATzso|yy0&lD6BJT30F>?_A_ogG3SL+PsB_}fQ{)bIcC6G~WtGLaHeeMDGH9bh1}?N=!utZ+bi(}K0OrF5f;M=V z`o6C9VUxzOQxpSonE4f`sileHPU=d-qU!w6BR%JaNQjN);pSejKJb8#!AFxD0>Bcp z2rb_o=4MdcfE8GfdkZf5^M=grY}bs{%N_V_Jky{~L4ePQJCa-Y2$5udH|c<& zP;p(I@;Cr-4Glm95u=cS$?Otaf#e}W!P}(>ei0E0B1$%wos>$xy%rRajhVVS!J85| z{DFnR+SRaNyAq-Ta#GR|C7CN79edIh&yb28oZ508kA-{Hqjrr>8NN`A?N)qRRMcMN z5&gY}zSbj)Vh4wZXG&g{04Gn#Fs8zUS3}A6aDt& z@l!wl?W=-b&k8dmhka+Rke8?OIqHjvRR+6;EnXacfO9gW(RgBxdicFGq*-;9p1*z} zU@G`%8myt#S9pNoWdT1UaEVE|m637FEEgW$!dZPYtE^U3D)-@eS*7Xi`k6CArUTlv~3LaWj!klt$ zbIzK7?HGpceuPG-w;XQjfTIL#?kZ)F@T7W{YE6pwyY zQaL#)FZg4WQEU;%7U8$iTRzmR4Of$`lw{NlE+;(Cn>?40K)blmepX6VHW!Uu4|eRL zqLw1aHFnztl%~HnOf@QC?nXv0 zw=pYIwCd>Hh1%5nsnhjPW>G4#NcTqbVnNTX-(j`^26PeXm&whE zA6)()*z{r;{cR!wIk{NrSI?fwn-i$IWvXdod&F3;#E{5HT~Ashj5f25o?z)HFHl;d z8pb1{fLK-eqLEiMzAW>XSV%3wB5T(GTqjQ|!Z{>pIxvk~O2j)M-Y3aEIy7b%b zPfS9Cxp|o%Y_nG|Z2H;qe8}RZUn`kPo4m+KM@3%hBD$a&Foe9^=vGQ8YSPNyRavfz9r7$%B%w`70 z9b;q0Q!lxP2lG^`vWy({1I(})o_+EUEhbEwN3lAqQKX%INg$&QXmEnS^8id%uI5HJ z2RskM7HX6lom&MZw)1Wtj{6m-wAE(?*nw$+5y-`>1z(WujF&wIyKajd=xKbXPC}o4 znnD5xu;6va!RywiU!4f{-#@2*Mi{52-&s-PvgB4Sb4`SPPXAsLMe|230uN8l)3V2( z=uX|ujrl|_)S%)(<#}vuRNg6f#!t$Xm*>f^qgY=miv9*-O9G>@F`pnq-ORtwo0?i8 z8!K9TZfeCvQb;noC37X`V#c?F7wEe&dx0TVdMv1?6uSS&y zKVMsR%*kpUEZQB36LnWsNb~Y+^78UE#kIA6$idN?MGp_Al`!sDn*DviH|y&~oF~1m zVx9MG?0ub#jlK#RJ-KFu%Troe%*MgUNX4-Qw#e2)0%qW0P*h}Brx3f9z4sP5KcK0B zwmx%i@*)CLdrn0mWK=cObV0R?ew!s;abfG%QMVR9;Q2 zQ>CUtmJ;^g@0&BN<3T||larHA8XG|;^g@wdl0$@wikKYP{c=}U zhV*7Y^NoGI@mLQ)`#@s?4kLZM1jl)uE*v zP61}*eZQcxzvl;xl}RDt>s%=IhlL?40n>y^f=YE1M@@wVFT=0mNS<-d343XQaZ+Z!NNaK}IxFT~&z6TN0(6MYNz(gj_e9gUh*=8*6C!XZPX)5w*o z1>&hFn)acAO;Aq)d#U`6-bcwKA54jMLa~eub3#KxJPb5DzA2r$ct=LYij&wcFtKxK ze%{2B>88&8ih?y;r-_M?xWvTZXRqXTBA!1FRqVC2)dqI2bPqOMLrsukT!)*ex(jX?B#I^&!6S zhJ%Ltb!jQuL`?j$vkwxHlq5w0H482&O?lDLehyAjLeY^n_yw@caW2SL0$05WfSo&- zi#_*0XQw5bwuU|aUOOX&jYmcn>U}Y7G3z`fuI~_bGI|#J*%AVly~aUL-#Ya|PF_CM zlbxB$0Y-ng9^W0gs0{sEd1r%TE<~=NdHN}7t)(_f zubnsn6)I|D7SQD*p+Wv>#n+n{{K&6J;e#P0sJm3$w&tZmRvWkApF{x8T)a!U`l(34 zhqLcCy}sANa5lZ~>bi&P_2qOIZ*){te}8{(K~d4hdl258Hk+w`ycZCF8)RV>+AX}L zy5svdQ0|K|b!s3a_aAbVfZ-}Q!QmLH*xkS11!g#!(I!_}QUm8H#JRyJ%RjrCnXo=9 zD|5Gof;Y(G(dKk>5QCy%pAp*nN$1%*cr^f{XNJyB;(FYXx#RaK?Qmy@TkVQJWB2p9 zBE{@$>yd!nb`h5gZKe$qg-4Ff?v)`Cx(f3KW=j1-Ltro04OStulqU$m0Q6T`^5Gia z+aF!H-h1yuL$UghXAspkBdl9J?`?TO0Vc*^rKLrTkAHNo`=xLQ;?p9GhrSa6?w|W< ze_G#i-?1_@q||9-FQ37;x$qA#5WcVR-T6fItIwIiJ0&<;*Hul%DyK?9^-OkRD&GSG z+)I~gAL~w@&b@n+`yCw|Tp;KNKDV`{MNvV)m}sO(UxGF;B;*>=49j|lumH;MHm1@O zJq=TMhmEk0j*D4dhOMHjyBp~dkrY?CQ=?&9zH?QuO}@3w*6gP?H7PbSsVfU-(07*d zK3L)#8&h?R+h+8Ne)q213n0S7yU_uLE-)=N%zs|ycU;0+;~3pl%ZIZB(3=I~r+*6U z0VJ7{1%i5fdJ^M%CeY54X{omMPbln;RL;HU(XqKT-o9V&JY-;FMJVXk{?B zyIV0cmw5wG?Zk^03l)@4uX1uOJT{qtS&5B}or)bs+{ekz-W!b@djIcOs;(Y&v!u!G z+b8sBX}G!R`81PECnxvPkn?vaX5Ke7N#aAYJB(b^;M-cAGw3z_r{6HvzgIZ-9`Gn& zN5C(tNUx3wVb$K&3Hk6-H}Um>!;+k=_I*;*?VPz##P-%NJ7uzeyvB0VU?(VjHCjou zyk@Bf%%|Rt*6B{Z3NF?mu?eRTTxyREuYo~ZQBi)`TUYnX=?`69k9Ps4bz6)Dwc@4Z zK|oSkNFQWmW>z05L!nwHr*MGvYc0IQlm0pMxCZX_sHV@I|W3T`L9IDks&YJ1w*3|dugFfcs+c%qc^Wm(5 zM(^zFsPUtIbcB1~6t%RgcyH2YK@G|n`8P~QP@~;EnkNFL5J`eeOnm0g`)T3BRIP_z znf7!r+(%AfKG6H`bb0@cww>To9~wHqC39^cXhf!8eaSB~&#H8@0vDgneGszRSfn715JuSYX~ z(&BP{du#O9zkeD_$D+^Er@j1Jox0y=o%B5_07U*);mcql#qav5 zx8K*&)z!5})6m?^!g@qMn7%O3LD9}m&N`1FP$UxeaVTjCkl_Fj1~|KzV}5R0n)vrn zYVS+_{wGc1YkZD@cLhI0bs_k)fdqaDavzhFrXbsfOoDpB6I$!LG2jH&8b+D?@@4&1 zJiO$H>t>+N)#yY*)ye?p0#w3%VxZ!bc7ko{V0UD`R6VKd8®pxZ@CDdHK3*a{9t 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 Aj{pDw literal 0 HcmV?d00001 diff --git a/_static/images/studio_icon_close.png b/_static/images/studio_icon_close.png index 72759ca703aacc58fba1e04c045f70e70e3365d2..c8bc59ba2fd545264a0139510d4910f68bced16a 100644 GIT binary patch delta 141 zcmV;80CNA=0nh=E83+OZ006WP(5;anHF{-9L_t(IPh>; vU@F3*4Mh(qtg$!-sEt5a69$7<&;S1bA&E7lPY-ed00000NkvXXu0mjfdqp;; delta 149 zcmV;G0BZlx0oMVL83+ad0028}NBWT=HGgbLL_t(IPhJ2BGs&0iG~{Y21w001zM$u=rg7 z1GIDr#bJU=18##b3;{Z5MvY9~M}y1H-oAvf8jMO4G4nyDr|?eTQ8=A_a5j0tOSSPz)XYv1Q8m!GA6i zl@f-M95QzmdhScX+h!_%h*5r<20Vl( zB{&}vsAiK+HVW?x2iPC^;L{d55mEGVi&!WYaLV33wx7aQwM1(j3;H&ez}F;*nu?@U zMy*k&wI6MvmH#5pEej**IJ(#7+op$Q@|dTAFu*&`_cTkNwihM<00007~a diff --git a/_static/images/studio_icon_ddl_edit.png b/_static/images/studio_icon_ddl_edit.png index a16dcb782cdd3f07d2224265a4df781b43e3ac0a..f6fdedd56f4afde480dce5f3f25dda7fbf7ac5d3 100644 GIT binary patch delta 454 zcmV;%0XhDs1cn5V83+OZ008YN;bf5^HGi8)L_t(IPsNf;O9D|8$NMIIguX`Yf);IR z)uL4pMDzs;+E>sb=&>;i3`-Kl#7WE-(L||}qLVg`GwS#pol)nG9hf`9;3ez<{rNN8 z!#%%y?woU{hQHHa^L>OAZ9sGnX}YfCJX01P;CY{O=IV^-IgcaNkZ`Ig3lBvg4}S+^ zTBh95atQ~f2t3@PAh*g&x73v-Rl$3c^Yxy3!KNvJyXDw;MZkNL^YDGFiVq?W4wv~4 zxotFUQohyiIrG``90RuJ-d<|e@9{l^vaJTwsEu4vyGYkB*)-e*rV?KJj|bMH#5yT7#_kQ^Sl&r`}q7; zJh&S2CF|0n-?bhI7zlyKfhoAod%Fou5tR-s;B@#YSQxt&Ue&a5ex!{UMKeof9GJ53 wFz3w}HElm4de-BBS>jYv7XAnNUw%0J1V)sFdx{1XkN^Mx07*qoM6N<$f;Cat5C8xG delta 487 zcmVqDh;ih(m=&}T^IUMV=g;5KBMf^(m-hr$5}w<`huam*$;(Atd%s- dpU{7S0=W783+OZ005(mkVKIoHGkYmL_t(IPtA`z3c^4XMO}=wOVBOYxgIxR zDcC83plFve5D*cx(?$?YBq)9o!5L=~4^jNU6I(C0IP-GfC%N>O{xV^#jkUtSqx7Cg zl4QQ$m7OjIc;4%;gtd0KSrGIpGDXe7lYTA;IL?Hmo>349J%%rB0auc?*5~1^Rkvq?8-1Fd!$U+psujVL(VQ zc@hSteiH-2rIhyP*j+9#AS4)TjJae2ge{0Ft?2m~eI!KvN~Gxx1|j#kZSj3t00000 LNkvXXu0mjf@l9|p delta 288 zcmV+*0pI?|0^tIX83+ad001oR2NRJYHGlR=L_t(IPu-BsO2a@DMtzvBeT4QE-1$7d zgv&yAiXbR;*JU73L@+zu2vVC8l(zYS{7iDqxe!PwGm@*^%DJs#vbcvf(0n2}{!N`IDR z3T|D43p!O*rQpu+HcjN}#aD1=*bg@{xtlAvHO$zz??^6Jj|%R5U{Mqj$FYJt*Ps)> z0DnF(X}fvtu7EqkLA&Sl=~lt5VaC2jq0E*y3T}NM7yB#~@AE^!tzkwQV0Ea(`(2PST5D?OgTPF~}HDCS&6+r@cbppZT!-X3q o4?p|~^I{ ziCtA$f+R@fCJjjiqN2K?0);?9Lh`kfj@Z!so1}7IH=lU2*$q}KWAZZg*I=M7HToal zj?%E9hB|5#m4<3wJT8l4HgtRP=q`*2Aj*#kANn{1`ISV`@iy0XB4ude`@%$AjK*3F(E{-7<{%f6d%yJCDvOc5=O;dwS>Vko)(S zugtohsBm+AcAKh5{Z+NTjn_U+OziUfs5bQvPy7_E@KsXkoAW-rZq1J>*1qN}e*5sF zj*6e3RNm`p{j9fm+5X|M#4MGgi&q)!-E%N!gRY{_E~oy-3%%PPoJw$&FpLnnoaB?Y fQt9w~jTUu=sMW_Ty3)CUu4nLc^>bP0l+XkK(U^1I literal 0 HcmV?d00001 diff --git a/_static/images/studio_icon_right.png b/_static/images/studio_icon_right.png index d4b84a24791f637b26ff8c338dd04768e62aa456..e02c65a9360bf8ce082a24ac91e83d5a8917c821 100644 GIT binary patch delta 207 zcmZo;`o*Z&8Q|y6%O%Cdz`(%k>ERLtq=iA4g9%9fHCi}(qM~Vizo(01h=qUh4}U$0 zPge5(e#Yu&`@$L-hVFBRF26rA{j5fe-Q)k0lLHiU7@+V&?-=8Fs0<*e|`punf#oJ>h_m_Ze;Lu^>bP0 Hl+XkK_t{f3 delta 219 zcmV<103`qV0fqu0iBL{Q4GJ0x0000DNk~Le0000H0000O2nGNE032c#GLa!Qf161} zK~y+TWB5-6Flq=U7%_&tzW9I3MrF#;Q6N`wI*fX6$3{{R08WfA}c0+u*1tPJ`89{_&s VGQ>p*WNrWe002ovPDHLkV1nwRPP+gA diff --git a/_static/images/studio_icon_search.png b/_static/images/studio_icon_search.png new file mode 100644 index 0000000000000000000000000000000000000000..4e687f7e2576d0eb09640e87763bbb3e539b19d6 GIT binary patch literal 415 zcmV;Q0bu@#P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0W?WOK~y+TosvyY zgFp~K{nMT_UNm~Jek9VQ2aPqtp^5x~CiK$KOAB5aJQe=|+~A0BcSeCNG1eCjJG1*{ zhk>K!U-Y!9u9k5;3*RPBkJG?kCrMEjy4R=Gwpn&|aejPya&`kSAhbFQLk%oOV*or753+y2XjJ0GBp&3}dzc1+1{R~yH{Ew<*oA?yyG|30Ek3$d@^QJA0mzyzcyku>DAIG5Rs%ZO zyr(aLkH!tlRV;1K7m;K3v|n({ziJ?+{4NJ*fJx^p4%3vT`2z0`_. +For more information, in Studio, see `Executing Statements from the Toolbar `_. @@ -186,7 +186,7 @@ When using a **JDBC client driver**, you can configure a client connection to a jdbc:Sqream://127.0.0.1:3108/raviga;user=rhendricks;password=Tr0ub4dor&3;service=etl;cluster=true;ssl=false; -For more information, see the `JDBC Client Driver `_. +For more information, see the `JDBC Client Driver `_. Using an ODBC Client Driver @@ -213,7 +213,7 @@ For example, ``Service="etl"``: On Windows, change the parameter in the :ref:`DSN editing window`. -For more information, see the `ODBC Client Driver `_. +For more information, see the `ODBC Client Driver `_. Using a Python Client Driver @@ -228,7 +228,7 @@ When using a **Python client driver**, you can configure a client connection to , username='rhendricks', password='Tr0ub4dor&3' , clustered=True, use_ssl = False, service='etl') -For more information, see the `Python (pysqream) connector `_. +For more information, see the `Python (pysqream) connector `_. Using a Node.js Client Driver @@ -250,4 +250,4 @@ When using a **Node.js client driver**, you can configure a client connection to service: 'etl' }; -For more information, see the `Node.js Client Driver `_. +For more information, see the `Node.js Client Driver `_. \ No newline at end of file diff --git a/getting_started/executing_statements_in_sqream.rst b/getting_started/executing_statements_in_sqream.rst index bab18ec76..f02260e3f 100644 --- a/getting_started/executing_statements_in_sqream.rst +++ b/getting_started/executing_statements_in_sqream.rst @@ -5,6 +5,6 @@ Executing Statements in SQream **************************** You can execute statements in SQream using one of the following tools: -* `SQream SQL CLI `_ - a command line interface -* `SQream Acceleration Studio `_ - an intuitive and easy-to-use interface. +* `SQream SQL CLI `_ - a command line interface +* `SQream Acceleration Studio `_ - an intuitive and easy-to-use interface. diff --git a/getting_started/installing_sqream.rst b/getting_started/installing_sqream.rst index cf7c9517b..3c8b202c1 100644 --- a/getting_started/installing_sqream.rst +++ b/getting_started/installing_sqream.rst @@ -6,6 +6,6 @@ Installing SQream The **Installing SQream** section includes the following SQream installation methods: -* `Installing SQream natively `_ - Describes installing SQream using binary packages provided by SQream. -* `Installing SQream with Kubernetes `_ - Describes installing SQream using the Kubernetes open source platform. -* `Installing and running SQream in a Docker container `_ - Describes how to run SQream in a Docker container. \ No newline at end of file +* `Installing SQream natively `_ - Describes installing SQream using binary packages provided by SQream. +* `Installing SQream with Kubernetes `_ - Describes installing SQream using the Kubernetes open source platform. +* `Installing and running SQream in a Docker container `_ - Describes how to run SQream in a Docker container. \ No newline at end of file diff --git a/getting_started/preparing_your_machine_to_install_sqream.rst b/getting_started/preparing_your_machine_to_install_sqream.rst index 9a5e61956..a517eb906 100644 --- a/getting_started/preparing_your_machine_to_install_sqream.rst +++ b/getting_started/preparing_your_machine_to_install_sqream.rst @@ -37,4 +37,4 @@ To prepare your machine to install SQream, do the following: For more information, see the following: * :ref:`recommended_pre-installation_configurations` -* `Hardware Guide `_ \ No newline at end of file +* `Hardware Guide `_ \ No newline at end of file diff --git a/glossary.rst b/glossary.rst index edcd36a5e..f6dfc1f76 100644 --- a/glossary.rst +++ b/glossary.rst @@ -7,26 +7,26 @@ Glossary The following table shows a glossary of commonly-used terms: -+-----------------------+----------------------------------------------------------------------------------------------------------------+ -| **Term** | **Description** | -+=======================+================================================================================================================+ -| Authentication | The process of verifying identity by validating a user or role identity using a username and password. | -+-----------------------+----------------------------------------------------------------------------------------------------------------+ -| Authorization | Defines the set of actions that an authenticaed role can perform after gaining access to the system. | -+-----------------------+----------------------------------------------------------------------------------------------------------------+ -| Catalog | A set of views containing metadata information about objects in a database. | -+-----------------------+----------------------------------------------------------------------------------------------------------------+ -| Cluster | A SQream deployment containing several workers running on one or more nodes. | -+-----------------------+----------------------------------------------------------------------------------------------------------------+ -| Metadata | SQream's internal storage containing details about database objects. | -+-----------------------+----------------------------------------------------------------------------------------------------------------+ -| Node | A machine used to run SQream workers. | -+-----------------------+----------------------------------------------------------------------------------------------------------------+ -| Role | A group or a user. For more information see SQream Studio. | -+-----------------------+----------------------------------------------------------------------------------------------------------------+ -| Storage cluster | The directory where SQream stores data. | -+-----------------------+----------------------------------------------------------------------------------------------------------------+ -| User-Defined Function | A feature that extends SQream's built-in SQL functionality with user-written Python code. | -+-----------------------+----------------------------------------------------------------------------------------------------------------+ -| Worker | A SQream application that responds to statements. Several workers running on one or more nodes form a cluster. | -+-----------------------+----------------------------------------------------------------------------------------------------------------+ ++-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| **Term** | **Description** | ++=======================+============================================================================================================================================================+ +| Authentication | The process of verifying identity by validating a user or role identity using a username and password. | ++-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Authorization | Defines the set of actions that an authenticaed role can perform after gaining access to the system. | ++-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Catalog | A set of views containing metadata information about objects in a database. | ++-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Cluster | A SQream deployment containing several workers running on one or more nodes. | ++-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Metadata | SQream's internal storage containing details about database objects. | ++-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Node | A machine used to run SQream workers. | ++-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Role | A group or a user. For more information see `SQream Acceleration Studio 5.4.3 `_. | ++-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Storage cluster | The directory where SQream stores data. | ++-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| User-Defined Function | A feature that extends SQream's built-in SQL functionality with user-written Python code. | ++-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Worker | A SQream application that responds to statements. Several workers running on one or more nodes form a cluster. | ++-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ diff --git a/index.rst b/index.rst index 3d044ee2f..66fc31a1a 100644 --- a/index.rst +++ b/index.rst @@ -4,7 +4,7 @@ SQream DB Documentation ************************* -For SQream DB Version Version 2020.3.2.1. +For SQream Version 2020.3.2.1. .. only:: html @@ -72,9 +72,9 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau`_ + `Troubleshooting Page `_ - `Gathering Information for SQream Support `_ + `Gathering Information for SQream Support `_ @@ -85,7 +85,7 @@ If you couldn't find what you're looking for, we're always happy to help. Visit .. rubric:: Looking for older versions? -This version of the documentation is for SQream DB |latest_version|. +This version of the documentation is for SQream version 2020.3.2.1. If you're looking for an older version of the documentation, versions 1.10 through 2019.2.1 are available at http://previous.sqream.com . diff --git a/installation_guides/installing_prometheus_using_binary_packages.rst b/installation_guides/installing_prometheus_using_binary_packages.rst index a6104bdd0..1512abfe7 100644 --- a/installation_guides/installing_prometheus_using_binary_packages.rst +++ b/installation_guides/installing_prometheus_using_binary_packages.rst @@ -102,7 +102,7 @@ You must install Prometheus before installing the Dashboard Data Collector. $ sudo chown -R prometheus:prometheus /etc/prometheus/consoles $ sudo chown -R prometheus:prometheus /etc/prometheus/console_libraries -For more information on installing the Dashboard Data Collector, see `Installing the Dashboard Data Collector `_. +For more information on installing the Dashboard Data Collector, see `Installing the Dashboard Data Collector `_. Back to :ref:`Installing Prometheus Using Binary Packages` @@ -230,12 +230,6 @@ You can access the Prometheus user interface by running the following command: The Prometheus user interface is displayed. -From the **Query** tab you can query metrics, as shown below: +From the **Query** tab you can query metrics. -.. list-table:: - :widths: auto - :header-rows: 0 - - * - .. image:: /_static/images/3c9c4e8b-49bd-44a8-9829-81d1772ed962.gif - -Back to :ref:`Installing Prometheus Using Binary Packages` +Back to :ref:`Installing Prometheus Using Binary Packages` \ No newline at end of file diff --git a/installation_guides/installing_sqream_with_binary.rst b/installation_guides/installing_sqream_with_binary.rst index dd1207ab7..f4079b598 100644 --- a/installation_guides/installing_sqream_with_binary.rst +++ b/installation_guides/installing_sqream_with_binary.rst @@ -274,6 +274,6 @@ For an example of stopping actively running SQream services, see :ref:`Launching 1 row time: 0.050603s -For more information, see the `upgrade_storage `_ command line program. +For more information, see the `upgrade_storage `_ command line program. -For more information about installing Studio on a stand-alone server, see `Installing Studio on a Stand-Alone Server `_. \ No newline at end of file +For more information about installing Studio on a stand-alone server, see `Installing Studio on a Stand-Alone Server `_. \ No newline at end of file diff --git a/operational_guides/exporting_data.rst b/operational_guides/exporting_data.rst index 18a90cc64..62d32f1c8 100644 --- a/operational_guides/exporting_data.rst +++ b/operational_guides/exporting_data.rst @@ -6,10 +6,10 @@ Exporting Data You can export data from SQream, which you may want to do for the following reasons: -* To use data in external tables. See `Working with External Data `_. +* To use data in external tables. See `Working with External Data `_. * To share data with other clients or consumers with different systems. * To copy data into another SQream cluster. SQream provides the following methods for exporting data: -* Copying data from a SQream database table or query to another file - See `COPY TO `_. \ No newline at end of file +* Copying data from a SQream database table or query to another file - See `COPY TO `_. \ No newline at end of file diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 783e571b1..8de3e83c9 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -14,6 +14,7 @@ This section summarizes the following operational guides: access_control + optimization_best_practices creating_or_cloning_a_storage_cluster external_data exporting_data diff --git a/operational_guides/viewing_system_objects_as_ddl.rst b/operational_guides/seeing_system_objects_as_ddl.rst similarity index 97% rename from operational_guides/viewing_system_objects_as_ddl.rst rename to operational_guides/seeing_system_objects_as_ddl.rst index fe4649c3b..fc8ff3b83 100644 --- a/operational_guides/viewing_system_objects_as_ddl.rst +++ b/operational_guides/seeing_system_objects_as_ddl.rst @@ -1,7 +1,7 @@ -.. _viewing_system_objects_as_ddl: +.. _seeing_system_objects_as_ddl: ******************************** -Seeing System Objects as DDL +Seeing system objects as DDL ******************************** Dump specific objects @@ -10,7 +10,7 @@ Dump specific objects Tables ---------- -See :ref:`get_ddl` for more information. +See :ref:`get_ddl` for more information. .. rubric:: Examples diff --git a/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst b/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst index 3fcac7861..889a4ea64 100644 --- a/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst +++ b/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst @@ -1,7 +1,7 @@ .. _configuring_your_instance_of_sqream: **************************** -Configuring Your Instance of SQreams +Configuring Your Instance of SQream **************************** The **Configuration** section lets you edit parameters from one centralized location. While you can edit these parameters from the **worker configuration file (config.json)** or from your CLI, you can also modify them in Studio in an easy-to-use format. diff --git a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst index 3be680e9b..8dc5e8072 100644 --- a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst @@ -112,23 +112,23 @@ The database object functions are used to perform the following: * - Function - Description * - Insert statement - - Generates an `INSERT `_ statement for the selected table in the editing area. + - Generates an `INSERT `_ statement for the selected table in the editing area. * - Delete statement - - Generates a `DELETE `_ statement for the selected table in the editing area. + - Generates a `DELETE `_ statement for the selected table in the editing area. * - Create Table As statement - - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. + - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. * - Rename statement - - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. + - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. * - Adding column statement - - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. + - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. * - Truncate table statement - - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. + - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. * - Drop table statement - Generates a ``DROP`` statement for the selected object in the editing area. * - Table DDL - - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL `_. + - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL `_. * - DDL Optimizer - - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. + - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. Optimizing Database Tables Using the DDL Optimizer ----------------------- @@ -153,7 +153,7 @@ The following table describes the DDL Optimizer screen: Clicking **Run Optimizer** adds a tab to the Statement panel showing the optimized results of the selected object. -For more information, see `Optimization and Best Practices `_. +For more information, see `Optimization and Best Practices `_. Executing Pre-Defined Queries from the System Queries Panel --------------- @@ -198,7 +198,7 @@ You can add and name new tabs for each statement that you need to execute, and S You can also rename the default tab name by double-clicking it and typing a new name and write multiple statements in tandem in the same tab by separating them with semicolons (``;``).If too many tabs to fit into the Statement Pane are open at the same time, the tab arrows are displayed. You can scroll through the tabs by clicking |icon-left| or |icon-right|, and close tabs by clicking |icon-close|. You can also close all tabs at once by clicking **Close all** located to the right of the tabs. -.. tip:: If this is your first time using SQream, see `Getting Started `_. +.. tip:: If this is your first time using SQream, see `Getting Started `_. .. Keyboard shortcuts @@ -336,8 +336,6 @@ The Execution Tree tracks each phase of your query in real time as a vertical tr Each node displays a number displaying its **node ID**, its **type**, **table name** (if relevant), **status**, and **runtime**. The nodes are color-coded for easy identification. Green nodes indicate **completed nodes**, yellow indicates **nodes in progress**, and red indicates **slowest nodes**, typically joins, as shown below: -.. image:: /_static/images/nodes.png - Viewing Query Statistics ^^^^^^^^^^^^ The following statistical information is displayed in the top left corner, as shown in the figure above: diff --git a/sqream_studio_5.4.3/getting_started.rst b/sqream_studio_5.4.3/getting_started.rst index 7f401f5fa..85747b30b 100644 --- a/sqream_studio_5.4.3/getting_started.rst +++ b/sqream_studio_5.4.3/getting_started.rst @@ -5,7 +5,7 @@ Getting Started with SQream Acceleration Studio 5.4.3 **************************** Setting Up and Starting Studio ---------------- -Studio is included with all `dockerized installations of SQream DB `_. When starting Studio, it listens on the local machine on port 8080. +Studio is included with all `dockerized installations of SQream DB `_. When starting Studio, it listens on the local machine on port 8080. Logging In to Studio --------------- diff --git a/sqream_studio_5.4.3/monitoring_workers_and_services_from_the_dashboard.rst b/sqream_studio_5.4.3/monitoring_workers_and_services_from_the_dashboard.rst index 993b11761..9966137fa 100644 --- a/sqream_studio_5.4.3/monitoring_workers_and_services_from_the_dashboard.rst +++ b/sqream_studio_5.4.3/monitoring_workers_and_services_from_the_dashboard.rst @@ -47,7 +47,7 @@ The following is a brief description of the Dashboard panels: Subscribing to Workers from the Services Panel -------------------------- -Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined `service queues `_. +Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined `service queues `_. @@ -79,7 +79,7 @@ You can add a service by clicking **+ Add** and defining the service name. You can manage workers from the **Workers** panel. For more information about managing workers, see the following: * :ref:`Managing Workers from the Workers Panel` -* `Workers `_ +* `Workers `_ :ref:`Back to Monitoring Workers and Services from the Dashboard` @@ -151,7 +151,7 @@ Clicking the ellipsis in a service shows the following additional options: * **Stop Query** - stops the query. * **Show Execution Plan** - shows the execution plan as a table. The columns in the **Show Execution Plan** table can be sorted. -For more information on the current query plan, see `SHOW_NODE_INFO `_. For more information on checking active sessions across the cluster, see `SHOW_SERVER_STATUS `_. +For more information on the current query plan, see `SHOW_NODE_INFO `_. For more information on checking active sessions across the cluster, see `SHOW_SERVER_STATUS `_. .. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst :start-line: 67 @@ -259,7 +259,7 @@ The license information section shows the following: * The amount of time in days remaining on the license. * The license storage capacity. -.. image:: /_static/images/license_storage_capacity.png + -:ref:`Back to Monitoring Workers and Services from the Dashboard` +:ref:`Back to Monitoring Workers and Services from the Dashboard` \ No newline at end of file diff --git a/third_party_tools/client_drivers/index.rst b/third_party_tools/client_drivers/index.rst index 7ae1894f4..2df0a1811 100644 --- a/third_party_tools/client_drivers/index.rst +++ b/third_party_tools/client_drivers/index.rst @@ -19,8 +19,8 @@ The following are applicable to all operating systems: * **JDBC** - recommended installation via ``mvn``: - * `JDBC .jar file `_ - sqream-jdbc-4.4.0 (.jar) - * `JDBC driver `_ + * `JDBC .jar file `_ - sqream-jdbc-4.5.3 (.jar) + * `JDBC driver `_ .. _python: @@ -28,7 +28,7 @@ The following are applicable to all operating systems: * **Python** - Recommended installation via ``pip``: * `Python .tar file `_ - pysqream v3.1.3 (.tar.gz) - * `Python driver `_ + * `Python driver `_ .. _nodejs: @@ -36,7 +36,7 @@ The following are applicable to all operating systems: * **Node.JS** - Recommended installation via ``npm``: * `Node.JS `_ - sqream-v4.2.4 (.tar.gz) - * `Node.JS driver `_ + * `Node.JS driver `_ .. _tableau_connector: @@ -44,7 +44,7 @@ The following are applicable to all operating systems: * **Tableau**: * `Tableau connector `_ - SQreamDB (.taco) - * `Tableau manual installation `_ + * `Tableau manual installation `_ @@ -72,12 +72,12 @@ Linux The following are applicable to Linux: * `SQream SQL (x86_64) `_ - sqream-sql-v2020.1.1_stable.x86_64.tar.gz -* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for Intel-based machines +* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for Intel-based machines :: * `SQream SQL*(IBM POWER9) `_ - sqream-sql-v2020.1.1_stable.ppc64le.tar.gz -* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for IBM POWER9-based machines +* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for IBM POWER9-based machines :: @@ -88,7 +88,7 @@ The following are applicable to Linux: * C++ connector - `libsqream-4.0 `_ -* `C++ shared object library `_ +* `C++ shared object library `_ .. toctree:: diff --git a/third_party_tools/client_drivers/nodejs/index.rst b/third_party_tools/client_drivers/nodejs/index.rst index 8ddd0d0bc..b634179ed 100644 --- a/third_party_tools/client_drivers/nodejs/index.rst +++ b/third_party_tools/client_drivers/nodejs/index.rst @@ -33,7 +33,7 @@ If you need to install the driver in an offline system, see the offline method b Install from an offline package ------------------------------------- -The Node driver is provided as a tarball for download from the `SQream Drivers page `_ . +The Node driver is provided as a tarball for download from the `SQream Drivers page `_ . After downloading the tarball, use ``npm`` to install the offline package. @@ -360,6 +360,7 @@ BIGINT support The Node.JS connector supports fetching ``BIGINT`` values from SQream DB. However, some applications may encounter an error when trying to serialize those values. The error that appears is: + .. code-block:: none TypeError: Do not know how to serialize a BigInt @@ -378,5 +379,4 @@ For example: ? value.toString() : value // return everything else unchanged )); - console.log(json); // [{"test": "1"}] - + console.log(json); // [{"test": "1"}] \ No newline at end of file diff --git a/third_party_tools/client_platforms/sql_workbench.rst b/third_party_tools/client_platforms/sql_workbench.rst index 16265ebd4..6fe9713af 100644 --- a/third_party_tools/client_platforms/sql_workbench.rst +++ b/third_party_tools/client_platforms/sql_workbench.rst @@ -16,7 +16,7 @@ Installing SQL Workbench with the SQream DB installer (Windows only) SQream DB's driver installer for Windows can install the Java prerequisites and SQL Workbench for you. -#. Get the JDBC driver installer available for download from the `SQream Drivers page `_. The Windows installer takes care of the Java prerequisites and subsequent configuration. +#. Get the JDBC driver installer available for download from the `SQream Drivers page `_. The Windows installer takes care of the Java prerequisites and subsequent configuration. #. Install the driver by following the on-screen instructions in the easy-to-follow installer. By default, the installer does not install SQL Workbench. Make sure to select the item! @@ -54,7 +54,7 @@ For Windows, SQream recommends Zulu 8 https://www.azul.com/downloads/zulu-commun Get the SQream DB JDBC driver ------------------------------- -SQream DB's JDBC driver is provided as a zipped JAR file, available for download from the `SQream Drivers page `_. +SQream DB's JDBC driver is provided as a zipped JAR file, available for download from the `SQream Drivers page `_. Download and extract the JAR file from the zip archive. diff --git a/third_party_tools/client_platforms/tableau.rst b/third_party_tools/client_platforms/tableau.rst index c74c2e9b1..e43c8f893 100644 --- a/third_party_tools/client_platforms/tableau.rst +++ b/third_party_tools/client_platforms/tableau.rst @@ -48,7 +48,7 @@ If you are using Windows, after installing the Tableau Desktop application you c :: -#. Download the most current version of the `SQream JDBC driver `_. +#. Download the most current version of the `SQream JDBC driver `_. :: @@ -446,8 +446,7 @@ If Tableau cannot locate the SQream JDBC driver, do the following: :: - * **For Windows** - add an environment variable for the classpath: + * **For Windows** - add an environment variable for the classpath. - .. image:: /_static/images/third_party_connectors/tableau/envrionment_variable_for_classpath.png -If you experience issues after restarting Tableau, see the `SQream support portal `_. +If you experience issues after restarting Tableau, see the `SQream support portal `_. \ No newline at end of file From 70a18609909e5d1ef4a4dd8af55d9db48b668311 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 20 Feb 2022 18:51:01 +0200 Subject: [PATCH 188/300] Updated Menu Updated: Configuration menu Release Notes menu --- configuration_guides/admin/admin_flags.rst | 4 +- configuration_guides/admin/bin_sizes.rst | 12 - .../admin/check_cuda_memory.rst | 12 - .../admin/compiler_gets_only_ufs.rst | 12 - configuration_guides/configuration_flags.rst | 20 + .../configuration_methods.rst | 19 + .../current_configuration_method.rst | 377 ++++++++++++++++++ configuration_guides/generic/spooling.rst | 4 +- .../generic_regular_flags.rst | 4 +- configuration_guides/index.rst | 15 +- .../previous_configuration_method.rst | 268 +++++++++++++ configuration_guides/spool_memory_gb.rst | 11 + configuration_guides/spooling.rst | 69 ++++ releases/2019.2.1.rst | 2 +- releases/2020.1.rst | 14 +- releases/2020.2.rst | 2 +- releases/2020.3.1.rst | 73 ++-- releases/2020.3.2.1.rst | 24 +- releases/2020.3.rst | 104 +---- releases/2020.3_index.rst | 18 + releases/index.rst | 9 +- 21 files changed, 872 insertions(+), 201 deletions(-) delete mode 100644 configuration_guides/admin/bin_sizes.rst delete mode 100644 configuration_guides/admin/check_cuda_memory.rst delete mode 100644 configuration_guides/admin/compiler_gets_only_ufs.rst create mode 100644 configuration_guides/configuration_flags.rst create mode 100644 configuration_guides/configuration_methods.rst create mode 100644 configuration_guides/current_configuration_method.rst create mode 100644 configuration_guides/previous_configuration_method.rst create mode 100644 configuration_guides/spool_memory_gb.rst create mode 100644 configuration_guides/spooling.rst create mode 100644 releases/2020.3_index.rst diff --git a/configuration_guides/admin/admin_flags.rst b/configuration_guides/admin/admin_flags.rst index c4c170841..93aee2cb9 100644 --- a/configuration_guides/admin/admin_flags.rst +++ b/configuration_guides/admin/admin_flags.rst @@ -39,6 +39,4 @@ The **Administration Flags** page describes the following flags, which can be mo statement_Lock_Timeout use_Config_IP use_Legacy_Decimal_Literals - use_Legacy_String_Literals - - + use_Legacy_String_Literals \ No newline at end of file diff --git a/configuration_guides/admin/bin_sizes.rst b/configuration_guides/admin/bin_sizes.rst deleted file mode 100644 index d058c0ac9..000000000 --- a/configuration_guides/admin/bin_sizes.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. _bin_sizes: - -************************* -Bin Size -************************* -The ``binSizes`` flag sets the custom bin size in the cache to enable high granularity over bin control. - -The following describes the ``binSizes`` flag: - -* **Modification type** - Regular -* **Data type** - string -* **Default value** - ``16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,786432000,107374,1824,1342177280,1610612736,1879048192,2147483648,2415919104,2684354560,2952790016,3221225472`` \ No newline at end of file diff --git a/configuration_guides/admin/check_cuda_memory.rst b/configuration_guides/admin/check_cuda_memory.rst deleted file mode 100644 index 6952968f5..000000000 --- a/configuration_guides/admin/check_cuda_memory.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. _check_cuda_memory: - -************************* -Check CUDA Memory -************************* -The ``checkCudaMemory`` flag sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. - -The following describes the ``checkCudaMemory`` flag: - -* **Modification type** - Regular -* **Data type** - boolean -* **Default value** - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/admin/compiler_gets_only_ufs.rst b/configuration_guides/admin/compiler_gets_only_ufs.rst deleted file mode 100644 index 2216dc5cf..000000000 --- a/configuration_guides/admin/compiler_gets_only_ufs.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. _compiler_gets_only_ufs: - -************************* -compilerGetsOnlyUFs -************************* -The ``compilerGetsOnlyUFs`` flag sets the runtime to pass only utility functions names to the compiler. - -The following describes the ``compilerGetsOnlyUFs`` flag: - - -* **Data type** - boolean -* **Default value** - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/configuration_flags.rst b/configuration_guides/configuration_flags.rst new file mode 100644 index 000000000..3a25dc9bd --- /dev/null +++ b/configuration_guides/configuration_flags.rst @@ -0,0 +1,20 @@ +.. _configuration_flags: + +************************* +Configuration Flags +************************* +SQream provides two methods for configuration your instance of SQream. The current configuration method is based on cluster and session-based configuration, described in more detail below. Users can also use the previous configuration method done using a configuration file. + +The **Configuration Methods** page describes the following configurations methods: + +.. toctree:: + :maxdepth: 1 + :glob: + :titlesonly: + + admin_flags + generic_flags + + + + diff --git a/configuration_guides/configuration_methods.rst b/configuration_guides/configuration_methods.rst new file mode 100644 index 000000000..00a70ab5c --- /dev/null +++ b/configuration_guides/configuration_methods.rst @@ -0,0 +1,19 @@ +.. _configuration_methods: + +************************* +Configuration Methods +************************* +SQream provides two methods for configuration your instance of SQream. The current configuration method is based on cluster and session-based configuration, described in more detail below. Users can also use the previous configuration method done using a configuration file. + +The **Configuration Methods** page describes the following configurations methods: + +.. toctree:: + :maxdepth: 1 + :glob: + :titlesonly: + + current_configuration_method + previous_configuration_method + + + diff --git a/configuration_guides/current_configuration_method.rst b/configuration_guides/current_configuration_method.rst new file mode 100644 index 000000000..9bd214b7b --- /dev/null +++ b/configuration_guides/current_configuration_method.rst @@ -0,0 +1,377 @@ +.. _current_configuration_method: + +************************** +Configuring SQream +************************** +The **Configuring SQream** page describes SQream’s method for configuring your instance of SQream and includes the following topics: + +.. contents:: + :local: + :depth: 1 + +Overview +----- +Modifications that you make to your configurations are persistent based on whether they are made at the session or cluster level. Persistent configurations are modifications made to attributes that are retained after shutting down your system. + +Modifying Your Configuration +---- +The **Modifying Your Configuration** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Modifying Your Configuration Using the Worker Configuration File +~~~~~~~~~~~ +You can modify your configuration using the **worker configuration file (config.json)**. Changes that you make to worker configuration files are persistent. Note that you can only set the attributes in your worker configuration file **before** initializing your SQream worker, and while your worker is active these attributes are read-only. + +The following is an example of a worker configuration file: + +.. code-block:: postgres + + { + “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, + “gpu”: 0, + “licensePath”: “home/test_user/SQream/tests/license.enc”, + “machineIP”: “127.0.0.1”, + “metadataServerIp”: “127.0.0.1”, + “metadataServerPort”: “3105, + “port”: 5000, + “useConfigIP”” true, + “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” + } + +You can access the legacy configuration file from the ``legacyConfigFilePath`` parameter shown above. If all (or most) of your workers require the same flag settings, you can set the ``legacyConfigFilePath`` attribute to the same legacy file. + +Modifying Your Configuration Using a Legacy Configuration File +~~~~~~~~~~~ +You can modify your configuration using a legacy configuration file. + +The Legacy configuration file provides access to the read/write flags used in SQream’s previous configuration method. A link to this file is provided in the **legacyConfigFilePath** parameter in the worker configuration file. + +The following is an example of the legacy configuration file: + +.. code-block:: postgres + + { + “developerMode”: true, + “reextentUse”: false, + “useClientLog”: true, + “useMetadataServer”” false + } + +Session vs Cluster Based Configuration +============================== +.. contents:: + :local: + :depth: 1 + +Cluster-Based Configuration +-------------- +SQream uses cluster-based configuration, enabling you to centralize configurations for all workers on the cluster. Only flags set to the regular or cluster flag type have access to cluster-based configuration. Configurations made on the cluster level are persistent and stored at the metadata level. The parameter settings in this file are applied globally to all workers connected to it. + +For more information, see the following: + +* `Using SQream SQL `_ - modifying flag attributes from the CLI. +* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. + +For more information on flag-based access to cluster-based configuration, see **Configuration Flag Types** below. + +Session-Based Configuration +---------------- +Session-based configurations are not persistent and are deleted when your session ends. This method enables you to modify all required configurations while avoiding conflicts between flag attributes modified on different devices at different points in time. + +The **SET flag_name** command is used to modify flag attributes. Any modifications you make with the **SET flag_name** command apply only to your open session, and are not saved when it ends + +For example, when the query below has completed executing, the values configured will be restored to its previous setting: + +.. code-block:: console + + set spoolMemoryGB=700; + select * from table a where date='2021-11-11' + +For more information, see the following: + +* `Using SQream SQL `_ - modifying flag attributes from the CLI. +* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. + +Configuration Flag Types +========== +The flag type attribute can be set for each flag and determines its write access as follows: + +* **Administration:** session-based read/write flags that can be stored in the metadata file. +* **Cluster:** global cluster-based read/write flags that can be stored in the metadata file. +* **Worker:** single worker-based read-only flags that can be stored in the worker configuration file. + +The flag type determines which files can be accessed and which commands or commands sets users can run. + +The following table describes the file or command modification rights for each flag type: + +.. list-table:: + :widths: 20 20 20 20 + :header-rows: 1 + + * - **Flag Type** + - **Legacy Configuration File** + - **ALTER SYSTEM SET** + - **Worker Configuration File** + * - :ref:`Regular` + - Can modify + - Can modify + - Cannot modify + * - :ref:`Cluster` + - Cannot modify + - Can modify + - Cannot modify + * - :ref:`Worker` + - Cannot modify + - Cannot modify + - Can modify + +.. _regular_flag_types: + +Regular Flag Types +--------------------- +The following is an example of the correct syntax for running a **Regular** flag type command: + +.. code-block:: console + + SET spoolMemoryGB= 11; + executed + +The following table describes the Regular flag types: + +.. list-table:: + :widths: 2 5 10 + :header-rows: 1 + + * - **Command** + - **Description** + - **Example** + * - ``SET `` + - Used for modifying flag attributes. + - ``SET developerMode=true`` + * - ``SHOW / ALL`` + - Used to preset either a specific flag value or all flag values. + - ``SHOW `` + * - ``SHOW ALL LIKE`` + - Used as a wildcard character for flag names. + - ``SHOW `` + * - ``show_conf_UF`` + - Used to print all flags with the following attributes: + + * Flag name + * Default value + * Is developer mode (Boolean) + * Flag category + * Flag type + - ``rechunkThreshold,90,true,RND,regular`` + * - ``show_conf_extended UF`` + - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. + - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` + ``utility functions names,boolean,true,false`` + * - ``show_md_flag UF`` + - Used to show a specific flag/all flags stored in the metadata file. + - + * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` + * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` + * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` + +.. _cluster_flag_types: + +Cluster Flag Types +--------------------- +The following is an example of the correct syntax for running a **Cluster** flag type command: + +.. code-block:: console + + ALTER SYSTEM RESET useMetadataServer; + executed + +The following table describes the Cluster flag types: + +.. list-table:: + :widths: 1 5 10 + :header-rows: 1 + + * - **Command** + - **Description** + - **Example** + * - ``ALTER SYSTEM SET `` + - Used to storing or modifying flag attributes in the metadata file. + - ``ALTER SYSTEM SET `` + * - ``ALTER SYSTEM RESET `` + - Used to remove a flag or all flag attributes from the metadata file. + - ``ALTER SYSTEM RESET `` + * - ``SHOW / ALL`` + - Used to print the value of a specified value or all flag values. + - ``SHOW `` + * - ``SHOW ALL LIKE`` + - Used as a wildcard character for flag names. + - ``SHOW `` + * - ``show_conf_UF`` + - Used to print all flags with the following attributes: + + * Flag name + * Default value + * Is developer mode (Boolean) + * Flag category + * Flag type + - ``rechunkThreshold,90,true,RND,regular`` + * - ``show_conf_extended UF`` + - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. + - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` + ``utility functions names,boolean,true,false`` + * - ``show_md_flag UF`` + - Used to show a specific flag/all flags stored in the metadata file. + - + * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` + * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` + * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` + +.. _worker_flag_types: + +Worker Flag Types +--------------------- +The following is an example of the correct syntax for running a **Worker** flag type command: + +.. code-block:: console + + SHOW spoolMemoryGB; + +The following table describes the Worker flag types: + +.. list-table:: + :widths: 1 5 10 + :header-rows: 1 + + * - **Command** + - **Description** + - **Example** + * - ``ALTER SYSTEM SET `` + - Used to storing or modifying flag attributes in the metadata file. + - ``ALTER SYSTEM SET `` + * - ``ALTER SYSTEM RESET `` + - Used to remove a flag or all flag attributes from the metadata file. + - ``ALTER SYSTEM RESET `` + * - ``SHOW / ALL`` + - Used to print the value of a specified value or all flag values. + - ``SHOW `` + * - ``SHOW ALL LIKE`` + - Used as a wildcard character for flag names. + - ``SHOW `` + * - ``show_conf_UF`` + - Used to print all flags with the following attributes: + + * Flag name + * Default value + * Is developer mode (Boolean) + * Flag category + * Flag type + - ``rechunkThreshold,90,true,RND,regular`` + * - ``show_conf_extended UF`` + - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. + - + ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` + ``utility functions names,boolean,true,false`` + * - ``show_md_flag UF`` + - Used to show a specific flag/all flags stored in the metadata file. + - + * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` + * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` + * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` + +Configuration Commands +========== +The configuration commands are associated with particular flag types based on permissions. + +The following table describes the commands or command sets that can be run based on their flag type. Note that the flag names described in the following table are described in the :ref:`Configuration Roles` section below. + +.. list-table:: + :header-rows: 1 + :widths: 1 2 10 17 + :class: my-class + :name: my-name + + * - Flag Type + - Command + - Description + - Example + * - Regular + - ``SET `` + - Used for modifying flag attributes. + - ``SET developerMode=true`` + * - Cluster + - ``ALTER SYSTEM SET `` + - Used to storing or modifying flag attributes in the metadata file. + - ``ALTER SYSTEM SET `` + * - Cluster + - ``ALTER SYSTEM RESET `` + - Used to remove a flag or all flag attributes from the metadata file. + - ``ALTER SYSTEM RESET `` + * - Regular, Cluster, Worker + - ``SHOW / ALL`` + - Used to print the value of a specified value or all flag values. + - ``SHOW `` + * - Regular, Cluster, Worker + - ``SHOW ALL LIKE`` + - Used as a wildcard character for flag names. + - ``SHOW `` + * - Regular, Cluster, Worker + - ``show_conf_UF`` + - Used to print all flags with the following attributes: + + * Flag name + * Default value + * Is developer mode (Boolean) + * Flag category + * Flag type + + + + - ``rechunkThreshold,90,true,RND,regular`` + * - Regular, Cluster, Worker + - ``show_conf_extended UF`` + - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. + - ``spoolMemoryGB,15,false,generic,regular,Amount of memory (GB)`` + ``the server can use for spooling,”Statement that perform “”group by””,`` + ``“”order by”” or “”join”” operation(s) on large set of data will run`` + ``much faster if given enough spool memory, otherwise disk spooling will`` + ``be used resulting in performance hit.”,uint,,0-5000`` + * - Regular, Cluster, Worker + - ``show_md_flag UF`` + - Used to show a specific flag/all flags stored in the metadata file. + - + * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` + * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` + * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` + +.. _configuration_roles: + +Configuration Roles +=========== +SQream divides flags into the following roles, each with their own set of permissions: + +* **`Administration flags `_**: can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command. +* **`Generic flags `_**: can be modified by standard users on a session basis. + +Showing All Flags in the Catalog Table +======= +SQream uses the **sqream_catalog.parameters** catalog table for showing all flags, providing the scope (default, cluster and session), description, default value and actual value. + +The following is the correct syntax for a catalog table query: + +.. code-block:: console + + SELECT * FROM sqream_catalog.settings + +The following is an example of a catalog table query: + +.. code-block:: console + + externalTableBlobEstimate, 100, 100, default, + varcharEncoding, ascii, ascii, default, Changes the expected encoding for Varchar columns + useCrcForTextJoinKeys, true, true, default, + hiveStyleImplicitStringCasts, false, false, default, + +This guide covers the configuration files and the ``SET`` statement. \ No newline at end of file diff --git a/configuration_guides/generic/spooling.rst b/configuration_guides/generic/spooling.rst index dcf1c775f..e96928c6f 100644 --- a/configuration_guides/generic/spooling.rst +++ b/configuration_guides/generic/spooling.rst @@ -65,5 +65,5 @@ The following is an example of setting ``spoolMemoryGB`` value in the previous c For more information about configuring the ``spoolMemoryGB`` flag, see the following: -* **Current configuration method**: Configuration flags -* **Previous configuration method**: Runtime global flags \ No newline at end of file +* `Current configuration method `_ +* `Previous configuration method `_ \ No newline at end of file diff --git a/configuration_guides/generic_regular_flags.rst b/configuration_guides/generic_regular_flags.rst index 0181f1ce1..251a913e4 100644 --- a/configuration_guides/generic_regular_flags.rst +++ b/configuration_guides/generic_regular_flags.rst @@ -12,4 +12,6 @@ The **Regular Generic Flags** page describes **Regular** modification type flags flip_join_order log_sys_level - max_avg_blob_size_to_compress_on_gpu \ No newline at end of file + max_avg_blob_size_to_compress_on_gpu + limit_query_memory_gb + spool_memory_gb \ No newline at end of file diff --git a/configuration_guides/index.rst b/configuration_guides/index.rst index 8e1e81728..0456e7ee6 100644 --- a/configuration_guides/index.rst +++ b/configuration_guides/index.rst @@ -3,18 +3,13 @@ ************************* Configuration Guides ************************* -Once installed, you can configure your instance of SQream using the SQream Acceleration Studio. -The SQream Acceleration Studio divides flags into the following roles, each with their own set of permissions: +The **Configuration Guides** page describes the following configuration information: .. toctree:: - :maxdepth: 2 + :maxdepth: 1 :glob: - admin_flags - generic_flags - -For more information, see the following: - -* :ref:`SQream Acceleration Studio 5.4.2` -* :ref:`Configuring Your Instance of SQream` \ No newline at end of file + spooling + configuration_methods + configuration_flags \ No newline at end of file diff --git a/configuration_guides/previous_configuration_method.rst b/configuration_guides/previous_configuration_method.rst new file mode 100644 index 000000000..ff48e7cc1 --- /dev/null +++ b/configuration_guides/previous_configuration_method.rst @@ -0,0 +1,268 @@ +.. _previous_configuration_method: + +************************** +Configuring SQream Using the Previous Configuration Method +************************** +The **Configuring SQream Using the Previous Configuration Method** page describes SQream’s previous method for configuring your instance of SQream, and includes the following topics: + +.. contents:: + :local: + :depth: 1 + +By default, configuration files are stored in ``/etc/sqream``. + +A very minimal configuration file looks like this: + +.. code-block:: json + + { + "compileFlags": { + }, + "runtimeFlags": { + }, + "runtimeGlobalFlags": { + }, + "server": { + "gpu": 0, + "port": 5000, + "cluster": "/home/sqream/sqream_storage", + "licensePath": "/etc/sqream/license.enc" + } + } + +* Each SQream DB worker (``sqreamd``) has a dedicated configuration file. + +* The configuration file contains four distinct sections, ``compileFlags``, ``runtimeFlags``, ``runtimeGlobalFlags``, and ``server``. + +In the example above, the worker will start on port 5000, and will use GPU #0. + +Frequently Set Parameters +------ +.. todo + list-table:: Compiler flags + :widths: auto + :header-rows: 1 + + * - Name + - Section + - Description + - Default + - Value range + - Example + * - + - + - + - + - + - + +.. list-table:: Server flags + :widths: auto + :header-rows: 1 + + * - Name + - Section + - Description + - Default + - Value range + - Example + * - ``gpu`` + - ``server`` + - Controls the GPU ordinal to use + - ✗ + - 0 to (number of GPUs in the machine -1). Check with ``nvidia-smi -L`` + - ``"gpu": 0`` + * - ``port`` + - ``server`` + - Controls the TCP port to listen on + - ✗ + - 1024 to 65535 + - ``"port" : 5000`` + * - ``ssl_port`` + - ``server`` + - Controls the SSL TCP port to listen on. Must be different from ``port`` + - ✗ + - 1024 to 65535 + - ``"ssl_port" : 5100`` + * - ``cluster`` + - ``server`` + - Specifies the cluster path root + - ✗ + - Valid local system path + - ``"cluster" : "/home/sqream/sqream_storage"`` + * - ``license_path`` + - ``server`` + - Specifies the license file for this worker + - ✗ + - Valid local system path to license file + - ``"license_path" : "/etc/sqream/license.enc"`` + +.. list-table:: Runtime global flags + :widths: auto + :header-rows: 1 + + * - Name + - Section + - Description + - Default + - Value range + - Example + * - ``spoolMemoryGb`` + - ``runtimeGlobalFlags`` + - Modifies RAM allocated for the worker for intermediate results. Statements that use more memory than this setting will spool to disk, which could degrade performance. We recommend not to exceed the amount of RAM in the machine. This setting must be set lower than the ``limitQueryMemoryGB`` setting. + - ``128`` + - 1 to maximum available RAM in gigabytes. + - ``"spoolMemoryGb": 250`` + * - ``limitQueryMemoryGB`` + - ``runtimeGlobalFlags`` + - Modifies the maximum amount of RAM allocated for a query. The recommended value for this is ``total host memory`` / ``sqreamd workers on host``. For example, for a machine with 512GB of RAM and 4 workers, the recommended setting is ``512/4 → 128``. + - ``10000`` + - ``1`` to ``10000`` + - ``"limitQueryMemoryGB" : 128`` + * - ``cudaMemQuota`` + - ``runtimeGlobalFlags`` + - Modifies the maximum amount of GPU RAM allocated for a worker. The recommended value is 99% for a GPU with a single worker, or 49% for a GPU with two workers. + - ``90`` % + - ``1`` to ``99`` + - ``"cudaMemQuota" : 99`` + * - ``showFullExceptionInfo`` + - ``runtimeGlobalFlags`` + - Shows complete error message with debug information. Use this for debugging. + - ``false`` + - ``true`` or ``false`` + - ``"showFullExceptionInfo" : true`` + * - ``initialSubscribedServices`` + - ``runtimeGlobalFlags`` + - Comma separated list of :ref:`service queues` that the worker is subscribed to + - ``"sqream"`` + - Comma separated list of service names, with no spaces. Services that don't exist will be created. + - ``"initialSubscribedServices": "sqream,etl,management"`` + * - ``logClientLevel`` + - ``runtimeGlobalFlags`` + - Used to control which log level should appear in the logs + - ``4`` (``INFO``) + - ``0`` SYSTEM (lowest) - ``4`` INFO (highest). See :ref:`information level table` for explanation about these log levels. + - ``"logClientLevel" : 3`` + * - ``nodeInfoLoggingSec`` + - ``runtimeGlobalFlags`` + - Sets an interval for automatically logging long-running statements' :ref:`show_node_info` output. Output is written as a message type ``200``. + - ``60`` (every minute) + - Positive whole number >=1. + - ``"nodeInfoLoggingSec" : 5`` + * - ``useLogMaxFileSize`` + - ``runtimeGlobalFlags`` + - Defines whether SQream logs should be cycled when they reach ``logMaxFileSizeMB`` size. When ``true``, set the ``logMaxFileSizeMB`` accordingly. + - ``false`` + - ``false`` or ``true`` + - ``"useLogMaxFileSize" : true`` + * - ``logMaxFileSizeMB`` + - ``runtimeGlobalFlags`` + - Sets the size threshold in megabytes after which a new log file will be opened. + - ``20`` + - ``1`` to ``1024`` (1MB to 1GB) + - ``"logMaxFileSizeMB" : 250`` + * - ``logFileRotateTimeFrequency`` + - ``runtimeGlobalFlags`` + - Control frequency of log rotation + - ``never`` + - ``daily``, ``weekly``, ``monthly``, ``never`` + - ``"logClientLevel" : 3`` + * - ``useMetadataServer`` + - ``runtimeGlobalFlags`` + - Specifies if this worker connects to a cluster (``true``) or is standalone (``false``). If set to ``true``, also set ``metadataServerIp`` + - ``true`` + - ``false`` or ``true`` + - ``"useMetadataServer" : true`` + * - ``metadataServerIp`` + - ``runtimeGlobalFlags`` + - Specifies the hostname or IP of the metadata server, when ``useMetadataServer`` is set to ``true``. + - ``127.0.0.1`` + - A valid IP or hostname + - ``"metadataServerIp": "127.0.0.1"`` + * - ``useConfigIP`` + - ``runtimeGlobalFlags`` + - Specifies if the metadata should use a pre-determined hostname or IP to refer to this worker. If set to ``true``, set the ``machineIp`` configuration accordingly. + - ``false`` - automatically derived by the TCP socket + - ``false`` or ``true`` + - ``"useConfigIP" : true`` + * - ``machineIP`` + - ``runtimeGlobalFlags`` + - Specifies the worker's external IP or hostname, when used from a remote network. + - No default + - A valid IP or hostname + - ``"machineIP": "10.0.1.4"`` + * - ``tempPath`` + - ``runtimeGlobalFlags`` + - Specifies an override for the temporary file path on the local machine. Set this to a local path to improve performance for spooling. + - Defaults to the central storage's built-in temporary folder + - A valid path to a folder on the local machine + - ``"tempPath": "/mnt/nvme0/temp"`` + + + +.. list-table:: Runtime flags + :widths: auto + :header-rows: 1 + + * - Name + - Section + - Description + - Default + - Value range + - Example + * - ``insertParsers`` + - ``runtimeFlags`` + - Sets the number of CSV parsing threads launched during bulk load + - 4 + - 1 to 32 + - ``"insertParsers" : 8`` + * - ``insertCompressors`` + - ``runtimeFlags`` + - Sets the number of compressor threads launched during bulk load + - 4 + - 1 to 32 + - ``"insertCompressors" : 8`` + * - ``statementLockTimeout`` + - ``runtimeGlobalFlags`` + - Sets the delay in seconds before SQream DB will stop waiting for a lock and return an error + - 3 + - >=1 + - ``"statementLockTimeout" : 10`` + + +.. list the main configuration options and how they are used + +.. point to the best practices as well + +.. warning:: JSON files can't contain any comments. + +Recommended Configuration File +----- + +.. code-block:: json + + { + "compileFlags":{ + }, + "runtimeFlags":{ + "insertParsers": 16, + "insertCompressors": 8 + }, + "runtimeGlobalFlags":{ + "limitQueryMemoryGB" : 121, + "spoolMemoryGB" : 108, + "cudaMemQuota": 90, + "initialSubscribedServices" : "sqream", + "useMetadataServer": true, + "metadataServerIp": "127.0.0.1", + "useConfigIP": true, + "machineIP": "127.0.0.1" + }, + "server":{ + "gpu":0, + "port":5000, + "ssl_port": 5100, + "cluster":"/home/sqream/sqream_storage", + "licensePath":"/etc/sqream/license.enc" + } + } \ No newline at end of file diff --git a/configuration_guides/spool_memory_gb.rst b/configuration_guides/spool_memory_gb.rst new file mode 100644 index 000000000..9aa651a74 --- /dev/null +++ b/configuration_guides/spool_memory_gb.rst @@ -0,0 +1,11 @@ +.. _spool_memory_gb: + +************************* +Setting the Spool Memory +************************* +The ``spoolMemoryGB`` flag sets the amount of memory (GB) available to the server for spooling. + +The following describes the ``spoolMemoryGB`` flag: + +* **Data type** - uint +* **Default value** - ``8`` \ No newline at end of file diff --git a/configuration_guides/spooling.rst b/configuration_guides/spooling.rst new file mode 100644 index 000000000..b2ae15c4d --- /dev/null +++ b/configuration_guides/spooling.rst @@ -0,0 +1,69 @@ +.. _spooling: + +************************** +Configuring the Spooling Feature +************************** +The **Configuring the Spooling Feature** page includes the following topics: + +.. contents:: + :local: + :depth: 1 + +Overview +-------- +From the SQream Acceleration Studio you can allocate the amount of memory (GB) available to the server for spooling using the ``spoolMemoryGB`` flag. SQream recommends setting the ``spoolMemoryGB`` flag to 90% of the ``limitQueryMemoryGB`` flag. The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. + +In addition, the ``limitQueryMemoryGB`` defines how much total system memory is used by each worker. SQream recommends setting ``limitQueryMemoryGB`` to 5% less than the total host memory divided by the amount of ``sqreamd`` workers on host. + +Note that ``spoolMemoryGB`` must bet set to less than the ``limitQueryMemoryGB``. + +Example Configurations +---------- +The **Example Configurations** section shows the following example configurations: + +.. contents:: + :local: + :depth: 1 + +Example 1 - Recommended Settings +~~~~~~~~~~~ +The following is an example of the recommended settings for a machine with 512GB of RAM and 4 workers: + +.. code-block:: console + + limitQueryMemoryGB - ⌊(512 * 0.95 / 4)⌋ → ~ 486 / 4 → 121 + spoolMemoryGB - ⌊( 0.9 * limitQueryMemoryGB )⌋ → ⌊( 0.9 * 121 )⌋ → 108 + +Example 2 - Setting Spool Memory +~~~~~~~~~~~ +The following is an example of setting ``spoolMemoryGB`` value in the current configuration method per-worker for 512GB of RAM and 4 workers: + +.. code-block:: console + + { + “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, + “gpu”: 0, + “licensePath”: “home/test_user/SQream/tests/license.enc”, + “machineIP”: “127.0.0.1”, + “metadataServerIp”: “127.0.0.1”, + “metadataServerPort”: “3105, + “port”: 5000, + “useConfigIP”” true, + “limitQueryMemoryGB" : 121, + “spoolMemoryGB" : 108 + “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” + } + +The following is an example of setting ``spoolMemoryGB`` value in the previous configuration method per-worker for 512GB of RAM and 4 workers: + +.. code-block:: console + + “runtimeFlags”: { + “limitQueryMemoryGB” : 121, + “spoolMemoryGB” : 108 + + +For more information about configuring the ``spoolMemoryGB`` flag, see the following: + +* `Current configuration method `_ +* `Previous configuration method `_ \ No newline at end of file diff --git a/releases/2019.2.1.rst b/releases/2019.2.1.rst index 784ab5eff..c9c96b59b 100644 --- a/releases/2019.2.1.rst +++ b/releases/2019.2.1.rst @@ -1,7 +1,7 @@ .. _2019.2.1: ****************************** -What's new in 2019.2.1 +Release Notes 2019.2.1 ****************************** * 250 bugs fixed. Thanks to all of our customers and an unprecedented number of deployments for helping us find and fix these! diff --git a/releases/2020.1.rst b/releases/2020.1.rst index da6f31afe..e4928855e 100644 --- a/releases/2020.1.rst +++ b/releases/2020.1.rst @@ -1,7 +1,7 @@ .. _2020.1: ************************** -What's New in 2020.1 +Release Notes 2020.1 ************************** SQream DB v2020.1 contains lots of new features, improved performance, and bug fixes. @@ -13,7 +13,7 @@ The latest release vastly improves reliability and performance, and makes gettin The core of SQream DB v2020.1 contains new integration features, more analytics capabilities, and better drivers and connectors. -New Features +New features ================ Integrations @@ -35,7 +35,7 @@ Integrations See :ref:`logging` for more information. -SQL Support +SQL support --------------- * @@ -53,7 +53,7 @@ SQL Support * Added lots of new :ref:`aggregate functions`, including ``VAR_SAMP``, ``VAR_POP``, ``COVAR_POP``, etc. -Improvements and Fixes +Improvements and fixes ======================== SQream DB v2020.1 includes hundreds of small new features and tunable parameters that improve performance, reliability, and stability. Existing SQream DB users can expect to see a general speedup of around 10% on most statements and queries! @@ -94,7 +94,7 @@ SQream DB v2020.1 includes hundreds of small new features and tunable parameters * Additional CSV date formats (date parsers) added for compatibility -Behaviour Changes +Behaviour changes ======================== * ``ClientCmd`` is now known as :ref:`sqream sql` @@ -162,8 +162,8 @@ Operations -Known Issues and Limitations - +Known Issues & Limitations +================================ * An invalid formatted CSV can cause an ``insufficient memory`` error on a :ref:`copy_from` statement if a quote isn't closed and the file is much larger than system memory. diff --git a/releases/2020.2.rst b/releases/2020.2.rst index 17d77383c..3dc25b78a 100644 --- a/releases/2020.2.rst +++ b/releases/2020.2.rst @@ -1,7 +1,7 @@ .. _2020.2: ************************** -What's New in 2020.2 +Release Notes 2020.2 ************************** SQream v2020.2 contains some new features, improved performance, and bug fixes. diff --git a/releases/2020.3.1.rst b/releases/2020.3.1.rst index 755d75684..0667306d7 100644 --- a/releases/2020.3.1.rst +++ b/releases/2020.3.1.rst @@ -1,59 +1,72 @@ .. _2020.3.1: ************************** -What's New in 2020.3.1 +Release Notes 2020.3.1 ************************** +The 2020.3.1 release notes were released on October 8, 2020 and describe the following: -SQream DB v2020.3.1 contains minor features, many performance improvements and bug fixes. +.. contents:: + :local: + :depth: 1 -New or expanded features -========================= + +New Features +------------- +The following list describes the new features: + * TEXT data type: - * Full support for MIN and MAX aggregate functions on TEXT columns in GROUP BY queries - * Support Text-type as window partition keys (e.g., select distinct name, max(id) over (partition by name) from textTable;) - * Support Text-type fields in windows order by keys - * Support join on Text columns (e.g., t1.x = t2.y where x and y are columns of type Text) - * Complete the implementation of LIKE on TEXT columns (previously limited to prefix & suffix) - * Support for cast fromm TEXT to REAL/FLOAT - * New string function - REPEAT which repeats a string value for a specified number of times + * Full support for ``MIN`` and ``MAX`` aggregate functions on ``TEXT`` columns in ``GROUP BY`` queries. + * Support Text-type as window partition keys (e.g., select distinct name, max(id) over (partition by name) from ``textTable;``). + * Support Text-type fields in windows order by keys. + * Support join on ``TEXT`` columns (such as ``t1.x = t2.y`` where ``x`` and ``y`` are columns of type ``TEXT``). + * Complete the implementation of ``LIKE`` on ``TEXT`` columns (previously limited to prefix and suffix). + * Support for cast fromm ``TEXT`` to ``REAL/FLOAT``. + * New string function - ``REPEAT`` for repeating a string value for a specified number of times. -* Allow mapping DECIMAL ORC columns to SQream's floating-point types +* Support mapping ``DECIMAL ORC`` columns to SQream's floating-point types. -* Support LIKE on non-literal patterns (i.e., columns and complex expressions) +* Support ``LIKE`` on non-literal patterns (such as columns and complex expressions). -* Catch OS signals and save the signal along with the stack trace in the SQream debug log +* Catch OS signals and save the signal along with the stack trace in the SQream debug log. -* Support equijoins conditions on columns with different types (i.e., tinyint, smallint, int & bigint) +* Support equijoin conditions on columns with different types (such as ``tinyint``, ``smallint``, ``int`` and ``bigint``). -* `DUMP_DATABASE_DDL` now includes foreign tables in the output +* ``DUMP_DATABASE_DDL`` now includes foreign tables in the output. -* New utility function - TRUNCATE_IF_EXISTS +* New utility function - ``TRUNCATE_IF_EXISTS``. Performance Enhancements -========================= -* Introduced the "MetaData on Demand" feature which results in signicant proformance improvements +------------- +The following list describes the performance enhancements: + + +* Introduced the "MetaData on Demand" feature which results in signicant proformance improvements. + +* Implemented regex functions (``RLIKE``, ``REGEXP_COUNT``, ``REGEXP_INSTR``, ``REGEXP_SUBSTR``, ``PATINDEX``) for ``TEXT`` columns on GPU. + -* Implement regex functions (RLIKE, REGEXP_COUNT, REGEXP_INSTR, REGEXP_SUBSTR, PATINDEX) for TEXT columns on GPU +Resolved Issues +------------- +The following list describes the resolved issues: -Bug fixes -============ -* Multiple distinct aggregates no longer need to be used with developerMode flag -* In some scenrios, the statement_id and connection_id values are incorrectly recorded as -1 in the log -* NOT RLIKE is not supported for TEXT in the compiler -* Cast from TEXT to date/datetime returns an error when the TEXT column contains NULL +* Multiple distinct aggregates no longer need to be used with developerMode flag. +* In some scenarios, the ``statement_id`` and ``connection_id values`` are incorrectly recorded as ``-1`` in the log. +* ``NOT RLIKE`` is not supported for ``TEXT`` in the compiler. +* Casting from ``TEXT`` to ``date/datetime`` returns an error when the ``TEXT`` column contains ``NULL``. -Known Issues & Limitations -================================ +Known Issues and Limitations +------------- +No known issues and limitations. Upgrading to v2020.3.1 -======================== +---------------- Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. -Contact your account manager to get the latest release of SQream DB. +Contact your account manager to get the latest release of SQream DB. \ No newline at end of file diff --git a/releases/2020.3.2.1.rst b/releases/2020.3.2.1.rst index caf07b6f2..3c551b636 100644 --- a/releases/2020.3.2.1.rst +++ b/releases/2020.3.2.1.rst @@ -1,23 +1,31 @@ .. _2020.3.2.1: ************************** -What's New in 2020.3.2.1 +Release Notes 2020.3.2.1 ************************** +The 2020.3.2.1 release notes were released on October 8, 2020 and describe the following: +.. contents:: + :local: + :depth: 1 + + +Overview +----------------- SQream DB v2020.3.2.1 contains major performance improvements and some bug fixes. Performance Enhancements -========================= -* Metadata on Demand optimization resulting in reduced latency and improved overall performance +------------- +* Metadata on Demand optimization resulting in reduced latency and improved overall performance. -Known Issues & Limitations -================================ -* Multiple count distinct operations - is blocked for Text data type +Known Issues and Limitations +------------- +* Multiple count distinct operations is enabled for all data types. Upgrading to v2020.3.2.1 -======================== +------------- Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. -Contact your account manager to get the latest release of SQream DB. +Contact your account manager to get the latest release of SQream DB. \ No newline at end of file diff --git a/releases/2020.3.rst b/releases/2020.3.rst index 1bb5ebe44..52bf63991 100644 --- a/releases/2020.3.rst +++ b/releases/2020.3.rst @@ -1,112 +1,18 @@ .. _2020.3: ************************** -What's New in 2020.3 +Release Notes 2020.3 ************************** -SQream DB v2020.3 contains new features, performance enhancements, and resolved issues. - -The 2020.3 Release Notes describe the following: +The 2020.3 release notes were released on October 8, 2020 and describe the following: .. contents:: :local: :depth: 1 -:::: - -Release Notes Version 2020.3.2.1 -============== -SQream DB v2020.3.2.1 contains major performance improvements and some bug fixes. - -Performance Enhancements -------------- -* Metadata on Demand optimization resulting in reduced latency and improved overall performance. - - -Known Issues and Limitations -------------- -* Multiple count distinct operations is enabled for all data types. - -Upgrading to v2020.3.2.1 -------------- - -Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. - -Contact your account manager to get the latest release of SQream DB. - - - -:::: - - - -Release Notes Version 2020.3.1 -================= -New Features -------------- -The following list describes the new features: - - -* TEXT data type: - * Full support for ``MIN`` and ``MAX`` aggregate functions on ``TEXT`` columns in ``GROUP BY`` queries. - * Support Text-type as window partition keys (e.g., select distinct name, max(id) over (partition by name) from ``textTable;``). - * Support Text-type fields in windows order by keys. - * Support join on ``TEXT`` columns (such as ``t1.x = t2.y`` where ``x`` and ``y`` are columns of type ``TEXT``). - * Complete the implementation of ``LIKE`` on ``TEXT`` columns (previously limited to prefix and suffix). - * Support for cast fromm ``TEXT`` to ``REAL/FLOAT``. - * New string function - ``REPEAT`` for repeating a string value for a specified number of times. - -* Support mapping ``DECIMAL ORC`` columns to SQream's floating-point types. - -* Support ``LIKE`` on non-literal patterns (such as columns and complex expressions). - -* Catch OS signals and save the signal along with the stack trace in the SQream debug log. - -* Support equijoin conditions on columns with different types (such as ``tinyint``, ``smallint``, ``int`` and ``bigint``). - -* ``DUMP_DATABASE_DDL`` now includes foreign tables in the output. - -* New utility function - ``TRUNCATE_IF_EXISTS``. - - -Performance Enhancements -------------- -The following list describes the performance enhancements: - - -* Introduced the "MetaData on Demand" feature which results in signicant proformance improvements. - -* Implemented regex functions (``RLIKE``, ``REGEXP_COUNT``, ``REGEXP_INSTR``, ``REGEXP_SUBSTR``, ``PATINDEX``) for ``TEXT`` columns on GPU. - - -Resolved Issues -------------- -The following list describes the resolved issues: - - -* Multiple distinct aggregates no longer need to be used with developerMode flag. -* In some scenarios, the ``statement_id`` and ``connection_id values`` are incorrectly recorded as ``-1`` in the log. -* ``NOT RLIKE`` is not supported for ``TEXT`` in the compiler. -* Casting from ``TEXT`` to ``date/datetime`` returns an error when the ``TEXT`` column contains ``NULL``. - - -Known Issues and Limitations -------------- -No known issues and limitations. - - -Upgrading to v2020.3.1 ----------------- - -Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. - -Contact your account manager to get the latest release of SQream DB. - - -:::: - -Release Notes Version 2020.3 -================= +Overview +------------ +SQream DB v2020.3 contains new features, performance enhancements, and resolved issues. New Features diff --git a/releases/2020.3_index.rst b/releases/2020.3_index.rst new file mode 100644 index 000000000..e54d1d615 --- /dev/null +++ b/releases/2020.3_index.rst @@ -0,0 +1,18 @@ +.. _2020.3_index: + +************************** +Release Notes 2020.3 +************************** +The 2020.3 release notes describe the following releases: + +.. contents:: + :local: + :depth: 1 + +.. toctree:: + :maxdepth: 1 + :glob: + + 2020.3.2.1 + 2020.3.1 + 2020.3 \ No newline at end of file diff --git a/releases/index.rst b/releases/index.rst index e7ed2a03c..516a20780 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -1,15 +1,18 @@ .. _releases: ********** -Releases +Release Notes ********** + .. list-table:: :widths: auto :header-rows: 1 + * - Version - Release Date + - June 13, 2021 * - :ref:`2020.3` - October 8, 2020 * - :ref:`2020.2` @@ -24,6 +27,6 @@ Releases :glob: :hidden: - 2020.3 + 2020.3_index 2020.2 - 2020.1 \ No newline at end of file + 2020.1 From d1bee5f92237984da3a440e41d7a20f43fbf9ff8 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 20 Feb 2022 19:19:32 +0200 Subject: [PATCH 189/300] Update index.rst --- releases/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/releases/index.rst b/releases/index.rst index 516a20780..22bcdce89 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -12,7 +12,6 @@ Release Notes * - Version - Release Date - - June 13, 2021 * - :ref:`2020.3` - October 8, 2020 * - :ref:`2020.2` From a49b89ddfa34081e6c106a474c59c908269ef302 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 22 Feb 2022 12:12:23 +0200 Subject: [PATCH 190/300] Update preparing_your_machine_to_install_sqream.rst Removed Ubuntu 18.04. Changed Amazon Linux to Amazon Linux 7. Corrected Hardware Guide link. --- .../preparing_your_machine_to_install_sqream.rst | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/getting_started/preparing_your_machine_to_install_sqream.rst b/getting_started/preparing_your_machine_to_install_sqream.rst index a517eb906..74af66820 100644 --- a/getting_started/preparing_your_machine_to_install_sqream.rst +++ b/getting_started/preparing_your_machine_to_install_sqream.rst @@ -11,16 +11,11 @@ To prepare your machine to install SQream, do the following: * Verify you have an NVIDIA-capable server, either on-premise or on supported cloud platforms: - * Red Hat Enterprise Linux v7.x - + * Red Hat Enterprise Linux v7.x * CentOS v7.x - - - * Ubuntu 18.04 - - * Amazon Linux + * Amazon Linux 7 * Verify that you have the following: @@ -37,4 +32,4 @@ To prepare your machine to install SQream, do the following: For more information, see the following: * :ref:`recommended_pre-installation_configurations` -* `Hardware Guide `_ \ No newline at end of file +* `Hardware Guide `_ From 2b94cca1239988d7aa8500b28751df5daf59c90f Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 24 Feb 2022 10:08:44 +0200 Subject: [PATCH 191/300] Update recommended_pre-installation_configurations.rst Updated according to Slavi's comments. --- ...mended_pre-installation_configurations.rst | 517 +++++++++++------- 1 file changed, 312 insertions(+), 205 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 2c8fa5284..cf6328a34 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -3,8 +3,7 @@ ********************************************* Recommended Pre-Installation Configuration ********************************************* - -Before :ref:`installing SQream DB`, SQream recommends you to tune your system for better performance and stability. +Before :ref:`installing SQream DB`, SQream recommends you to tune your system for better performance and stability. This page provides recommendations for production deployments of SQream and describes the following: @@ -12,12 +11,11 @@ This page provides recommendations for production deployments of SQream and desc :local: :depth: 1 - Recommended BIOS Settings ========================== -The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. +The first step when setting your pre-installation configurations is to use the recommended BIOS settings. -It is safe to skip any and all of the configuration steps, but this may impact performance. +The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. It is safe to skip any and all of the configuration steps, but this may impact performance. If any doubt arises, consult the documentation for your server or your hardware vendor for the correct way to apply the settings. @@ -31,7 +29,7 @@ If any doubt arises, consult the documentation for your server or your hardware * - **Management console access** - **Connected** - Connection to OOB required to preserve continuous network uptime. - * - **All drives.** + * - **All drives** - **Connected and displayed on RAID interface** - Prerequisite for cluster or OS installation. * - **RAID volumes.** @@ -40,7 +38,7 @@ If any doubt arises, consult the documentation for your server or your hardware * - **Fan speed Thermal Configuration.** - Dell fan speed: **High Maximum**. Specified minimum setting: **60**. HPe thermal configuration: **Increased cooling**. - NVIDIA Tesla GPUs are passively cooled and require high airflow to operate at full performance. - * - Power regulator or iDRAC power unit policy + * - **Power regulator or iDRAC power unit policy** - HPe: **HP static high performance** mode enabled. Dell: **iDRAC power unit policy** (power cap policy) disabled. - Other power profiles (such as "balanced") throttle the CPU and diminishes performance. Throttling may also cause GPU failure. * - **System Profile**, **Power Profile**, or **Performance Profile** @@ -49,9 +47,6 @@ If any doubt arises, consult the documentation for your server or your hardware * - **Power Cap Policy** or **Dynamic power capping** - **Disabled** - Other power profiles (like "balanced") throttle the CPU and may diminish performance or cause GPU failure. This setting may appear together with the above (Power profile or Power regulator). This setting allows disabling system ROM power calibration during the boot process. Power regulator settings are named differently in BIOS and iLO/iDRAC. - -.. - **Comment: is it necessary to show the different power regulator setting names in this document?** * - **Intel Turbo Boost** - **Enabled** - Intel Turbo Boost enables overclocking the processor to boost CPU-bound operation performance. Overclocking may risk computational jitter due to changes in the processor's turbo frequency. This causes brief pauses in processor operation, introducing uncertainty into application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. @@ -69,7 +64,7 @@ If any doubt arises, consult the documentation for your server or your hardware - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. * - **Processor C-States** (Minimum processor idle power core state) - **Disable** - - Processor C-States reduce server power when the system is in an idle state. This causes slower cold-starts when the system transitions from an idle to a load state, and may reduce query performance by up to 15%. **Comment: a hyperlinked footnote to an internal source was inserted into the Confluence doc here. Do we want to include this in the final version? Linked URL: https://www.dell.com/support/kbdoc/en-il/000060621/what-is-the-c-state** + - Processor C-States reduce server power when the system is in an idle state. This causes slower cold-starts when the system transitions from an idle to a load state, and may reduce query performance by up to 15%. * - **HPe**: **Energy/Performance bias** - **Maximum performance** - Configures processor sub-systems for high-performance and low-latency. Other power profiles (like "balanced") throttle the CPU and may diminish performance. Use this setting for environments that are not sensitive to power consumption. @@ -82,24 +77,16 @@ If any doubt arises, consult the documentation for your server or your hardware * - **HPe**: **Memory power savings mode** - **Maximum performance** - This setting configures several memory parameters to optimize the performance of memory sub-systems. The default setting is **Balanced**. - * - HPe **ACPI SLIT** + * - **HPe ACPI SLIT** - **Enabled** - ACPI SLIT sets the relative access times between processors and memory and I/O sub-systems. ACPI SLIT enables operating systems to use this data to improve performance by more efficiently allocating resources and workloads. - * - **QPI Snoop** **Comment: should we write that it is HPe or Intel? HPe: QPI Snoop** + * - **QPI Snoop** - **Cluster on Die** or **Home Snoop** - - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. - - - - - + - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. Installing the Operating System =================================================== -Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.6-7.9) must be installed before installing the SQream database. Either the customer or a SQream representative can perform the installation. - -.. - **Comment: I recommend leaving contact information here - Please call xxx-xxx-xxxx to contact a SQream representative.** +Once the BIOS settings have been set, you must install the operating system. Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.6-7.9) must be installed before installing the SQream database, by either the customer or a SQream representative. **To install the operating system:** @@ -110,9 +97,6 @@ Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.6-7.9) must be installe #. Set up the necessary drives and users as per the installation process. Using Debugging Tools is recommended for future problem-solving if necessary. - - .. - **Comment: In Step 4, why don't we document the entire procedure? I.e., why do we stop here and say "Continue the installation" and "Set up the necessary drives..."?** Selecting the **Development Tools** group installs the following tools: @@ -132,13 +116,11 @@ Selecting the **Development Tools** group installs the following tools: * rpm-build * rpm-sign - - The root user is created and the OS shell is booted up. Configuring the Operating System =================================================== -When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. +Once you've installted your operation system, you can configure it. When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. Logging In to the Server -------------------------------- @@ -155,11 +137,11 @@ Automatically Creating a SQream User $ sudo id sqream -The ID **1000** is used on each server in the following example: + The ID **1000** is used on each server in the following example: - .. code-block:: console + .. code-block:: console - $ uid=1000(sqream) gid=1000(sqream) groups=1000(sqream) + $ uid=1000(sqream) gid=1000(sqream) groups=1000(sqream) 2. If the ID's are different, delete the SQream user and SQream group from both servers: @@ -192,7 +174,7 @@ SQream enables you to manually create users. This section shows you how to manua $ sudo usermod -aG wheel sqream -You can remove the SQream user from the **wheel** group when the installation and configuration are complete: + You can remove the SQream user from the **wheel** group when the installation and configuration are complete: .. code-block:: console @@ -200,7 +182,7 @@ You can remove the SQream user from the **wheel** group when the installation an 3. Log out and log back in as **sqream**. -**Note:** If you deleted the **sqream** user and recreated it with different ID, to avoid permission errors, you must change its ownership to /home/sqream. + .. note:: If you deleted the **sqream** user and recreated it with different ID, to avoid permission errors, you must change its ownership to /home/sqream. 4. Change the **sqream** user's ownership to /home/sqream: @@ -266,7 +248,7 @@ Installing Python 3.6.7 .. code-block:: console - $ cd Python-3.6.7/Python-3 + $ cd Python-3.6.7 4. Run the **./configure** script: @@ -290,7 +272,7 @@ Installing Python 3.6.7 .. code-block:: console - $ python3.6.7 + $ python3 Installing NodeJS on CentOS -------------------------------- @@ -308,11 +290,17 @@ Installing NodeJS on CentOS $ sudo yum clean all && sudo yum makecache fast -3. Install the **node.js**) file: +3. Install the **node.js** file: .. code-block:: console $ sudo yum install -y nodejs + +4. Install npm and make it available for all users: + + .. code-block:: console + + $ sudo npm install pm2 -g Installing NodeJS on Ubuntu -------------------------------- @@ -330,24 +318,117 @@ Installing NodeJS on Ubuntu $ sudo apt-get install -y nodejs -3. Verify the node version: +3. Install npm and make it available for all users: + + .. code-block:: console + + $ sudo npm install pm2 -g + +Installing NodeJS Offline +------------------------------------------- +**To install NodeJS Offline** + +1. Download the NodeJS source code tarball file from the following URL into the **/home/sqream** directory: + + .. code-block:: console + + $ wget https://nodejs.org/dist/v12.13.0/node-v12.13.0-linux-x64.tar.xz + +2. Move the node-v12.13.0-linux-x64 file to the */usr/local* directory. + + .. code-block:: console + + $ sudo mv node-v12.13.0-linux-x64 /usr/local + +3. Navigate to the */usr/bin/* directory: + + .. code-block:: console + + $ cd /usr/bin + +4. Create a symbolic link to the */local/node-v12.13.0-linux-x64/bin/node node* directory: + + .. code-block:: console + + $ sudo ln -s ../local/node-v12.13.0-linux-x64/bin/node node + +5. Create a symbolic link to the */local/node-v12.13.0-linux-x64/bin/npm npm* directory: + + .. code-block:: console + + $ sudo ln -s ../local/node-v12.13.0-linux-x64/bin/npm npm + +6. Create a symbolic link to the */local/node-v12.13.0-linux-x64/bin/npx npx* directory: + + .. code-block:: console + + $ sudo ln -s ../local/node-v12.13.0-linux-x64/bin/npx npx + +7. Verify that the node versions for the above are correct: + + .. code-block:: console + + $ node --version + +Installing the pm2 Service Offline +------------------------------------------- +**To install the pm2 Service Offline** + +1. On a machine with internet access, install the following: + + * nodejs + * npm + * pm2 + +2. Extract the pm2 module to the correct directory: + + .. code-block:: console + + $ cd /usr/local/node-v12.13.0-linux-x64/lib/node_modules + $ tar -czvf pm2_x86.tar.gz pm2 + +3. Copy the **pm2_x86.tar.gz** file to a server without access to the internet and extract it. + + :: + +4. Move the **pm2** folder to the */usr/local/node-v12.13.0-linux-x64/lib/node_modules* directory: -.. - **Comment: - is this step relevant only for installing on Ubuntu, or on CentOS as well?** - .. code-block:: console - $ node -v + $ sudo mv pm2 /usr/local/node-v12.13.0-linux-x64/lib/node_modules + +5. Navigate back to the */usr/bin* directory: + + .. code-block:: console + + $ cd /usr/bin again + +6. Create a symbolink to the **pm2** service: + + .. code-block:: console + + $ sudo ln -s /usr/local/node-v12.22.3-linux-x64/lib/node_modules/pm2/bin/pm2 pm2 + +7. Verify that installation was successful: + + .. code-block:: console + + $ pm2 list + + .. note:: This must be done as a **sqream** user, and not as a **sudo** user. + +8. Verify that the node version is correct: + + .. code-block:: console + + $ node -v -Configuring the Network Time Protocol (NTP) +Configuring the Network Time Protocol ------------------------------------------- -This section describes how to configure your NTP. +This section describes how to configure your **Network Time Protocol (NTP)**. If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server `__. -.. - **Comment: - Is this the correct procedure on the linked URL: Configure NTP Client to Synchronize with NTP Server?* - **To configure your NTP:** 1. Install the NTP file. @@ -398,7 +479,7 @@ If your organization has an NTP server, you can configure it. $ sudo timedatectl -Checking that synchronization is enabled generates the following output: + Checking that synchronization is enabled generates the following output: .. code-block:: console @@ -415,9 +496,7 @@ Checking that synchronization is enabled generates the following output: Sun 2019-03-10 03:00:00 EDT Next DST change: DST ends (the clock jumps one hour backwards) at Sun 2019-11-03 01:59:59 EDT - Sun 2019-11-03 01:00:00 EST - - + Sun 2019-11-03 01:00:00 EST Configuring the Server to Boot Without the UI --------------------------------------------- @@ -453,7 +532,7 @@ Configuring the Kernel Parameters $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf -**Notice:** In the past, the **vm.zone_reclaim_mode** parameter was set to **7.** In the latest Sqream version, the vm.zone_reclaim_mode parameter must be set to **0**. If it is not set to **0**, when a numa node runs out of memory, the system will get stuck and will be unable to pull memory from other numa nodes. + .. note:: In the past, the **vm.zone_reclaim_mode** parameter was set to **7.** In the latest Sqream version, the vm.zone_reclaim_mode parameter must be set to **0**. If it is not set to **0**, when a numa node runs out of memory, the system will get stuck and will be unable to pull memory from other numa nodes. 2. Check the maximum value of the **fs.file**. @@ -461,13 +540,25 @@ Configuring the Kernel Parameters $ sysctl -n fs.file-max -3. *Optional* - If the maximum value of the **fs.file** is smaller than **2097152**, run the following command: +3. If the maximum value of the **fs.file** is smaller than **2097152**, run the following command: .. code-block:: console $ echo "fs.file-max=2097152" >> /etc/sysctl.conf -**IP4 forward** must be enabled for Docker and K8s installation only. + **IP4 forward** must be enabled for Docker and K8s installation only. + +4. Run the following command: + + .. code-block:: console + + $ sudo echo “net.ipv4.ip_forward = 1” >> /etc/sysctl.conf + +5. Reboot your system: + + .. code-block:: console + + $ sudo reboot Configuring the Firewall -------------------------------- @@ -486,34 +577,29 @@ The example in this section shows the open ports for four sqreamd sessions. If m .. code-block:: console $ firewall-cmd --zone=public --permanent --add-port=8080/tcp - $ firewallfirewall-cmd --zone=public --permanent --add-port=3105/tcp + $ firewall-cmd --zone=public --permanent --add-port=3105/tcp $ firewall-cmd --zone=public --permanent --add-port=3108/tcp $ firewall-cmd --zone=public --permanent --add-port=5000-5003/tcp $ firewall-cmd --zone=public --permanent --add-port=5100-5103/tcp $ firewall-cmd --permanent --list-all - -.. - **Comment: - does *--list-all* add the entire list of ports to the permanent firewall?** - 3. Reload the firewall: .. code-block:: console $ firewall-cmd --reload -4. Start the service and enable FirewallID on boot: +4. Enable FirewallID on boot: .. code-block:: console - $ systemctl start firewalld + $ systemctl enable firewalld If you do not need the firewall, you can disable it: .. code-block:: console - $ sudo systemctl disable firewalld - + $ sudo systemctl disable firewalld Disabling selinux -------------------------------- @@ -533,13 +619,13 @@ Disabling selinux 3. Change **SELINUX=enforcing** to **SELINUX=disabled**. -The above changes will only take effect after rebooting the server. + The above changes will only take effect after rebooting the server. -You can disable selinux immediately after rebooting the server by running the following command: + You can disable selinux immediately after rebooting the server by running the following command: -.. code-block:: console + .. code-block:: console - $ sudo setenforce 0 + $ sudo setenforce 0 Configuring the /etc/hosts File -------------------------------- @@ -556,11 +642,9 @@ Configuring the /etc/hosts File .. code-block:: console $ 127.0.0.1 localhost - $ - -.. - **Comment: - Is the above an output or a step?** - + $ + $ + Configuring the DNS -------------------------------- **To configure the DNS:** @@ -575,19 +659,14 @@ Configuring the DNS .. code-block:: console - DNS1="4.4.4.4" - DNS2="8.8.8.8" - - - -.. - **Comment: - is the above input correct?** + $ DNS1="4.4.4.4" + $ DNS2="8.8.8.8" Installing the Nvidia CUDA Driver =================================================== +After configuring your operating system, you must install the Nvidia CUDA driver. - -**Warning:** If your UI runs on the server, the server must be stopped before installing the CUDA drivers. + .. warning:: If your UI runs on the server, the server must be stopped before installing the CUDA drivers. CUDA Driver Prerequisites -------------------------------- @@ -617,7 +696,6 @@ CUDA Driver Prerequisites $ sudo apt-get install gcc - Updating the Kernel Headers -------------------------------- **To update the kernel headers:** @@ -662,14 +740,16 @@ You can disable Nouveau, which is the default driver. $ lsmod | grep nouveau -If the Nouveau driver has been loaded, the command above generates output. + If the Nouveau driver has been loaded, the command above generates output. 2. Blacklist the Nouveau drivers to disable them: .. code-block:: console - $ cat <`__ for the additional set-up requirements. + +To Tune Up NVIDIA Performance when Driver Installed from the Runfile +~~~~~~~~~~~~~~~~~~~~ +**To tune up NVIDIA performance when the driver was installed from the runfile:** + +1. Change the permissions on the **rc.local** file to **executable**: + .. code-block:: console + + $ sudo chmod +x /etc/rc.local + +2. Edit the **/etc/yum.repos.d/cuda-10-1-local.repo** file: + + .. code-block:: console + + $ sudo vim /etc/rc.local + 3. Add the following lines: - a. **For V100**: + * **For V100/A100**: .. code-block:: console $ nvidia-persistenced - b. **For IBM (mandatory)**: + * **For IBM (mandatory)**: .. code-block:: console + $ sudo systemctl start nvidia-persistenced $ sudo systemctl enable nvidia-persistenced - -**Notice**: Setting up the NVIDIA POWER9 CUDA driver includes additional set-up requirements. The NVIDIA POWER9 CUDA driver will not function properly if the additional set-up requirements are not followed. See `POWER9 Setup `__ for the additional set-up requirements. - - - c. **For K80**: + + * **For K80**: .. code-block:: console @@ -904,7 +1028,8 @@ This section describes how to tune up NVIDIA performance. The procedures in this .. code-block:: console $ nvidia-smi - + +.. note:: Setting up the NVIDIA POWER9 CUDA driver includes additional set-up requirements. The NVIDIA POWER9 CUDA driver will not function properly if the additional set-up requirements are not followed. See `POWER9 Setup `__ for the additional set-up requirements. Disabling Automatic Bug Reporting Tools ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -916,10 +1041,8 @@ Disabling Automatic Bug Reporting Tools $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done - The server is ready for the SQream software installation. - 2. Run the following checks: a. Check the OS release: @@ -951,53 +1074,33 @@ The server is ready for the SQream software installation. .. code-block:: console $ sysctl -n fs.file-max - - The desired output when checking the maximum value of the **fs.file** is greater or equal to **2097152**. - + f. Run the following command as a SQream user: - -.. - **Comment: - **Question - what do the following command parameter do? -c?** .. code-block:: console $ ulimit -c -u -n - -.. - **Comment: - See https://ss64.com/bash/ulimit.html** - The following shows the desired output when ****: + The following shows the desired output: .. code-block:: console - $ core file size (blocks, -c) unlimited - $ max user processes (-u) 1000000 - $ open files (-n) 1000000 - -3. Configure the security limits by running the **echo -e** command as a root user logged in shell: - - .. code-block:: console - - $ sudo bash - $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + $ core file size (blocks, -c) unlimited + $ max user processes (-u) 1000000 + $ open files (-n) 1000000 Enabling Core Dumps =================================================== +After installing the Nvidia CUDA driver, you can enable your core dumps. While SQream recommends enabling your core dumps, it is optional. -Enabling core dumps is recommended, but optional. - -**To enable core dumps:** - -1. Check the **abrtd** Status - -2. Set the limits - -3. Create the core dumps directory. +The **Enabling Core Dumps** section describes the following: +.. contents:: + :local: + :depth: 1 Checking the abrtd Status --------------------------------------------------- - **To check the abrtd status:** 1. Check if **abrtd** is running: @@ -1017,10 +1120,8 @@ Checking the abrtd Status $ sudo chkconfig abrt-xorg off $ sudo chkconfig abrtd off - Setting the Limits ---------------------------------------------------- - +--------------------------------------------------- **To set the limits:** 1. Set the limits: @@ -1039,8 +1140,7 @@ Setting the Limits 3. Log out and log in to apply the limit changes. Creating the Core Dumps Directory ---------------------------------------------------- - +--------------------------------------------------- **To set the core dumps directory:** 1. Make the **/tmp/core_dumps** directory: @@ -1059,11 +1159,12 @@ Creating the Core Dumps Directory .. code-block:: console - $ sudo chmod -R 777 /tmp/core_dumps + $ sudo chmod -R 777 /tmp/core_dumps + +.. warning:: Because the core dump file may be the size of total RAM on the server, verify that you have sufficient disk space. In the example above, the core dump is configured to the */tmp/core_dumps* directory. You must replace path according to your own environment and disk space. Setting the Output Directory of the /etc/sysctl.conf File ------------------------------------------------------------------ - +----------------------------------------------------------------- **To set the output directory of the /etc/sysctl.conf file:** 1. Edit the **/etc/sysctl.conf** file: @@ -1080,10 +1181,7 @@ Setting the Output Directory of the /etc/sysctl.conf File $ kernel.core_pattern = //core-%e-%s-%u-%g-%p-%t $ fs.suid_dumpable = 2 -.. - **Comment: - leave a note that the user can choose his correct location of the folder.** - -3. To apply the changes without rebooting the server, run: +3. To apply the changes without rebooting the server, run the following: .. code-block:: console @@ -1106,7 +1204,6 @@ Setting the Output Directory of the /etc/sysctl.conf File .. code-block:: console $ select abort_server(); - Verifying that the Core Dumps Work --------------------------------------------------- @@ -1116,15 +1213,13 @@ You can verify that the core dumps work only after installing and running SQream 1. Stop and restart all SQream services. + :: + 2. Connect to SQream with ClientCmd and run the following command: .. code-block:: console $ select abort_server(); - - -.. - **Comment: - what did the author mean by "Stage 3"?** Troubleshooting Core Dumping --------------------------------------------------- @@ -1134,6 +1229,8 @@ This section describes the troubleshooting procedure to be followed if all param 1. Reboot the server. + :: + 2. Verify that you have folder permissions: .. code-block:: console @@ -1150,7 +1247,8 @@ This section describes the troubleshooting procedure to be followed if all param .. code-block:: console - $ unlimited + $ core file size (blocks, -c) unlimited + $ open files (-n) 1000000 4. If all parameters have been configured correctly, but running **ulimit -c** outputs **0**, run the following: @@ -1162,10 +1260,19 @@ This section describes the troubleshooting procedure to be followed if all param .. code-block:: console - $ ulimit -S -c 0 > /dev/null 2>&1 - + $ ulimit -S -c 0 > /dev/null 2>&1 + +6. Log out and log in. + + :: + +7. Run the ulimit -c command: + + .. code-block:: console + + $ ulimit -c command -6. If the line is not found in **/etc/profile** directory, do the following: +8. If the line is not found in **/etc/profile** directory, do the following: a. Run the following command: From ef1367735a42aaccb8c9fe4b2b8087e24dafee74 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 24 Feb 2022 12:03:40 +0200 Subject: [PATCH 192/300] Added Informatica to menu --- third_party_tools/client_platforms/index.rst | 1 + .../client_platforms/informatica.rst | 173 ++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 third_party_tools/client_platforms/informatica.rst diff --git a/third_party_tools/client_platforms/index.rst b/third_party_tools/client_platforms/index.rst index 6b354524b..3b1fd8207 100644 --- a/third_party_tools/client_platforms/index.rst +++ b/third_party_tools/client_platforms/index.rst @@ -26,6 +26,7 @@ If you are looking for a tool that is not listed, SQream and our partners can he tableau pentaho microstrategy + informatica r php xxspotfire diff --git a/third_party_tools/client_platforms/informatica.rst b/third_party_tools/client_platforms/informatica.rst new file mode 100644 index 000000000..6bc50b22a --- /dev/null +++ b/third_party_tools/client_platforms/informatica.rst @@ -0,0 +1,173 @@ +.. _informatica: + +************************* +Connect to SQream Using Informatica Cloud Services +************************* + +Overview +========= +The **Connecting to SQream Using Informatica Cloud Services** page is quick start guide for connecting to SQream using Informatica cloud services. + +It describes the following: + +.. contents:: + :local: + +Establishing a Connection between SQream and Informatica +----------------- +The **Establishing a Connection between SQream and Informatica** page describes how to establish a connection between SQream and the Informatica data integration Cloud. + +**To establish a connection between SQream and the Informatica data integration Cloud:** + +1. Go to the `Informatica Cloud homepage `_. + + :: + +2. Do one of the following: + + 1. Log in using your credentials. + + :: + + 2. Log in using your SAML Identity Provider. + +3. From the **Services** window, select **Administrator** or click **Show all services** to show all services. + + + The SQream dashboard is displayed. + + + :: + + +4. In the menu on the left, click **Runtime Environments**. + + + The **Runtime Environments** panel is displayed. + + :: + +5. Click **Download Secure Agent**. + + :: + +6. When the **Download the Secure Agent** panel is displayed, do the following: + + 1. Select a platform (Windows 64 or Linux 64). + + :: + + + 2. Click **Copy** and save the token on your local hard drive. + + The token is used in combination with your user name to authorize the agent to access your account. + + +7. Click **Download**. + + The installation begins. + + :: + +8. When the **Informatica Cloud Secure Agent Setup** panel is displayed, click **Next**. + + + :: + + +9. Provide your **User Name** and **Install Token** and click **Register**. + + :: + + + +10. From the Runtime Environments panel, click **New Runtime Environment**. + + + The **New Secure Agent Group** window is displayed. + + :: + +11. On the New Secure Agent Group window, click **OK** to connect your Runtime Environment with the running agent. + + .. note:: If you do not download Secure Agent, you will not be able to connect your Runtime Environment with the running agent and continue establishing a connection between SQream and the Informatica data integration Cloud. + +Establishing a Connection In Your Environment +----------------- + +The **Establishing a Connection In Your Environment** describes the following: + +.. contents:: + :local: + +Establishing an ODBC DSN Connection In Your Environment +~~~~~~~~~~~~~ +After establishing a connection between SQream and Informatica you can establish an ODBC DSN connection in your environment. + +**To establish an ODBC connection in your environment:** + +1. Click **Add**. + + :: + +2. Click **Configure**. + + .. note:: Verify that **Use Server Picker** is selected. + +3. Click **Test**. + + :: + +4. Verify that the connection has tested successfully. + + :: + +5. Click **Save**. + + :: + +6. Click **Actions** > **Publish**. + +Establishing a JDBC Connection In Your Environment +~~~~~~~~~~~~~ +After establishing a connection between SQream and Informatica you can establish a JDBC connection in your environment. + +**To establish a JDBC connection in your environment:** + +1. Create a new DB connection by clicking **Connections** > **New Connection**. + + The **New Connection** window is displayed. + + :: + + +2. In the **JDBC_IC Connection Properties** section, in the **JDBC Connection URL** field, establish a JDBC connection by providing the correct connection string. + + For connection string examples, see `Connection Strings `_. + + :: + +3. Click **Test**. + + :: + +4. Verify that the connection has tested successfully. + + :: + +5. Click **Save**. + + :: + +6. Click **Actions** > **Publish**. + +Supported SQream Driver Versions +--------------- + +SQream supports the following SQream driver versions: + +* **JDBC** - Version 4.3.4 and above. + + :: + +* **ODBC** - Version 4.0.0 and above. From 5226e7e550f04ced57f2b10c5bb411595b29b5c3 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 24 Feb 2022 12:22:52 +0200 Subject: [PATCH 193/300] Update running_sqream_in_a_docker_container.rst --- .../running_sqream_in_a_docker_container.rst | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst index 35b96b3be..7f698ede4 100644 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ b/installation_guides/running_sqream_in_a_docker_container.rst @@ -27,7 +27,6 @@ SQream recommends installing a clean OS on the host to avoid any installation is .. warning:: Docker-based installation supports only single host deployment and cannot be used on a multi-node cluster. Installing Docker on a single host you will not be able to scale it to a multi-node cluster. - Creating a Local User ---------------- To run SQream in a Docker container you must create a local user. @@ -122,8 +121,6 @@ After installing the recommended tools you must update to the current version of SQream recommends updating to the current version of the operating system. This is not recommended if the nvidia driver has **not been installed.** - - Configuring the NTP Package ---------------- After updating to the current version of the operating system you must configure the NTP package. @@ -202,6 +199,7 @@ You can abort the above but-reporting tools by running the following command: Installing the Nvidia CUDA Driver ------------------------------------- +**To install the Nvidia CUDA driver:** 1. Verify that the Tesla NVIDIA card has been installed and is detected by the system: @@ -526,14 +524,10 @@ You can install the Docker Engine on an IBM Power9 processor by running the foll .. code-block:: console - $ wget - $ http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm - $ wget - $ http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm + $ wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm + $ wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm $ yum install -y container-selinux-2.9-4.el7.noarch.rpm $ docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - - For more information on installing the Docker Engine CE on an IBM Power9 processor, see `Install Docker Engine on Ubuntu `_. From 3a15ca54190414cc755542c516a1659b13d8b4a4 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 24 Feb 2022 15:54:41 +0200 Subject: [PATCH 194/300] Update sqream_storage.rst --- reference/cli/sqream_storage.rst | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/reference/cli/sqream_storage.rst b/reference/cli/sqream_storage.rst index 72f931b96..f47b04a87 100644 --- a/reference/cli/sqream_storage.rst +++ b/reference/cli/sqream_storage.rst @@ -3,20 +3,17 @@ ************************* SqreamStorage ************************* +You can use the **SqreamStorage** program to create a new :ref:`storage cluster`. -``SqreamStorage`` allows the creation of a new :ref:`storage cluster`. - -This page serves as a reference for the options and parameters. +The **SqreamStorage** page serves as a reference for the options and parameters. Running SqreamStorage ======================= +The **SqreamStorage** program is located in the **bin** directory of your SQream installation.. -``SqreamStorage`` can be found in the ``bin`` directory of your SQream DB installation.. - -Command line arguments +Command Line Arguments ========================== - -``SqreamStorage`` supports the following command line arguments: +The **SqreamStorage** program supports the following command line arguments: .. list-table:: :widths: auto @@ -32,20 +29,13 @@ Command line arguments - ``-r`` - Specifies the cluster path. The path must **not** already exist. - -Examples +Example ============= - -Create a new storage cluster ----------------------------------- - -Create a new cluster at ``/home/rhendricks/raviga_database``: +The **Examples** section describes how to create a new storage cluster at ``/home/rhendricks/raviga_database``: .. code-block:: console $ SqreamStorage --create-cluster --cluster-root /home/rhendricks/raviga_database Setting cluster version to: 26 -This can also be written shorthand as ``SqreamStorage -C -r /home/rhendricks/raviga_database``. - -This message confirms the creation of the cluster successfully. +Alternatively, you can write this in shorthand as ``SqreamStorage -C -r /home/rhendricks/raviga_database``. A message is displayed confirming that your cluster has been created. From df31b23ea82add01b6ae7009a14dccef8825c4e6 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 3 Mar 2022 13:49:18 +0200 Subject: [PATCH 195/300] Updated Menu Added Data Type Guides. Removed data type content from Reference Guides. --- .../converting_and_casting_types.rst | 26 + data_type_guides/index.rst | 14 + data_type_guides/sql_data_types_boolean.rst | 53 ++ data_type_guides/sql_data_types_date.rst | 112 ++++ .../sql_data_types_floating_point.rst | 80 +++ data_type_guides/sql_data_types_integer.rst | 83 +++ data_type_guides/sql_data_types_numeric.rst | 38 ++ data_type_guides/sql_data_types_string.rst | 92 +++ data_type_guides/supported_casts.rst | 17 + data_type_guides/supported_data_types.rst | 80 +++ index.rst | 3 +- reference/index.rst | 5 +- reference/sql_data_types.rst | 605 ------------------ 13 files changed, 599 insertions(+), 609 deletions(-) create mode 100644 data_type_guides/converting_and_casting_types.rst create mode 100644 data_type_guides/index.rst create mode 100644 data_type_guides/sql_data_types_boolean.rst create mode 100644 data_type_guides/sql_data_types_date.rst create mode 100644 data_type_guides/sql_data_types_floating_point.rst create mode 100644 data_type_guides/sql_data_types_integer.rst create mode 100644 data_type_guides/sql_data_types_numeric.rst create mode 100644 data_type_guides/sql_data_types_string.rst create mode 100644 data_type_guides/supported_casts.rst create mode 100644 data_type_guides/supported_data_types.rst delete mode 100644 reference/sql_data_types.rst diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst new file mode 100644 index 000000000..ee5e273da --- /dev/null +++ b/data_type_guides/converting_and_casting_types.rst @@ -0,0 +1,26 @@ +.. _converting_and_casting_types: + +************************* +Converting and Casting Types +************************* +SQream supports explicit and implicit casting and type conversion. The system may automatically add implicit casts when combining different data types in the same expression. In many cases, while the details related to this are not important, they can affect the query results of a query. When necessary, an explicit cast can be used to override the automatic cast added by SQream DB. + +For example, the ANSI standard defines a ``SUM()`` aggregation over an ``INT`` column as an ``INT``. However, when dealing with large amounts of data this could cause an overflow. + +You can rectify this by casting the value to a larger data type, as shown below: + +.. code-block:: postgres + + SUM(some_int_column :: BIGINT) + +SQream supports the following three data conversion types: + +* ``CAST( TO )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO VARCHAR(30))``. + + :: + +* `` :: ``, a shorthand for the ``CAST`` syntax. For example, ``'1997-01-01' :: DATE``, ``3.45 :: SMALLINT``, ``(3+5) :: BIGINT``. + + :: + +* See the :ref:`SQL functions reference ` for additional functions that convert from a specific value which is not an SQL type, such as :ref:`from_unixts`, etc. \ No newline at end of file diff --git a/data_type_guides/index.rst b/data_type_guides/index.rst new file mode 100644 index 000000000..6afec60cf --- /dev/null +++ b/data_type_guides/index.rst @@ -0,0 +1,14 @@ +.. _data_type_guides: + +************************* +Data Type Guides +************************* +This section describes the following: + +.. toctree:: + :maxdepth: 1 + :glob: + + converting_and_casting_types + supported_data_types + supported_casts \ No newline at end of file diff --git a/data_type_guides/sql_data_types_boolean.rst b/data_type_guides/sql_data_types_boolean.rst new file mode 100644 index 000000000..84b7c14ce --- /dev/null +++ b/data_type_guides/sql_data_types_boolean.rst @@ -0,0 +1,53 @@ +.. _sql_data_types_boolean: + +************************* +Boolean +************************* +The following table describes the Boolean data type. + +.. list-table:: + :widths: 30 30 30 + :header-rows: 1 + + * - Values + - Syntax + - Data Size (Not Null, Uncompressed) + * - ``true``, ``false`` (case sensitive) + - When loading from CSV, ``BOOL`` columns can accept ``0`` as ``false`` and ``1`` as ``true``. + - 1 byte, but resulting average data sizes may be lower after compression. + +Boolean Examples +^^^^^^^^^^ +The following is an example of the Boolean syntax: + +.. code-block:: postgres + + CREATE TABLE animals (name TEXT, is_angry BOOL); + + INSERT INTO animals VALUES ('fox',true), ('cat',true), ('kiwi',false); + + SELECT name, CASE WHEN is_angry THEN 'Is really angry!' else 'Is not angry' END FROM animals; + +The following is an example of the correct output: + +.. code-block:: text + + "fox","Is really angry!" + "cat","Is really angry!" + "kiwi","Is not angry" + +Boolean Casts and Conversions +^^^^^^^^^^^^^^^^^^^^^^^ + +The following table shows the possible Boolean value conversions: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Type + - Details + * - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT`` + - ``true`` → ``1``, ``false`` → ``0`` + * - ``REAL``, ``DOUBLE`` + - ``true`` → ``1.0``, ``false`` → ``0.0`` \ No newline at end of file diff --git a/data_type_guides/sql_data_types_date.rst b/data_type_guides/sql_data_types_date.rst new file mode 100644 index 000000000..da83f80cc --- /dev/null +++ b/data_type_guides/sql_data_types_date.rst @@ -0,0 +1,112 @@ +.. _sql_data_types_date: + +************************* +Date +************************* +``DATE`` is a type designed for storing year, month, and day. ``DATETIME`` is a type designed for storing year, month, day, hour, minute, seconds, and milliseconds in UTC with 1 millisecond precision. + + +Date Types +^^^^^^^^^^^^^^^^^^^^^^ +The following table describes the Date types: + +.. list-table:: Date Types + :widths: auto + :header-rows: 1 + + * - Name + - Details + - Data Size (Not Null, Uncompressed) + - Example + * - ``DATE`` + - Date + - 4 bytes + - ``'1955-11-05'`` + * - ``DATETIME`` + - Date and time pairing in UTC + - 8 bytes + - ``'1955-11-05 01:24:00.000'`` + +Aliases +^^^^^^^^^^ + +``DATETIME`` is also known as ``TIMESTAMP`` or ``DATETIME2``. + + +Syntax +^^^^^^^^ +``DATE`` values are formatted as string literals. + +The following is an example of the DATETIME syntax: + +.. code-block:: console + + '1955-11-05' + +.. code-block:: console + + date '1955-11-05' + +``DATETIME`` values are formatted as string literals conforming to `ISO 8601 `_. + +The following is an example of the DATETIME syntax: + + +.. code-block:: console + + '1955-11-05 01:26:00' + +SQream attempts to guess if the string literal is a date or datetime based on context, for example when used in date-specific functions. + +Size +^^^^^^ +A ``DATE`` column is 4 bytes in length, while a ``DATETIME`` column is 8 bytes in length. + +However, the size of these values is compressed by SQream DB. + +Date Examples +^^^^^^^^^^ +The following is an example of the Date syntax: + +.. code-block:: postgres + + CREATE TABLE important_dates (a DATE, b DATETIME); + + INSERT INTO important_dates VALUES ('1997-01-01', '1955-11-05 01:24'); + + SELECT * FROM important_dates; + +The following is an example of the correct output: + +.. code-block:: text + + 1997-01-01,1955-11-05 01:24:00.0 + +The following is an example of the Datetime syntax: + +.. code-block:: postgres + + SELECT a :: DATETIME, b :: DATE FROM important_dates; + +The following is an example of the correct output: + +.. code-block:: text + + 1997-01-01 00:00:00.0,1955-11-05 + + +.. warning:: Some client applications may alter the ``DATETIME`` value by modifying the timezone. + +Date Casts and Conversions +^^^^^^^^^^^^^^^^^^^^^^^ + +The following table shows the possible ``DATE`` and ``DATETIME`` value conversions: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Type + - Details + * - ``VARCHAR(n)`` + - ``'1997-01-01'`` → ``'1997-01-01'``, ``'1955-11-05 01:24'`` → ``'1955-11-05 01:24:00.000'`` \ No newline at end of file diff --git a/data_type_guides/sql_data_types_floating_point.rst b/data_type_guides/sql_data_types_floating_point.rst new file mode 100644 index 000000000..18227140c --- /dev/null +++ b/data_type_guides/sql_data_types_floating_point.rst @@ -0,0 +1,80 @@ +.. _sql_data_types_floating_point: + +************************* +Floating Point +************************* +The **Floating Point** data types (``REAL`` and ``DOUBLE``) store extremely close value approximations, and are therefore recommended for values that tend to be inexact, such as Scientific Notation. While Floating Point generally runs faster than Numeric, it has a lower precision of ``9`` (``REAL``) or ``17`` (``DOUBLE``) compared to Numeric's ``38``. For operations that require a higher level of precision, using :ref:`Numeric ` is recommended. + +The floating point representation is based on `IEEE 754 `_. + +Floating Point Types +^^^^^^^^^^^^^^^^^^^^^^ +The following table describes the Floating Point data types. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Name + - Details + - Data Size (Not Null, Uncompressed) + - Example + * - ``REAL`` + - Single precision floating point (inexact) + - 4 bytes + - ``3.141`` + * - ``DOUBLE`` + - Double precision floating point (inexact) + - 8 bytes + - ``0.000003`` + +The following table shows information relevant to the Floating Point data types. + +.. list-table:: + :widths: 30 30 30 + :header-rows: 1 + + * - Aliases + - Syntax + - Data Size (Not Null, Uncompressed) + * - ``DOUBLE`` is also known as ``FLOAT``. + - A double precision floating point can be entered as a regular literal, such as ``3.14``, ``2.718``, ``.34``, or ``2.71e-45``. To enter a ``REAL`` floating point number, cast the value. For example, ``(3.14 :: REAL)``. + - Floating point types are either 4 or 8 bytes, but size could be lower after compression. + +Floating Point Examples +^^^^^^^^^^ +The following are examples of the Floating Point syntax: + +.. code-block:: postgres + + CREATE TABLE cool_numbers (a REAL NOT NULL, b DOUBLE); + + INSERT INTO cool_numbers VALUES (1,2), (3.14159265358979, 2.718281828459); + + SELECT * FROM cool_numbers; + +.. code-block:: text + + 1.0,2.0 + 3.1415927,2.718281828459 + +.. note:: Most SQL clients control display precision of floating point numbers, and values may appear differently in some clients. + +Floating Point Casts and Conversions +^^^^^^^^^^^^^^^^^^^^^^^ +The following table shows the possible Floating Point value conversions: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Type + - Details + * - ``BOOL`` + - ``1.0`` → ``true``, ``0.0`` → ``false`` + * - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT`` + - ``2.0`` → ``2``, ``3.14159265358979`` → ``3``, ``2.718281828459`` → ``2``, ``0.5`` → ``0``, ``1.5`` → ``1`` + * - ``VARCHAR(n)`` (n > 6 recommended) + - ``1`` → ``'1.0000'``, ``3.14159265358979`` → ``'3.1416'`` + +.. note:: As shown in the above examples, casting ``real`` to ``int`` rounds down. \ No newline at end of file diff --git a/data_type_guides/sql_data_types_integer.rst b/data_type_guides/sql_data_types_integer.rst new file mode 100644 index 000000000..9d4210731 --- /dev/null +++ b/data_type_guides/sql_data_types_integer.rst @@ -0,0 +1,83 @@ +.. _sql_data_types_integer: + +************************* +Integer +************************* +Integer data types are designed to store whole numbers. + +For more information about identity sequences (sometimes called auto-increment or auto-numbers), see :ref:`identity`. + +Integer Types +^^^^^^^^^^^^^^^^^^^ +The following table describes the Integer types. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Name + - Details + - Data Size (Not Null, Uncompressed) + - Example + * - ``TINYINT`` + - Unsigned integer (0 - 255) + - 1 byte + - ``5`` + * - ``SMALLINT`` + - Integer (-32,768 - 32,767) + - 2 bytes + - ``-155`` + * - ``INT`` + - Integer (-2,147,483,648 - 2,147,483,647) + - 4 bytes + - ``1648813`` + * - ``BIGINT`` + - Integer (-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807) + - 8 bytes + - ``36124441255243`` + +The following table describes the Integer data type. + +.. list-table:: + :widths: 25 25 + :header-rows: 1 + + * - Syntax + - Data Size (Not Null, Uncompressed) + * - An integer can be entered as a regular literal, such as ``12``, ``-365``. + - Integer types range between 1, 2, 4, and 8 bytes - but resulting average data sizes could be lower after compression. + +Integer Examples +^^^^^^^^^^ +The following is an example of the Integer syntax: + +.. code-block:: postgres + + CREATE TABLE cool_numbers (a INT NOT NULL, b TINYINT, c SMALLINT, d BIGINT); + + INSERT INTO cool_numbers VALUES (1,2,3,4), (-5, 127, 32000, 45000000000); + + SELECT * FROM cool_numbers; + +The following is an example of the correct output: + +.. code-block:: text + + 1,2,3,4 + -5,127,32000,45000000000 + +Integer Casts and Conversions +^^^^^^^^^^^^^^^^^^^^^^^ + +The following table shows the possible Integer value conversions: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Type + - Details + * - ``REAL``, ``DOUBLE`` + - ``1`` → ``1.0``, ``-32`` → ``-32.0`` + * - ``VARCHAR(n)`` (All numberic values must fit in the string length) + - ``1`` → ``'1'``, ``2451`` → ``'2451'`` \ No newline at end of file diff --git a/data_type_guides/sql_data_types_numeric.rst b/data_type_guides/sql_data_types_numeric.rst new file mode 100644 index 000000000..8a78e19fa --- /dev/null +++ b/data_type_guides/sql_data_types_numeric.rst @@ -0,0 +1,38 @@ +.. _sql_data_types_numeric: + +************************* +Numeric +************************* +The **Numeric** data type (also known as **Decimal**) is recommended for values that tend to occur as exact decimals, such as in Finance. While Numeric has a fixed precision of ``38``, higher than ``REAL`` (``9``) or ``DOUBLE`` (``17``), it runs calculations more slowly. For operations that require faster performance, using :ref:`Floating Point ` is recommended. + +The correct syntax for Numeric is ``numeric(p, s)``), where ``p`` is the total number of digits (``38`` maximum), and ``s`` is the total number of decimal digits. + +Numeric Examples +^^^^^^^^^^ + +The following is an example of the Numeric syntax: + +.. code-block:: postgres + + $ create or replace table t(x numeric(20, 10), y numeric(38, 38)); + $ insert into t values(1234567890.1234567890, 0.123245678901234567890123456789012345678); + $ select x + y from t; + +The following table shows information relevant to the Numeric data type: + +.. list-table:: + :widths: 30 30 30 + :header-rows: 1 + + * - Description + - Data Size (Not Null, Uncompressed) + - Example + * - 38 digits + - 16 bytes + - ``0.123245678901234567890123456789012345678`` + +Numeric supports the following operations: + + * All join types. + * All aggregation types (not including Window functions). + * Scalar functions (not including some trigonometric and logarithmic functions). \ No newline at end of file diff --git a/data_type_guides/sql_data_types_string.rst b/data_type_guides/sql_data_types_string.rst new file mode 100644 index 000000000..beb970b8d --- /dev/null +++ b/data_type_guides/sql_data_types_string.rst @@ -0,0 +1,92 @@ +.. _sql_data_types_string: + +************************* +String +************************* +``TEXT`` and ``VARCHAR`` are types designed for storing text or strings of characters. + +SQream separates ASCII (``VARCHAR``) and UTF-8 representations (``TEXT``). + +.. note:: The data type ``NVARCHAR`` has been deprecated by ``TEXT`` as of version 2020.1. + +String Types +^^^^^^^^^^^^^^^^^^^^^^ +The following table describes the String types: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Name + - Details + - Data Size (Not Null, Uncompressed) + - Example + * - ``TEXT [(n)]``, ``NVARCHAR (n)`` + - Varaiable length string - UTF-8 unicode. ``NVARCHAR`` is synonymous with ``TEXT``. + - Up to ``4*n`` bytes + - ``'キウイは楽しい鳥です'`` + * - ``VARCHAR (n)`` + - Variable length string - ASCII only + - ``n`` bytes + - ``'Kiwis have tiny wings, but cannot fly.'`` + +Length +^^^^^^^^^ +When using ``TEXT``, specifying a size is optional. If not specified, the text field carries no constraints. To limit the size of the input, use ``VARCHAR(n)`` or ``TEXT(n)``, where ``n`` is the permitted number of characters. + +The following apply to setting the String type length: + +* If the data exceeds the column length limit on ``INSERT`` or ``COPY`` operations, SQream DB will return an error. +* When casting or converting, the string has to fit in the target. For example, ``'Kiwis are weird birds' :: VARCHAR(5)`` will return an error. Use ``SUBSTRING`` to truncate the length of the string. +* ``VARCHAR`` strings are padded with spaces. + +Syntax +^^^^^^^^ +String types can be written with standard SQL string literals, which are enclosed with single quotes, such as +``'Kiwi bird'``. To include a single quote in the string, use double quotations, such as ``'Kiwi bird''s wings are tiny'``. String literals can also be dollar-quoted with the dollar sign ``$``, such as ``$$Kiwi bird's wings are tiny$$`` is the same as ``'Kiwi bird''s wings are tiny'``. + +Size +^^^^^^ +``VARCHAR(n)`` can occupy up to *n* bytes, whereas ``TEXT(n)`` can occupy up to *4*n* bytes. However, the size of strings is variable and is compressed by SQream. + +String Examples +^^^^^^^^^^ +The following is an example of the String syntax: + +.. code-block:: postgres + + CREATE TABLE cool_strings (a TEXT NOT NULL, b TEXT); + + INSERT INTO cool_strings VALUES ('hello world', 'Hello to kiwi birds specifically'); + + INSERT INTO cool_strings VALUES ('This is ASCII only', 'But this column can contain 中文文字'); + + SELECT * FROM cool_strings; + +The following is an example of the correct output: + +.. code-block:: text + + hello world ,Hello to kiwi birds specifically + This is ASCII only,But this column can contain 中文文字 + +.. note:: Most clients control the display precision of floating point numbers, and values may appear differently in some clients. + +String Casts and Conversions +^^^^^^^^^^^^^^^^^^^^^^^ +The following table shows the possible String value conversions: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Type + - Details + * - ``BOOL`` + - ``'true'`` → ``true``, ``'false'`` → ``false`` + * - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT`` + - ``'2'`` → ``2``, ``'-128'`` → ``-128`` + * - ``REAL``, ``DOUBLE`` + - ``'2.0'`` → ``2.0``, ``'3.141592'`` → ``3.141592`` + * - ``DATE``, ``DATETIME`` + - Requires a supported format, such as ``'1955-11-05`` → ``date '1955-11-05'``, ``'1955-11-05 01:24:00.000'`` → ``'1955-11-05 01:24:00.000'`` \ No newline at end of file diff --git a/data_type_guides/supported_casts.rst b/data_type_guides/supported_casts.rst new file mode 100644 index 000000000..34053b647 --- /dev/null +++ b/data_type_guides/supported_casts.rst @@ -0,0 +1,17 @@ +.. _supported_casts: + +************************* +Supported Casts +************************* +The **Supported Casts** section describes supported casts for the following types: + +.. toctree:: + :maxdepth: 1 + :glob: + + sql_data_types_numeric + sql_data_types_boolean + sql_data_types_integer + sql_data_types_floating_point + sql_data_types_string + sql_data_types_date \ No newline at end of file diff --git a/data_type_guides/supported_data_types.rst b/data_type_guides/supported_data_types.rst new file mode 100644 index 000000000..2743b054b --- /dev/null +++ b/data_type_guides/supported_data_types.rst @@ -0,0 +1,80 @@ +.. _supported_data_types: + +************************* +Supported Data Types +************************* +The **Supported Data Types** page describes SQream's supported data types: + +The following table shows the supported data types. + +.. list-table:: + :widths: 20 15 20 30 20 + :header-rows: 1 + + * - Name + - Description + - Data Size (Not Null, Uncompressed) + - Example + - Alias + * - ``BOOL`` + - Boolean values (``true``, ``false``) + - 1 byte + - ``true`` + - ``BIT`` + * - ``TINYINT`` + - Unsigned integer (0 - 255) + - 1 byte + - ``5`` + - NA + * - ``SMALLINT`` + - Integer (-32,768 - 32,767) + - 2 bytes + - ``-155`` + - NA + * - ``INT`` + - Integer (-2,147,483,648 - 2,147,483,647) + - 4 bytes + - ``1648813`` + - ``INTEGER`` + * - ``BIGINT`` + - Integer (-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807) + - 8 bytes + - ``36124441255243`` + - ``NUMBER`` + * - ``REAL`` + - Floating point (inexact) + - 4 bytes + - ``3.141`` + - NA + * - ``DOUBLE`` + - Floating point (inexact) + - 8 bytes + - ``0.000003`` + - ``FLOAT``/``DOUBLE PRECISION`` + * - ``TEXT [(n)]``, ``NVARCHAR (n)`` + - Variable length string - UTF-8 unicode + - Up to ``4*n`` bytes + - ``'キウイは楽しい鳥です'`` + - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR``, ``NVARCHAR`` + * - ``NUMERIC`` + - 38 digits + - 16 bytes + - ``0.123245678901234567890123456789012345678`` + - ``DECIMAL`` + * - ``VARCHAR (n)`` + - Variable length string - ASCII only + - ``n`` bytes + - ``'Kiwis have tiny wings, but cannot fly.'`` + - ``SQL VARIANT`` + * - ``DATE`` + - Date + - 4 bytes + - ``'1955-11-05'`` + - NA + * - ``DATETIME`` + - Date and time pairing in UTC + - 8 bytes + - ``'1955-11-05 01:24:00.000'`` + - ``TIMESTAMP``, ``DATETIME2`` + +.. note:: SQream compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. \ No newline at end of file diff --git a/index.rst b/index.rst index 66fc31a1a..1e69cc36e 100644 --- a/index.rst +++ b/index.rst @@ -98,7 +98,7 @@ If you're looking for an older version of the documentation, versions 1.10 throu getting_started/index installation_guides/index - data_ingestion_guides/index + data_ingestion/index third_party_tools/index feature_guides/index operational_guides/index @@ -106,6 +106,7 @@ If you're looking for an older version of the documentation, versions 1.10 throu architecture/index configuration_guides/index reference/index + data_type_guides/index releases/index troubleshooting/index glossary diff --git a/reference/index.rst b/reference/index.rst index 9360f33c5..f1a4a600e 100644 --- a/reference/index.rst +++ b/reference/index.rst @@ -1,17 +1,16 @@ .. _reference: ************************* -Reference +Reference Guides ************************* -This section provides reference for using SQream DB's interfaces and SQL features. +The **Reference Guides** section provides reference for using SQream DB's interfaces and SQL features. .. toctree:: :maxdepth: 5 :caption: In this section: :glob: - sql_data_types sql/index catalog_reference cli/index diff --git a/reference/sql_data_types.rst b/reference/sql_data_types.rst deleted file mode 100644 index 4e438a3a2..000000000 --- a/reference/sql_data_types.rst +++ /dev/null @@ -1,605 +0,0 @@ -.. _data_types: - -************************* -Data Types -************************* - -This topic describes the data types that SQream supports, and how to convert between them. - -This page describes the following: - -.. contents:: - :local: - :depth: 2 - -Supported Types -================= - -The following table shows the supported data types. - -.. list-table:: - :widths: 20 15 20 30 20 - :header-rows: 1 - - * - Name - - Description - - Data Size (Not Null, Uncompressed) - - Example - - Alias - * - ``BOOL`` - - Boolean values (``true``, ``false``) - - 1 byte - - ``true`` - - ``BIT`` - * - ``TINYINT`` - - Unsigned integer (0 - 255) - - 1 byte - - ``5`` - - NA - * - ``SMALLINT`` - - Integer (-32,768 - 32,767) - - 2 bytes - - ``-155`` - - NA - * - ``INT`` - - Integer (-2,147,483,648 - 2,147,483,647) - - 4 bytes - - ``1648813`` - - ``INTEGER`` - * - ``BIGINT`` - - Integer (-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807) - - 8 bytes - - ``36124441255243`` - - ``NUMBER`` - * - ``REAL`` - - Floating point (inexact) - - 4 bytes - - ``3.141`` - - NA - * - ``DOUBLE`` - - Floating point (inexact) - - 8 bytes - - ``0.000003`` - - ``FLOAT``/``DOUBLE PRECISION`` - * - ``TEXT [(n)]``, ``NVARCHAR (n)`` - - Variable length string - UTF-8 unicode - - Up to ``4*n`` bytes - - ``'キウイは楽しい鳥です'`` - * - ``NUMERIC`` - - 38 digits - - 16 bytes - - ``0.123245678901234567890123456789012345678`` - - ``DECIMAL`` - * - ``VARCHAR (n)`` - - Variable length string - ASCII only - - ``n`` bytes - - ``'Kiwis have tiny wings, but cannot fly.'`` - - ``SQL VARIANT`` - * - ``DATE`` - - Date - - 4 bytes - - ``'1955-11-05'`` - - NA - * - ``DATETIME`` - - Date and time pairing in UTC - - 8 bytes - - ``'1955-11-05 01:24:00.000'`` - - ``TIMESTAMP``, ``DATETIME2`` - -.. note:: SQream compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. - -.. _cast: - -Converting and Casting Types -============================== -SQream supports explicit and implicit casting and type conversion. The system may automatically add implicit casts when combining different data types in the same expression. In many cases, while the details related to this are not important, they can affect the query results of a query. When necessary, an explicit cast can be used to override the automatic cast added by SQream DB. - -For example, the ANSI standard defines a ``SUM()`` aggregation over an ``INT`` column as an ``INT``. However, when dealing with large amounts of data this could cause an overflow. - -You can rectify this by casting the value to a larger data type, as shown below: - -.. code-block:: postgres - - SUM(some_int_column :: BIGINT) - -SQream DB supports the following three data conversion types: - -* ``CAST( AS )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' AS DATE)``, ``CAST(3.45 AS SMALLINT)``, ``CAST(some_column AS VARCHAR(30))``. - -* `` :: ``, a shorthand for the ``CAST`` syntax. For example, ``'1997-01-01' :: DATE``, ``3.45 :: SMALLINT``, ``(3+5) :: BIGINT``. - - :: - -* See the :ref:`SQL functions reference ` for additional functions that convert from a specific value which is not an SQL type, such as :ref:`from_unixts`, etc. - -The **Data Type Reference** section below provides more details about the supported casts for each type. - -Data Type Reference -====================== - -.. _numeric: - - -Numeric - -The **Numeric** data type (also known as **Decimal**) is recommended for values that tend to occur as exact decimals, such as in Finance. While Numeric has a fixed precision of ``38``, higher than ``REAL`` (``9``) or ``DOUBLE`` (``17``), it runs calculations more slowly. For operations that require faster performance, using :ref:`Floating Point ` is recommended. - -The correct syntax for Numeric is ``numeric(p, s)``), where ``p`` is the total number of digits (``38`` maximum), and ``s`` is the total number of decimal digits. - -Numeric Examples -^^^^^^^^^^ - -The following is an example of the Numeric syntax: - -.. code-block:: postgres - - $ create or replace table t(x numeric(20, 10), y numeric(38, 38)); - $ insert into t values(1234567890.1234567890, 0.123245678901234567890123456789012345678); - $ select x + y from t; - -The following table shows information relevant to the Numeric data type: - - -.. list-table:: - :widths: 30 30 30 - :header-rows: 1 - - * - Description - - Data Size (Not Null, Uncompressed) - - Example - * - 38 digits - - 16 bytes - - ``0.123245678901234567890123456789012345678`` - -Numeric supports the following operations: - - * All join types. - * All aggregation types (not including Window functions). - * Scalar functions (not including some trigonometric and logarithmic functions). - - - - -Boolean -------------------- -The following table describes the Boolean data type. - -.. list-table:: - :widths: 30 30 30 - :header-rows: 1 - - * - Values - - Syntax - - Data Size (Not Null, Uncompressed) - * - ``true``, ``false`` (case sensitive) - - When loading from CSV, ``BOOL`` columns can accept ``0`` as ``false`` and ``1`` as ``true``. - - 1 byte, but resulting average data sizes may be lower after compression. - -Boolean Examples -^^^^^^^^^^ -The following is an example of the Boolean syntax: - -The following is an example of the Boolean syntax: - -.. code-block:: postgres - - CREATE TABLE animals (name TEXT, is_angry BOOL); - - INSERT INTO animals VALUES ('fox',true), ('cat',true), ('kiwi',false); - - SELECT name, CASE WHEN is_angry THEN 'Is really angry!' else 'Is not angry' END FROM animals; - -The following is an example of the correct output: - -.. code-block:: text - - "fox","Is really angry!" - "cat","Is really angry!" - "kiwi","Is not angry" - -Boolean Casts and Conversions -^^^^^^^^^^^^^^^^^^^^^^^ - -The following table shows the possible Boolean value conversions: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Type - - Details - * - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT`` - - ``true`` → ``1``, ``false`` → ``0`` - * - ``REAL``, ``DOUBLE`` - - ``true`` → ``1.0``, ``false`` → ``0.0`` - -Integers ------------------------------------------------------------- -Integer data types are designed to store whole numbers. - -For more information about identity sequences (sometimes called auto-increment or auto-numbers), see :ref:`identity`. - -Integer Types -^^^^^^^^^^^^^^^^^^^ -The following table describes the Integer types. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Name - - Details - - Data Size (Not Null, Uncompressed) - - Example - * - ``TINYINT`` - - Unsigned integer (0 - 255) - - 1 byte - - ``5`` - * - ``SMALLINT`` - - Integer (-32,768 - 32,767) - - 2 bytes - - ``-155`` - * - ``INT`` - - Integer (-2,147,483,648 - 2,147,483,647) - - 4 bytes - - ``1648813`` - * - ``BIGINT`` - - Integer (-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807) - - 8 bytes - - ``36124441255243`` - -The following table describes the Integer data type. - -.. list-table:: - :widths: 25 25 - :header-rows: 1 - - * - Syntax - - Data Size (Not Null, Uncompressed) - * - An integer can be entered as a regular literal, such as ``12``, ``-365``. - - Integer types range between 1, 2, 4, and 8 bytes - but resulting average data sizes could be lower after compression. - -Integer Examples -^^^^^^^^^^ -The following is an example of the Integer syntax: - -.. code-block:: postgres - - CREATE TABLE cool_numbers (a INT NOT NULL, b TINYINT, c SMALLINT, d BIGINT); - - INSERT INTO cool_numbers VALUES (1,2,3,4), (-5, 127, 32000, 45000000000); - - SELECT * FROM cool_numbers; - -The following is an example of the correct output: - -.. code-block:: text - - 1,2,3,4 - -5,127,32000,45000000000 - -Integer Casts and Conversions -^^^^^^^^^^^^^^^^^^^^^^^ - -The following table shows the possible Integer value conversions: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Type - - Details - * - ``REAL``, ``DOUBLE`` - - ``1`` → ``1.0``, ``-32`` → ``-32.0`` - * - ``VARCHAR(n)`` (All numberic values must fit in the string length) - - ``1`` → ``'1'``, ``2451`` → ``'2451'`` - -.. _floating_point: - - -Floating Point ------------------------------------------------- -The **Floating Point** data types (``REAL`` and ``DOUBLE``) store extremely close value approximations, and are therefore recommended for values that tend to be inexact, such as Scientific Notation. While Floating Point generally runs faster than Numeric, it has a lower precision of ``9`` (``REAL``) or ``17`` (``DOUBLE``) compared to Numeric's ``38``. For operations that require a higher level of precision, using :ref:`Numeric ` is recommended. - -The floating point representation is based on `IEEE 754 `_. - -Floating Point Types -^^^^^^^^^^^^^^^^^^^^^^ -The following table describes the Floating Point data types. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Name - - Details - - Data Size (Not Null, Uncompressed) - - Example - * - ``REAL`` - - Single precision floating point (inexact) - - 4 bytes - - ``3.141`` - * - ``DOUBLE`` - - Double precision floating point (inexact) - - 8 bytes - - ``0.000003`` - -The following table shows information relevant to the Floating Point data types. - -.. list-table:: - :widths: 30 30 30 - :header-rows: 1 - - * - Aliases - - Syntax - - Data Size (Not Null, Uncompressed) - * - ``DOUBLE`` is also known as ``FLOAT``. - - A double precision floating point can be entered as a regular literal, such as ``3.14``, ``2.718``, ``.34``, or ``2.71e-45``. To enter a ``REAL`` floating point number, cast the value. For example, ``(3.14 :: REAL)``. - - Floating point types are either 4 or 8 bytes, but size could be lower after compression. - -Floating Point Examples -^^^^^^^^^^ -The following are examples of the Floating Point syntax: - -.. code-block:: postgres - - CREATE TABLE cool_numbers (a REAL NOT NULL, b DOUBLE); - - INSERT INTO cool_numbers VALUES (1,2), (3.14159265358979, 2.718281828459); - - SELECT * FROM cool_numbers; - -.. code-block:: text - - 1.0,2.0 - 3.1415927,2.718281828459 - -.. note:: Most SQL clients control display precision of floating point numbers, and values may appear differently in some clients. - -Floating Point Casts and Conversions -^^^^^^^^^^^^^^^^^^^^^^^ -The following table shows the possible Floating Point value conversions: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Type - - Details - * - ``BOOL`` - - ``1.0`` → ``true``, ``0.0`` → ``false`` - * - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT`` - - ``2.0`` → ``2``, ``3.14159265358979`` → ``3``, ``2.718281828459`` → ``2``, ``0.5`` → ``0``, ``1.5`` → ``1`` - * - ``VARCHAR(n)`` (n > 6 recommended) - - ``1`` → ``'1.0000'``, ``3.14159265358979`` → ``'3.1416'`` - -.. note:: As shown in the above examples, casting ``real`` to ``int`` rounds down. - - -String ---------- -``TEXT`` and ``VARCHAR`` are types designed for storing text or strings of characters. - - -SQream separates ASCII (``VARCHAR``) and UTF-8 representations (``TEXT``). - -.. note:: The data type ``NVARCHAR`` has been deprecated by ``TEXT`` as of version 2020.1. - -String Types -^^^^^^^^^^^^^^^^^^^^^^ - -The following table describes the String types: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Name - - Details - - Data Size (Not Null, Uncompressed) - - Example - * - ``TEXT [(n)]``, ``NVARCHAR (n)`` - - Varaiable length string - UTF-8 unicode. ``NVARCHAR`` is synonymous with ``TEXT``. - - Up to ``4*n`` bytes - - ``'キウイは楽しい鳥です'`` - * - ``VARCHAR (n)`` - - Variable length string - ASCII only - - ``n`` bytes - - ``'Kiwis have tiny wings, but cannot fly.'`` - -Length -^^^^^^^^^ -When using ``TEXT``, specifying a size is optional. If not specified, the text field carries no constraints. To limit the size of the input, use ``VARCHAR(n)`` or ``TEXT(n)``, where ``n`` is the permitted number of characters. - - -The following apply to setting the String type length: - - -* If the data exceeds the column length limit on ``INSERT`` or ``COPY`` operations, SQream DB will return an error. -* When casting or converting, the string has to fit in the target. For example, ``'Kiwis are weird birds' :: VARCHAR(5)`` will return an error. Use ``SUBSTRING`` to truncate the length of the string. -* ``VARCHAR`` strings are padded with spaces. - -Syntax -^^^^^^^^ -String types can be written with standard SQL string literals, which are enclosed with single quotes, such as - -``'Kiwi bird'``. - -To include a single quote in the string, use double quotations, such as ``'Kiwi bird''s wings are tiny'``. - -String literals can also be dollar-quoted with the dollar sign ``$``, such as ``$$Kiwi bird's wings are tiny$$`` is the same as ``'Kiwi bird''s wings are tiny'``. - - - -Size -^^^^^^ -``VARCHAR(n)`` can occupy up to *n* bytes, whereas ``TEXT(n)`` can occupy up to *4*n* bytes. However, the size of strings is variable and is compressed by SQream. - - -String Examples -^^^^^^^^^^ -The following is an example of the String syntax: - -.. code-block:: postgres - - CREATE TABLE cool_strings (a TEXT NOT NULL, b TEXT); - - INSERT INTO cool_strings VALUES ('hello world', 'Hello to kiwi birds specifically'); - - INSERT INTO cool_strings VALUES ('This is ASCII only', 'But this column can contain 中文文字'); - - SELECT * FROM cool_strings; - -The following is an example of the correct output: - -.. code-block:: text - - hello world ,Hello to kiwi birds specifically - This is ASCII only,But this column can contain 中文文字 - -.. note:: Most clients control the display precision of floating point numbers, and values may appear differently in some clients. - -String Casts and Conversions -^^^^^^^^^^^^^^^^^^^^^^^ -The following table shows the possible String value conversions: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Type - - Details - * - ``BOOL`` - - ``'true'`` → ``true``, ``'false'`` → ``false`` - * - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT`` - - ``'2'`` → ``2``, ``'-128'`` → ``-128`` - * - ``REAL``, ``DOUBLE`` - - ``'2.0'`` → ``2.0``, ``'3.141592'`` → ``3.141592`` - * - ``DATE``, ``DATETIME`` - - Requires a supported format, such as ``'1955-11-05`` → ``date '1955-11-05'``, ``'1955-11-05 01:24:00.000'`` → ``'1955-11-05 01:24:00.000'`` - - - -Date (``DATE``, ``DATETIME``) ------------------------------------------------- -``DATE`` is a type designed for storing year, month, and day. - -``DATETIME`` is a type designed for storing year, month, day, hour, minute, seconds, and milliseconds in UTC with 1 millisecond precision. - - -Date Types -^^^^^^^^^^^^^^^^^^^^^^ -The following table describes the Date types. - -.. list-table:: Date types - -Date ------------------------------------------------- -``DATE`` is a type designed for storing year, month, and day. ``DATETIME`` is a type designed for storing year, month, day, hour, minute, seconds, and milliseconds in UTC with 1 millisecond precision. - - -Date Types -^^^^^^^^^^^^^^^^^^^^^^ -The following table describes the Date types: - -.. list-table:: Date Types - :widths: auto - :header-rows: 1 - - * - Name - - Details - - Data Size (Not Null, Uncompressed) - - Example - * - ``DATE`` - - Date - - 4 bytes - - ``'1955-11-05'`` - * - ``DATETIME`` - - Date and time pairing in UTC - - 8 bytes - - ``'1955-11-05 01:24:00.000'`` - -Aliases -^^^^^^^^^^ - -``DATETIME`` is also known as ``TIMESTAMP`` or ``DATETIME2``. - - -Syntax -^^^^^^^^ -``DATE`` values are formatted as string literals. - -The following is an example of the DATETIME syntax: - -.. code-block:: console - - '1955-11-05' - -.. code-block:: console - - date '1955-11-05' - -``DATETIME`` values are formatted as string literals conforming to `ISO 8601 `_. - -The following is an example of the DATETIME syntax: - - - -.. code-block:: console - - '1955-11-05 01:26:00' - -SQream attempts to guess if the string literal is a date or datetime based on context, for example when used in date-specific functions. - -Size -^^^^^^ -A ``DATE`` column is 4 bytes in length, while a ``DATETIME`` column is 8 bytes in length. - -However, the size of these values is compressed by SQream DB. - -Date Examples -^^^^^^^^^^ -The following is an example of the Date syntax: - -.. code-block:: postgres - - CREATE TABLE important_dates (a DATE, b DATETIME); - - INSERT INTO important_dates VALUES ('1997-01-01', '1955-11-05 01:24'); - - SELECT * FROM important_dates; - -The following is an example of the correct output: - -.. code-block:: text - - 1997-01-01,1955-11-05 01:24:00.0 - -The following is an example of the Datetime syntax: - -.. code-block:: postgres - - SELECT a :: DATETIME, b :: DATE FROM important_dates; - -The following is an example of the correct output: - -.. code-block:: text - - 1997-01-01 00:00:00.0,1955-11-05 - - -.. warning:: Some client applications may alter the ``DATETIME`` value by modifying the timezone. - -Date Casts and Conversions -^^^^^^^^^^^^^^^^^^^^^^^ - -The following table shows the possible ``DATE`` and ``DATETIME`` value conversions: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Type - - Details - * - ``VARCHAR(n)`` - - ``'1997-01-01'`` → ``'1997-01-01'``, ``'1955-11-05 01:24'`` → ``'1955-11-05 01:24:00.000'`` From 928130c9529786af9f4c5a6da79fd927a0fc8540 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 3 Mar 2022 17:10:32 +0200 Subject: [PATCH 196/300] Update index.rst --- installation_guides/index.rst | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/installation_guides/index.rst b/installation_guides/index.rst index d77e357be..47f89c219 100644 --- a/installation_guides/index.rst +++ b/installation_guides/index.rst @@ -3,21 +3,13 @@ ************************* Installation Guides ************************* +Before you get started using SQream, consider your business needs and available resources. SQream was designed to run in a number of environments, and to be installed using different methods depending on your requirements. This determines which installation method to use. -The **Installation Guides** page incudes the following installation guides: +The **Installation Guides** section describes the following installation guide sets: .. toctree:: :maxdepth: 1 :glob: - sqream_studio_installation installing_and_launching_sqream - xxrecommended_pre-installation_configurations - xxrunning_sqream_in_a_docker_container - xxinstalling_sqream_with_binary - xxinstalling_monit - xxinstalling_sqream_with_kubernetes - xxinstalling_prometheus_exporters - xxinstalling_studio_on_stand_alone_server - - + sqream_studio_installation \ No newline at end of file From e97bf342549617d5acbf00aacb8fcdfaea93aa71 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 8 Mar 2022 17:28:48 +0200 Subject: [PATCH 197/300] Added Avro Added Avro and Data Ingestion Guides --- data_ingestion_guides/avro.rst | 344 ++++++++++++++++++++++++++++++++ data_ingestion_guides/index.rst | 7 +- 2 files changed, 348 insertions(+), 3 deletions(-) create mode 100644 data_ingestion_guides/avro.rst diff --git a/data_ingestion_guides/avro.rst b/data_ingestion_guides/avro.rst new file mode 100644 index 000000000..14bbbc38f --- /dev/null +++ b/data_ingestion_guides/avro.rst @@ -0,0 +1,344 @@ +.. _avro: + +************************** +Inserting Data from Avro +************************** +The **Inserting Data from Avro** page describes inserting data from Avro into SQream and includes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +=========== +**Avro** is a well-known data serialization system that relies on schemas. Due to its flexibility and nesting as an efficient data storage method, SQream supports the Avro binary data format as an alternative to JSON. + +Avro Data Types +=========== + +Avro includes the following data types: + +.. contents:: + :local: + :depth: 1 + +Primitive Data Types +-------------- +The following table shows the supported **Primitive** data types: + ++-------------+-------------------------------------------+ +| Avro Type | SQream Type | +| +--------+---------------+--------+---------+ +| | Number | Date/Datetime | String | Boolean | ++=============+========+===============+========+=========+ +| ``null`` | ✓ | ✓ | ✓ | ✓ | ++-------------+--------+---------------+--------+---------+ +| ``boolean`` | | | ✓ | ✓ | ++-------------+--------+---------------+--------+---------+ +| ``int`` | ✓ | | ✓ | | ++-------------+--------+---------------+--------+---------+ +| ``long`` | ✓ | | ✓ | | ++-------------+--------+---------------+--------+---------+ +| ``float`` | ✓ | | ✓ | | ++-------------+--------+---------------+--------+---------+ +| ``double`` | ✓ | | ✓ | | ++-------------+--------+---------------+--------+---------+ +| ``bytes`` | | | | | ++-------------+--------+---------------+--------+---------+ +| ``string`` | | ✓ | ✓ | | ++-------------+--------+---------------+--------+---------+ + + + + + + +Complex Data Types +-------------- +The following table shows the supported **Complex** data types: + ++------------+-------------------------------------------+ +| | SQream Type | +| +--------+---------------+--------+---------+ +|Avro Type | Number | Date/Datetime | String | Boolean | ++============+========+===============+========+=========+ +| ``record`` | | | | | ++------------+--------+---------------+--------+---------+ +| ``enum`` | | | ✓ | | ++------------+--------+---------------+--------+---------+ +| ``array`` | | | | | ++------------+--------+---------------+--------+---------+ +| ``map`` | | | | | ++------------+--------+---------------+--------+---------+ +| ``union`` | ✓ | ✓ | ✓ | ✓ | ++------------+--------+---------------+--------+---------+ +| ``fixed`` | | | | | ++------------+--------+---------------+--------+---------+ + + +Logical Data Types +-------------- +The following table shows the supported **Logical** data types: + ++----------------------------+-------------------------------------------+ +| Avro Type | SQream Type | +| +--------+---------------+--------+---------+ +| | Number | Date/Datetime | String | Boolean | ++============================+========+===============+========+=========+ +| ``decimal`` | ✓ | | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``uuid`` | | | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``date`` | | ✓ | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``time-millis`` | | | | | ++----------------------------+--------+---------------+--------+---------+ +| ``time-micros`` | | | | | ++----------------------------+--------+---------------+--------+---------+ +| ``timestamp-millis`` | | ✓ | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``timestamp-micros`` | | ✓ | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``local-timestamp-millis`` | | | | | ++----------------------------+--------+---------------+--------+---------+ +| ``local-timestamp-micros`` | | | | | ++----------------------------+--------+---------------+--------+---------+ +| ``duration`` | | | | | ++----------------------------+--------+---------------+--------+---------+ + + +Mapping Objects to Rows +=============== +When mapping objects to rows, each Avro object or message must contain one ``record`` type object corresponding to a single row in SQream. The ``record`` fields are associated by name to their target table columns. + +Additional unmapped fields will be ignored. Note that using the JSONPath option overrides this. + +Ingesting Avro Files +==================== +This section describes how to ingest Avro files into SQream and covers the following: + + +.. contents:: + :local: + :depth: 1 + + +Preparing Your Avro Source File +---------- +Prepare your Avro source files according to the following requirements: + +* RFC 4180 standard CSV files, but can also be modified to support non-standard CSVs (with multi-character delimiters, unquoted fields, etc). + + :: + +* Files are encoded with UTF-8 or ASCII. + + :: + +* Field delimiter is an ASCII character or characters. + + :: + +* Record delimiter, also known as a new line separator, is a Unix-style newline (``\n``), DOS-style newline (``\r\n``), or Mac style newline (``\r``). + + :: + +* If a field is quoted, any double quote that appears must be double-quoted (similar to the :ref:`string literals quoting rules`. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. + + :: + +* Fields can be enclosed by double-quotes (optional), or mandatory quotes if they contain one of the following characters: + + * The record delimiter or field delimiter. + + :: + + * A double quote character. + + :: + + * A newline. + +SQream does not support other modes of escaping, such as ``1,"What are \"birds\"?"``. + +``NULL`` values can be marked in the following ways in Avro files: + + * An explicit null marker. For example, ``col1,\N,col3``. + + :: + + * An empty field delimited by the field delimiter. For example, ``col1,,col3``. + + .. note:: If a text field is quoted but contains no content (``""``) it is considered an empty text field and not ``NULL``. + +For more information about standard CSV files, see `RFC 4180 standard CSVs `_. + +Making Avro Files Accessible to Workers +--------------------- +To give workers access to files every node must have the same view of the storage being used. + +The following apply for Avro files to be accessible to workers: + +* For files hosted on NFS, ensure that the mount is accessible from all servers. + +* For HDFS, ensure that SQream servers have access to the HDFS name node with the correct **user-id**. For more information, see :ref:`hdfs`. + +* For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. + +For more information about restricted worker access, see :ref:`workload_manager`. + +Basing Your Table Structure on Inserted Tables +--------------------- +Before loading data, you must build the ``CREATE EXTERNAL TABLE`` to correspond with the file structure of the inserted table. + +The example in this section is based on the source ``nba.parquet`` table shown below: + +.. csv-table:: nba.parquet + :file: nba-t10.csv + :widths: auto + :header-rows: 1 + +The following example shows the correct file structure used to create the ``CREATE EXTERNAL TABLE`` statement based on the **nba.parquet** table: + +.. code-block:: postgres + + CREATE FOREIGN TABLE ext_nba + ( + Name VARCHAR(40), + Team VARCHAR(40), + Number BIGINT, + Position VARCHAR(2), + Age BIGINT, + Height VARCHAR(4), + Weight BIGINT, + College VARCHAR(40), + Salary FLOAT + ) + WRAPPER parquet_fdw + OPTIONS + ( + LOCATION = 's3://sqream-demo-data/nba.parquet' + ); + +.. tip:: + + An exact match must exist between the SQream and Avro types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. + +.. note:: The **nba.parquet** file is stored on S3 at ``s3://sqream-demo-data/nba.parquet``. + +Verifying Your Table Output +--------------------- +Because external tables do not automatically verify the file integrity or structure, you must manually verify that the table output is identical to the original inserted table. + +The following is an example of the output based on the **nba.parquet** table: + +.. code-block:: psql + + t=> SELECT * FROM ext_nba LIMIT 10; + Name | Team | Number | Position | Age | Height | Weight | College | Salary + --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- + Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 + Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 + John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | + R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 + Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 + Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 + Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 + Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 + Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 + Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 + +.. note:: If your table output has errors, verify that the structure of the Avro files correctly corresponds to the external table structure that you created. + +Loading Data into SQream +--------------------- + +Syntax +~~~~~~~~~~~~~~~~~~~~~ +The following is the correct syntax for loading data into SQream: + +.. code-block:: postgres + + CREATE TABLE

AS + SELECT * FROM ; + +The following is an example of loading data into SQream: + +.. code-block:: postgres + + CREATE TABLE nba AS + SELECT * FROM ext_nba; + +For more information about the **CREATE TABLE AS** statement, see :ref:`create_table_as`. + +Examples +~~~~~~~~~~~~~~~~~~~~~ + +This section includes the following examples of loading data into SQream: + +.. contents:: + :local: + :depth: 1 + +Omitting Unsupported Column Types +********************** +When loading data, you can omit columns using the ``NULL as`` argument. You can use this argument to omit unsupported columns from queries that access external tables. By omitting them, these columns will not be called and will avoid generating a "type mismatch" error. + +In the example below, the ``Position`` column is not supported due its type. + +.. code-block:: postgres + + CREATE TABLE nba AS + SELECT Name, Team, Number, NULL as Position, Age, Height, Weight, College, Salary FROM ext_nba; + + +Modifying Data Before Loading +********************** +One of the main reasons for staging data using the ``EXTERNAL TABLE`` argument is to examine and modify table contents before loading it into SQream. + +For example, we can replace pounds with kilograms using the :ref:`create_table_as` statement + +In the example below, the ``Position`` column is set to the default ``NULL``. + +.. code-block:: postgres + + CREATE TABLE nba AS + SELECT name, team, number, NULL as Position, age, height, (weight / 2.205) as weight, college, salary + FROM ext_nba + ORDER BY weight; + + +Loading a Table from a Directory of Avro Files on HDFS +********************** +The following is an example of loading a table from a directory of Avro files on HDFS: + +.. code-block:: postgres + + CREATE FOREIGN TABLE ext_users + (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + WRAPPER parquet_fdw + OPTIONS + ( + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet' + ); + + CREATE TABLE users AS SELECT * FROM ext_users; + +For more configuration option examples, see the `CREATE FOREIGN TABLE parameters `_. + +Loading a Table from a Directory of Avro Files on S3 +********************** +The following is an example of loading a table from a directory of Avro files on S3: + +.. code-block:: postgres + + CREATE FOREIGN TABLE ext_users + (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + WRAPPER parquet_fdw + OPTIONS + ( LOCATION = 's3://pp-secret-bucket/users/*.parquet', + AWS_ID = 'our_aws_id', + AWS_SECRET = 'our_aws_secret' + ); + + CREATE TABLE users AS SELECT * FROM ext_users; \ No newline at end of file diff --git a/data_ingestion_guides/index.rst b/data_ingestion_guides/index.rst index 09c121fcd..7f602992c 100644 --- a/data_ingestion_guides/index.rst +++ b/data_ingestion_guides/index.rst @@ -1,17 +1,18 @@ -.. _data_ingestion_guides: +.. _data_ingestion: ************************* Data Ingestion Sources ************************* -The **Data Ingestion Sources** page provides information about the following data ingestion sources: +The **Data Ingestion Sources** provides information about the following data ingestion sources: .. toctree:: :maxdepth: 1 :glob: + avro csv parquet orc oracle -For information about database tools and interfaces that SQream supports, see `Third Party Tools `_. +For information about database tools and interfaces that SQream supports, see `Third Party Tools `_. \ No newline at end of file From 11e8796e5bd3f868d7e79b6cd871c5685a5577f6 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 8 Mar 2022 17:34:47 +0200 Subject: [PATCH 198/300] Fixed folder name --- {data_ingestion_guides => data_ingestion}/avro.rst | 0 {data_ingestion_guides => data_ingestion}/csv.rst | 0 {data_ingestion_guides => data_ingestion}/index.rst | 0 {data_ingestion_guides => data_ingestion}/inserting_data.rst | 0 {data_ingestion_guides => data_ingestion}/nba-t10.csv | 0 {data_ingestion_guides => data_ingestion}/oracle.rst | 0 {data_ingestion_guides => data_ingestion}/orc.rst | 0 {data_ingestion_guides => data_ingestion}/parquet.rst | 0 {data_ingestion_guides => data_ingestion}/to_csv.sql | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename {data_ingestion_guides => data_ingestion}/avro.rst (100%) rename {data_ingestion_guides => data_ingestion}/csv.rst (100%) rename {data_ingestion_guides => data_ingestion}/index.rst (100%) rename {data_ingestion_guides => data_ingestion}/inserting_data.rst (100%) rename {data_ingestion_guides => data_ingestion}/nba-t10.csv (100%) rename {data_ingestion_guides => data_ingestion}/oracle.rst (100%) rename {data_ingestion_guides => data_ingestion}/orc.rst (100%) rename {data_ingestion_guides => data_ingestion}/parquet.rst (100%) rename {data_ingestion_guides => data_ingestion}/to_csv.sql (100%) diff --git a/data_ingestion_guides/avro.rst b/data_ingestion/avro.rst similarity index 100% rename from data_ingestion_guides/avro.rst rename to data_ingestion/avro.rst diff --git a/data_ingestion_guides/csv.rst b/data_ingestion/csv.rst similarity index 100% rename from data_ingestion_guides/csv.rst rename to data_ingestion/csv.rst diff --git a/data_ingestion_guides/index.rst b/data_ingestion/index.rst similarity index 100% rename from data_ingestion_guides/index.rst rename to data_ingestion/index.rst diff --git a/data_ingestion_guides/inserting_data.rst b/data_ingestion/inserting_data.rst similarity index 100% rename from data_ingestion_guides/inserting_data.rst rename to data_ingestion/inserting_data.rst diff --git a/data_ingestion_guides/nba-t10.csv b/data_ingestion/nba-t10.csv similarity index 100% rename from data_ingestion_guides/nba-t10.csv rename to data_ingestion/nba-t10.csv diff --git a/data_ingestion_guides/oracle.rst b/data_ingestion/oracle.rst similarity index 100% rename from data_ingestion_guides/oracle.rst rename to data_ingestion/oracle.rst diff --git a/data_ingestion_guides/orc.rst b/data_ingestion/orc.rst similarity index 100% rename from data_ingestion_guides/orc.rst rename to data_ingestion/orc.rst diff --git a/data_ingestion_guides/parquet.rst b/data_ingestion/parquet.rst similarity index 100% rename from data_ingestion_guides/parquet.rst rename to data_ingestion/parquet.rst diff --git a/data_ingestion_guides/to_csv.sql b/data_ingestion/to_csv.sql similarity index 100% rename from data_ingestion_guides/to_csv.sql rename to data_ingestion/to_csv.sql From d59b309c28477d9819104fb253dc057028ac3595 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 8 Mar 2022 17:49:10 +0200 Subject: [PATCH 199/300] Update conf.py Updated Copyright year. Removed Author from Title page. --- conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf.py b/conf.py index c6b56c9e9..5fd88b4cd 100644 --- a/conf.py +++ b/conf.py @@ -21,8 +21,8 @@ # -- Project information ----------------------------------------------------- project = 'SQream DB' -copyright = '2021 SQream' -author = 'Sean Tomarian' +copyright = '2022 SQream' +' # The full version, including alpha/beta/rc tags From 01bff3a959eb71059e7e23d95c3c194c6f8a728b Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 8 Mar 2022 18:20:05 +0200 Subject: [PATCH 200/300] Update conf.py --- conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/conf.py b/conf.py index 5fd88b4cd..a6d282dbb 100644 --- a/conf.py +++ b/conf.py @@ -22,6 +22,7 @@ project = 'SQream DB' copyright = '2022 SQream' +author = 'SQream Documentation' ' # The full version, including alpha/beta/rc tags From 1de2d658d7d22c8c29a8f780ff276504bd83841f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 8 Mar 2022 19:19:22 +0200 Subject: [PATCH 201/300] Updated menu Lower granularity to avoid H4. Updated links to current branch. --- configuration_guides/admin/admin_flags.rst | 4 +- configuration_guides/admin_cluster_flags.rst | 7 +-- configuration_guides/admin_regular_flags.rst | 54 +++++++++---------- configuration_guides/admin_worker_flags.rst | 12 ++--- .../generic/generic_flags.rst | 4 +- configuration_guides/generic/spooling.rst | 4 +- .../generic_regular_flags.rst | 21 ++++---- configuration_guides/generic_worker_flags.rst | 6 +-- configuration_guides/index.rst | 5 +- configuration_guides/spooling.rst | 8 +-- 10 files changed, 59 insertions(+), 66 deletions(-) diff --git a/configuration_guides/admin/admin_flags.rst b/configuration_guides/admin/admin_flags.rst index 93aee2cb9..c4c170841 100644 --- a/configuration_guides/admin/admin_flags.rst +++ b/configuration_guides/admin/admin_flags.rst @@ -39,4 +39,6 @@ The **Administration Flags** page describes the following flags, which can be mo statement_Lock_Timeout use_Config_IP use_Legacy_Decimal_Literals - use_Legacy_String_Literals \ No newline at end of file + use_Legacy_String_Literals + + diff --git a/configuration_guides/admin_cluster_flags.rst b/configuration_guides/admin_cluster_flags.rst index e1120b468..18a1809ce 100644 --- a/configuration_guides/admin_cluster_flags.rst +++ b/configuration_guides/admin_cluster_flags.rst @@ -6,9 +6,4 @@ Cluster Administration Flags The **Cluster Administration Flags** page describes **Cluster** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: -.. toctree:: - :maxdepth: 1 - :glob: - - csv_limit_row_length - extent_storage_file_size_mb \ No newline at end of file +* `Persisting Your Cache Directory `_ \ No newline at end of file diff --git a/configuration_guides/admin_regular_flags.rst b/configuration_guides/admin_regular_flags.rst index 7ee3fe555..0a228ce00 100644 --- a/configuration_guides/admin_regular_flags.rst +++ b/configuration_guides/admin_regular_flags.rst @@ -3,33 +3,31 @@ ************************* Regular Administration Flags ************************* - The **Regular Administration Flags** page describes **Regular** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: -.. toctree:: - :maxdepth: 1 - :glob: - - bin_sizes - check_cuda_memory - compiler_gets_only_ufs - copy_to_restrict_utf8 - cpu_reduce_hashtable_size - cuda_mem_cpy_max_size_bytes - cuda_mem_cpy_synchronous - developer_mode - enable_device_debug_messages - enable_log_debug - enable_nv_prof_markers - end_log_message - gather_mem_stat - increase_chunk_size_before_reduce - increase_mem_factors - level_db_write_buffer_size - memory_reset_trigger_mb - mt_read - mt_read_workers - orc_implicit_casts - statement_lock_timeout - use_legacy_decimal_literals - use_legacy_string_literals \ No newline at end of file +* `Setting Bin Size `_ +* `Setting CUDA Memory `_ +* `Limiting Runtime to Utility Functions `_ +* `Enabling High Bin Control Granularity `_ +* `Reducing CPU Hashtable Sizes `_ +* `Setting Chunk Size for Copying from CPU to GPU `_ +* `Indicating GPU Synchronicity `_ +* `Enabling Modification of R&D Flags `_ +* `Checking for Post-Production CUDA Errors `_ +* `Enabling Modification of clientLogger_debug File `_ +* `Activating the NVidia Profiler Markers `_ +* `Appending String at End of Log Lines `_ +* `Monitoring and Printing Pinned Allocation Reports `_ +* `Increasing Chunk Size to Reduce Query Speed `_ +* `Adding Rechunker before Expensing Chunk Producer `_ +* `Setting the Buffer Size `_ +* `Maximum Pinned Percentage of Total RAM `_ +* `Memory Merge Blob Offset Count `_ +* `Setting Memory Used to Abort Server `_ +* `Splitting Large Reads for Concurrent Execution `_ +* `Setting Worker Amount to Handle Concurrent Reads `_ +* `Setting Implicit Casts in ORC Files `_ +* `Setting Timeout Limit for Locking Objects before Executing Statements `_ +* `Interpreting Decimal Literals as Double Instead of Numeric `_ +* `Interpreting VARCHAR as TEXT `_ +* `VARCHAR Identifiers `_ diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst index c5eddb721..412955510 100644 --- a/configuration_guides/admin_worker_flags.rst +++ b/configuration_guides/admin_worker_flags.rst @@ -5,11 +5,7 @@ Worker Administration Flags ************************* The **Worker Administration Flags** page describes **Worker** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: -.. toctree:: - :maxdepth: 1 - :glob: - - cuda_mem_quota - machine_ip - metadata_server_port - use_config_ip \ No newline at end of file +* `Setting Total Device Memory Usage in SQream Instance `_ +* `Enabling Manually Setting Reported IP `_ +* `Setting Port Used for Metadata Server Connection `_ +* `Assigning Local Network IP `_ \ No newline at end of file diff --git a/configuration_guides/generic/generic_flags.rst b/configuration_guides/generic/generic_flags.rst index 4a79c94b8..879e2eac1 100644 --- a/configuration_guides/generic/generic_flags.rst +++ b/configuration_guides/generic/generic_flags.rst @@ -12,7 +12,7 @@ The **Administration Flags** page describes the following flags, which can be mo :glob: flip_Join_Order - limit_Query_Memory_GB + limit_query_memory_gb log_Sys_Level max_Avg_Blob_Size_To_Compress_On_Gpu - spool_Memory_GB \ No newline at end of file + spool_memory_gb \ No newline at end of file diff --git a/configuration_guides/generic/spooling.rst b/configuration_guides/generic/spooling.rst index e96928c6f..dcf1c775f 100644 --- a/configuration_guides/generic/spooling.rst +++ b/configuration_guides/generic/spooling.rst @@ -65,5 +65,5 @@ The following is an example of setting ``spoolMemoryGB`` value in the previous c For more information about configuring the ``spoolMemoryGB`` flag, see the following: -* `Current configuration method `_ -* `Previous configuration method `_ \ No newline at end of file +* **Current configuration method**: Configuration flags +* **Previous configuration method**: Runtime global flags \ No newline at end of file diff --git a/configuration_guides/generic_regular_flags.rst b/configuration_guides/generic_regular_flags.rst index 251a913e4..4c2a4a2a6 100644 --- a/configuration_guides/generic_regular_flags.rst +++ b/configuration_guides/generic_regular_flags.rst @@ -6,12 +6,15 @@ Regular Generic Flags The **Regular Generic Flags** page describes **Regular** modification type flags, which can be modified by standard users on a session basis: -.. toctree:: - :maxdepth: 1 - :glob: - - flip_join_order - log_sys_level - max_avg_blob_size_to_compress_on_gpu - limit_query_memory_gb - spool_memory_gb \ No newline at end of file +* `Flipping Join Order to Force Equijoins `_ +* `Determining Client Level `_ +* `Setting CPU to Compress Defined Columns `_ +* `Setting Query Memory Processing Limit `_ +* `Setting the Spool Memory `_ +* `Partitioning Caches `_ +* `Evicting Caches `_ +* `Caching RAM `_ +* `Caching Your Disk `_ +* `Caching Your Disk Directory `_ +* `Persisting Your Cache `_ +* `Persisting Your Cache Directory `_ \ No newline at end of file diff --git a/configuration_guides/generic_worker_flags.rst b/configuration_guides/generic_worker_flags.rst index 14f2de0c6..f46e933b1 100644 --- a/configuration_guides/generic_worker_flags.rst +++ b/configuration_guides/generic_worker_flags.rst @@ -5,8 +5,4 @@ Worker Generic Flags ************************* The Worker Generic Flags** page describes **Worker** modification type flags, which can be modified by standard users on a session basis: -.. toctree:: - :maxdepth: 1 - :glob: - - limit_query_memory_gb \ No newline at end of file + * `Persisting Your Cache Directory `_ \ No newline at end of file diff --git a/configuration_guides/index.rst b/configuration_guides/index.rst index 0456e7ee6..6a65853f0 100644 --- a/configuration_guides/index.rst +++ b/configuration_guides/index.rst @@ -12,4 +12,7 @@ The **Configuration Guides** page describes the following configuration informat spooling configuration_methods - configuration_flags \ No newline at end of file + configuration_flags + + + diff --git a/configuration_guides/spooling.rst b/configuration_guides/spooling.rst index b2ae15c4d..e96928c6f 100644 --- a/configuration_guides/spooling.rst +++ b/configuration_guides/spooling.rst @@ -9,8 +9,9 @@ The **Configuring the Spooling Feature** page includes the following topics: :local: :depth: 1 + Overview --------- +---------- From the SQream Acceleration Studio you can allocate the amount of memory (GB) available to the server for spooling using the ``spoolMemoryGB`` flag. SQream recommends setting the ``spoolMemoryGB`` flag to 90% of the ``limitQueryMemoryGB`` flag. The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. In addition, the ``limitQueryMemoryGB`` defines how much total system memory is used by each worker. SQream recommends setting ``limitQueryMemoryGB`` to 5% less than the total host memory divided by the amount of ``sqreamd`` workers on host. @@ -62,8 +63,7 @@ The following is an example of setting ``spoolMemoryGB`` value in the previous c “limitQueryMemoryGB” : 121, “spoolMemoryGB” : 108 - For more information about configuring the ``spoolMemoryGB`` flag, see the following: -* `Current configuration method `_ -* `Previous configuration method `_ \ No newline at end of file +* `Current configuration method `_ +* `Previous configuration method `_ \ No newline at end of file From 272452dbabe651dcc237d2aa6088efd20adf1969 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 10 Mar 2022 13:05:27 +0200 Subject: [PATCH 202/300] Update index.rst Hid Avro. --- data_ingestion/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_ingestion/index.rst b/data_ingestion/index.rst index 7f602992c..d626dcd22 100644 --- a/data_ingestion/index.rst +++ b/data_ingestion/index.rst @@ -9,10 +9,10 @@ The **Data Ingestion Sources** provides information about the following data ing :maxdepth: 1 :glob: - avro + xxavro csv parquet orc oracle -For information about database tools and interfaces that SQream supports, see `Third Party Tools `_. \ No newline at end of file +For information about database tools and interfaces that SQream supports, see `Third Party Tools `_. From aa93bba6f64e431d27e89b44e4eccc45b725c28b Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 13 Mar 2022 11:03:43 +0200 Subject: [PATCH 203/300] Update conf.py Removed ' from Line 26. I suspect that was causing build failures. --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index a6d282dbb..551ecebdd 100644 --- a/conf.py +++ b/conf.py @@ -23,7 +23,7 @@ project = 'SQream DB' copyright = '2022 SQream' author = 'SQream Documentation' -' + # The full version, including alpha/beta/rc tags From 254665072a8184e097b08ea367815a906991133b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 13 Mar 2022 11:30:53 +0200 Subject: [PATCH 204/300] Delete avro.rst Feature not completed. Will restore it when completed. --- data_ingestion/avro.rst | 344 ---------------------------------------- 1 file changed, 344 deletions(-) delete mode 100644 data_ingestion/avro.rst diff --git a/data_ingestion/avro.rst b/data_ingestion/avro.rst deleted file mode 100644 index 14bbbc38f..000000000 --- a/data_ingestion/avro.rst +++ /dev/null @@ -1,344 +0,0 @@ -.. _avro: - -************************** -Inserting Data from Avro -************************** -The **Inserting Data from Avro** page describes inserting data from Avro into SQream and includes the following: - -.. contents:: - :local: - :depth: 1 - -Overview -=========== -**Avro** is a well-known data serialization system that relies on schemas. Due to its flexibility and nesting as an efficient data storage method, SQream supports the Avro binary data format as an alternative to JSON. - -Avro Data Types -=========== - -Avro includes the following data types: - -.. contents:: - :local: - :depth: 1 - -Primitive Data Types --------------- -The following table shows the supported **Primitive** data types: - -+-------------+-------------------------------------------+ -| Avro Type | SQream Type | -| +--------+---------------+--------+---------+ -| | Number | Date/Datetime | String | Boolean | -+=============+========+===============+========+=========+ -| ``null`` | ✓ | ✓ | ✓ | ✓ | -+-------------+--------+---------------+--------+---------+ -| ``boolean`` | | | ✓ | ✓ | -+-------------+--------+---------------+--------+---------+ -| ``int`` | ✓ | | ✓ | | -+-------------+--------+---------------+--------+---------+ -| ``long`` | ✓ | | ✓ | | -+-------------+--------+---------------+--------+---------+ -| ``float`` | ✓ | | ✓ | | -+-------------+--------+---------------+--------+---------+ -| ``double`` | ✓ | | ✓ | | -+-------------+--------+---------------+--------+---------+ -| ``bytes`` | | | | | -+-------------+--------+---------------+--------+---------+ -| ``string`` | | ✓ | ✓ | | -+-------------+--------+---------------+--------+---------+ - - - - - - -Complex Data Types --------------- -The following table shows the supported **Complex** data types: - -+------------+-------------------------------------------+ -| | SQream Type | -| +--------+---------------+--------+---------+ -|Avro Type | Number | Date/Datetime | String | Boolean | -+============+========+===============+========+=========+ -| ``record`` | | | | | -+------------+--------+---------------+--------+---------+ -| ``enum`` | | | ✓ | | -+------------+--------+---------------+--------+---------+ -| ``array`` | | | | | -+------------+--------+---------------+--------+---------+ -| ``map`` | | | | | -+------------+--------+---------------+--------+---------+ -| ``union`` | ✓ | ✓ | ✓ | ✓ | -+------------+--------+---------------+--------+---------+ -| ``fixed`` | | | | | -+------------+--------+---------------+--------+---------+ - - -Logical Data Types --------------- -The following table shows the supported **Logical** data types: - -+----------------------------+-------------------------------------------+ -| Avro Type | SQream Type | -| +--------+---------------+--------+---------+ -| | Number | Date/Datetime | String | Boolean | -+============================+========+===============+========+=========+ -| ``decimal`` | ✓ | | ✓ | | -+----------------------------+--------+---------------+--------+---------+ -| ``uuid`` | | | ✓ | | -+----------------------------+--------+---------------+--------+---------+ -| ``date`` | | ✓ | ✓ | | -+----------------------------+--------+---------------+--------+---------+ -| ``time-millis`` | | | | | -+----------------------------+--------+---------------+--------+---------+ -| ``time-micros`` | | | | | -+----------------------------+--------+---------------+--------+---------+ -| ``timestamp-millis`` | | ✓ | ✓ | | -+----------------------------+--------+---------------+--------+---------+ -| ``timestamp-micros`` | | ✓ | ✓ | | -+----------------------------+--------+---------------+--------+---------+ -| ``local-timestamp-millis`` | | | | | -+----------------------------+--------+---------------+--------+---------+ -| ``local-timestamp-micros`` | | | | | -+----------------------------+--------+---------------+--------+---------+ -| ``duration`` | | | | | -+----------------------------+--------+---------------+--------+---------+ - - -Mapping Objects to Rows -=============== -When mapping objects to rows, each Avro object or message must contain one ``record`` type object corresponding to a single row in SQream. The ``record`` fields are associated by name to their target table columns. - -Additional unmapped fields will be ignored. Note that using the JSONPath option overrides this. - -Ingesting Avro Files -==================== -This section describes how to ingest Avro files into SQream and covers the following: - - -.. contents:: - :local: - :depth: 1 - - -Preparing Your Avro Source File ----------- -Prepare your Avro source files according to the following requirements: - -* RFC 4180 standard CSV files, but can also be modified to support non-standard CSVs (with multi-character delimiters, unquoted fields, etc). - - :: - -* Files are encoded with UTF-8 or ASCII. - - :: - -* Field delimiter is an ASCII character or characters. - - :: - -* Record delimiter, also known as a new line separator, is a Unix-style newline (``\n``), DOS-style newline (``\r\n``), or Mac style newline (``\r``). - - :: - -* If a field is quoted, any double quote that appears must be double-quoted (similar to the :ref:`string literals quoting rules`. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. - - :: - -* Fields can be enclosed by double-quotes (optional), or mandatory quotes if they contain one of the following characters: - - * The record delimiter or field delimiter. - - :: - - * A double quote character. - - :: - - * A newline. - -SQream does not support other modes of escaping, such as ``1,"What are \"birds\"?"``. - -``NULL`` values can be marked in the following ways in Avro files: - - * An explicit null marker. For example, ``col1,\N,col3``. - - :: - - * An empty field delimited by the field delimiter. For example, ``col1,,col3``. - - .. note:: If a text field is quoted but contains no content (``""``) it is considered an empty text field and not ``NULL``. - -For more information about standard CSV files, see `RFC 4180 standard CSVs `_. - -Making Avro Files Accessible to Workers ---------------------- -To give workers access to files every node must have the same view of the storage being used. - -The following apply for Avro files to be accessible to workers: - -* For files hosted on NFS, ensure that the mount is accessible from all servers. - -* For HDFS, ensure that SQream servers have access to the HDFS name node with the correct **user-id**. For more information, see :ref:`hdfs`. - -* For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. - -For more information about restricted worker access, see :ref:`workload_manager`. - -Basing Your Table Structure on Inserted Tables ---------------------- -Before loading data, you must build the ``CREATE EXTERNAL TABLE`` to correspond with the file structure of the inserted table. - -The example in this section is based on the source ``nba.parquet`` table shown below: - -.. csv-table:: nba.parquet - :file: nba-t10.csv - :widths: auto - :header-rows: 1 - -The following example shows the correct file structure used to create the ``CREATE EXTERNAL TABLE`` statement based on the **nba.parquet** table: - -.. code-block:: postgres - - CREATE FOREIGN TABLE ext_nba - ( - Name VARCHAR(40), - Team VARCHAR(40), - Number BIGINT, - Position VARCHAR(2), - Age BIGINT, - Height VARCHAR(4), - Weight BIGINT, - College VARCHAR(40), - Salary FLOAT - ) - WRAPPER parquet_fdw - OPTIONS - ( - LOCATION = 's3://sqream-demo-data/nba.parquet' - ); - -.. tip:: - - An exact match must exist between the SQream and Avro types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. - -.. note:: The **nba.parquet** file is stored on S3 at ``s3://sqream-demo-data/nba.parquet``. - -Verifying Your Table Output ---------------------- -Because external tables do not automatically verify the file integrity or structure, you must manually verify that the table output is identical to the original inserted table. - -The following is an example of the output based on the **nba.parquet** table: - -.. code-block:: psql - - t=> SELECT * FROM ext_nba LIMIT 10; - Name | Team | Number | Position | Age | Height | Weight | College | Salary - --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- - Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 - Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 - John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | - R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 - Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 - Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 - Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 - Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 - Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 - Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 - -.. note:: If your table output has errors, verify that the structure of the Avro files correctly corresponds to the external table structure that you created. - -Loading Data into SQream ---------------------- - -Syntax -~~~~~~~~~~~~~~~~~~~~~ -The following is the correct syntax for loading data into SQream: - -.. code-block:: postgres - - CREATE TABLE
AS - SELECT * FROM ; - -The following is an example of loading data into SQream: - -.. code-block:: postgres - - CREATE TABLE nba AS - SELECT * FROM ext_nba; - -For more information about the **CREATE TABLE AS** statement, see :ref:`create_table_as`. - -Examples -~~~~~~~~~~~~~~~~~~~~~ - -This section includes the following examples of loading data into SQream: - -.. contents:: - :local: - :depth: 1 - -Omitting Unsupported Column Types -********************** -When loading data, you can omit columns using the ``NULL as`` argument. You can use this argument to omit unsupported columns from queries that access external tables. By omitting them, these columns will not be called and will avoid generating a "type mismatch" error. - -In the example below, the ``Position`` column is not supported due its type. - -.. code-block:: postgres - - CREATE TABLE nba AS - SELECT Name, Team, Number, NULL as Position, Age, Height, Weight, College, Salary FROM ext_nba; - - -Modifying Data Before Loading -********************** -One of the main reasons for staging data using the ``EXTERNAL TABLE`` argument is to examine and modify table contents before loading it into SQream. - -For example, we can replace pounds with kilograms using the :ref:`create_table_as` statement - -In the example below, the ``Position`` column is set to the default ``NULL``. - -.. code-block:: postgres - - CREATE TABLE nba AS - SELECT name, team, number, NULL as Position, age, height, (weight / 2.205) as weight, college, salary - FROM ext_nba - ORDER BY weight; - - -Loading a Table from a Directory of Avro Files on HDFS -********************** -The following is an example of loading a table from a directory of Avro files on HDFS: - -.. code-block:: postgres - - CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) - WRAPPER parquet_fdw - OPTIONS - ( - LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet' - ); - - CREATE TABLE users AS SELECT * FROM ext_users; - -For more configuration option examples, see the `CREATE FOREIGN TABLE parameters `_. - -Loading a Table from a Directory of Avro Files on S3 -********************** -The following is an example of loading a table from a directory of Avro files on S3: - -.. code-block:: postgres - - CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) - WRAPPER parquet_fdw - OPTIONS - ( LOCATION = 's3://pp-secret-bucket/users/*.parquet', - AWS_ID = 'our_aws_id', - AWS_SECRET = 'our_aws_secret' - ); - - CREATE TABLE users AS SELECT * FROM ext_users; \ No newline at end of file From 0cf30045a0ae18e19151dd63b87f0464d0f62d62 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 13 Mar 2022 12:04:52 +0200 Subject: [PATCH 205/300] Updated Configuration Guides section Added new flags. Updated links. --- configuration_guides/admin_cluster_flags.rst | 2 +- configuration_guides/admin_regular_flags.rst | 3 +-- configuration_guides/cache_disk_dir.rst | 12 +++++++++ configuration_guides/cache_disk_gb.rst | 12 +++++++++ .../cache_eviction_milliseconds.rst | 12 +++++++++ configuration_guides/cache_partitions.rst | 12 +++++++++ configuration_guides/cache_persistent_dir.rst | 12 +++++++++ configuration_guides/cache_persistent_gb.rst | 12 +++++++++ configuration_guides/cache_ram_gb.rst | 12 +++++++++ configuration_guides/check_cuda_memory.rst | 3 ++- .../compiler_gets_only_ufs.rst | 3 ++- .../copy_to_restrict_utf8.rst | 12 +++++++++ .../cpu_reduce_hashtable_size.rst | 11 ++++---- configuration_guides/csv_limit_row_length.rst | 3 ++- .../cuda_mem_cpy_max_size_bytes.rst | 3 ++- .../cuda_mem_cpy_synchronous.rst | 3 ++- configuration_guides/cuda_mem_quota.rst | 1 + configuration_guides/developer_mode.rst | 3 ++- .../enable_device_debug_messages.rst | 3 ++- configuration_guides/enable_log_debug.rst | 3 ++- .../enable_nv_prof_markers.rst | 3 ++- configuration_guides/flip_join_order.rst | 3 ++- configuration_guides/gather_mem_stat.rst | 3 ++- .../generic_regular_flags.rst | 25 ++++++++++--------- configuration_guides/generic_worker_flags.rst | 4 +-- .../increase_chunk_size_before_reduce.rst | 3 ++- configuration_guides/increase_mem_factors.rst | 3 ++- .../level_db_write_buffer_size.rst | 3 ++- .../limit_query_memory_gb.rst | 5 ++-- configuration_guides/log_sys_level.rst | 3 ++- configuration_guides/machine_ip.rst | 3 ++- .../max_avg_blob_size_to_compress_on_gpu.rst | 3 ++- .../memory_reset_trigger_mb.rst | 1 + configuration_guides/metadata_server_port.rst | 3 ++- configuration_guides/mt_read.rst | 3 ++- configuration_guides/mt_read_workers.rst | 1 + configuration_guides/orc_implicit_casts.rst | 3 ++- configuration_guides/session_tag.rst | 12 +++++++++ configuration_guides/spool_memory_gb.rst | 3 ++- .../statement_lock_timeout.rst | 1 + configuration_guides/use_config_ip.rst | 3 ++- .../use_legacy_decimal_literals.rst | 3 ++- .../use_legacy_string_literals.rst | 3 ++- configuration_guides/varchar_identifiers.rst | 12 +++++++++ 44 files changed, 198 insertions(+), 48 deletions(-) create mode 100644 configuration_guides/cache_disk_dir.rst create mode 100644 configuration_guides/cache_disk_gb.rst create mode 100644 configuration_guides/cache_eviction_milliseconds.rst create mode 100644 configuration_guides/cache_partitions.rst create mode 100644 configuration_guides/cache_persistent_dir.rst create mode 100644 configuration_guides/cache_persistent_gb.rst create mode 100644 configuration_guides/cache_ram_gb.rst create mode 100644 configuration_guides/copy_to_restrict_utf8.rst create mode 100644 configuration_guides/session_tag.rst create mode 100644 configuration_guides/varchar_identifiers.rst diff --git a/configuration_guides/admin_cluster_flags.rst b/configuration_guides/admin_cluster_flags.rst index 18a1809ce..6a1b63406 100644 --- a/configuration_guides/admin_cluster_flags.rst +++ b/configuration_guides/admin_cluster_flags.rst @@ -6,4 +6,4 @@ Cluster Administration Flags The **Cluster Administration Flags** page describes **Cluster** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: -* `Persisting Your Cache Directory `_ \ No newline at end of file +* `Setting Maximum CSV Row Length `_ \ No newline at end of file diff --git a/configuration_guides/admin_regular_flags.rst b/configuration_guides/admin_regular_flags.rst index 0a228ce00..4818a7d6b 100644 --- a/configuration_guides/admin_regular_flags.rst +++ b/configuration_guides/admin_regular_flags.rst @@ -22,7 +22,6 @@ The **Regular Administration Flags** page describes **Regular** modification typ * `Adding Rechunker before Expensing Chunk Producer `_ * `Setting the Buffer Size `_ * `Maximum Pinned Percentage of Total RAM `_ -* `Memory Merge Blob Offset Count `_ * `Setting Memory Used to Abort Server `_ * `Splitting Large Reads for Concurrent Execution `_ * `Setting Worker Amount to Handle Concurrent Reads `_ @@ -30,4 +29,4 @@ The **Regular Administration Flags** page describes **Regular** modification typ * `Setting Timeout Limit for Locking Objects before Executing Statements `_ * `Interpreting Decimal Literals as Double Instead of Numeric `_ * `Interpreting VARCHAR as TEXT `_ -* `VARCHAR Identifiers `_ +* `VARCHAR Identifiers `_ \ No newline at end of file diff --git a/configuration_guides/cache_disk_dir.rst b/configuration_guides/cache_disk_dir.rst new file mode 100644 index 000000000..012955bc3 --- /dev/null +++ b/configuration_guides/cache_disk_dir.rst @@ -0,0 +1,12 @@ +.. _cache_disk_dir: + +************************* +Setting Spool Saved File Directory Location +************************* +The ``cacheDiskDir`` flag sets the ondisk directory location for the spool to save files on. + +The following describes the ``cacheDiskDir`` flag: + +* **Data type** - size_t +* **Default value** - ``128`` +* **Allowed values** - Any legal string \ No newline at end of file diff --git a/configuration_guides/cache_disk_gb.rst b/configuration_guides/cache_disk_gb.rst new file mode 100644 index 000000000..eb3d530cd --- /dev/null +++ b/configuration_guides/cache_disk_gb.rst @@ -0,0 +1,12 @@ +.. _cache_disk_gb: + +************************* +Setting Disk Spool Memory +************************* +The ``cacheDiskGB`` flag sets the amount of memory (GB) to be used by Spool on the disk. + +The following describes the ``cacheDiskGB`` flag: + +* **Data type** - size_t +* **Default value** - ``128`` +* **Allowed values** - 0-4000000000 \ No newline at end of file diff --git a/configuration_guides/cache_eviction_milliseconds.rst b/configuration_guides/cache_eviction_milliseconds.rst new file mode 100644 index 000000000..129d6281b --- /dev/null +++ b/configuration_guides/cache_eviction_milliseconds.rst @@ -0,0 +1,12 @@ +.. _cache_eviction_milliseconds: + +************************* +Setting Cache Flushing +************************* +The ``cacheEvictionMilliseconds`` flag sets how long the cache stores contents before being flushed. + +The following describes the ``cacheEvictionMilliseconds`` flag: + +* **Data type** - size_t +* **Default value** - ``2000`` +* **Allowed values** - 1-4000000000 \ No newline at end of file diff --git a/configuration_guides/cache_partitions.rst b/configuration_guides/cache_partitions.rst new file mode 100644 index 000000000..0637e347c --- /dev/null +++ b/configuration_guides/cache_partitions.rst @@ -0,0 +1,12 @@ +.. _cache_partitions: + +************************* +Setting Cache Partitions +************************* +The ``cachePartitions`` flag sets the number of partitions that the cache is split into. + +The following describes the ``cachePartitions`` flag: + +* **Data type** - size_t +* **Default value** - ``4`` +* **Allowed values** - 1-4000000000 \ No newline at end of file diff --git a/configuration_guides/cache_persistent_dir.rst b/configuration_guides/cache_persistent_dir.rst new file mode 100644 index 000000000..c3e298189 --- /dev/null +++ b/configuration_guides/cache_persistent_dir.rst @@ -0,0 +1,12 @@ +.. _cache_persistent_dir: + +************************* +Setting Spool Persistent Saved File Directory Location +************************* +The ``cachePersistentDir`` flag sets the persistent directory location for the spool to save files on. + +The following describes the ``cachePersistentDir`` flag: + +* **Data type** - string +* **Default value** - ``/tmp`` +* **Allowed values** - Any legal string \ No newline at end of file diff --git a/configuration_guides/cache_persistent_gb.rst b/configuration_guides/cache_persistent_gb.rst new file mode 100644 index 000000000..418364e5c --- /dev/null +++ b/configuration_guides/cache_persistent_gb.rst @@ -0,0 +1,12 @@ +.. _cache_persistent_gb: + +************************* +Setting Data Stored Persistently on Cache +************************* +The ``cachePersistentGB`` flag sets the amount of data (GB) for the cache to store persistently . + +The following describes the ``cachePersistentGB`` flag: + +* **Data type** - size_t +* **Default value** - ``128`` +* **Allowed values** - 0-4000000000 \ No newline at end of file diff --git a/configuration_guides/cache_ram_gb.rst b/configuration_guides/cache_ram_gb.rst new file mode 100644 index 000000000..31d56613b --- /dev/null +++ b/configuration_guides/cache_ram_gb.rst @@ -0,0 +1,12 @@ +.. _cache_ram_gb: + +************************* +Setting InMemory Spool Memory +************************* +The ``cacheRamGB`` flag sets the amount of memory (GB) to be used by Spool InMemory. + +The following describes the ``cacheRamGB`` flag: + +* **Data type** - size_t +* **Default value** - ``16`` +* **Allowed values** - 0-4000000000 \ No newline at end of file diff --git a/configuration_guides/check_cuda_memory.rst b/configuration_guides/check_cuda_memory.rst index 84eec3f07..9ac78f767 100644 --- a/configuration_guides/check_cuda_memory.rst +++ b/configuration_guides/check_cuda_memory.rst @@ -8,4 +8,5 @@ The ``checkCudaMemory`` flag sets the pad device memory allocation with safety b The following describes the ``checkCudaMemory`` flag: * **Data type** - boolean -* **Default value** - ``FALSE`` \ No newline at end of file +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/configuration_guides/compiler_gets_only_ufs.rst b/configuration_guides/compiler_gets_only_ufs.rst index 1190adc3e..00e8b44d8 100644 --- a/configuration_guides/compiler_gets_only_ufs.rst +++ b/configuration_guides/compiler_gets_only_ufs.rst @@ -8,4 +8,5 @@ The ``compilerGetsOnlyUFs`` flag sets the runtime to pass only utility functions The following describes the ``compilerGetsOnlyUFs`` flag: * **Data type** - boolean -* **Default value** - ``FALSE`` \ No newline at end of file +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/configuration_guides/copy_to_restrict_utf8.rst b/configuration_guides/copy_to_restrict_utf8.rst new file mode 100644 index 000000000..5d5990243 --- /dev/null +++ b/configuration_guides/copy_to_restrict_utf8.rst @@ -0,0 +1,12 @@ +.. _copy_to_restrict_utf8: + +************************* +Enabling High Bin Control Granularity +************************* +The ``copyToRestrictUtf8`` flag sets sets the custom bin size in the cache to enable high bin control granularity. + +The following describes the ``copyToRestrictUtf8`` flag: + +* **Data type** - boolean +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/configuration_guides/cpu_reduce_hashtable_size.rst b/configuration_guides/cpu_reduce_hashtable_size.rst index c2b01604c..d32450cd3 100644 --- a/configuration_guides/cpu_reduce_hashtable_size.rst +++ b/configuration_guides/cpu_reduce_hashtable_size.rst @@ -1,11 +1,12 @@ .. _cpu_reduce_hashtable_size: ************************* -Enabling High Bin Control Granularity +Setting Hashtable Size for GROUP BY Queries ************************* -The ``copyToRestrictUtf8`` flag sets the custom bin size in the cache to enable high bin control granularity. +The ``cpuReduceHashtableSize`` flag sets the size of the hashtable in your CPU while running a ``GROUP BY`` query. -The following describes the ``checkCudaMemory`` flag: +The following describes the ``cpuReduceHashtableSize`` flag: -* **Data type** - boolean -* **Default value** - ``FALSE`` \ No newline at end of file +* **Data type** - uint +* **Default value** - ``10000`` +* **Allowed values** - 1-4000000000 \ No newline at end of file diff --git a/configuration_guides/csv_limit_row_length.rst b/configuration_guides/csv_limit_row_length.rst index 03f31c697..41bc124df 100644 --- a/configuration_guides/csv_limit_row_length.rst +++ b/configuration_guides/csv_limit_row_length.rst @@ -8,4 +8,5 @@ The ``csvLimitRowLength`` flag sets the maximum supported CSV row length. The following describes the ``csvLimitRowLength`` flag: * **Data type** - uint -* **Default value** - ``100000`` \ No newline at end of file +* **Default value** - ``100000`` +* **Allowed values** - 1-4000000000 \ No newline at end of file diff --git a/configuration_guides/cuda_mem_cpy_max_size_bytes.rst b/configuration_guides/cuda_mem_cpy_max_size_bytes.rst index 371c9bda4..c28827077 100644 --- a/configuration_guides/cuda_mem_cpy_max_size_bytes.rst +++ b/configuration_guides/cuda_mem_cpy_max_size_bytes.rst @@ -8,4 +8,5 @@ The ``cudaMemcpyMaxSizeBytes`` flag sets the chunk size for copying from CPU to The following describes the ``cudaMemcpyMaxSizeBytes`` flag: * **Data type** - uint -* **Default value** - ``0`` \ No newline at end of file +* **Default value** - ``0`` +* **Allowed values** - 0-4000000000 \ No newline at end of file diff --git a/configuration_guides/cuda_mem_cpy_synchronous.rst b/configuration_guides/cuda_mem_cpy_synchronous.rst index 81e762071..2f8662947 100644 --- a/configuration_guides/cuda_mem_cpy_synchronous.rst +++ b/configuration_guides/cuda_mem_cpy_synchronous.rst @@ -8,4 +8,5 @@ The ``CudaMemcpySynchronous`` flag indicates if copying from/to GPU is synchrono The following describes the ``CudaMemcpySynchronous`` flag: * **Data type** - boolean -* **Default value** - ``FALSE`` \ No newline at end of file +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/configuration_guides/cuda_mem_quota.rst b/configuration_guides/cuda_mem_quota.rst index 43f9d4943..d5f417978 100644 --- a/configuration_guides/cuda_mem_quota.rst +++ b/configuration_guides/cuda_mem_quota.rst @@ -9,3 +9,4 @@ The following describes the ``cudaMemQuota`` flag: * **Data type** - uint * **Default value** - ``90`` +* **Allowed values** - 0-100 diff --git a/configuration_guides/developer_mode.rst b/configuration_guides/developer_mode.rst index fbb6c0cec..1fa0eb32c 100644 --- a/configuration_guides/developer_mode.rst +++ b/configuration_guides/developer_mode.rst @@ -8,4 +8,5 @@ The ``developerMode`` flag enables modifying R&D flags. The following describes the ``developerMode`` flag: * **Data type** - boolean -* **Default value** - ``FALSE`` +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` diff --git a/configuration_guides/enable_device_debug_messages.rst b/configuration_guides/enable_device_debug_messages.rst index c7d340b65..d48f0e94e 100644 --- a/configuration_guides/enable_device_debug_messages.rst +++ b/configuration_guides/enable_device_debug_messages.rst @@ -8,4 +8,5 @@ The ``enableDeviceDebugMessages`` flag checks for CUDA errors after producing ea The following describes the ``enableDeviceDebugMessages`` flag: * **Data type** - boolean -* **Default value** - ``FALSE`` +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` diff --git a/configuration_guides/enable_log_debug.rst b/configuration_guides/enable_log_debug.rst index 1566c4882..bfc0e5acb 100644 --- a/configuration_guides/enable_log_debug.rst +++ b/configuration_guides/enable_log_debug.rst @@ -8,4 +8,5 @@ The ``enableLogDebug`` flag enables creating and logging in the **clientLogger_d The following describes the ``enableLogDebug`` flag: * **Data type** - boolean -* **Default value** - ``FALSE`` \ No newline at end of file +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/configuration_guides/enable_nv_prof_markers.rst b/configuration_guides/enable_nv_prof_markers.rst index 9edbf28e3..df18a10e7 100644 --- a/configuration_guides/enable_nv_prof_markers.rst +++ b/configuration_guides/enable_nv_prof_markers.rst @@ -8,4 +8,5 @@ The ``enableNvprofMarkers`` flag activates the NVidia Profiler (nvprof) markers. The following describes the ``enableNvprofMarkers`` flag: * **Data type** - boolean -* **Default value** - ``FALSE`` \ No newline at end of file +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/configuration_guides/flip_join_order.rst b/configuration_guides/flip_join_order.rst index 341f12ada..806bde99d 100644 --- a/configuration_guides/flip_join_order.rst +++ b/configuration_guides/flip_join_order.rst @@ -8,4 +8,5 @@ The ``flipJoinOrder`` flag reorders join to force equijoins and/or equijoins sor The following describes the ``flipJoinOrder`` flag: * **Data type** - boolean -* **Default value** - ``FALSE`` \ No newline at end of file +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/configuration_guides/gather_mem_stat.rst b/configuration_guides/gather_mem_stat.rst index 802e12b1f..3cc034194 100644 --- a/configuration_guides/gather_mem_stat.rst +++ b/configuration_guides/gather_mem_stat.rst @@ -8,4 +8,5 @@ The ``gatherMemStat`` flag monitors all pinned allocations and all **memcopies** The following describes the ``gatherMemStat`` flag: * **Data type** - boolean -* **Default value** - ``FALSE`` \ No newline at end of file +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/configuration_guides/generic_regular_flags.rst b/configuration_guides/generic_regular_flags.rst index 4c2a4a2a6..224ebf88e 100644 --- a/configuration_guides/generic_regular_flags.rst +++ b/configuration_guides/generic_regular_flags.rst @@ -6,15 +6,16 @@ Regular Generic Flags The **Regular Generic Flags** page describes **Regular** modification type flags, which can be modified by standard users on a session basis: -* `Flipping Join Order to Force Equijoins `_ -* `Determining Client Level `_ -* `Setting CPU to Compress Defined Columns `_ -* `Setting Query Memory Processing Limit `_ -* `Setting the Spool Memory `_ -* `Partitioning Caches `_ -* `Evicting Caches `_ -* `Caching RAM `_ -* `Caching Your Disk `_ -* `Caching Your Disk Directory `_ -* `Persisting Your Cache `_ -* `Persisting Your Cache Directory `_ \ No newline at end of file +* `Flipping Join Order to Force Equijoins `_ +* `Determining Client Level `_ +* `Setting CPU to Compress Defined Columns `_ +* `Setting Query Memory Processing Limit `_ +* `Setting the Spool Memory `_ +* `Setting Cache Partitions `_ +* `Setting Cache Flushing `_ +* `Setting InMemory Spool Memory `_ +* `Setting Disk Spool Memory `_ +* `Setting Spool Saved File Directory Location `_ +* `Setting Data Stored Persistently on Cache `_ +* `Setting Persistent Spool Saved File Directory Location `_ +* `Setting Session Tag Name `_ \ No newline at end of file diff --git a/configuration_guides/generic_worker_flags.rst b/configuration_guides/generic_worker_flags.rst index f46e933b1..74b65458d 100644 --- a/configuration_guides/generic_worker_flags.rst +++ b/configuration_guides/generic_worker_flags.rst @@ -3,6 +3,6 @@ ************************* Worker Generic Flags ************************* -The Worker Generic Flags** page describes **Worker** modification type flags, which can be modified by standard users on a session basis: +The **Worker Generic Flags** page describes **Worker** modification type flags, which can be modified by standard users on a session basis: - * `Persisting Your Cache Directory `_ \ No newline at end of file + * `Limits Available Query Processing Memory `_ \ No newline at end of file diff --git a/configuration_guides/increase_chunk_size_before_reduce.rst b/configuration_guides/increase_chunk_size_before_reduce.rst index 982d3db35..99d44a226 100644 --- a/configuration_guides/increase_chunk_size_before_reduce.rst +++ b/configuration_guides/increase_chunk_size_before_reduce.rst @@ -8,4 +8,5 @@ The ``increaseChunkSizeBeforeReduce`` flag increases the chunk size to reduce qu The following describes the ``increaseChunkSizeBeforeReduce`` flag: * **Data type** - boolean -* **Default value** - ``FALSE`` +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` diff --git a/configuration_guides/increase_mem_factors.rst b/configuration_guides/increase_mem_factors.rst index 166a57e14..e1f7898f5 100644 --- a/configuration_guides/increase_mem_factors.rst +++ b/configuration_guides/increase_mem_factors.rst @@ -8,4 +8,5 @@ The ``increaseMemFactors`` flag adds a rechunker before expensive chunk producer The following describes the ``increaseMemFactors`` flag: * **Data type** - boolean -* **Default value** - ``TRUE`` \ No newline at end of file +* **Default value** - ``true`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/configuration_guides/level_db_write_buffer_size.rst b/configuration_guides/level_db_write_buffer_size.rst index c3cd60516..14eae1588 100644 --- a/configuration_guides/level_db_write_buffer_size.rst +++ b/configuration_guides/level_db_write_buffer_size.rst @@ -8,4 +8,5 @@ The ``leveldbWriteBufferSize`` flag sets the buffer size. The following describes the ``leveldbWriteBufferSize`` flag: * **Data type** - uint -* **Default value** - ``524288`` \ No newline at end of file +* **Default value** - ``524288`` +* **Allowed values** - 1-4000000000 \ No newline at end of file diff --git a/configuration_guides/limit_query_memory_gb.rst b/configuration_guides/limit_query_memory_gb.rst index 7099674f2..38123f56d 100644 --- a/configuration_guides/limit_query_memory_gb.rst +++ b/configuration_guides/limit_query_memory_gb.rst @@ -1,11 +1,12 @@ .. _limit_query_memory_gb: ************************* -Setting Query Memory Processing Limit +Limiting Available Query Processing Memory ************************* The ``limitQueryMemoryGB`` flag prevents a query from processing more memory than the defined value. The following describes the ``limitQueryMemoryGB`` flag: * **Data type** - uint -* **Default value** - ``100000`` \ No newline at end of file +* **Default value** - ``100000`` +* **Allowed values** - 1-4000000000 \ No newline at end of file diff --git a/configuration_guides/log_sys_level.rst b/configuration_guides/log_sys_level.rst index 07e1e5800..031cee32f 100644 --- a/configuration_guides/log_sys_level.rst +++ b/configuration_guides/log_sys_level.rst @@ -16,4 +16,5 @@ The ``logSysLevel`` flag determines the client log level, as follows: The following describes the ``logSysLevel`` flag: * **Data type** - uint -* **Default value** - ``100000`` \ No newline at end of file +* **Default value** - ``1`` +* **Allowed values** - 0-6 \ No newline at end of file diff --git a/configuration_guides/machine_ip.rst b/configuration_guides/machine_ip.rst index 66a8a9a10..d184ed134 100644 --- a/configuration_guides/machine_ip.rst +++ b/configuration_guides/machine_ip.rst @@ -8,4 +8,5 @@ The ``machineIP`` flag enables you to manually set the reported IP. The following describes the ``machineIP`` flag: * **Data type** - string -* **Default value** - ``127.0.0.1`` \ No newline at end of file +* **Default value** - ``127.0.0.1`` +* **Allowed values** - char(16) \ No newline at end of file diff --git a/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst b/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst index 1081e0225..18d8f0408 100644 --- a/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst +++ b/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst @@ -8,4 +8,5 @@ The ``maxAvgBlobSizeToCompressOnGpu`` flag sets the CPU to compress columns with The following describes the ``maxAvgBlobSizeToCompressOnGpu`` flag: * **Data type** - uint -* **Default value** - ``120`` \ No newline at end of file +* **Default value** - ``120`` +* **Allowed values** - 1-4000000000 \ No newline at end of file diff --git a/configuration_guides/memory_reset_trigger_mb.rst b/configuration_guides/memory_reset_trigger_mb.rst index bb8a383bb..c3430dda8 100644 --- a/configuration_guides/memory_reset_trigger_mb.rst +++ b/configuration_guides/memory_reset_trigger_mb.rst @@ -9,3 +9,4 @@ The following describes the ``memoryResetTriggerMB`` flag: * **Data type** - uint * **Default value** - ``0`` +* **Allowed values** - 0-4000000000 diff --git a/configuration_guides/metadata_server_port.rst b/configuration_guides/metadata_server_port.rst index 20f9a2db8..0dcd9bbe0 100644 --- a/configuration_guides/metadata_server_port.rst +++ b/configuration_guides/metadata_server_port.rst @@ -8,4 +8,5 @@ The ``metadataServerPort`` flag sets the port used to connect to the metadata se The following describes the ``metadataServerPort`` flag: * **Data type** - uint -* **Default value** - ``3105`` \ No newline at end of file +* **Default value** - ``3105`` +* **Allowed values** - 1-65535 \ No newline at end of file diff --git a/configuration_guides/mt_read.rst b/configuration_guides/mt_read.rst index 4aca17185..929d1c0e0 100644 --- a/configuration_guides/mt_read.rst +++ b/configuration_guides/mt_read.rst @@ -8,4 +8,5 @@ The ``mtRead`` flag splits large reads into multiple smaller ones and executes t The following describes the ``mtRead`` flag: * **Data type** - boolean -* **Default value** - ``FALSE`` +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` diff --git a/configuration_guides/mt_read_workers.rst b/configuration_guides/mt_read_workers.rst index 5f18fd4b3..90eb5cefd 100644 --- a/configuration_guides/mt_read_workers.rst +++ b/configuration_guides/mt_read_workers.rst @@ -9,3 +9,4 @@ The following describes the ``mtReadWorkers`` flag: * **Data type** - uint * **Default value** - ``30`` +* **Allowed values** - 1-4000000000 diff --git a/configuration_guides/orc_implicit_casts.rst b/configuration_guides/orc_implicit_casts.rst index 04cc903e9..e1b1287eb 100644 --- a/configuration_guides/orc_implicit_casts.rst +++ b/configuration_guides/orc_implicit_casts.rst @@ -8,4 +8,5 @@ The ``orcImplicitCasts`` flag sets the implicit cast in orc files, such as **int The following describes the ``orcImplicitCasts`` flag: * **Data type** - boolean -* **Default value** - ``TRUE`` +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/configuration_guides/session_tag.rst b/configuration_guides/session_tag.rst new file mode 100644 index 000000000..12a98f01c --- /dev/null +++ b/configuration_guides/session_tag.rst @@ -0,0 +1,12 @@ +.. _session_tag: + +************************* +Setting Session Tag Name +************************* +The ``sessionTag`` flag sets the name of the session tag. + +The following describes the ``sessionTag`` flag: + +* **Data type** - string +* **Default value** - ``default`` +* **Allowed values** - Any legal string \ No newline at end of file diff --git a/configuration_guides/spool_memory_gb.rst b/configuration_guides/spool_memory_gb.rst index 9aa651a74..cb7135d03 100644 --- a/configuration_guides/spool_memory_gb.rst +++ b/configuration_guides/spool_memory_gb.rst @@ -8,4 +8,5 @@ The ``spoolMemoryGB`` flag sets the amount of memory (GB) available to the serve The following describes the ``spoolMemoryGB`` flag: * **Data type** - uint -* **Default value** - ``8`` \ No newline at end of file +* **Default value** - ``8`` +* **Allowed values** - 0-5000 \ No newline at end of file diff --git a/configuration_guides/statement_lock_timeout.rst b/configuration_guides/statement_lock_timeout.rst index 639f5d02d..ae552083a 100644 --- a/configuration_guides/statement_lock_timeout.rst +++ b/configuration_guides/statement_lock_timeout.rst @@ -9,3 +9,4 @@ The following describes the ``statementLockTimeout`` flag: * **Data type** - uint * **Default value** - ``3`` +* **Allowed values** - 0-4000000000 diff --git a/configuration_guides/use_config_ip.rst b/configuration_guides/use_config_ip.rst index 8779899b1..f195c9615 100644 --- a/configuration_guides/use_config_ip.rst +++ b/configuration_guides/use_config_ip.rst @@ -8,4 +8,5 @@ The ``useConfigIP`` flag activates the machineIP (``true``). Setting this flag t The following describes the ``useConfigIP`` flag: * **Data type** - boolean -* **Default value** - ``FALSE`` \ No newline at end of file +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/configuration_guides/use_legacy_decimal_literals.rst b/configuration_guides/use_legacy_decimal_literals.rst index 63650a95b..9f26a5af1 100644 --- a/configuration_guides/use_legacy_decimal_literals.rst +++ b/configuration_guides/use_legacy_decimal_literals.rst @@ -8,4 +8,5 @@ The ``useLegacyDecimalLiterals`` flag interprets decimal literals as **Double** The following describes the ``useLegacyDecimalLiterals`` flag: * **Data type** - boolean -* **Default value** - ``FALSE`` +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/configuration_guides/use_legacy_string_literals.rst b/configuration_guides/use_legacy_string_literals.rst index a00e2f7eb..0720de8d4 100644 --- a/configuration_guides/use_legacy_string_literals.rst +++ b/configuration_guides/use_legacy_string_literals.rst @@ -8,4 +8,5 @@ The ``useLegacyStringLiterals`` flag interprets ASCII-only strings as **VARCHAR* The following describes the ``useLegacyStringLiterals`` flag: * **Data type** - boolean -* **Default value** - ``FALSE`` \ No newline at end of file +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/configuration_guides/varchar_identifiers.rst b/configuration_guides/varchar_identifiers.rst new file mode 100644 index 000000000..889e5c16e --- /dev/null +++ b/configuration_guides/varchar_identifiers.rst @@ -0,0 +1,12 @@ +.. _varchar_identifiers: + +************************* +Interpreting VARCHAR as TEXT +************************* +The ``varcharIdentifiers`` flag activates using **varchar** as an identifier. + +The following describes the ``varcharIdentifiers`` flag: + +* **Data type** - boolean +* **Default value** - ``true`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file From f7eb617f3edd1113fe223cdb62cfddd6063c6444 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 13 Mar 2022 12:48:10 +0200 Subject: [PATCH 206/300] Updated --- _static/images/chunking2.png | Bin 0 -> 248578 bytes _static/images/chunking_metadata2.png | Bin 0 -> 147663 bytes .../use_legacy_string_literals.rst | 2 +- feature_guides/concurrency_and_locks.rst | 7 +- feature_guides/delete.rst | 214 +++++++++++++ feature_guides/delete_guide.rst | 214 +++++++++++++ ...ata_clustering_data_clustering_methods.rst | 13 +- feature_guides/index.rst | 9 +- glossary.rst | 55 ++-- .../launching_sqream_with_monit.rst | 290 ++++++++++++++++++ reference/configuration.rst | 5 - reference/index.rst | 3 +- third_party_tools/client_drivers/index.rst | 29 +- .../client_platforms/power_bi.rst | 143 +++++++++ 14 files changed, 916 insertions(+), 68 deletions(-) create mode 100644 _static/images/chunking2.png create mode 100644 _static/images/chunking_metadata2.png create mode 100644 feature_guides/delete.rst create mode 100644 feature_guides/delete_guide.rst create mode 100644 installation_guides/launching_sqream_with_monit.rst delete mode 100644 reference/configuration.rst create mode 100644 third_party_tools/client_platforms/power_bi.rst diff --git a/_static/images/chunking2.png b/_static/images/chunking2.png new file mode 100644 index 0000000000000000000000000000000000000000..4922eb04a53bdf9353cbc72743fcaf0e2b777ba3 GIT binary patch literal 248578 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

WHjnsKaZref;3JJ}ms*bZ2}7gc*3r(2(L& zV_e6rqd~(r1j_E#4H&N}hlq>v!C1Q1B;;oIo`{#B9G?#FDTly4vk6azV&NH`b%fO+ z9VW+JEZ+KYimXhyT`=zT7C*n{ubB4G3I=iAy!_RYTsZM^+}zGm-uxeA|u3185IFf%XFM;_y9)`n{{ zI)jw;B0HPC1Wb0g>?3gw)Mc`>d(`PZjwLrRQJ|!Dj~Y=Yv@%60LQ?1WKu`FQ8NX_t znODNx5c$c7Mxk|J*92VPFt)krCR6>YI`>{$QxgOv?&~&xs%Y?8whUUO6Avm~voS+d zb-#8+)S{!5J{O=K4mq;Tb=I%Z1B!8W!H6rLZ%UCiCQO5XC3%nY{5R^W`HgSXu2zWC z?nifx6+S|$Yo2d1^`B2#SAj_2!J$j5k8(T9?(|`+%G$X>BtZyRaq>Tgm0Oe|X0HZ9tHCd0$FA_eUJp9I|Ko7|^R0LS9+y%&<)A+{0iY%TsXIeBaJ-=-ChM{jirIbD{&<}=fahoLl8*5@k0hT1(Ft<)o{w%L?$;6mOc2w&(nUR3Vlz) zzRA}F&{+%pwG0d`}F1d1tI1KvVQ2CqLXbYM5GD52^nWZh|D z*U33uUJoi4QQ>3v=}@3?*<447-ZY!y%iW2&5+A>Q*op^$@Y$ERJS;4BZ5?LU%S_UN z@T79jhllqjnfnudIWq`~cuHnK|McgJ_RblXSGhxew~>qq44y(&e&t@RKTkt0O2oFs(le-LlFkH?In#bU_DYrm+jG#)|9&0*jukx5XH}5pWNa-CK8k#UnxfWp zV4#4r9|6R=rHp=0+PW`l_7N0oX!6ml&)n5uu^lxBHq-PvS=79EICJWI@mq%o>)p?z zU1C7SFjqfVLJ`PuZCJFpg2i;-erGN>ftn9gtdELTQyH1Q^RVyKe@0Q zxZ1H$HUhr!vakHm$Ug_5d7G9Iyk_U+vc7b|6ql(e1mW%W8!xQi_>xJq*fhU`linaG za>~!v1d0Q5ULKYj!wo(%2vCPM^7Y3%T5#bhMnnxxU|d)7(;`Ke z3!H8Ps(9>-FF`aKE0T5|woV6TKJZ)1?dx63unn6+M^AXln)TMYj{5=7XZQOT>H3#u zh#n`OFPfHQyvF2VzNBDo+0uoaHSF4Akt##+_lf0`x`>`v~EG8h;dsm!6P zB<41dRG#%sW?1ZU7TH z;ro*kRz1)+w{Uz(I@_jUcddzH;WoOihLd#t_Vb|?r7=+34C^3}wMTB-Np6qbdbBhkZlV{ry}P zeFf}-<;(0T_Mb$8On&|n-pd8$m#1z9b~m&NxPYPfCHZSI+e47F3cbdxNzzeuqNWz# zFQ`nwZ;Vd0jy1_WN6Y=inTgNkeWLV~Um{NWw_h!Vl>cwGWE|3I)K-_uSlHsG`47Z@ z9ENE$6F}(E3+y?AlFmTdIiCa)ukX~jdQQ+d`to!w=yp;GJk2xtQZeQHTaA?O!4M*K z3{}}$9!&DK%Iom9>+uXX4z_tw{9fD`CWn{lUBYD#UBCH-yj#9=H|*6xr7{pG@LHev zHHir*F}$*DudY%Wi@!Un)GWuVmv4MnfVJ|q6U53ZUhl&mcio`fBVN)Wz2+p)ue;17 zbphe#=v2X=A#L!SQ>;7s4eQ)BrJZ>-^F|ZmDzsb=Zk1Brg8@#e0s2ZL~Vpd#@&}wOTo6)UCZXsC}~q^u(c)= zhEKEO%;hD?^`Zm!f&s_MYVO@|Nd3o-_VlrB?3C4SWpUEk9XNZY7QYx(*!@rn5c=l0 zvx-;q8|oDWn8U4`k~qOGVYMi!eKBe!k&lS(he{aLF!AIJ4Mg#nvZo!Bd;s>W6cso= zdB81PcA@Ldi#l&s9W4j`N{ol8=S!3L!7`G9c3};|(#alq(B6XfAVxTP<$Lgu7FVY-M+y59_!R-i(*N{T9 zxDul|@v$YsDVbXzN_0Ma8oqMcP|IG}iZt+c2n(*_dNgEkO=dD?)d<${2j5D+zGv`l z3T-WdaRV3<6S$7Exv*dYNzP%sEmP4r$_>*g*mw+sP49!uY_5fsGjrm zgnDqYU3q6#nyw~D-J>i`!Hnr1HP=3W+x$ZIbY?#ln!gIynVp6>Z31m{jyi7yB#%PE zxng%oY-h^$3kL4%$|8FtjM`WPtgId5{_P7tm4K4${a(I${>G$y(^ZsaP313xc1~-B zmD80SB{y`)?1k2-8zHL!2E)x?)_OFu{p=e%Yk3~H;)exA^0pHe&4G>3*(SY4H$qLN zk;iW9v$VA75}*=;yp!|&{!jTG5lt>C=PMn{tBxGrf{vn)^{HB(Em6MoY>{TXAD z;XUXi%da!KtC98k@(4gY#3jo>&vy~ahsBM)sMw%#S;7#Ki9Hvar0XS)YB>B40H2%eD3K@=sWMmlFB zjxw))_Lvi$cGl)pXR^nw_P(;dez*OpAZF^~Q=MGP{*w*LF%1vv2~R@%*>qJtpix0t zy{zvKmU^zBi=aXB9cAA>VfCxS4S9I2RqT*K zMxjDw9kzmvBi7ZV2%|Z4(LMtl_f2rdii^ZqGMCArN{2^tccLSDI2+3`q@HRh17>Sx zUs~sLt|4p?Sgf)Yh#1*3^yea_NNGur1NAXQ*yiRKV2&ks`{3Q2p1d3{M1g3SEKhZe z*HLBmAM9*Dt zDi5E6#h>T`cU3eYQS$Q*t7~vU6@}izy^>L5-rV+$i$YNj);A0^=z(TE-fdaDBA3eb zRcn7XCq>E#dwT1s-?cyisiK#wj7i1P)b>$?PZV9B@<*UrE{3e6pBe!>#cgb zMVSdm-tnu_ZsQ+8Lt1sNwb9MN5y8>LOUf&Lk-0^4muIZNY#1kv-VUP4odHH(M(BIj zB_+QxeZ2JZ-cEM_N%VA9&GEBmf1u_cgf9LbZ267aif6U&-3kfwhkWMdlgOVV*?_PE zvSl6xf%GwfOESB^$vz=gS9-@QQkS050R$hV5_>o&KBA&t)IR+cQ5Ei~(^+K@ZSH?fwSutRS}ormjHM@!G$k2986QHSnp)Dz=N9mpi3f{MmMbOvng*sNlZQZ71AH>tYrZ7#=k><1+G{R0S3Z-EZkjV=N$DQf)$iQ z6GpS7v|hj&Smt;*y1z$z3kI2A|13Gjfgm64woGNmI_!K+8$*U- z*Sfzao$^nmL&HmbP2btO`b6NqpS|aZjr!A%FJkAq;8?g^%`f5q!;@l3*(3;a}mh1u<1p5hb zvTc~kr`8Gct_B%@U3J2@N(^%4Bz49jb~+NUM+kdpueEO^7Ek1S&s{_khRG^oN&NTD zlvbiXda|R=y*~x2ARSOE^fp{m{8Wkgy9s1ltxPudJbahYHa51aj#TRCfP&M^+=Zc` zN}+IGsc{>J33?X7g_u`V6x<@Z<`rz?(h{B0H|%;G#ov#2+v}3cF(9KxC8AR$eb4gp zx*n)23pWl0HhD^C#|C`e-ChRD(wTB#8+rISFK=dBbF8jI$NsrSRe_5xJwORsdy~5y zm&;{MR)~!_e)&;c#uDbBoYIqlTxgD!%6*N|>YoZiPFmKQLqS zXu6FXOtic_g&&p#n9L<=qGBOafCRwZ^29;Jmm(mGrGoRMdA@mTEe9wOA4OfYB7fCm zak`HAb2!inAFWcD`MF*a3{6Ds1~ksj$25nQG3+4Z95;^ld-Sfo6lI9KRjOM3)N=DR z|InY(@O_?FU^@CC^Nr>q^YZqGkIA`#z`0X#S183RrQ;Xz^WVudD9tN+fErLLfqH*P ze@i`cBkEOts^R$CYd_}&fct*PlBnA3M2ZfVHndQruYWEjd%cN4Yvrl1Z5bHU?km>) zzU1njd1LKc+32k1BE|J6rhW!yph@KnZw0kW$^&85Cw81_Y@cF^=R2&6))UYq#a zsy_?aL}h7iXsy{2L@JRRXzqD673tUi@g648*Lxt6=wTlSU3G@Xwm^wa~N8AE!&pWlQ|>!R{YpwR5Tj68<8cB$7FAozG?mtMBl6h$M>RPx;*2r z)x@U9G)#nj5kd8tLjM^5uL#B*wyJH@1Sb+PR_-teEWH>t!Hr@0TcU|8Kzm9;Kpoc$ zw6Mv>+L|>LRiqwhgyzrJ+Oj$V;5wlruX((Zgq4+h(I=SPnR<_@hEYlC;MZ71unmrn)eiO z2d$q_hx*%Efwd&C3nINqc+rVzEMYWe{XO#Dx1@pa=KwdtYIwmL8SnZ2+<{WYsTYYV zigWsz1>Y6SRI-pV(EjY!5iX)>uX_G{qetciA;I^#AeEike}z~Dj@nl!&Djd?tX@+ZN=SHam$O=L{*Uz7&vv!DO&wDMb?ie*mn!S)clo;BGa}UQ1=*G3fB8E}KW&f~ ztAF3sdEvn;)QklU>MB2rM7)g;eK&fjUWSRfQBsaiykrt~qH8K!{j>5QCM=zXV&@5Y z;Sd#Tz=e;#v=c(~RY*izF)WQ|sWOn{IOBrdiyD!7XAWR%wnZ>Dd} zRixJZ8on>Z=vpDaOCn=Z-~Un8$v?07$z9H<_t}+yq7k`tyI@kF6jh$Hp|*orgVCwK zYcci)&lF7~AMj=tSCnmI#a)iT-z(p^yQ`Sw>N8kOEV8{S-hhe6x6ALRT42&&O_z> zYg(lF0~)r+WzYq@_gx*a7U4y~xE9AWTJ*3ImD@8^3rdAqCK)?riuXVJGfWP#Vu1(d zE&;s5G|^ihySMiXoj=i-?1pC{O^Gc$Y5pq$?HU$3HX6hp%y&ClxSG_9!~1xIFs33u zf9`b^VM9?Zu~IuAb(q6Nc(>zXxw}OFe#3dgbLHwPvg7gOkF2}Lioxdd*&Y$+E)E_| z5jEW?71ihjRmEoGYA)rmlD+oJ(Cu8647_Gj(Uql_orpLw5pRAM2FBJ?cRE|x+t0x1 zl%6Uc@%pQ0XIVfl^36iCwdKE-!{#(YXw~$ebWjn!s?EmiU{s6_3c4)0TLH2thUYF% zur}6O-c_iang4NrOWv) z2ep&7)UQht50R2(ebr8g*x!|DvL;LWVc-_mOR^HUT+!aCi~5~6_>rALxINeaD! zBWB6nbW8C{zc;j4>#Hd0?&Qb_Q_YdKL}|Y}0d9wz^q}%k|OGVhhrqs|7*XED|?M zu4PB?7F}cp4mL{I9;{fhb!FS|@4iQqFiX0`Pjh5s@*8OU1I<}~qt@OA42vA}{9k7D z*7qpU!$~zfvglnuZ{X3pc$1?+D_F>WLi|LXV#C+?1<(Lv(1L{D(wvWG>GG=S=FC1O z@=1^MR&zsM_eQ^ku`h(kds=L4assx6vm6K;Wa&Z>LrbEH*wa&M9#z4h#VyO>IoH21 z3Xu0>eS9_wEJ4Vp^AIs3F0-(b9xdgu~km_!6DHj&5Sh9*$8AL*ZS2l+qJG*gSTnT;x|SF^t{(s)k2r} zRgvT-Zi=T<2Ga*ChQ604*gL&0(I4PzZoC$?_ZUTr{OA&U_;zAlO1kV}I{Z+p z1Tv-9dG*#VCJ^Q7(fUY%5E|M7x4^r@jHcgWS24Hm;RzedGTqlaFw( z*UdEhP(Y;hPj=4!s@#coVn{&+@G z%HY2?Dsr_%f0Wc3&m6M4>C^kq5MGRFdj9F*bgHo}GmXd z;AQ3RuYX-bv~Bf7561^`3;GU|2n?6IyDQu3Z3xt=H(hS``TbNtoN#4_V5)-bIa|&i zJf5YCPImZydce0MtUdHWq#Y+6L#kX@W+>!FEZRn!Cv225@~HWGW8+iiF!^k!h)KtN z(5$&sr`TX8T1(>&3{py!QP~a-dR}rTz%TC7^DE0?U)&!VRaC)Z$&(A+1dOQ4#MCvV zdU0lLh1wkkh=T`%`yq;n`cF8w;=kD}jYN5z*=`!km#>M8Zo}5GeogYSE#XCwH zH=IV`c~=Yy$EO{=FMutMYp$XAM*~a^j>37^%oJx~uyG=mh>rS&U-9=10Y7LYrB!ZQ zhaXOMYbhXomi#-a7jDeZsG@OW^P+i&rHkzsSRi+_&e;ekhwpzuB1~la+#n4qmj5QO z0zboALfL(L>~lc4Td%1+Bu&6;8(0!JluhSe^o!!|q$(aud2)rdXWQCV$83Hj7Sy#* z0wzl8Vwznu7c!|%u+T#1{K82jQsIt0O$UH44%8$1XGh`HQ)<2fR_30*B}lOW?krfy zX?k5tr@ks9*0y4?1#9+=Un*#6?)i);0xW|ZV+)%2V95Hq!diu~|;S zNTU~+jWDR0+BtVfexQ||x!xdNlL2>AL1(D*x!zp{oLghsV*Qv&iG8d&w>|<9c2Vuf zjp!>rr&sWST%eKr%*(NP_L@X+g)oY%|1a*|GAgd1TN_M5u;A{HKyW9x26wmM!Gkr> zNCywW-Q6Jpf(8iEG#1=FXgAtefX3aXbMKwCzIWD|b?5i|K6Os*Q&oFc)t2Y+9lLpB z>Z0SzVp{ztHVSQKr~A)}Q$;RM?2C2{=Py)d)$N+ULp5xlyg!7H@F7bc3>{Dt9RH-k zGZ1bi@nly8l7KKhQZ-5xA;(`ae?zZi>LslC5~KIcWk;z;xqV%oI*i$S1pe&fbKSd6 zY6*MBZXW}_P4;aq|Emw8??X=PfU;-66 z=vs-JCQ(Ghct?Qt>6shs$E6#crQB|ddu-uvc~EguY5i>(!mG7uXWuH!@KZ8S_C=$Tkcb&L@3PUesiR8Ey+=irmj4}2EUnENtx7_$r|x_7 z^?YSN@Q66Q>9vzy=+k|EfWOW5IF#=y-(v*~vLhYIWpK3l_DZqMZBY{2B-UtR4PW@Y zq4h7h5i*!F3?_XV>W+1Bh#`J_9Au1zXVEMrFi?qWeW>x&+`0b_Xr>BH=mwT6Xg-c-2^ z)cK_!Kg?ZzK%|G86q7FFY zWL>DUvkRZgLM{v6tzf7{;JEtB0)=LBr~$SG#q6U$unZV|s zKX_5>RGj+!Gg-%$*M9=5*|YXl3n}v@d@<(LtX_5c+sw~3K5F8B^-^E(<%6veF9E3&eqF(R%b*TU z&s)HV`iF$rpJ%%RDMLMCJUXYs2iq}9GuVa_1f+Lek0z03NMd`XaQT{MG~i8`{^ zp#niE_1%rT7xUtmVqn!|An)mAplQaso>N1A!0pWoY@OcPw~1-g-(4fBim#eBM>@CH zinMXBnSTmFyEv+?ff*MKl-~hq;mL}vy z=vV7k(v_!OBAbd0xpA!>pF$n>4m!Tz73J48hcYH3_n$I59!4IEL0bOoFW5mR$`Edj zrr;zt3C}sM-rjXITJ8q`!G$PX2C(v)cLHB9Hl)=90cNicK`u$D*YSS{e)uhPa z!_MIGAG;RB4RU1L=IaNWakwD&_*0spvKi_94nePz-?-UnmP(l_o`jq0%fGKeGgeQJ zAMiV37<)R7hyxaO5K0SB#QX$};VWA-EYb z14jL>&I>AVX1-iok&nM4G4{GK?*v6=48i)@06xxEU&IEW_oX5~d4zU^C0<3$xfp?N zitAa%SE2WB>Y5q6%?WZBPSq5_U)ZN*8q_ZfuELO*n(_PZZB^6(!oa!`yhcTZslK?q zUtF^L_VP$Tze&Gk_p^8gAm&*|o*$^E8>h90%v_#}#?@R<&!geq`XN!4OkBA|mD7tJ z5ZD{ux~ix%I|qeQGWrnb#t7mG75iKSZyjzj}=JUmR!MW1@_oABzT zD{OCaRxdPLWNU{QSX7R?71*D!cXqw!3&C|A;^{WF2@A9QrBoa5^0tKU({RON8g=td^<2g632yIe0k|rJ~YkRqyC_p zCSWi1DpB^M3|BZOg=LX+y?O5~(T#!)!zwO3T`AOt1m%kt4}XFKSej zSSzvm1&g1G9!3RGiux#Y+b92|S(wkze^Z0eOTy!f-4mIxZDN!Sq~_$*qy-Eq2&%Zkn6`-J_bAO>6w#g&SwoH=OdW#Z$uk+P;)l6)omr{CSvud>3mC+dl?AXaqCOX7tf!q3N5w(6K_7KvpH?I9b2=;=I? z&D0Dr1<<~x)9I>D3&+gAc?Zk$ub`~5&BrN_Es~q4Ps(I1?v$pQ@eLq;Uz#H(Wfvpd z+{%njZc#^V#zTh6)0DcYJ}F|Veaa=TpB4O1#Vqub9XkhMSb6h-<6o(DwOO=?dnM0Ob3dn6x4<4v6LnRur)OVZ;R+9KL?h$M56O{#CZ*pirKJnmxrd8)cIIsXh7EIxK5xrpx5 z)$T!m>ZEHC(&4k&riSRiovy6~{xKQ0^0-{}{WDQ_^=0Gr*<0BpWpp)3*uIMEUr^h@ zqFK1)duH%mCyFM*`}4aq6Z$`%N$ves>5=QSx}9&Q3v}V3u+5)F^^{BW;mY7ApZ;yL z@C2ysZuTQ9=;_@}e%ZQX#E|h*#R_69t~O)o{w2J)yfk+3H~V@uRZO!?^8|wL9Orrn z_C)X**xZwowMyuNVE#ytv{dyyj)mL(Xu_ThsM?YqIS(;47W#c%5kj0GECL(j>ZhTP zTjZ>Fq9cPs#42<28CsPg8QcCWe!q2Z1MhMu9xxOTmnh`mWfS04-6@F7`)PdX@qHgx ze0J5FCuQ|O;K{vO`fQ*Ag6~&I5+tv@`?C+w`<>|_?%7M*E1@07cdrQZ5=RKOdLpSe zUOn!M|Ak;OfbO2hLJv8?R4(8duZai?<(veGzo-!_Rt&&wN}}~i{kIh0k;!K z8v1usq08FI)Ad&GtAo{`=NdxqZi64ks);mKalX%IT`3}k!}|yaxDLVI2M}O28ubVk z7`Ck8D-cnVZeLHT>||aS_z9>tuZ(h3-P4(jj!p_7dzTY1bx8!jGCgG7sfwXlO+29- zV$-;i;p(@acmv$EG7Bh(NP;{d>v1lTHLt#Iy^8x2olSY!OhI{c>GVZ6uam+s}>9s|JiMwjiBO zu!PsVM<)HO$8`_F0-rH}{8SM-s4es-hee&3QsbNLS5jYO4S@$w^hlc27rzH#9WVb4 z*;5a&xtw0Ae`nfKD8AB6y!p%3!ND>LYNWz*K&~h>eN$nc`-ZrG`!p!ZJm~9xy=fLM z^y>e9_3H>HcKzgKJx{3YQQTG9G^(3mv6)C%bOjr=D08~MwN+>M|D(5zqKyBLwCm|7 zazWaXgW2(s1E~7n|7jM!@}GUhBHM8O|G5p#7Q!Bh?nTrC8CIkVI1hTd3Oc954oG<; z8~(8nhekB@F(-K4<>c}1DCquV0Qt!5Y`=g=Zk{#|ym!yPCq^X@V0&I*3pdy%F`N;t zPk06%xsCy4ad%w5=vccu>MVP*+YPxt?!jw`EC_lOc@RSBS+<%il-~90iNO2!Fx|2z zya;UkyYL}y-3+yet()u?FT5ivF%ch)l7sla+P|2y?)vilU*A0UW!emZdDmr`!*CqK zZPsfJk%ML#&e!zdw*ru_b4dX&k$mTp*I#N#dLRRa76GUh$D0XK(?RdfrSTOu=>u=J zGR{}Av0brt1Nok9RXSa&`aH0196$q^5-~oCD|A+WI2yN!jjn zfS``zgk0@w#)#DHB_w(o@}Ssp#sj>f`5(pPJ132WlKeAIjQ?!`xMW?CpUc-WTP82i zuDkuTHr?~shPiU{N|LQ~>N`oJR@<*^{~b#>LJX;`|4h*T%R-eXs`~-{Sv5Y*d6wwF zuZh@bzOab|BS|%kS*w{=eaOLg@jd^C*suO+Cm~WJ(2+V_)Qq%5ct5Hf{3(q-4~y1S zL({}bzxgn5@iavmq#TLILIVaY;Q*;GNf7LIRHV^BDo+6Bf1B75c#Y75Z z_Nde(-2MYCC;O`Y|2ptB@3nyQ!*i@BJ~#gI8^6u+p=LqiyInVt_ZxrfheeG|JN*9F z^ zc|Nqyb;vR(Zof_=ko%MS4Fb7JLDc^-=f3I)JIQv!%UQ(f%;;bh(07KaPLKDGtGbE{V96bF|2M8;^x5 z*9D=+$>UO?3#8rux6S^Sk|DEghG600{oks9VnHf~az)Wwn@*PUV#aMqFR~#1 z_fGG+rv5UXz-s{ zW=aF~!>wHl-4gZ%)smD82FP3yN)|sss8IduPI#VQUN&}Q%FRm1hZt6Tcd`$t22-cm~l30o;PS)i%B2RAq5^8ggtg4xe*v0f~f_ai2P7u z#!l1&WrdP&$%4^vG$3od@@drTysCTE4@3%xSG^-}z!(-Fx-P4`9*lw>D3)jkEp`Fc zK)akpG3AxZy`oQ`MnM5ri)0q#0vaO2d$&f5lUT@tQ9AXhJXU+Ed8 zh2B@unsZ)%T-t**fQQZ?@N!Yo@YlX(6>3)}V0gghJe%_KPQ^BSKsmY$luh)*mWoz%v_v94y9RDs5oX5xC^Sc#71rH+z zucQ><540UXq07tXrWr}Hdvnf~BF2Bfb$cYmMg7@8&+#+nE8J9%_C?F8OXZ3dC~-jy zByI=y{>G`*%Q*2pJFK?C$%*a$qI5Os#(T|lvymC5+X8*%duD>Bz|6QZhHsny$Y3@{ zT3R%!5XhRan`(BZumvcT2KNA3<@__h%H&_hf=YCWdSTjfiZl-oU9}4LXed_a-^wcO z=trB@x?DS{uMg>T-PYm?y^BoblgV25OBbbPMDU0yh23ges(!e?y7D>tk&O#%F8tQd zT>pLx=xG90eYh-$ndFbDu5~Tc>0mg{fc(fPIid*#-Nga^23rJ*VXqu2ylpQiZhDPr zDCc!Sr^KVYJ|~l+=c{PXN89s&0Z4oUAO8pPzxTwQ8Y%C& z@+a4baY$H(WZOB*Pu)a^x{^}18RD?iWU1H)#od}3->r?Hjn87OxZLHgJpYPaNjIo9 zaB9t`FwENgp+zcqR{>FKX5wRkisH6bONc(nk;Lt|OGC^n=r+*#)QdHY!Gvg*Q?YWD z=D4IajnVN68-=4Pu((7%>FXI?&%5r9p%54i{ea>2bMbS_YJUC!y%2d6BKe?h>h-Lh zODEBO`DPdfuqg4;7&S_6ao{mEt9sOo@|3*S_uhxijd~j)JtIIAx%QR=67n`HGI=yZG?wko zUTl|d~2{&p=#JV#|Hr$nE(rYw4kB%D#0%ldKJWchS%l#PueI)=ge|EAJ=MF7YDJ}Jg9Tm8 zeaRfS4&8x|=ddO=yI>x^_Fu)ArL3%TH~hom4-*CG3B>tqFG6Hq-|zUR8ZB~7vTWJD zxQrWy?dIs4Gndmh+Wv(HeJt&ux#dQ?05dClw&_}6qMYv5b6^kBtp@Pi53KXNE|c)X zhx|!f??OkTa$ifZXn)!)*mPgh54zp{=;2|l?k#tkk|XFyXks`KM#HfDY2|zma+TML z-j`&k%6Nb(ItZJNUMf%3p&7aU&i3fi`8#IyQnyH}O(aaeZ>v#n0~D+Q%s3`v1*IYL zv@s0D^3TaP1G9N8`P*{Rt2YTWpTk9t- zdtbp%ch0}>l8@Kj(DIg5jwPUR}H$~7!Cj1?T>X-fQ;cZ(j|MQ;rYwu^=@)NSJ~P+64AH}&->fMj7= z#Y8P*t#R>@bu|}~%G;B;j^D6pL@^n*s_b7t3*IB$a9*F%p`l8|{af90s_1=M$(`wg zg+|C!Fi=1wzfTQWiiT@8pNHTfSLwaF@cx*++@*wE+^aL4^{O~M!IZnDlPhkEqOK!6 z{p_F6g#wfN*~3$7fhb!ndu@U#_=$&Qh7Fgb+`Se|NnMVoEflcDMPMX?pmqKA@p!T* zWT1M1!P1EO*z}7SrvDbevaPIh#S_&QN4RA$83};6@5C74L44BlkpdE=*+jzUO4)7Q zFFqSKKz!q2W0D|}be@TR7&6{IYyHSQ0y}t*eIHYiEQF&_{!@#{XQxNilB*nr`M&iTIxU`3yR;@6y$UC8 zr}v<&{@0A{g4M_rx{K(}?3EG25M`hiFIm=!0H)Uyz(9IOc~B;u?qt?7tWl=G~I zpxRf^`5=Z^0zdnYIjiG8(I-9o9mNJ7-e(1~E0tQRRjs6V(7XAD{_mn!FV z$fsvC^k#*hWITM+wJ4N-LuZ&Jwq|#&M0IHdR-^1SulVE9(y6mEM%I-uR0AkP9hPMA z*<5xBO`v!~F$m^xh0G%nt`Wpx5c;K+6c?Q<5e~Tq@6HtK%%LyYD=;E%itk1_MmanM051T2ZY_t zdY6}26iRcXKS$%QJg7@WrJSOGj%kc&zCV7PXouL*^5JU`t23=FLWHVgx6tC>`NNsc zUJ`SnY^EIrsVc`9xd8ZkGm;aGMawdwH!aKglmoYM@#3zu{Zu?B6)4w zn+p#ua&6cpuo;UDxS_=+=qI8OjXYn@c)!hqb3u7`mYB4O?ZU^a`zRGyhPd`{fkNmG z9H3z<;k>|PrzB|rJ7!2jdO@8IyxpOkfab#q!#TYrr<9f0sCeA=`a;f!pYqrNgoO#1 z_4k}V4O6RQ{}LPUok1jukprq|a4;da;GDGQEW%$UD@?I*8M|UU3f%{S^1i-l4e;S? zGziT(Un5^y$7_0AdvGD6ItfAgYVc|qI!$eZ63pK^sbk+`4IAGTm{B1`+XK0cGI4&!4W1oivndwW2}7GOf)8s)_|{%71|#19VCiemp|YY z8`Ru3zfR|qlC9X2Mm9Nww`~e4`|&)zl18>-vdQtxM$B5Ep}mUpi6hcuBhEV;#ebOq z)&kAKJWRsJ{c&B_RXW4Yvt)8)Vh#G~wRFFYOOKwQT%FjAU_Vnd{q(tjFWs{}eug_m zZ?_|aiiS_;l0@GOa*41{qv$ueyS=xJ-40q|0LQ!_zV*qW6%n=!{We$Kmu{wj2b)wz zY!~wY=6-AD7HcyM)AgI0-+ZtocFGD1MGz5}+d6)0VH4^-T6=leBgXW@_`qEJQpp5t zLeb0lEAd9&u_pmi9SsiFThm(a<7_fMn~HUT4Z@;d>Zw?7(*ZZIdO4G;yZ7+Zi>Q3L zK^0Z#>t^nACNZK_(vhFJ*v3h(9j)i_tNTz<^>&Ejq+uNV#|q$F$G6rC6D zjfg%F%_%#>B8W3+?N?$7W2JmmEYCw!HPy?lS!>FFh=h_FHtr5mev8@?zRfDOVE!ED zD^mU=uS|C-SNJd%i;iL^%*u4KNHBZX!m}6SlbP=l^h-w)++#pb{qSYl%O_qQZ>6>V zQ_?O$p*QNrg*4N-#VO?u`xNx*WwlwJNaht<7UqIH{*PN1KPqZ=kM$lY%*hyNe$7%7 zB0>r6M3~_kUqiCfW#RJNY~tTooSX;cNpf9b?-@6NKk9UJ%yJ{+geE4p-nh4XLL_Xv zXy-WSGZNrBmeyo&KHO7}7nCJ0<#qm*HGe^CHVoVNQps}GJJyOazgRfx`NbkDcCN)o zQF~C{W0Mqq z`Zk5S;`{pdtWen?!pvZRY*d5Qj+w@i$@(P7LByCCsG8ym|LjoomT)A#czCLhg-3>O z|I^(jOVqhEgPus`sgIdHwhHj*ufE>RMu$9$8WICr`O`{+7&+_o^eH*(o5j>k;xEYK zxR++&_Q$C1%)4vTc0Uv(**9pPZ>=g$XoTCkx`jF^sGxpVpw4YB+heW>l92I>Nb;Yq$90W%s|^1n7Kf0P3tIgqmG8w%q_IVn#U?%~?KMT1HDvXXbvxMZtJMU6og& zU7OCU^&yuamcJ%H9v2f6x3#r-FZKAW^ip~cg9O85ilE#2Gz}vEn6b{w>^yhp{J{BH z&3B!CkGERG(d#&KWjhw?B5TWLtPDE&hEl9+S;~b*h$6MHNr4t<(-))&#_{) zgoNiZY;OAyqo~_IPsR)oUd*85po3uD=&CiON?3e)hHgMWpaT4&Ny!j)2xQ2mlC&bD8{YA&Ni<$$?@)@7{y-ByGpH-A0tJq`xjP!jkf! z)lm7wVUcE~XpB|D91|vx3z+({fMG#~0hb|z1xV#{^m^zsqKtV?Ly-&5#Eet>i!fOL zaiJ49hBKE(3qxdxft(j>Da-xhP<=Ecp7H>E*t%vqL~3NE7)^yI5chEQ5euRo6GC)f{ykfk=l z!fwCU7FGL?-e;#{QiUUS!O-vKf1B=}BKOQ&>z=7>Hk9^jg8a2={9{i^aUdKj$tKzT#f<(*4x zbmwlWQ)oE*M)$I?V+r|YXR+X;n9gUR+xM?)3;5>>U0eRDM*aLCqen=(zpwpNNPl@8 zO`O=P9B$sfoV0Bsin$-N-pMd__(4<|%WT*Tu*-z}Q+f8cji95EO zyr0s|@06J#ORtKJvl#Rs&zSb;G)M8xfdLD{y3Y^+Ov%;Sc5u@47o8`!Eu|}*ID7BJ zL3i7?3g7!sb!5arK#_%GKha?Z&hZx5Dq(DWvecPfq>ohe{$+UCzpPP}Z)$fhxfOT4u7_cRsf5g(WR**u1zERI ztTzZTvZQP?ZPQB)4hIAas7GyTU-B;Xp$x;8oh5%hHDc|B1Hv@HeP_NE|79{C>w-=c z`M(hg<;qo5$Zq+%Wcc8Q8impHniQOv0y$8fTFlpz=_X(lp)rbVIP@-`bZP!8)KJPn zz6?o&JiqvJl@zma-!mA7th3Qf)-GJMJYSKh5L7aP7fEX%>d6ql@AOPOj{l9@(`v(;2R%O(tUg3BnCv5ol8$N zzIE!~O}wWBjqc5v-z+ejAspceDT|q9mT>Nc7!7iH@%QmxnHeQTBlw>JWshv@I^-M- zSz+?+gRjZ$o;_~xO;gXMT6zc{9CcbKmQhEa9`N`?n-9Cz`B!%Cz6ODn@wB#oBr~Ir zbuRQ1s2Y_ACSgM`GD*|bko~zz%s4Sh)0teQl?2WcNTvfH z=$xbRs5drAHKwR^3o*5ok`$xQ!i`J+>KIw8u9sk%8>^o<;-0gXXbhk!aF^F19=U)9 zefl#l&G7?keNiI}%rc}59xJb3FL_BEPVHC?1bxS~-->I>mwN^_Nh{d(^K9v+9g=3R zf#D1n+b6$-+XBfDLsx&JhbkDfFYs@cSqDQM^PJJa%o!l;3_cw}NP&5_r*2a_)P-ed zZhK{sp{mn!_LF6vSsCIM_>N}WrEXEuSS^?V^oIO<^}+1u>)!^XX_T$E-TYg3a@inz ziVd;YXTat!J!AY?Pmk9Ex{J&uEy1YxVp-G|j7-aAYdQciTO#P!o;N2AVg?&aG_8NP zMykh@V#Z%x)$39-cRHaug-zA%<0Ua&%G)|>qmJXBX|3AbSu_aJJ=!k&{B>LNR{o>m zj_92EV_(A;Ot1DG8M}~8l4f`m6$a&X2u#0(prbE4a8Wng-%n0;2aP2q!-6=k^U>W~ z9)2&{!wv9OKb6?h#hHH?h%4s`DsGsXl-n;gar?=g6;|?>zo*?wrqUS~7W+Qi7@!w0 zW}Vj=J~C#;QT)l?<}6dqb^`$nZXe#RFk+eRf;4p*A_)KZR4_Xdoz=W3V~~M0 zTq9ci&~y>7>&Wh*U^wE0MIYr2h(Hd{n1AKr=xAl~13O*dCW^(-y1#Eh z1lcwUt0K{SPfaK1g?U#=9r-+bS;2-jE`qpZVr~K7w~;KC8g9ppx~g(;1^+W-fbKYJ zNC;0OG)vTt6F;OCSK%j^b;fSfg~5nFrlUj*d+?6{(rm^FFbYq?&jYDHA5IZbf8v-k zM{F+|_UGq}5E4-F+72nKQ+R|qY%5{xUsFmrdgzu2t+9jHEB2#@9YOn2CPk!^(#Qz* z<%h{Elc-?cFwei{-$S6Bo-?5#RBx*uuIyAlH>a~Jj+kx5jjTDE5q%a~o#M4%0#%-^ zJ90Z!cCVWHreYXkX_}mgzXbpMZnLI9lZ=HwlJaX9hPtzPDfSDe-1jx8M9r}c_YE1Q z2o*eeVuE7oGvaCzh7vJ8=halX#k8_S>*mX=Qg1v%p%1`h_ymUdCGb_`CQd-?xig_S zQw5G5yL7Rs?HMS$N%XI4=|MS;>s0~cBc>*A_)k`Q8s<#DGp|f-0*D!H!&)mtm&GbrVzI~HFw2Ytuz)ffEx;iO962*0cIv1Zh*Bm;T%2)`^ z6SwOZ>Z}%VAoK6ba(mMxs-wV;7AIyScF1vIuGjmgqX}Z`r7)r2wpojXM?`(#et|C& zRxn5V;27iJ<_mBJssK!XHlN@+Q@5zN#vTZKi&7el9I39ZnfOr~uXtQoum6JSAytIH z@R`&Vx?2+Z+vYbfz|@)B^9l$q%B$wdUHu3y2nCE;N0LY6>uDsd@VonRR~ou@)z72< zoUEDJO^(NzB|`ZWqk->z)p}8~o@dyu@$S&^m;|)_vCcOY*9Y`A$3nM~Hok=iKkYBg zSlb}FggvwGWwCBr|2p?{6>x$45PKN)K7KOKaeo<_MxijXLuy*dLr}z6pMCbRC}Y@9 zva4v@v?^fb@X6Ju|XwfZ?Y&3nKQ$KY6agFKXP8OePGQuf!>=m1+^uRYJnsMlO& z!{$pRn<1cRIksv$4d}3r;*tGL#;Evupj5sJel#x z*#jOi%BEM=3UF2KXg1Z+(PU;Ckax94<>El>UoC-9d<5RzvOaz313Q$)}Y} z9jk9{@F2-%7kJkLZN$>3bcyZgpE=yjs!BT=!Wj&jXJDs(yE?lden8hp)M|9?Pt<{R zT$WWVV2FZ&Q@w_kqk*}lrQq;^CGeRo?L^1%re!@9f5v)i%ctrdFQcj>X7x@&(h6vg z&7$7T?}9c?q;qB-Ontq6-&F9i6n8l#VMFMTfRLW#OqRR0wU}?-kZ!2Dve4Y+dxYSh zxeVLQE+WM(w>21#Y2-ImETr=mdw)1lH^qovxAQ?&@1Sz3GeDllW-^hWGvMb<`u*5( zv}i}lGgr(GV1~?;F!15T+v06;;7G#Dj~OOf05A0bS=Y`oa0qnFryMPZ$89?+$Q!0$ z;pi^2*tj*Z21^y>`0cg+t70r;7*@I+%^|E6Qi8tjIQC+ib^b#dL8xhyYl?K));H27 zXkC|suE^h*#HrDD>xbsP_k`e>k<|}Za%I<-2Jm{NF$%C}9mX@+pLN?Sq-ECAZo7Wt z68+_|jSFi5RWOZ?$7%evBcjY z;wEp%ktSE!%4JJ}xP$WMB75~w^qIYj@8Rp*i`J5Ktff9?@yT#6hx~rGxp&@lvcZ-6 zCZqb+G|e@|-&&B`g!&boECnS89oxL)?8QdJ+;=4Jb+-jVkO99Mvw6YK^$eZ;oX+KE zx0iC9_iP8t?Qb^u&7oFafjA{;=^&QZWC*ZR-R0=F(Bd@mm-5Z(-+fk3IfnKv=& zI^fwd?Tw>BzXO`%p7;?4Jc;ftXGe`4K}q3e&m4ZIe(<%g7+*d6serPC)Mi5aeE2Yg zz#-DbOdPVDYG6qElDSdepH{6^{uzzL9Le`?`HE`eC=7V0Q!J5Xy#rWmXGaPt_P4Dx zb)3?j6(*Jmy(To(TWK#@UFNc=dxw8Z5S{j&1QqQ&EZUieY01x{?vU6ZB!_Kg?q+i6 z06)fpgQ~o6WS%$|=fhRkPJz|nJ77jzrWe6Bg!ecIYAvbIFgD#3PKoW$7pcifaQR%0le41gtuPu20hQ2@agKnct@Ys6)`S~Ud z%{n&-wiSYHI604}lzZcBkyCavbU`~3G0a8f7c1L_m7U1zzr|I~rX($3Tb8nO6M(+- zrnDnzwV3(KST6g%9YI<>XJBRRyWLHsB}6MA8|c51$1Xi=mUZP|J?{Sw zJ?x~~NI$S1wu_<``DmBfI~G>4#SU^hb4SBs6hPKKB^!RlYEPr5B-7hsK51u|U&l7@ zRpa9XE#l?iEJMcze=h6>_`cDA%+N=#yo_w_#1F7+n3GM7>r7AI z?Xmf7;3tt}9Pf-^TUJ6JE{W=cnvSV%48YlFD<2tmSwKS>t*rhMnG(k2D3igl8V%02 z^h35!SbBMrZMJaZ4U*L{6JbXbQVDN_WP{^lTldQhO4uVGm3;i(3J`w%{r^^Iu?OL(fn9YVm z%FT)5k2z!o1GXy6OsIZLpm(mMw|T#V`Ao*#*06xTH59@7po#+oE~zT~s3|6Ersk~} z4Ph{&$@fsJUa#g)+hfyl(Dtjh`}gf|T;q%@F(Bi1)6QA(iupA39eAX=mMuI_q?)4~ zs?I(BIv<<{tEWJ}{XXU714)Fuv}CGGnsP=7h9gv6OU}MS!+2!th98rmi6KMEUOa=G_}obAq_;r>1Vy6 z{%Wc)T-2H!RCUZtQ{1}(ZO(0nbLxfBz?1dXX7nKB{Rb@t@Y5#-Lsf1h&Ro@$(lVlm z7jz+QT9qkkZX-Wpc9~ez!f!`#ZtzNatER2)4q(qlq8y7;bF_=R_!{OExxzCP3iZ%; z*t$8S%3UzNP4}+KW}mQYU~;y{@}~-Ia)Sz1Yy9oLSbv|-?EcnF(L*jwJwMayr{y&o zGQrq94C~3>(f%R6lAIJfFsN!(NoxE$UDH|lvziLR+gP15Li>G9Dbo)nIeCpLCh_gV zgJf@u7E5#eKd<1#1IFH%yvMbS&3@W?gQ%vFcuz+G6+T8!Dka?Vziyi3Gp_SEzzu1V zuSSyxg1J?Em{Q+rbs{98zF0GtuhoH)hp&AJkScuZ?$bKaXp+pa$MAI!R>}qd&lAmr zoR)+&{Y7RfGG~zGdcOf#7LFVN9%nyBd;vE9H8Sg<0wx)C;DSGYJ9Z}|UVMI=;L4&L zrIspUSFxL%W4JgO2JO2UVQ@*++S(GWWdX6LaQ6w*Wijx(4**bl+yK6Kq9hjABQTZ` z;++O6lMi(k)?04^*ejnI9xXTne42@wnDk zTfge{F{oK(s55{36?TS`vDN|v5O6qB{Z%a)-aO}@tA77o<1TfXr`86+i#%wv=IECl z@cnX>Rs}TH!{wr^b7e_??>g!m0iZnUCl)r$CrOY%hhV#5nUVw+^GWPYJ3}uds0Yvu zjY#DC6vrhv9!U1^uoo3nN}K)jnZ29Oqs11$!#cnx*Qu(O!HmMq;P%(OolScLGl<5! zE;Q91z#9SCfK4F28i4O0$GPje=|lmZH}`SHB}}z*w47U+I`az#1>VUJ3avJKrhp>x z04Vj$fs?e7$>TxWx61nkZD%qEBAGga8Q@g`k``KN&*X<$v8sBpzlzTQb^2h3VH%`? z`H6vFTLuUVk4qlWw$sL>NL^$sifl?|tZU&?G#D&#ukzDGy0C?k{Zr~YIb;w0*+0)q^W1hdm2O~R(CWbi4|(NF_V!|E^^kj?l98BqX|Gfz zuTGn}K5a)bRQ`2(9_1RvM_XHOncFH#OC;{=0;YWc{6IZ`-B5TRx1a)0!7cA_w2S!K zAZc??jtW>)uWZNI4!001{+S~@(jS*BcB#U$pC=qdcOvWSB0Jw)Pi~CN;G>GR8fl0B z5mHScH4b83Lyhp%&>sSTL364q2LzOyN9GIo8Us(R$P&3ecaK^pt_Ak-D>S8uVj zNI#1#dyZ#%*>@~{LNQd>lYImVtsD2vSi9*Y(`<3U4|Hp>6!C+p+qWx8E-B%Nsv#nW z1h5^2`1XOV-x@D0Ioct?h#Do~NBzOGSJuevZZ0@LR-O;-(c#h<+n;9KqoIjTQr)Yk zYn7uhit@VBHkIc%u2!3^v6-R7TMu4x*@fMVD;-5-%9OzWb%_8>B+wqmF{q^bMn zS|-=~4$Lfk$iBL@yH{D^88wfqZc#n4&XkpB8j?J+;u{!?TYNKY_Sfr1>SsiJs7tGI zN9EtX2iZ??36l5}eMkEGTfBI6Aj}($n90+nrr%hySDp-@h(Lw7Zqmoso*FW`?`YKf zVA8cTcMNwq#Sa649=F0S{TewNx zlRiRlF17gCtxm~a>!g1izmpGe-d%`|rS$Y!NO6uW`P*t>^Ti@e%~j7n3?r#FK;LY6 z0^chc@{;zI1y$WTorofJqTrB$!otV7_j;Fv7kymD2wVrBBYE`jpC9Pi&GivYk`R;Z za6Ttx0>y$8RHEoOF;aXgP9$H#Hn^aRkxKLmUYo;_Wcb{LU2a_CNlNd`pC_$? z8Az7Sv$vftH6GcBv(}3ARae_9HN_Q7ze>)V{KU8H{o2;eE~A-al^<#3HcppzXQy%5 zntP5;8t!MwNY0P}{=+?TchZ`pTrl;Y1}qw*?;7f>r}lzfNer3- zs_A46k>N;vhrmxmVSVM%~(pN#{zM?H@)3j0%d%K4?NRSeQq8CbqVlpeoGQTy(|Z>Jj#&a zHuWd?8n@gR8JCXC%$7kIl-{n<1D4vzs!v!de|f<^G9#r5=)4&@!t;*igoFg@|5-bf zN|1_2nMxCr?X38_U%i^3BTE?>w^A$yHgN|vEMu~!C!XR4;GHv1>*K?ck|Fg2YK*RF z8FR-R_8?$$k+|5^`0cyDccF4#W3*+xjVGTPCq_qHl^-AHgI%BIq`7tr-~NJ1bojCX z!DJ!pawmjfllu?vV0H{ZqwiJ;rq>+}Z~FAP@3UvAPt=`kN0B@S z@Ne3-c@f&kSQOqbeFQ*kr@be?nfBGW9HN^^&eViY!D;-hHcVJ{LL7cEJmGjHhcF1E z*aBWA*hO)hRk%r9{TQ!d9G0nae`gSH@mjv#K*jN{BdU^Kxe>gbo7GW z)O#$K>EcMuCxQd;l7dxFDoBskzT;xzNRSKPB8d4aP<+Cw=$fDo?>sg%Oz^P%i%NUB zgTL+bCn+UR14M`IseZ!v*zLU8EuP&80G2v!wF6z9=E3BJ@6O@9KO&eS*RjW++`WaS z>Y(#B;GghP^-~p6QUyJ)^X5I8&o~Vbq`L9NbYl*c!wC|xug9PG$J&5*}Oz-#Qm-am>T-_tU}i*S~DCtE}{C&pKIc20Ko!^R9Jba zd&W<67nReBJKs4KhdghHd$x!;T46FTf7pX_^##JB7l4FLSnc{}uV5mh-}OO!fE;0^ zi>h%L-(#Q58V!X{dwi+U&^Zm8x&D<^WO{0j%7@V>Y0b=D$Gid3W|A%i2*O*j<=pb# zJq4J04<7~SYn`&k+^fft^8{>ob{34;{O^r6K8hm8#BPkdScO>>0iPqpj`C6I`oH)? zi$I})1=|%qIs7GQUw$K#+b+p&v#@_5O`i*iuKBuIJvEID%4?yhd=Iv;?*i#M(Ob{+ zyIvF!8Tdzjx>we~hBGOrtXFcax-ELr}piLx8giNUN3}i6t<+vTDO`C=Y%c{40`sa#jN#DDJ1x zj5O|0#E6^yK^ijWso&b0zl!x`feNRvEPq8Q6bsd zMl#U$+m`?F)`Z)R;^KlVQh<%ApQe8GSd;bMqk|GvF}!~uR4I!c&**GoQy83xKxO3! zl4VuS2S+2v*TosQGtzksXpI?fJ~;3X{5a!;H@2Vz2fu*b+(f7DNj%`Uy+BytCz28t zKsBmwSPl%j`?&-!na^cn6$_*RtnDwV9e59_YU|H3S>RWgkxCcBP=V0i*?aPwi^J08 ziv+`%>tWWiZGh|TZ~Mr)LRmRgPRZAazlEquGfI_3yhJ~6in)a zDyiQ-xc2)0*)6w+0-@-QH%Hc~JRG?`GB0PZ3^uS+Bew8^p}e{kkwDWFjQi|n|Zd6j#9Yb%Se$?&CNrv8g2y1VS= z2T%I@<{+IFUrMTQwES?L4Q*;>cGBi3Xw^;e z)qSB}k_bKoAKocR+@D4^yiUY`frV4kVRx6K9!|Dolfm51)&e!9R0&gYv$g09W)wju zN8*%7l}pvjU9G%b>ur{%?t-qz0!Gfj&r2D(za0$Eec}xZk*HVSQUf+R&dJDq^h*z% zvcid73~2EjonV1w#~d2E&SPH_mDIH|GWDZIDd|N-#=?X&Eza&^>)@`x_Ut68CI%+W z3e5@M^)8Ehse!lQ?;yn12a?s^WI>8at&gIVw87SeJtY)Vecwud(=rwNCOj2k=Q_b} zOmACboeU3k32R(LS)BXCT^wRwM^rw2kEwXTSxu6%<^tXfIn?AB&9n>lwIy#R1%8ed zzLj10vnX!0GW0O@F41u+&8WSy&4**F&V}RrFb29}E|P4Ce@Y(Onh^uNR0J~XjmpZC ztG;KL9i}Fqf8Yz*D8Nm8RNCPd3#?p{%(N^!=O}AqxH=I`VDK+D~i3tx54o~=TyD|DaDn!qcFihi$$a?8y6S+A7 z=RE+jtGR`5JncZ;?_Si*WD?wN^mQGj0@7n9DUqLWpM9K1zlSdQN6WMh;|kZihehQC zp6PbLG99VGj4Byx2R3O9guZuL=HryEpK|LQr>VQy-dhFvzT|6nZyGov`}Q${kE-LR z>Z}P5NTrhH{^?K3Jl!;(q6C$rTDPR}1v&OO@1MFolMq8A+cnKuPU5fHi8{KtMFRWc zE;5MYp~b}J^P?)^d!+&h9=v8xXyVIBJr@J&$d3v8dNB3b8R`5u9nh!s{l(jm-;vk5 zuc%k!4_<;>G7!3P#(P_I`3IH*-t+QanTR)pWB7w9SL{%HP(nzqx}d|WwirEvxzl_= z%uKL?Y5ls1Z@ky9X)URSYjb&*zV5qU3@FD!8b(tdec|&@wz;Vi`O(qx%Hd#v%<=f8 z?lC#kR+qQYzDNGj6W5Cny_lhx-N^N^{GHK2@%A+gxXg&0I%L)ZA*9&K9IA;8H>GV` zhA=nxvDr_!)bl0VK@5p?SCxr_%LAOi5#cb0xI+#qw^33VMoy1T%=z>^NmOjJ`V-`&PWA))FQ`MNb-DDfU0iz?@@cD4g9N$eye zw-Pj_RH>Ts^{{pM%$PS24qK2;uA&Ly^nshPL*w9>7_0rQL!C~48f{2%pn&WRO$SRNBI6VIIMI$|!Bhyy*x=ac3Q#t99B9TSO)6Ub=1=v7dd?_`!47u|x6B}njuB)$$T%Ft!;w0ovdS3#_V$>YO) zmuX$m58gwB*~XAABbG7LIho~s7F6j(bsVDhy-;tfE#QpA`uJvd>#X{Zd?4&p*Je>; z|1$u`aIJ;tBg=Z_V9GhoZD-*_G`{?1G5NUFv|3N zI#SF=JnvT0^gKwJ;S<)hn|i)BWbkqn1zI5VW6rxgFmJ?P*d3FQaF57U;owMk-oU6% zkzcBFYQ}!>u;h$GOng&}EHHq7PbMNd^Ut_5bzpfwMRs=fcrok7x%pu!B{C*4XOEZ1 z*3Sb`GHXGbl&Ckk{k;-~1Jz!%@9~xwd099w3TQqMUS6NNeA(&S=393i1a0I@iupzZ zwQtWpZ)zfQlYW%aYZD!%Fp82DrT^luv-&|>+?f}|e)0~1Tg`6Jy`}P~%UdK|zq>O! zJDcUZI%hGw@;s2~kyK7o(jvWr?~f>99eI*Vb(V^)WIULZ_R;VtUJchcdtf}-T58lj)AlZ{7N;Rp=D@k|IW71x+B2y4`T?=h3<2T`_U1Vk}4os-sfM z?WDdep5^4#`toIE5u>7HIHx)@0k52H>JeOJ3-`TOtVSaAcm1Gy5%TY}R_@WVrVKQ{h>4Q<4f~E}- zm*m;lbqwC#rntD!Pz0YTQ%2kQ*{gU2UU9^EMLk_ufIg#>F!#Y>d?fNCV|(BAgur`mH! zk!GS@ZhuFwJ`7Zggvs|K6k%WppWE}{<^-G)sbnEA{JJY{Ka2MsQ`@0Bz&E0svPO{E zuh*|<*BDP@{bKl81{U+(HESre*XqV#?M>XR8IDd(-%gI?;N)db> zcv1_!`224Ec2lWDg=Gu%CgL5k6TdKYaJaNGqIQMt=*9{0!W$Xf5*(6h2`R07FlM4D85Ah^iKBLAR=&#fFBHxjZfx(U9}?WtL957aZHPg^iv1Woiw9?4y*{ z?D58ueuaK_T~JMPnGU0ol?tKLEXs+1UYgG7gt)@aX+jo4H;1Qo+xiHSRzkVJNa%{S z!wyNxm783@4)2a_Zj3BCIb~!?^Cv^oxcDE1o#9e`pofgF6p7);KRUxR+GQ`idGSj- zF}F6XO2YcqtCB0tQ)OsU&emG!EQsm&pU8MGa(PIVaB_l2-wxB27NgURjx!Z ztOoSH=~-k}o2LuT=~q#O_-M~hDTT#Q1yEQ7B126!(>m{ms2zAe5hW*iGsNn{$fZ6T zOu>a=_iKK^r*|5aZ6={-EsR~FHVo*jlfb57x@fy^<)G^y*tQsB;%4#8HW*ckIf|p> zJ)|U>tE%81$;=cmP|A-S!55%Wz{WEC-hC@NK5hEn2oWe+Y+_ZD^#XaH7{iYT`l~ z=ZkloR{(-qmo#>bab!dw$XC z(o&0}x3=PWmxR1mzjy>#-vX<$PUsB;o~1+X07?0w^nR2@8~=KSpudOE!H5Tr-oc3c zLqApd&vKsPTciuckz`FTp!m0$RE0N!>qAc2@j(;NU*pr__!mW=5#L>Wi)pyh$yc$& zy+>gNV-Rp=MFAnd%6&Hbs#xuh#zL+(_a`sBD}b$m89q0W$0Q-AH-e0TY5oUdFp$Oh zMhuGN7GC5>1`rnJTEkW{&(GsPN<$bDgg?+i4+;GffMr-3a=@eqe&s*3E9BpwIm-x! zEEVui-9?Y9UwGT>h19k^?6Y!){#2Q*%miRde|^=CXvXo<$Twf^a3{d4kf8b$(W%TS z#ba|h9al}W?!_k-W!nGY6YH*QOUgAjg&*BtN~LiuhhtdV$F-5vgaEi1>vKw=g~_f# zq-=w0($R$eG<(!-yQ`o3nc?PMcIQPl{wl@dh#LjvS!(6mCB6vr!|_A9!>N~@Uz7dU zP;f)sGh5!flwo>l#t3I|sDN`Ads>RtxZ^ejBNi-_w=4HNo+GdmL}j!{udd7K-p}OJ zRjZYwq$zg|1zSx_0*%Gs%{< zy$U5uIE@=-^D0Ezy_JuJ$7HmZtfqH3Al_cVB@~pnglov;-6irMauCwUrUy9=3~J&d z4oiXe70DJGTt~jjL5^O1ne*U})J$jSkfPY`YrkZ-PLD=AJJj|P@M(rrRGz~9`7=f+6xNqAlj1@I(HhuZdc=>-r<+mcHT39u*ls)v|=F2^CSmS#g(Ld zUUgH2dXusLLFcE|&xT_J#>ltxG1kWq_umDo5eTS2OO<0GdPqS2vV)>^h^Ih47pB=1 zsd1}dgGU#jpmnNY-@RFGx6UbXMQPAflUJMG^6?L}Ay3Tc+@eYRaX$|fmZ7?G+6t>L z47ORfpY1Zh1yRzZ%~$Rs&JP^k9@8O~emeiiVzMWW8Wjyz@E9zO$JnA4!UP$A^=hA-3c-_iOaf66= z0-Va2=Ya-A9|#Z(Khk^;uv0SjIBP<~7Yb^^{U`~F@oo zV!uft@p6tBN&o#xca!il(Wo}|3>tn}Cq69}SuCY#9rwxlRzdS&;8Koa$L7Rj%RRH= zRCFE?iJmJpgI8|rjA_RcCCUZ_vbWgwzIIcyKfyk*k6w;Z*Ch;)wM}l5pu)@4u?=Ff zgx=wOt{LO$@5NpI8YpLYlss>EGbVzSp~v1VZC%J`RBpbJs-?FWBQ&mPNTzqirCc9r zb7gg&q#!eQ%xS}+cK;gMz|VRrn!PKLDH@ii`)>YA2>a}H`ax$fN8^~Aia<)RYaH$HHOqj}PO>SEn1Cl{*rne+;lY(u z;xSee;?|n1mpgf<9+rO{su_5;Fq@)%Y<4Rf!UC%KqW~SqhMB{t^lFHNB%b z9!nJZS1$J-%m-MoI2`Kd8UZz(k4ZVwKE=E1K)me235nSc_*cw&y&j= z#AqlZmM#fJ5R7_-E9l^1(MMTe1~aivjc${f(YKsb_k}}YApz?GxfGY|ES4XmMw!w1 z@$~%)ab;LXZ7M9;%;u4K_+i^x`J+M}mR2f0-0NLV&SAC;&z!6tH6YD zu8jquW;6`}#}S$6?OC>{TajJ0_<%uI?PouB54sAVguyfRcL|oPu06#d$98|cUg(~c zcXjhINwCfcvAXD%E$tRxW^~Fy3fXsYvaw`Yr@auDZO5eotvITyYSfal>6(+eYPio6 zXB(wq%_X1W^1{o_x2GHtRBt5-j?me^=>2ZOqU;WMYq{`yqw?)YB-)G=taF;iZ>cSW zDdNj~<9g7Y^7n(!cb7{hSHLXlyIfD#82M|&BCP1O0jegVwB}Mrq{Y@)fh5(=oFA|G zfAOcA3!&R3TY6yHrCgDH08r79T4)nzkyep23ft}R5fz7i%^!Sps@>mubNf#!V zD}{%ik^N#{%xhZKp-?X$I4jaSir$4Q()0fO+AG2oUW0e}Ck!!fBa3tAXN+9^$4Mv0 zA=5^k1`vI|;2lt2rpX>HaN?TD!_~9?YWYJ;2zS_sDDMpJhdTSV5GfjXH26*utlgWO z1dWULRjhKh?cSWy$2lxQ*)*bKk3c5oh+93Do026>27wxLO3EiJkLQU=r_YC+6HT;< z{%vniFEX8zmpn-F^!2wtw@n&8muox{yP^MLQ}}?L?C@)Avemu7@(w}BRSkgJQ1u~$ zzy9Fv-KnXexbFoo4YL%Tg|fs65h>7Xvs15j2R=5Yq43!X8}=KBm~S5Bdf$&q`t{&V z_O>tsp&-w4ZM$Yo3kEea?Ij}FJgqOy&#|IHb5cG~Ag~_LsJFvKzvur-1PF}RYu6sZB-)u6A@>SYJD6OAnD@zR5x>6IMQRkXY0?%wK z7uR0~a|Sz@!58`*mwnU+5zXB-9gC=G8rqHNxBD9ZE>B@Wv~{)hzvz{k#QsWM!%?|d z2KJ-91nm3?9}{-`2ih=8p74%h(&6mQ4_8*OT5LYT)VrqN=oofQS8yP%9*-F$FIj9! zDu)n(l!ct}qs3KWUb@^5)_>WGAIV~%n!*~SWcW-qy5aSwdS>D(gA0OT8)Z=F6Q>UF zE5dL7f*a)rm)%)-<_#a|e5W_Bo7*5J)ohlr;$>*M?;cfeOCnnYTI-+xm8wIMP~2ka zmb}NFuU$Wvu?t;&I>&g|XuIuB)yjh&=_fXv@?C%J zV38-D6zbW3-t5;sz{A#vi&Ik|y9#g-4^0NLZ~vmSE`a(otp$5e9gqNuGV}#^XS^_t zw)TrNuLscEuEl>7A^+j!2_-@i35-Rn{bkYal`9Kllui=`ah)FxQsT9HfVOrMOA9`6 z7P^k;D@1qe`X6xZr!Y0Rv}p-X6qgWPRlQ6PlEZwq)4^{&)M8Brz@h(SF8}q|b& zI*%T1m~2Mhjy-pG$SO}XXSalZcr&W7`Z*8X`QNTiaEJ51c!0Xz?^I#t+P@ifg0|=v zH+eQjR%M;e+_Ejw+4Q4Vnm!9DjnF-qeHV2dA$n%P_%C=mAUMrmwx>81Q4qpt^sd5* zi-sE7Il<*i3qI8@Byc!3&@%1(uPBIv)D|Sh5?)ArVjvR8Da^ zB^R*@ZMqkppEEv=&UU3vxu({W3IC;Q(iyY5B^~@Y5MZAoS8$-w&7g4x8Dx<^Z!rq(VQ56$mgIo!xz^z;a<@nM7p&P|+5Qyb z{bpM9dHC0#h8qCp6nTEI2i{3MU9@R8C_3=ZXqRkA!?K;Yx*ED~1(r9RDDwF`PZvM4Cr8j)P@%F4=jHUZYj>_%@=LcRa?%BBQDfkOhHSXEi1&-LWs zMJ+axQf|_m<*vPLuBZdC0d^3*-)AEvX62W7OBB?B1pn_Z=TEY-ljm(HC!|<3ayL7v zHhUuYcQjLmKNJ-e?`+-#GvAqNLnYfz$Z4@S;RKWZ&UzNLbt_4XecW|O1WU)n>j=%2>@ zx$1vYwmp;lch^i%o5^o2`kIYfwZ(QCvIGCQEfnnz;8-F*Q>!y+%+4gLPh~(8%iQTh zXu*vcC_=WvHC1(Y^>Tkc{QuBZUGJMnATlSrIxFu-tU@2d<;RSy`s(St@gNOB9wVs^zs5k{obps5lk z)|N~Rr80x$KYqH9?RP7V@~;+_GUlJva^>5!}q5H^KItU=W68mDJ@V@Q;@Mr``F#UjFVbU@7Nd zF=N!_3vN5`)MNBh^Z8G!rYtnS+5MST+fW{Z-yXiuv4U|+KfkS-q5%wn|JsiK21Nh6 zj*Il$D-nu{8V)>sKyUsTFISx`KXXmDkl=fd46-cUPQHt>(l$X#p)ENm{7t%)*tGt! z){yu!9#=i;r$6TZGYtQeY6WHv|LW!fUm>tjL_tx!RVPnzk}6(01*f3Z?H0H@36;rF zkyX^9{WCp;z)>CK=w!=kbG;Nczw3zSyi?&xO3&TyAktm3x(+$hZJ90nEmB1tU zQiELLoH&#H$jD{wLPkN&^nXY~{f0YQYMv z`E0%?Z}W4YMdJHbW)e}F9$>8x{@d_)+Pr10X>0{NeMUd3fg~NJFSsIf+NNtE3>*Gx zSq&B0z+e*=+jgS!Tg+IWVfaUS6s3kyXYA*YLA~vCH5(O}`giG$>CSBFAMul^D=!>z z{QIaG*a--xr+CJ-@0tGD@%#mV0%_w%u8OIT=%K^xwu-sH#5#v*o|yZP=qg-puo3)BscTq!q>O)~XN+{`x6ODx3M}7YwME(Dk&ZElp_rsL+xZTe0oY7TIHQ06=(p52w61e%%u^u>%Y^1r#ptrXzerlr@9UMnhEf*vsj zXTxKduICm7uOLlkrMLqLdrqh+*d6Z(OCH{ea2Zsq1!yiRp@?!d;GU-O_RqN!d5z_%yYZtMR3ljf1!& zr2Nq6MMZz0`!bl^<7mVzH9xR0hyRibW=)r_VS& z43{Dh&lvS0Xu%x3;rT)seb5s|FYV_ z%hWnwVAABmnCaHH7z5q6t>67ki%~ICydN$P<0eluxjK+wag%??ck%f55207NG<*hq zi7p)K5!AhdtuZ~RO@M#X0f?`_YOj2F_lMSEddxDn-Nr>Q=ir=lod+b^#Q`&<2ES15 z&?+@?7&}AIG1YO$<>VD$a2i(Fd7vYOYoxVr)+o~RKqHot&a3E#upvyj9OPpcW!#Ze z*9~K;+TJ=$(}_kWATHVOs(Opv?s5j$Amu2vJJ+-v4>3Da`08@O6`a76uUx78BHil8 zsYMDeN5Se;*#o=RWs(Md`&3x@oE7BqXfBwf{+bV_Hs}6n{!jAp8>!6Sw z`-ifynG-W{=dD5cBAX5MU2uOa3jegg&|y3@e)=*W$MI;=09cT`H{4~s3!=Z(YWgmS zcG#rE$6UB!_Pv8JJPXheKS4hJHGx^>D&%a;(&3jJU1J5;!l)qW-rg96mA${|IV9}p zkFoY1u^qb!n)U(^a49){3Bxd%iOL)&I$~ah6q$X0KKLhHXi9I& zRP{rYUuerlB8o5NJ7Cw#2X5(fDOqLTUQy?@qQ?StM*@SD0r8djV0jMsOw?^sk3-*j z2hIXDtnHTKLY;6v6yKvB^*E1xvk@vO;B4LenDw@?1aLAu`9f2{Psklr0b z!-R(KkW@*#PfQ4+uof~x7MG^psyHc@mdDTWf=|gM?mN022ty|7-gCB{@l$lW<`$k^ zv1+Gc82}2jXhzhl6_3UEpf6}7AL1yf-0~WyL5!_X9Gt*yJn>?QR>^BnV@0)KJ%!SJ zr?p+Qs6N{Lfkk#@JMNwPuO^p6p2axlf+;l~P%7k79(5Y$_Ld;BGJs$t^=UC`RQUGm zZ?^qEzAPs^oHyykwW|-&d)@N`=wE`@h*l~q7|y;7_=@)#5AEtBdXxJ`jRz3T_bxL= z$%=C%7c>=JxFCV}>Rpbq&^5g*g?+<5SEZ84v-(6MYb$JukB16FwnvpGdJbAX9i5J6al^N>=}gbVAFb!B#wFD{ zEN97K*#yOs76lQ6R0)#^ZpC&?y?B3PxK=~vIcKDzysJN1{_{~k5qdd1T+e3ADn|M% zt~~up=;(lIxG&F3P0J+?V9dMu+v(R`=)2aRhi+@jp1CajcyR5{)^sh4E~^YTp*=q+?fOL2YnmVRgR-9f{a6^ju0{74y>j^4sa}RqXG9C!_E!!VnS*yy; zV-n!Za?fH)l~+{Mpm?zMfD&heHT#U`w(@OrN2+yslY98LKpI{mAU-=0LZ`Cq>H-=O z3?UVHkdDPD@x{7LZ1)&P`o`fH2Sz66EKU|xV`PP7yw_8V+~qB8yF!|O%u;xXXnbnQ zVQOlSaumt;NQTOXYXR&ZHBRsAc+$DvLX?K*6?euWD%%NP1qy%r<=oU4Yh7&{{R&u0 zQ@klIrMreC+0=U61d+W_F&Ic}NA?i5ALa5|UPGEHB4@=M(K0B13#la0N4b0JFDgSL zlXkjBqe*Dpy+?F9oS5k;O8fq+J!Wp?bwXvqT}sbEOwr+lH6cfo_8|TvUNzu{7~7a@ zx<30vE?JdTc#*0a)@nLI*yPAwnbf#>3cE}TUo9V09Z50#U{<*D)=x-Sprf)ri23qq zehDlIqC=ZV_@A;%-Lq4t|24kQ}gssa5gU?;)}f0yUoqO!|B zoNgH7a>Svo=#8zk30TVVOBsu@t5RSXAxO+E`Ib%yc{eF@y;ZQMXq>%>LMT>{{cSbP z{maIhE2 zAy6h>o()uO9&ST{nUsMOfXWBpPHe^T*dB&7$pkdA-~$K53-EcA74QI#Dic8QPaPF9 z-PgUSiZ-p;w2Y51BgTYFokLY(k(fR38SS*7xT%2H3z<3(Bk_xrfrBIhneK!h%t^ik zD*X8pUHkq~m)JG-Jph5O(}g`G+FwV;N-^Fl^Y1{c)NTkc5`wlmDd+G}C4X%f=<1G) z>-Z(<-L>!>=tfuT=bge4{pRD8K@#^$vTzeNWtXa%sI`!-As6E2j(>v~{eab@>)1#!?>@AHGxp@=>5$nh;Wn7@CS?I!g9s;6sJ z6$nviUDp!T<(w^xBC?!otcHV>QBwPhLDqW>$tiUhT^MeNFX}R!d zQvw6aM=$CoXq4^ZK^RR4 z3MVe@IsDsb-g@^i&D@w*(=S9N4|~7^_v(jVil@dL1=CE)^6s}gQ1B(vUIsC%fJH-4 zb}bkwrJ1qtsiJS07|p!;+aFqcuX{YTCdJB_v(jP*F`SEO(j27kru}27KpvFl^_C%O z0cBot?$SZc?IzQvU33u7GY&!I6Tft=HYC-VEWmW&s+vBgr^T*p)wvdv@hmzV?$Mw7 z7f|BKYGv|~=Mr>1V`J$?>a^I8)vZSyeAdVVzfX)UoHpo%CP1sG=8IQw`y`dmAMOMo z@M_^p0iUfaWPd_K3kqayK`)JG4ndvvCuJI6ThxQ7&9GxGv+7<^yJSHT)K;9QaQ%xd zEO*p@WK;Fr&twlEHRdWxQ;?!5UR6uQE9!p`Hy9bYZ;=Ky7AI(v;(d3K(@-@%jkbsl zd#CmmsFSF@Im+B#@6i{Mj)kT(y8Q*Y0V1g|-CwZ56m3h>RvXa*BjIGrR5*w*_km3u_!u)ws?d77uEo~!U~ zzp5y6F70K1F;jyXTzou8b92B!)G5LSG@e>IEko`BPlPw0g#p7W^+0z^9#rt2vSD!<`R z7`r>P+a{fQJZvdkvMs-Sw!A-Ap`YpttfVeu^r>x7`x@4nMFm1r7K(!Yc{N|%s3>5K zsadmX31e5RTTgW!$zPrHUs?vza2FibLe5kUMEUBRoOP;Jx#SarZUi~G*p&uA>xr#! z4@_`1E&~m|OXa0>9|<#m7JiD=A3I&Io0&6us9AcxYMrF z+!_@m=Xyl2dyJ!zK|;EN-s=%5NO{(Jf{WCvD~HF|SU?f~R!b)+Yr6w(0PbD@(oJF7 zKk``l(2(5$wu6YZGK_G#hnGCvKUYvTHuv3;E6*K+X|ae*@rR}XDcAa=pUM>pMa)->0q8S4_uP+w#rVC z;^7M_<42PDe!zO>q~2Ykpy$pR{JoRVudB@x__+JFVJxVt58f%|^`r1VEK#c;VL`8c zL-ulC0JyW|y5Bs(dpuNTgimc}6^3&q4k%__<=T>8DSCA$D!XxVsQz+Hhgnek$rZz` zqqi(5e2K4h(bX&)br3!1`@fGzkph)tUFW5Y(a-oTaZUaDv}}QBe;t!F`*pkzrL^fE z&9q5XE-LB4AD81zAwP6aHzv-;!0@V9 zf~fAs&dY6q59o{oL+bAgs>!&y>%DG6!KdfiO>GE;Ox&E`pC7M3f!3_=?NeCpUIbf~A#;7j2O$d8 z>Fd|M%HOk8WFY5L1+or*&pQdI?%hpl%Y3jH@TqRqh7c*~dyqlsMnuANiu!e*s0iRw zNTf!Wa?O3?BuNQ@_Tjd!Agczd>Youd9K-gILR)NXpZkl%qf zuo|vc427_CNI@Sd-u$gAiSVFi9}Si3*ruTF{c6a_ayQQ*U~HTiWky3e3?#!v?r{Q{ z&*`n-AJ9}gGM}-OT>4HAYPthr22o>q4+8VpCp_OP+>oA;P?q??b?tXtQi*KSd=TRF zKqQ9ERg1*j!thy36kju6qvb?U&f~SI6oh=7LmCMJ2NFs?)ZpX!DRm(B~Wl0DP{88NPsTchy){_)2@9r>;BRZx&ybI zv3<-G4mhhG&yf)v`cT=)|JbVPQ8h<>6Oq99aSwU>sk{r2-1-WUOF?xqAS_-=q+h(x(~C( zfq^3*Bv_d3aGAke>JOnhmYpuAs_0wRDncN;*0Knlh}A#m474j|9hn=>Fco92ev+x9 z3UO=F&mb*p#uE1)W;B2DNQ-#r;lG({{)^v$OW{Q@iNOH0zT;N{tOSgYSX=YAnW;;`>*?JI4bte;{kO)51O znnZt44$~Be&vq(8o%XlCoG@nnS{)UjZy0^EOK;g)+3_b65V3nQ@EnD?t?F75@0csk zK$WtK>I0Fa!#gd!i?APXTNS`sr|!%G*f_Yt4X+(gSKm?hMAtEDPFX(w49mc{Z6D9E z9KQq(B-Qa)wY@1Z+xuD4-&^8)_Jkt2jSF>F4r7QgLp);J;v49rdu$tn7Vhkrl#R#5 zHOgOYJP4+5=#-)C&+Beaf4=*)iJh{a{I)Ruo?>ELQbjDKRrc$b+p~J2->2&81-)t) zJi(O$nk#uEx>^g4A-!wQQmG?vEaDd| z{lCw3%?GE!^ zlIN~O<&V&rIckZ}sez86zZOOyI~+Xy0ak$>p>Y8Zd>QZA3pMN89dc&y^#HIJi-qi5 zh$RQ>(bER$%VMK>jLu8jM#uXsMz8>h{8fH&=^+f-ddGl}W(IxpQ1lRIK`LuwCF?l{ zl#P+J!13GJ%cdGF)!v5X&CB)<^J(7o!m_gXk2+-to2ZY9GY{=a*ByPKh~gC<^q1OX9?_ibyr?=PlAh?suyR z+TY4n%?^+TZnn8E4@^vmdBp~GHrIDz&Z49lu5DN#LfqhzE8eAqWf?EpQEpk7ZJ%r@ z48Z~%n8Ce4*6B53h=oGZu9o5Tv0L4q5`wljV=ZI((LG0@2W9sU@ zHM{S1a;W;VMJ+Tw8h?smQX{lo1ajzK6gpO`5+@Ahf$#A;XE$fz+y z$mBA7(aC!->HY*-_RinE1j^3Lit>PFWgYXTS2AsnQGx=;V~DX$a%bfQQmfjR1;pQj zna7MxYCL--HCnMc%_h5Ug`tb_OF}~19)M_8=~9kG6RGCeJVY80QT>dIqo%xyl3Kv_ z_+r8@dfYIeTk2#IIr>MTq%7Uw^Smyos2NjS?dumrsIx_Ni0=^l7|mnN>84_E;kejh z-!iL6#?3M7VKg2N*=qu3iGI7ISCnm;JOC-gjuKne7(Sgbe>JabSd_v-m{aX+nVNl| zuWc4MIr?laNC_Sne$}^3Yfe8Kj64|&m^@)QOlaL(WYAO==SF8N5Z)HHy1rYI=bAee zH5iZXmO($H#$hlE+?ZWakzLZPut;GYtME1+zg@_r%aLglS$2`xb4L~dl6tO$x@o;O z#PNL89A2>kf;WYfR#_tkyeU+(0_;ikolb8;Gt!FjOni2DjIc6kDj5~5GxXytRT zFou++@{t&!km6rsNSPXHcCix=74LK(p_$`5(n}wPZ{*ppBw!%fi7{$U9t>TvRi63q z&#KWu7GT3+DIF+~%?YX|1^ugRq~Q+H(yPBSI4M?mnujE zvwTc82GT@AKa0Wi#0w^ax3w%$du=VZ$l*2LSCv!_1L|K2W)p+2pY*BhUsQWO94?bZl zX*t_s99%BstJb(i`&O-Syn3XB7e71ga4rkj(1(nnpj;tqE7B^N?_+C~fhZ|e(x$L| zlj-nc$L}oT2|60dnQa-DU95)=nK*)S4DW-Qqw%u1%zmxGPiina+qMccJN~91Ehv># zS{nurDBiJwUG!;zv%L-#>yrHfWqWE*-F%|Sy=Y(S#UwkhR~RfWQZn3xe)<0p_SRul zc3r=yiimW#GzijybazR2cXuut>F(~74y7BUyF+5p9gFTdw~x=a&v*8IzkUAE>(Vvv zImVbH<{Wd(-wUxzNmof7zwJsfB+?I{;5!`tJEx~l|49lD{I;(g(%Rt z%$tuYWVTysiH_On?%s1AQ|Y^hd}dpPG3IHlGgIXtvQbVR*@9e1=6Ngtki9$;4hiZP z;am26Jc!rCbgtW4&uJoQ|9M||ed(+TGs2fW8qR-i2WJb38UYPWz*S`Dbzh{%=_poG<9kgX(*!SiaDE zsr$g<8OrBjOXii|4>_CtwQd$+1M}B<+a6d!9e30Ru;QM>PH3}Kem_Whbmsm z(S>>4=)3zvH}sc#gSjv54%mIu-4_`M8CNdSlo&zF;~Yyer;r%l{*9=a#moGyIDgB+9|-sFsgB=()P=G_3!9Zjsfka4x@ zfym?){x)w$!2^2{cT?eef>jl-lh)Vq7*+RKAy$#^(+;}VEfRfn+b?zz0f=VVka@mo z2T+Z1Y?LWWoXaFA^nGh#IV0CHqVjJ>=($d-sBm;$~CMg{gQIZT?C}q96;%A%|ZBA_E-jD-SL~y4GkoO zYUS$@t~uPRP-lZ-wxEi~L#mBBG?}?iZ6Gr&kB+dw4|cSYK+WmvDP+L+VQ>Yn}{^mH!?4E-aV3xK!I=Z z*JH;Hd>4iC%mcpx@D830&?Ysq8*lTS^+aRSZ`$}9mPz_8`Yrq8CjzMP;rBpGpN&H) zubAQX#NpU*N5N#v9m(lqAp%*dFoadNy%EvFk)!JSch3&khQ+LX*Tki*8$C2b;ATI~ zLEa)21iW^~i?jUp<*g(ZWxpv2NS9rb2`_xOOPisWoNIOgBM#+9Hv8{MUUnHE0~H;* z2F_)_VSVHW_g^<166r<`PsQaI+UZkObc8(`pRIEfv@0|nT3D^hqbf#Q3frs*;mUWE zL2b@R(d#TgTL4xg_SqmaTD&%gIh=a+k8Iyszd}R$nMSdY34NUAkS>6R4)k6?zGqm6 z81VsZ$_6@4&*A21oQclIMc?vye^UVCzjm{n&IJ0Bs)&U2M0A z?dZm1SvlzL#n9tFvnb~6(2$1jb-wD{eAYV{(@oy+PG>uVn8hp;Q7i*z zNbnC8Yy>G~?g2cUrmAWx)QO8h2LMY-U(NW7uu{cj*rsuDZTIr&6i|yw zC+oE)Ou*^16FW3~hKcRIs+gX6xr1vm<2!KBS2E5baxdJdMfI4k5FFp?LEjw&3S%tc z(Ft?O;evGl_mc3?DFS&su5$JX>B@CndNn?+4$@7#Cl;JaM(|!Nb4GvNh)1WkRIO2SROSd}E4~s+ z99;fdGksV{%=+6X*6Y$;%~ zYmm1QvHsUD(J3-4E1dR4#?ZsmRcg>eRNcL=QWjV~iy)A?SPGTEetDq8Cps&fTI-t9 za9C6WazOtA&vRjOsGzPCg}!gpX%eX@Ul$b4P?^6??=eVNfM6SX{;4^(g~^42@@c>t z!@Fqc2xQ0}u2>aB?;de0e6DFe__H)bHcxz4`%XN6!h&KWzDbN7r&Am5o40^iQ~E}j z0FUWo+{=UA>pU;hAvLTAL%EaN3;a-BQOSkGG;X_bM@1zKdn53J$@5`r)rX-w3M;4QHqhmuok-g_PVfc9W(#N;_>-;P7C3psdWBux$Lo zevR|y2`fASyqxe2k3fS3pQ7WU984=^9zd|D4>|Csvis^~n11uZ*!m8rA@dxcHoI8A zaQ4>lfZ_@8=I35|oo{mgFs<@+DOw6wvaGFv3Uo(jay@rDok8~&kX7%9Gv=PF%8;-` zBIl5H^(&8$xFh!%(2W@Pcw07y20L#(J}}v1JUEg-8%g>EQ9a_ZdIM0>X|XLY(vZI2 z1M7Z|j1S_&2kZj&vWUbwJY6ex7|Fcfr!l>XT!nylOxRMQDyu3a+}dC&1c|&N$$Zo?-Om&51{yXGk`IgttExy$vr3?OY1mk)Kve2tD{Pl z+h<366sw%0En{Y0ED?Io?AW{!w8x7c>REA8|=>&8K8zy^({Uk#m?EY!X>LjbAsd zRrQGN+W8`7HHJOQ`88%FwG7)`kIQ55K3>e04T0;qJ4U@-!XoIfOV+I>je!C{Lt%QR z-Jdj7=c5DK-r=cGh&#M`FGLzAKK7rP0sLej$6qmzgMFL@zQbJ50{DnbV;L{sQflx7D4OeNy7+u zhgpNNW$<^C){(p)wO1^1z%_f{P=ob`=zCIBO zxAWWEB^3^NCJ5`=;Fp#ke(>*#aR!o$=?L6xOXmS>!23NBRjKv{k>7UT2Lk-PIgzJg z_7by0_km|D@wV77rDJzqlN)XxqiBu#M$g9bN$Sy2;fVM@Jr`W+9nYpIS(jhUO01Tr z-uCmB8Q4$}BsfuksC9;C)l=OZJnBBF|f!NEqP~G5mFV`%G;!gG9=Bo z#4M)uIPO;J+gm@Q=^t+`pJK0j1Qh*(0f1#?Hwngc?3wy52MDXHUC&31>mVyF0jj3V zH5UVD%il8QURw7Npof(Qph6jV1$2{TWDPt=**ZKYd)+b?zymi*Q&xWX7@Hdu^e%hg zjbrj90Bp4Z^AzJfDbRt~@6Ykfkf$iQC!7hip`yv!`}GSEuY$>@*BHq8J*3nwD=)O7 zRn9R7?lS3;f~4A%x@nEqEEf6+*6+hKTQ#1-O$Us}@40@@g8N5f8Y#$0Bzp%Qg}TeY zYh@exTi~1y;>T2$q25Bg2apJz?zX;Nc&w3{4sy|RT_Cu%oj)BC4uUuMZO#`myWopF zN%OKhovj}5U~JsYcgPa9I(NW!bCs|ZM(-z}>p~fKim(_u_Y~a}94Uw~Kc3Ab5p=83 zI1v>s=UUSMj~fdqf%8IP!Nkc-g<(2M%Ak&&BK#KX7g!*Ho~=%i5=y7$emS2iI@mjg zY`gzc>?^y4QS`H%@0ipuIFqy-c9`u*1607=$LY?B!}}=_0N^35_k;-aBps3)%LT?f zLbf5FSS?fh@^Ftl^+(fVTN0o5rlwXSwV$t6Lu6e_(ar{K&Y;s@FhxD{4p(1HEr8oL z>=m3D%Rsj0+jR@!hiLPgq4<{7FdPjD8*m=0A4R+CbiwFif8B&0-s0jpS2A39wB8e^ z>cNe2=_1>klluZv(WA+!C~j4?qCi2?3m@I^m4TZ?tL0K+t&geM{Z$0K1expYIezz7 zlbOq2kwm1WG-KjS81h{1uMAVrXT2rY>byg!4#%>@{ee=s-tYDDo?LzrSb9!pp}A$N zJ;5PzBxCFAf=8%6d8G9fSnJAw-Z*BmOqA-5%;8g7`-h!E=H`_H^J{^=dh(?YSvPuc z$;g>4#Q?%0fE;YM{GlqmS{VId(6N?mNw3sAAmod1{cR zj`DY!dkQ@1>A;z-CVHxoJQAid;0;Zw0~_BIY_g!iK6P!PhshvKyEEyw!icsrYSMsA zQ(5C>=8D(3&6()7jg34DMpdm16$Pkd)p~q)0b1E}o^pPc?QK7%H5VqF{#Oc}(v2!} ztl^u)F${t&$RPm!cz-o(<1Y1i>jrG$)A9@mub6${4X@3)uT=Ix^F%slEC2_|1HeI^ z(bKHZFq*gOJ_Lv8$+9OMiS$U=*0QPiO_MdHKcXB<$Ux8-t}XeR9&Sa-Vddj6&x;47 zR=%m@!Q#8RKI293J{2!=NmNvoPMJNS08cUhsBUs=NhXGVQD~6z7pKl%G;xSS_#3;Q zE>Dj9P7^jVakJP~}{?xbJ zCpr+kUyejPl3ro^Ky*3hDMwrNer7{WI#ql0A*#(>IvRJnDlOeV<`wRVZ_y3M!K2r% zgTv0-){Mx!-E;hMVnM+6#WoruBDV6)nUoR~oj-a9ph|n>DOrk!gg#M)D)87;y{vo$ z3WU(o)lBJN=OzfOpfG(Pjx+7KX@@?`XFboc{uBw7t{PYkPkpj%4s1oV!%Kn&KbkkZ zVTU(jkg`#W;nuM5x;-5*Y}CSbPBmUg|)PY^U)n0wVwf<|HgIYuPWSk_(+XTyub z7?)}g_nKZw{Y1iHSXwR&fYsZG8CI{i?DuK2dbF)B79XHlh4~0XomC$lwtBk|p^!NUS zO9`~f!|s&zgj{Oy6dpv4C4s{J)`S>t8KU#1`|wXrElLbVarFm6vSGiQ$1ImDmtKv} z^5m5xOf+|;Q!lc-!R%5(3u@tVKMZd&JCEh6ar2kA_OAtc9(Il)bRJ1odl*!|Zg;my#HjD6V#hj=oTTw8Z?D=(=l7wS5r7K>OzETm~ z{&C>M^U_&6r`AYxDhZUiG<||X%&T$xJW}X)=A|~~w-|JNXrgyt4S`^?#H@yi*1(Zt zh;1PftX>3L)iet1(a^m;e6p_hnOgg4Q5_U*w@!|(5&)j_g3nLW@YPPVL$ zv&)B@J1e5Ph{JwIL)qdA&(wU~y7)b_0JuKv(lQbObA%1(x4bs3b56Grj#tdW56CKM z^rmnxysjwPOSRiO{zx$d*%iwYlc=Xv6i&=9(d-hS^sl1IC+A|Z%^#|WZvo0|X4M6L zXnX8b1cY;A$AVruQiGERwQ)p!d=y36J`3&Iw3C-_MSe8H2U;f#x@RW}OOP8^=8-aJ zyeW&DG4tWU-4%;wydToENX9of_VL{6g4SfbZxc;JIm4BkIg9YgA1Y!KFa40_JvY)g z*PFOk4hR!-*2OePPhFYiOXpXqaw~{o?$9d=V|Im`H+gKWG6YA(E)?4%KSip^Ei8w8Hps8> z+Ec5`-+BIV!7^$KTA zk=6L+BphJ^cWUXdqd}sy9gJuxv>#cDmClt^|mT&Xo)D>Sn1isedrRC-Xve9W}aGsl}>r!Ns7 zd`4)*oqSk&G0xx-94$;g?`NlF{Qbnu=(0Da&1ak|TuWhKzGqfdbzUWjB$+W7-Ca@5 z@;ZxOR2|w_S$THgd+yI~OBgRd^@CLP1Xm7hRB&{ z(iVfLNsnBvny90xPZZh$yAp^Sc2TJY*PWS)&wGD-RmlIs$}$tHEF+>n7V4E-ZHF)h zdY1nvqo_SErzp#NA+@|=;kllNUdFZ!lbgvGJufKoyeTyZfB@pV`5#i>fMbpgpLtAF z)p2E%$$#Z_>Pl_p%VLGw#5iu>8*k@7*@#C?sNV;N=oI*BzKh)nwOIgL6CtE9%Y5x+ z55yOEIO=PT`dw@_#sS}M%UApVfe(I5I zqOu@qIE9+KCUB=m#%tOh1)5(3=?KF-1XwqSzrZduxGE{n&CJiS<$1_?@yrSz)!(1r z6zvVBy6YPy&aljVAs&;IIAvtYV%94y=z>`~o^lK?@vmvE63I&aRDJ&&#eN#YU}*bl zNE_`X{;rT}AL<+XqsyjiZQ+#w>|$jK;`cR6DuH=A3jvEJ&k@%8KwUi!(7RO4xzN zONEa}HEzF$vK!llFJhJEmF8GkSp`-< zIILzQ;XMt0Fbu@^6~DBRg|w?TN$Fcjdn3#j1Mg zl?rw30<#|j-*cVNQmv0kboeIVPkhcP&UXZbDzNUP;1dyj>_L zt0*fit)LZ5K5cI%O7;#tufx5U7l)S(r=R?t0;TF<+$&3o{Q|4HWIl-2MXcJ=4fxO_ zM-s^oOv!JN8z*OLu8GNl!xs6cI9TUq^MFPgA2HfbMd=;Nde=pdg&bpAo7+q3bMczq zuE+^)<>=iT>6YxFN7cz?Wd)*AYctU#-TVYHAG8j4m_|7k>^k4urYMoAZr|`nzxun}_=*DOCKuz$E9QbR3O6T99Id$nn_V7&p2(!MB{$0%EAAmu14iXx>yZ$6joK zWd3nT96i@Igizlfmq;d+X?s3!ifEuw=Vn_wi}T3KMHB2gMro;3ImT+nhV;Jlu+$qqtY_>02fi?4`uFBAKz#d-wqlO!Ytr{=Z%o?XDw&WFc73cA?FI9mw52>)E zyCA2d@A@aM`7~kzXbKjj41(iL7 zHXM0p1`ukrkz+gp!*CeT0^C33i3sRrf}U)F^D(zd@e?;w*H}K0>__C2PVvD_(jW;2 zQfX$bD`B-Gs0Um7fmCN+qyG&|vHmhdrju$Gm9Q-p0M+yD?kC1Zr!>WI9xs5Z*^73o zFWP|K*r_>k(e<|oF4&KzE_m~aZ0@l*BvMF!h0^7JVJY^s$*5sPbp)c7E<+sS=pw+T z%-CLGuLJ`Oe>##Vj7^=cnEf*K%E@s8;D}z|fweh7VJ{Djqae_ysmek-q+C&J-j)ZS zA6&%<=6S*{&wYx(^G1=7{j1fC}A_q(Bd;PitHcCm#+Ag&M;MOzj4% zX;$)_MsQ0;Rq5E15jDDvNt){*d_;Ezw&Z; z_tVun4##7ke6baP1bxJ4d0X#oWOkf~&2$PR>@#ZA`W! zKN1E*W?mrBtCf7)VC(n^2fDk2rVH<8e;0lYoUu=NM#iX@_}?H9>GgN@k+GZpLLjbN z+;zAWbmE({MiEkfC6e^KbY60kH4^qVMEDr8SzJ%(B^x3$5hbDVT5~ic&gkb3W|A&OQ@@-#J-VUB3^$)(@k2@ef*3iBUjHGf*$;4BjkDcl2`>-;yUj|(L zCH3bPrws?l&mfl^X~OZ3X*L9UidzIsB-x7TSIGzCu=3%VIKEVO>?z85(!3FJKa*e* z)h&BRbtw|1*^glPvH(v1kvd`u@_66TJJNarQJ{lcdlD|RW{=eAhcAB{+wykY_Qc)g zKsUp33&Dc!b6Xp9V?X(yqQ^}CWgk~ttfM;vlebtiAke;J%p;55gr`z2MJvrQihB_^<2|32q@}O65%kI)aQ3trq9c7mBYwIJGkqjAJx5Rg^iu(Be*X-ZRrME z7Ftna>fhU*7QjH~&SnFfsQ8D(%~Bdw8!gzma;=h5&+~dkq#F)vZ!&lVj%1ZeZsDWj zfh^|wQW*|)+1fm7bql+TAK?LUct7!Y#ev=vYgb68C#~&cIj*xL!dp!G2uYir(v&vsVrWDkZwcA z)w7c1c1fTXHVq5I#r*r&cN!Xo!0n_nZEmbb+2n{A-TewrYD3^l7AS$`-dfD)PFc^D>R>!Yqc9()dnv8?yveyu55&MGPLI4m^tlLnd^T{ zj!w1we!?YR^tF@pZ!$7O3|E4taJ{0B)vjqOGo-VV(+;G^h#5+%I&NvJ5Q$E5N`xil zQW*;qU-9MrcLlyWw~7!!w!+USVr;K&qvC}67wUKhv#X8B&K~HR`}+*wrE8k3slsz6e82N8I##1LR9ORt!93WwPoX= z;%2868xY1vPE&gb6fOcdTL5~0E7e}HwwrKKQuEs#@%^_9$|M+n3L8m{b(v-Er$hXZ z&|86f{7R{y6X%FGtX>jZ^R`odp!}5bg z2v9#>bn$*5Jo3VsUiq46+-0T1M;Pl8 zmyDOA&M~NKQ6fY(DMo}`J@D2jKaO`JUYN<^r0O)eMdUeB{YGEtda^=5Z!Okv^rep+ zK}zQ6r2#}_C!euT)XA2t^~~Xj%`l4-pRyG}(HGZ4-hAyxV5Np4tfa=Tq*U-Jhgd=B zt^ChCJ)xiB^rU*ZQYY5?Z4Jiy@Qg2}EE;CrTOewQ=iS3KB?@DrOIBtAMmbaCD&^QE&oRgi3 zY&sbv{WP2+oYn`{MHD(3@%Sw=-IXv8mN;*UOJ7T%fi!taOM@}oH9F}H2DFCd@hiK| zLbn1Ggfibp$wr-IA@)-?kineafr0xV3o%eXm|Bf8`{;h#Z;^=kL-o;KEtt&06fdpOt?#hHLCW8a3Y@ZuKhb5+xBpF9|hdE(dl5X6WsL zUB32>F*CqG2DO1t3GjurkX(oVrtRY@@4qgtMI!bSNf0@&ws76cr%H*-!|bxz?gm(9iC;F%w`_lJeSrK6IDLUV1|!?E}l za}f#T94sd?*vcEHiy2(-m=;jCL_A5~v){?O)qMsWu@kTiJ_?Lulu+bh1j5k-J(V zS9y5F-}72OM16R7aJULE_39s{;L76HZnp-)pO-wNNjfBBGo+9TVC zU;Iawln}6pHuPTws=Pf>-@)wtSy;`-!lr*da+S|`jvW(3a&wRw<%SU>c4LzbQp*jJ4%liF zrit`J80%{fA!ab|Yh3ErUnY3<+-Hw{#RM3@ug0ZpJ>VZ0A$co)_Nvr8xS)$Lw=5Fq z78z0b66aW*Z(+v8@gAZ;37zf)gv(U`qiA{EyEKmDNpJW2yVvREUG#i|Uq{Lx?Pp{G zn*u%w=)U%hCLl`aO&cFSd(f-S#&CD|Kk_nKuBb%a!cZn^#E|{2a$xAj@|nIOuT+B{ z+d@iTU7Ebe^TD2zQjsVh-oA3YrsK{VqYvDU04&8ffLN^mOl+VaYL$xXD6`a!(+KGq zRM}chH}3%&7f(@$81Pl#`u*2-_ctt6G-Ic|#+IS2#4zLE$uH@T9g`gs=>GSF|95h~ zH$rcz>qu#o6Y+mnnI&5f){dLHSoGqp2{0A^Md1=e4pGQv5FNqch?0;+IPhTnN73YM zfBnA;^=gy;fDQ-red@xVtt^L=^SkGFdAW<3d)n3?KN38r&hgEc#H{O);t_6Jx)uV< z;V*k~+F|}jjvJVToe^35nlm=i{KXhN&yQ^hS6*xBh=Imka=WV2YPBGu;c|oVNdOo) zB_(S`J{y|EhqhQNJ62JqwG%i~tm?68#lZgy)8Mht9(1flW7t)6gTZbvjbnS#L z-_8ZDR@s$x?n{r02iukj=W*I}{K2@HQtvNx0$;ZDw?p1FB^emFU8;1>|^eU7>(p`f5p3+Z^ir+FgC%{m7VAb&L%m6l5Sh!HF{ z+LMjY2cQVP|J*mQ_d;z;DUpss5WOms3uPRA8cywUHWc?oZ(${;4#qFgXvNELtz!7o zhW7P9BP4PAKEe|fl}F+|NdU?ld*IKB)$|tKq3>d$akZZ;Q5uKXi)*XvtJ7pnhiv+` zVbPeV**?H&lX#oVdJ?>dxWCTIg+?7Tb_%^dgU+j__HMe3<(2gay7PXm5{jUqvDK zp5zjQnJvGLn$e-gp!bXL{;A=VC>46St6GMKut~}YOUbq_Qo|HakVWsA&)Ckyee| zaMh%8{k6wF%hEb4GOzqFhcH*CKWx93fcl4QVcye{oZ6jc(>c!R7(h}eEbF?~55=9o z<61WeCDR3S2PmrtWgT|&rg%xc1wj@EzmaeR<#Dyu4NMLFbbG>B|;1gzN`-yDX#x$A% z3g(Jqj4{sSU0mfc5b)Db*)8tfa-n8OFY;*fT2fYuy87@*$zds~;QL(PH-G8&FTUe$ z4RQXG;Z8P*_VlXPKljGVQHsVQuq#VET`Mamr`+VENp0|I|W4XWbhvS0} z5iNiImL?}fKjCQj;$QPKuC{4cskXaqrdpC$yZE6kgtqyPR&(kbuvq2!>-%n6^zE^K zhQz)5XVPM57ro~@F>_$pB&pNQ;9gfXUNh)MYOE4Yf;REXxBH%ggye)xSRFvH;&3>i zKMZ44!s-hwJC9^dS2&GLMy;3sBc$1by{6`XpNo<2ywqW)Kno!|VWkR?~n zX(Vy_5lN@};wL4faH6dxTTW>gQ^WP%dzxjoEJD|sk5J@B6qrhm^6xropoa+q@gsU! zJgGo>ZqhD3{48qh zUy>0qwY>GL2ImZ8QJ6|=ZbP$lbt-I+lJD~)NUTjv!{iGc>gQp(mf1|h_ zGkN}A4EuyfjPHk}Xus`G@0?7UqVj4$ttJDT(PtENdK;X#X+OUYSj{olFFXXb-4d7kHJ(YV7p5ZfPNdnM|1j?@XB+;t6x&*5E{O zA@{yn>0o6Or5kBvn4u&W9vCWEOz>BBQOll5bx*Ea25qmXtt}QrIa^GPc2uX^T2_Zc z@_-#S1#-CpH%|45rzvp!W&mpS9i_1vXaHniD4-f#aX&x40M_ zg?Vt;2p~mxx*_pj_)nZh)(-~-N#6Z2pknR6(qZ%XkOEqlZzi{{jAfAr;>M`%W zZDs?09-z_ncg^8+i6zH3IeBf|^=3)iz7h22Z%omI0XW)%UD{ga+&9B2cCB18U>csp*7u^ArkG08fz7Km zr(G5Gv4BM>Aj;LhcRm{mlda0}Ap5f{sQ(CA98O=tSj?83CS`IwT%+wJ@oroAB?aw| zHykMs@N5|j^M?JAp`Ww!^L_N%o4*X;>HiZq3OWZXn-Amj-BY~v5&@5RKN$k!-L$RM z{zFWsJ6(0e15>pcOz+@(n*pGW z-B2oOU}IT>Jk508ROd;eUCbp=SW${~#6{GgR<)lf4v-1cn`r0urumPS1pJNK3MA7X zW$n&whUzzCnIg>{fx~S2ih4}IUn!!$7g5bNA#B88$QNSM>pv^rY+w&GX89X}{<5*s zWgPvLte;(Cai%_+)1LA><#b`X&q|5Mr?_`k^+-z~68eS|v41q=ucOMm{4D=z8&iu{J1-qGVWwc$o&qt4mw_zoG*TEKGv@7IL0hOp&z|8X0*8_$ zypUC&vdsp)=$DJru7nKgW??p(itG|Rtru5inx065A@gKNoRknwT)==l+fJ!6A;G}!pN{|KYia?;yif)f@F~_r z#`YAkz|SGABR^YuW54JDhfKm?9C}%~X|jJE3j4p4oWG}MzhTslW8IeaV~G}-dU6+5 zGuTHwp_PC#a(SrWIV~;7tA|?^2Nv-CzZ2mV46WTNK-Zvfbn}a+U)Uda6$bprlzNcS{=;?G2jicb|TuXLubEL3es z?yZ0sKGi6^e2v)ng;M&uI>>hyJf$Ow@sG*nc6|Oz?b0yK4)}Cz5q#TP3@k%A*?RJC zT&EL=s*=tjs+OKBeUe2dDbGtLWnQI+@&7iIrfdVI4=bI6l7AwRWL12tW9-ZA@6oLc zQXOY$*=2rBb-EC#Dt0$E<9uT($L>3c^ZuRkg$B3&-1t9>u}b*YM;*fkl7`d)8>~UR zcY<@@Wqv~JL(W2}sj13x;hp)$C*FjYh4PKd-EH)zBK#4V{9ebO@hEXw;=&(SfGovm z23pcF1(6yw5$3QQ{`^)zgk-ba4GmR=1aP>#OE%Z_;yUL&C{wA@K@8RbuDCBjGsp`| zOWlH6?VcQecK1vmh?d$7y>_!Ou)F8=Z&V?fCv5)@4ua${tZwDQPI<*89@Co zXgAbsxJ;r|g9M0%K-OpT|9jK~1SyB@L8#*drjbGeVSe>*Pz&D0yr3@g*oYKX|ZYLZB7#Pz~xpb}XH6Jr4hTet zorTlSabx}T)J1Xj1GTB2vW$-uCpa{N8h{+gKS`1Q%7Oe1DUi4rdADcz`;TRe)DR$e zHujV3NZ2*-{eb(=Vv;fuVBwZ5-i^XA=2TPaF2`Gd3%-QH6QGtt($BxjB;= zADO~yw(JP}Ki73WP;6hLKK9}!2D#iXx>9I_WxTwr+Qw5)S+-Z3S0I6pkIK=S!!V?M z^#I=9X_tQPRh`l?knWU6I zJ+Jdm|2IfSW<_gE&HaZ%Wbem*5}ZrMx2xNI`uY6H`ECC&xuic(8^|FxOXAYYMM#Y% zU}Ig#bgf@`0=?(4l`-6#qab6?wQGehEH`{1^-gY>FkMV$@U5!&%&ZbWSvHtkCNkT= z142C$ry+wZHUpnS5z5=3ABQ|G^40nSy+G<#(lj}hjPFk{yU$y=jGI9>6h(=fR~)aq z0$^r-SaVog9PGp^^yEr`RMPDmIJYUjbT6J0^Vm$+Fgm=9Okp(pz`wCU?H`>Pjiuc^ zrFvsR42Ht!NBhvASUObX|As=HjBN z44|K!U5sieL7HT%OGW5oyVUjWdwF^=#7bu;61XWk4Ugk+8R3x%7V`bMR5`{uX|jkm zd>RDR*gLdi_bORwHAc#r_L_vu2sIZ>@uAE5U5+KcZ&I?24> zKDsK;qgH_-Km)RHz)xp#leZos{a(L{79G#LcEiKsF`>#Q6S>Z{aJm~ckJ@Yy>Y|Qu zFndY_M>i_-oiSlUMq%k&WSpgH3E-W`>Zq=DbC$@>D*-Xr8&<{cdgBlNzc}{@hYSBM z{95RzFPodlFA|Yyziy#Ly?cT;1#WD8)3L`*KF<`!YFwWSK6^8(~-kVrn5H`S><`YRj8^ zWHzbe&PnoG`YOb*2AB5wpl02v=$Vd!>nMyM{xb-N2ZR?H&{S}OhTsTWZx7dh{Ay(U z^M%W^X5VX-vz73N1y39HS~s%VpMkPDqh(IELg@h7k6c3^SP2>DE(2Cq-r9XsY(iYU z;&5U>(EU{&`7d~rqf%I-lTi2Qtud+VblVtg2dH-mxFSgGgS7m27By`YsV*Wv(7DPu z(~hJct}fOs^=a}xEk*P;z;|2eZQ^!9-8)XT_gM;MW@Rm z&Qoel3YWI@INuqJDGN7k5;AVLM(b7As1<1@3{3oM%A_&AAFd_UV2-)MM6UkNSbHE0 z(8bd@3=V?)?_I_*_7t&|NR`)yt}b7P?~_lkiWeA|T7~8uPHH1sQ0D@lM#<)(%ci zq*XRgnjKq9rXEQQ%MmmDpaz)fViWIdCeTKEE%oEZ8{K0At+pBVhJ>V8HTi-h=rM)o zm0Sg+5avJqBDbteL5NJ%pJjqLI37wV_OR5hZM%R?a19r#10#%8Z3DMmu1Cc4=QnIV zk0iCQ79kJd>E5{8%W4H4PHM9b2aT-k-j#gggE1A*{5?JpfIzgFZ>)J8M&m7N zcD;ThBPxD`kLvA%za>$H9U-(>a#`(4)qA5`A6FL_^8g*AnXZaU><9Y+dd&C+tk}%OO`~L zp>QZEGU2eKb5G7Kb-CQnclV=lS4ne0)ga|lM*VnaTzX5&YfHeViD?#kR2j}V2wf*I zO99HEz&E80l9*G@fR9YI1~WnGOLWu{(Y<81wXrN`VV1JodxX>y$1Lr!kuRYRY z`bg@5o-G(M#+uxdt~aK2-9$FdRoLV9pKo8>bAx3PHg|4JZ6A#Lz94=y^c65%4iu4l z88GgrSMIANlV#56k^1(HBHf|`^qgjnP$-S?qLL1?hDwsYa`3^K^P=< zd`JwjNXO}>&IG!vt*Q3$iaV#Y**z}a;8KH11D~ChOwaPl*U!sn($|$$=HT%0dPEKm z1M2(^hRAoNy|JcosT-1sZUWJk@x1GD+I@9MauA4y?8=INy~gg7qd^hSvC=Xra!tNoh!6|(YiHJl z=Z;2i>^%@Pa!gK`uw2bfn2g^VxMzhnd=!vonW5F8J(YEK_6uG^wUm%uX@OUiV{k3K z*-RZ>?XH~& zc1ULO$bhoL+Ggo;=&>`^WP}uiow+u8x#}59pF-w^xIhb4y*T_T->;*QPQG|I5SCyG z8yBW`r90f8wcoXIVuGd#n6pv@w5h3Go&TSv9Ewf))^T8g(&+**nhw*tirMOxfF zxJw{da42qt;_mJafgr_;Q(OWR_uy`4?Y*D#editTe*R<(NXS|=Vvh>-+K$MDv&} z@a$b-#5-cld=rhy@754f`dOZmccqD#ftToN$t!VW%6d)0^cQlV754X>fk=5R_qVP~ z7){=sHoc(Z0(Nezv}9tGj!Fh0Rbfwd&Vh}0`vr$wtf#adX(Mxe`c)1CG}Dx^pWFHQ z6YG_i{9YklKLz}x+S;l$h5fE@H0mPwNiF<(f=ib*>cv2}^=)VwOBASo#pl!d(rFF;~q36|BXDjDuO{~B3rH-l=##@VMfLY4b$b51ODwrYCa6( zDBgzCtmRtR>=Ouw-&%d-pJLjXKT!Ss<3DzW`Z<0dD|ZE{6aD?&qk+uxLwGhJrM%APjKCu3K2th z(X%t-_pK(0Gmwp`KbBlR&Ax_C>kaW7f$s$pwW1YN!Cz^EP|Ufr7#-mm{>u?$TU#snlvg`h=-7tMh zJS0I+Y)#mieRSctQ=laV86TN_j0QH1kgsl7{)WY8MThiAe2Zy)F2fj-Z2fR6$)IJ$ z-6_^cYkzl0ubTEo9D$$z5|JVqKd3u!snVO`&DRw12G&hK64SDO#?ueh5pZyNH@j^` zD63Plxo5WdY=A}hb~dk9qJ(GUUc|J6Fq|^q`z{4Db`}gB*@AeP*u-V>Vf5H_OG%sj zK6PSDP&CqLbioQ2kv&MwvNHEjwRuGj-QP>hsXaSW-5a6QfUDV_^-q=%4&6K5cgb(s z@H^Wb#O0W3s~srOq9&vXL4S+oR~vQR(`o8($ae}~p;4$mNwaY-*DYfy7X|mg#M#z> z69tEfM^of`c5ZXsH`<*^lkfh#Zcwu?7f0}02vO_JROksbGb+Qc_+W=$7y z@$q`7dd13pv{1FX7mjCom-B_0lo7*;P@!ypN!w{(Yu{Z535)vS#J5(q8`?L~>J=)c zt-o;UrWJK^n_c2zfZ#hsw%}Wo;7G$Gg&h7Tn$5O z5x!`ODBB?H7EL*;w*|ISp}+7SXuHdX(PUcl4Vx|S2fyPFtgBb(!rjgYzMokQs%(6Z ze(MJr>00Pd9H>+rxi=b^AP%fd$u18s8uA1dJ7`(Ltyb~ohXn?yf^yu zyw1_lmP~u0GgZJf-+3@b_9Y}?`bJ~W@A0&jYrBt~Iio}`NOg*(kUi^@{Yw@Q!V~=Q zmT8ytd05MdsldWlDcevuTh?ChMn9Y2i8E}FH%xj!WUFgmSZ=%k??GkADi5ihvF5#3SNAEs$mSA zW`TKqDNT?9do7NgK0-@+_`9?dPsKL)0{;+aKH14xyM|62-%aaN(pv{+Ne0ljh;A{G z*s3%h#eK?y4i%nso$r1T5>|5CWvwVCT0LpgKwN^i9Ky(I>vC7iGcnbkLU32B8$`wW z`dlDoGe-M54q<=2XYcxcaFKivUwJ77d;YPicj^E)(IMkhzylY5Tk3@Zj@JE%MK7&w z+tV_JoK@t7RJaJ6C^0@=;^sc}FYZ;a8>Ii;)_b}J^trvbM`4fZS>=+Kc()3hZG>Y7 zX{R4kOdQ{?shOW1vReugKv&DH+R2Fe?a2%#tg!_~19%V9uX7rEGvD=I7y~2q9IK8k zg_kYKYNTCfQ-I5s7&`Dvywda7euG~*QKn~WL%vvRI{R_UKh5=t&r%GQv)`^H2v-VW z{Cd6evs4r31O>IxdYy!00ZpQtE8sexlGg zUIj@hpu|-Cei^M+Onb9zm4z%{A|v%~a*_U>Y5K6xvV59D98iSf8Au3ro|;lxYIg11 z7&_Uk&=9uVkh?+seVV;Y*rBq>#m;@{aK_SLK452V47{KK^ZWUc-`4obR!G=Y%DP#Z z&Iz4z`(?j$?~K&3xL8?;erWaqCEth8D!F+I+Tv<8`!Q0d+!IIx^@iMOh;YJ)`n{ol zy=2w<=H}q{%?_P*4J(A44WJ`VFLB`svI*m*itsv(L&8M&l3aRZ`GPr@LxEm$VQa9?RvbMJj?g&8 zQCmQYa1`hH0Bv;lO+fM^xKzUA!yR};9z*^zO5OLTX#)9r0?}6bqX%(Nieiji%W=|q z?C+);Qwl$h?e1@4r*Gr>7<-!e=c($)xMG@~Kjr?uS7~n;h3MVV zv$pA)oNUOZ@C=j`mM~gsYr!u0u1zpVmb9k$kW;xYXA8=v%2WG@OjcA~t}{g#Ucxq-CqYVPm5ES`Zg%5HBgru8m51Cd#;UHr?%zNsD0`HqK2x^KH)~ z3Bo{&w*f8yrbq@%7b#6??|6<4E=jOyBCHzoD&L36|!-hZcu9dux?>;FUjc~G>Z zW8QZ-u}PAAR>hQr2@zZ7kyGe?7f9)n*tO7nioIwBO#ERreu|QN`~l~h1mC_G zRIL-3u%{Edxj9HcFW()D7F{0cthBib-oQZJ`skX)z!dyZ1SBWR%_N0-)>8SNRos{> zZJtK_=gQ305!pUkapjjH#*z65_%@*urFJKg^Fd=b_=q5tipX!k*@nQ+b%t|SNkSPh zS>^s{K>hf77grc{M!$CtHgS8(@d`qr))DzIL~>S;w{~i86_7r9Z}PdGh0+Y&1b6IL z!=J&FUv3wISeJ9Z@3ubhA?w{<{U-D-^-tPJqMp_G3Vh*RkK^_cE^Y};t}ua95}6kc z0n6^=`vx>4IpDN~Ow8SuM)h-=FJ`itPS!&g1qaE^B_}$ELpZM6K9awxhcU&n;zWQc&O0K@6>` zi>IgdjjG0SAWiiKyi5fz?!Geg2QeFo(W^QJTGAmq%*PjG2}H!lK!ZB3`yD49O#cT~ifquwL$AV4KJG#t+Y!RGUPM(F#8Jo%@8yo@_UEW% z+#vdql5)aYa_Dm9&FtrxA-B%JeSv-3+h8*JjuS?&c!%|TR$>n8*=@1*oO}mRZd0;- zV)m+=6r~(Tofi=n-sJGvaA6(x3NrNTgRA%957r>BXDM$l?ZXEPIAv`pB(L!y0a#)n z3)~~e-PSsi15S+spy;FXE0S)*!?e|7XR4s<-BHi9Gs3fx=NzF%)R{a5Ayhj@Ie14J zDd(nl!`Iu@fUyEz{M<65EL~*r*7It%@~xlnWp5y5O78-f>A}54%%d`VoUyljNU+N9 zRO6jZ!nF99_#Y19N3i&v8$akl8~KrphfwUX79!y8lg&)ycPKt_XMN+n!82DL!Q=ej zNsR|q=rqXfes5wVnXe=RrI)P{&pgOu(62 zMxLb3Z<^g^JRNC~9TXgbd&Lx(uuf#s)DZd+Jd-aNuD$54x1Sa4BEDa?>wu;>xNWjT zG;#&r=yQZ845^K!2mCYW6j`azhgj)KKcHu?lt;V%dX=#DMXs@OSNH1#1Cqc!(KJ2% z-U?NRwjff+lPE$~c4@!b2E#jMR{LL*@ADXU%UU?Q`|#HmW?s7(v)76(4wBOnlf0E!f|s;9;mFt7xqHw;;H$h+<-MoVXmB$1iT!?Z&H#y1>RlkX zK(Kh1X7X zn+)@rul~=P`OS78Z)7u-)g9UMK{W3-hjXp^D;tsbjaTVDFLJ%heT2DErAyklGK9%Y zlVw+HvfTdx9111#HX#78%B>Zs1cA0wJmfw97Ww2DCLp5zY*7u;V5KJ(3sJn^HqiWd zxd_QwpR@p7Q)O5G8L(rz?;Re07;_Vay2&;*kdvXyYkd+LU}((B>Mk=70^L(lz1Z1f zEEQk-lExw9u~lwczzHEVeN0woB^RA?RFULNRzKV4so-?d&|KS7n^HUGW7DgXUyXl1 z|1PKW$OB7;u6O9u^L%iV?BEoEE!A-egX7x*^Wo=-Z(Cd(K;G2dImKGrl7yTNh(C-D zm{y~b{C^lho`j%5#70i>)PB8RgsMkV9Psomer!MLqc}fH#&6_ll!#N%jEg90bwtqU z^*Y5V&nzoP-)kXkJXGQ~XjQj}l2yl1Sxf`3dLrCl8HmD$bpH?rD(y!PM#92HXyk49 z2MlwE_xk3Ew^;>4xR*n^IoA1H@8|8q z2EO|f!>m>Wru;Q&&yyKdv06#JXK3C(1^h#WN1hcs=Iw**j$w7*xAp7p!ypZ{e5^!s z)|HxAa~}M~Z?I@{XLv7@lgNy!^V2y8zbpOPKl7MrilHEf*P9$yoH&uLmcKZ+=Y2&{ zNy$GHVP{^C?I;0S>JX)u<#N_KM@lPs*0v(@lb}%`HJqu#3nu$O$KR<@Zq!z{L7qFO;CNOtmI3*9@P*}L?No#f4>B6-MQiEP z7Uy)Y-&1`H;ngxYTX0`qya;mgr`tSl>(-R#T-*qgNhE-GnnAkz@8w(H6VW!(pF2?@ z)e4$@tSckvas2pAVsGnW;1%5q#VEc;W|q*W1oF>ZdEXW>&7fJPp8AcUQi5Zsznf;x zSY03qx;qe4x)O4$jsCZrEB0dIAHorzOvz%}6sffWR^0k)i`~&$#+JM_*gS_I_F|A>#QdBpyF3*BdpN~_ zMEFkOh@S!J+#VL(Wq+Gh?!?(wH(i%X_y#%UjG&?H?&4+T>5AnI?lZ0a?JS)%77dZ&*pU_#=@2pg~YCoU5 zxVH&d`%v<<1b^|^-J|Cs+Eni^2;AY;MoAmhMc5P)wsQ!UNVGyMtxCoR%0fs-uNOgy zEZFld?2fnk17-AT6QbsMW$w^!d4lE|&*LhK2mhj}9JzxY-JqnCwyYW<%GT%S@-0w% z!hgCkq!iEA(%chiL*S&$qILT@fSTZV(6#|I#UbU?+t=m2@hKbfsr-?=2_L?i-mjTx zr{T%ntaU)BGQQ9RtDCJSP$u%5A$2w=je;V{1}|^nRg{rb(iIAm3lO?#o?GH5cU8~5 zIV?QQVVbUzDdDNkZ%$tgeodlmmi0Rj4%{-7o6I#g;%(Zp*?$YQ4>-d&me#$}<8!n| zB2*m;hSJYaCyw`jj69DtmP_Tp2(@h?@xJ^@HDQ1Aa}nP!VMZXLac+-8R%@+qf}g){ z1M5DK-DNFtsXz%&Y~ITnS*1=)gvtFDRWVO?5);0LQ+LH@P+o z_^558TkAfn0&!2C^|HD_%h2IyxLXIV79wllZp=~?jS%M#wpujkn8knp@0=LXvMbyPN6b1+6lwsI2!v%fVvK?eXt|uzlrVx>K4yyVA{ap1qn$$0dT+M3{b)XTM+t9ILOs zq;;X*u{MNXr1p*=-B6FJTi5k;+I!5;>uk||ydl*M8$X0HN#}W;zz4+%mxGop$8Q9* zlx}si^q7{AMWYYvlsjg+)I7q!@>*sRTtvQ6{BateSQ@vB99hNviv{`|cE;BCdCN;# z^1kR9Gg^KIJN{4RMl|NAtebi^k1PTid+IA{mXC&xkub9-Gzs)%z7bcdr!g9fbHKbP znkakp5!T^#?e6y=&hx1`GykCZ)%qJR-QQM!{;<=mf2Oe~f-Du*v{E#4qG z-I!vlEDN&MZ}WRu=-S0JZ-u1x+w?v`PYReTq$Sfvoe|#+ItQ1W^o0i}&sSLjbWno4 zNE@Sc#SD#97E{2KYO3=qS3SH9E>S@ST=!pfjAOI$|LRCGzD2=-%99e5CUthVe94Fm zVkd)6*@QxDYAbpoek#^KtLR?NcsKnm~=UXC0u`lLyP&uG&Bw zo!fWluUuTN)0j`U+TV+JZ=atRXMm?uTweB%CcNBSERnADlem{jxPCRIYgA#q$vs>q zifBRKS6nE@!5e!GBm&7GSW7dW#^gZYsZAppC%-T^Hb+S6Gxm;OCs;%yVJlV3whH4F zR;LC{$#TfC&`c_`fQO`8xw?WRi~8}}gN|Ezx_Kn{em9at&*Q0)9r7bmP4dTyT?#0LkI@Hd&iu4J`qfyKX8(-T54YKx^}z~Q}kp> z;#R&Tn=nXS0`uL;o`{d4?RPEw;mabe6@&O9&IUJ?t^5b>s1 z`GDkVH!{h1Fx^QY5Q#W*nQSyr2wT)`v6U5lI<5x~gns(@zc}WWoIuv*>klWH4!+dL zVoIzASoEihdyJ;H$Y^!7F2sg_#-6qH|(VuEVo5%^GH|9f4pI+?i8f5&2ULlA)fd? za#&VMFYl-2d;28ahoAfR9m|hR zEe_jroQkqzK=zZM?4*Xe{z=gu2x5{+h$8qef5MRd=3NH-!B7Aw?M6=4eDnK`82ys~Ipc06aMw=DsDhBJRuw5+wn&aX`BGf3)$x{M8Bd zR9K3k<6AjgsFQrJhMqib=p#^O%p0WF`K;MuVTF>4ivQ<|@dEkrB}L)2t*sXrkh7i1 zQ>edNe@6g@!GeR6Q(jvRHmKF(|Kas@afy^yu9>uPp$SANr5~_YCef{)jje-%;ir1g zzpRAE*R0fkDK&0ioei7-hcEfA!WgU1OpST;OwaP=%Vdq7zVd8oN9?YJc0W|@oL0-> zR9?HSI-_3fYyO=e=YvHo3`kEn@!$VO?$;Roh4}_sNrJ5F{LMBMMA zc~er?4KI=fxC0yV9P$sYUDyER0igfW*2O9Mb1dk4g2P8QIDJI7iUbRH`@IdSpgXb* zcw%67@L%qx&}OlI4Rj)wDtX0bl)>V-Fz9T{CnWynIZ%V z$N{T4r?6V|ri+w+N8U5=(v*<5)SvqV{6pc4=g({!!aRr-#V)+?{vGspKp(I)9P0;6 zf?vT0e?W!1ZDa4Zj$^{t_WFmL{RsaR!@nleEvu}pcAoCrx^n*ollI&@u+!~M_{7?z zaP#liiWN6x2P`xoWdBYR7s_Q#HJG~c*R+GX-}$dYUa0>a>}Q|gXIy9;vnVtzyq~4i z3ovB={S)LIhr0G@szw9<$E}gn*fGp8#QEQ^4W()y{_FTjAZJC}R^soRl?+q2Ap9|! zxo`h|?Grw|=i5rH1Qc&-WHK+Ej!UfE1sL_;zjz?gs4Y#6Wx#`qhQY_)o0r%ae-&r` zOX+OMr&|U4?jj$R^eLC#LJ`3^KxoWZZi2!9xFjd0?8!01rQ@_0#{Zu2Kvaq#N2$gz z^(kM$dk#Lw6;%PEXiyhp$=Y~;?zl3fA^nY*NH2kqf`LcodexQ~(L&>H$Z-ewGqbeD z+<}$g(EFk+{tInj==uPZC)Sx$b~3syRzbk#41V&M~FN=WGMI?Q`ds{xxZ+k9Mxli~oY{;e&xntwET@J#E z0L{L-2=CLXPcx_rxzBL^E8=8<1UfLTSEY$bGv)R?Y##_o0^ZTZN#^uRT6=9u%jV;t zHw;_lPx1ag6XCjPt&{->AxJ6fD19u# z<_YDJx76g@b1FUzhGHw%j(`MW9g+hy&jZ&>7aGV3Lx5wX8p%#3L0d_n!oaX!LxlLt zxF^}VKm8;mZlb=&x@;Xiv7|4|4|+!;HX5A@dz855?ifXSvCxtwqdQ=MtGeDfQ@giiP;>UR*&;-;@mskrxz#YOU8WP=IHXP)3#TC*v z5-8V265dqVB78Kzti`JTBeqHHt})4tuf645jo*SY znV)FzCB2pJa^H>j1FvPKpzF&X@z?WGa(Z=M%q4{%=V0XnTw&(jMqs8ae6g;ahYU}R; zLiu*TLoV`;eubg0$vjwu(3U!p(}qp~?#NYE`6%Q*+NqNH5+A}@R1RXuuz51yA(;$) zsKw0WKLh;fKV5?L^+p_Ccj2iV>-#rtl;8!0G&?w!X_tHldE7DRx`hnE$U}j^1;7%>GddsbOO-rywA)7C|WJ3;2o6LiE&SQcEbOYca1EeG_ zYxJF4FX`SDsCu(#HmIA98&t>V1QJ4rVzuj@GT0BiMoCcpoOB2`OXarV)34H-?kBR0 z(ncsE$_S6L;!kL;GULPU8{;?|Guw>CHdw{@iZxuP@2pU$i z(X!*e6tj3eW@gu@A)uY@+WDaQ#jHH(+TJ{5SW`H0P3mpXi03nA-d1;1nd+Try-fCT zX6>GZY$C<{3RoZkfP>6&#jrbUko635s_UAVjOX$1*1@!~Yr1m^fyPqD|9vNO|qi1DJl1X@}!)2^47XrEhbRC zpf^y7LD@~|HHeW;;b||o4yxza>nE_b0OpJ8;En>hASV40i}fuR83FfwthmzG5;D4u zF2{W8GdA@#lmM0#we4q$Y$~+>BtX4xvUB%~Cj)xm^v@>eez{t*$8@(6SnE&lE&{GA zxb4?4^UCj*6jx?sARdZ)ulI9$&j&`bM<7h!PD0;9pm4g-q0i3BqorV$>Q8_UwXB4X%J2wQTke}hmzbtP!~bte&cU$@VY&6KnCiFF z4AYebMi$lXmvk#`GFS~I5&fs6M)F&=_KbG@BJvaC7{cA_SW~{w%q0b-0gtzLzX{ggP$>GwGcB&8 z#OVCI*d$o;;jr>b!HQ{?Ho*R1TJJOfo5u!wJ*f@t*21>v5+sP=$~ys?$&OvlDoSST ziQMh@j&~;QD7|tH(TH&Gp>I<{{d91AH%$?eE6eom;IjmSIeu?)gTzjB^TV6c8_o!n z-)WN&ufMpSM9JwZ_kAMM+q7ezeg^ z6h9<6XUo@i(*Ousm969{oFe-R7y9b76%CXdxySYK0AGiDPS>Q}Cuo*kC?ts}>$;$3 zLMrOfdmqP9>~X(6st<^Ob35D*7~*Ye>0(W={^I~%2mSF^B0Si`mk?1wfK1484e%)X z=nLF=fF4SZ4s|mWlepI4cI|2TWcJ4$FpG$iY*gfI?gdtZ^~`nbi~fKdDlZceFIN#~ zh*O8Omd9fSwrhDehQB?N?)IRexC*kg>0aeM1puIElln6`LM?Ld#pD zG^(KYl$oA!*#E1SKGXCpEM-4>-P8C!^D9FNc8d6+aV|o#~_5Fbq%`_wi}femr1!9uTUQWs znd;}SB|+Geo*KHVlWGX&aQl-f^5RS@4wY%`TRxV@BDs=Ff{wc2t$XQSCqY4{AZ!pT z#lUEmH#Rwg*?Nq7&J`NGP};u%d1%{~ANJ+;a8+U9BurD=K;T5;_9iTH(c5ga_u+QL zY;=<+z|($n91lH{#oWcMIOAQcCPxGbX853BH_rJ3*Yj_>z?6gxoopgiGet$VZIjgE;=Ri;-GDy2%oDY+sku2|XZ zKaxel;Ri6~8ONl62H9 zHDlw}aCbxe_vY%wSun6wKd2PlaWf5u+XsFF5(00t!x&*@dOznGkfFZv#|QKeo8$XN zn=>8XEJzl3;q?r!BSK~BOI2HYFNR{tf;zL9>DKxwwkE-dvI?qVuz*m#-hF4cnz}Em zX;g3HSpd62Sba0!YA1Qbk*k;EZz-br98U}bYX%-^?CTFBTAFonZ%12lU;`%vuK{(p zc5N^--XA-?^0gJYogDOuQAGYx*|?_IH@HauGko(tTxP<=wVrXyqQ)o|g`D)o$BApT z_I(f@l_6KdCQLUcTBLm^lOY(Hdf0c&JWpO>`l@kEz&Ch|4`}eb(p0zM+0(fXX-<=0 z`M&1M;H#&0UYzK#^HX#xpE5QpJ|UnHmuxOsUJTj$-<6`B5K@;lm_%?pXxB9{c(BR-lyJf{y z<+pud{1TDsw-y3KXZ!vK!bzE~jKd7!O>4yU@Z#uR$!d9eoCk}JLw4h&ss~c;>k^!Y zgBsh#8&iZ!P08*Bk&Y@w+fKsU(W3?VAe?J^l-Q&S12jg;g5Y_D5ylPJ)dJgi%E{e| za93v}r7(DpGN(;RZN}?fMa3C6K~Eg{{G-MFW~Sgg^nG83{oM7Y3>RdU{o&nwj`6@0 zMxo`|FTN`7RhHP*6Dm+>+8SM1-F0N?JL~vvhm8wls2K^}&;iq6-xQ=l_Sr~?2IEzf{ovaYgN7>|kA)GdEttFGl=qsvcoHJl znGa1-G4+Wq$kqGu>_7UBaIn~#S&7YBe-B>sA@2>_5MyoS~KzQU2~44ei? zpd$H+nISCy^JIkAsT$M!uK^v`_V%M*7$YthrV!}$=m9b2hS12KG_i5t;ATOlpm+6o z=btB0YYAK-z`&4sL-z}U>Ub;n)t;Txx}QuQ!*%Q9^q6g@>J9{Cv6k2DKv&#)f)fs3 zqXI-DSs0f4@zGKZp98zYfTZeopLHt&1^YAEgpSi^|Ez_)o*I^&o#g_HAZp0P&%8@c zoUug)q}mHu>VQ3_5tqd(*u(}RQ+Skt>TE+=KfAB1Vh{qe`U{iRl-AYg6a5F1X4BWq z&aw3Qtx_nyE%svKN!r{K$)6@!JuxG;dR*4S&rY=2U%rb5_)MArNMt6>ymPA)f;n)| z12W4t?kX(vG1}#FRy&=+h7-B*3{JiHTREM>W`EB$rR;3VX7){QYL55pG~Xuyzk!ut zeIvj1<4)qiv!*#qQ@31l(zA&TndAbty^$e#r4WUqyOyEg%sO`HP~=13k9k*IlEDI& z9SKm@KG3uCi94zaXgbR1)Q~f9TddrZ8q45?*-+39RFjk+<$h9Gf^m;QpyQ|yX>YvE zdi!2pvbZM3)k2_Ad*^ynA1~uyLRJ)CyJ*r-BpohX<1JY%27PnArOw_fUZ)z0!)%mp z6vcrM>n1w%nKWjo%6U~?VQU8NP01n3(2Iw>GTA*kXnCEk_(K-A9pg(&h8d40Av48% z->QyBTMBpA)^P#)slj{*ZE$AQ@{rkHtcdG6e?E(LBqS+gHDq7MJGc%9Tg_Y- zaNo&p=lru%zUu?h$>@-|fMjjD%Vu-)-e914z7Zz(ncll z@zb&GY43VG=+|YlwXAH-UI3-HOB`&>I|~{*eei324z8e_`MM_Bx2n9vuEC2X)f61* z!wHNJG2&iAt!%SXz#Du{6}o)Ls<9MqS{2eD*f{Tu$aC4h-@8OVikh9~81+i{rE|?C zcD0O>l2>ns=GTsRsQ$y@q*Wr2`e$Z8St$7m+tusBB^YKDLt?%^z&YPnv)BX8dX$dX z7X_eFT|TBLqkhsP%#HQ}&56dL&_Z~n#bDgD-!l@r!klzm>JWHoWShUZ1AQn`DvBG4 z$a3^CoU{4H6{k*4~yi)#c8!fR=w68OVGvhPJo&nVW zy9?G?$efG~|UI%ug=x2KD27R2y0Uqq))1^QsC(i34@Li8nx6<t-ld8mM$VnDDudw(plgZc6DEyWwVlgcb zrLiyHOKC7)-)s|QR*(MktJNk13T@%zHlcRdRr?4#4fK+Gkz` zyIuyQ^6z@56!ThCB|*`mZtE+2f$bJS=Wo7w!;30jhw$M>%|;i$n~14|3l_b`a4w^$ z;WRQTwun$TDKTa@=T{o}qE&B23Pn6ei-C+lqopX`gqj4|H1mSVqtMJcI!ta)F13Mc zUFr|8vI3N>h6zBS8bTXttoGQI_}*@Gu_(tB@sgERQA9y@RCg$VvjnNVUoEC{7IiOY+%KY_LVXky7K2$kE{?6_?N>7s~CS|33Z4oqE)T_)# z2_+pP;}jUozcm8F&G>I#XCJMx5JR)#nHiG9>FXnvrAa7*CxPTAnUwcf(;KKwx ze*$xjlD*3lxy@N7L|Xz2;sOJ&ulWpqEMx~+9<&N~dc_ZWnlm~%8BO7fQ%Vz?_mN1; z0}DpjyvsrPHA~`}zbNp$@cdSwnmrU-v8jDu=z_mvdBdBZHp++OUi&ZsPg76LxgLg- z@Prj*DiYZ9c6(iCyi0r_`EaA5)Y*B+)&cm;!DrZ?hv;)oX~=a9?0GMoWgCoIpPtxV zwCEIRlKL~Br z=6q0-D}a67Jp3nDiWasY5i|rdd->>V<9EwZpTZr|ZQ~q69Vg1-dn5nA>ust*p5) z__wJz=){sir73WaE1%H>>5ey~9SjJAIN- zN0jS8SjvAO(m#ukcM(W2`iLN{u8IYdw1^=a0bg(^oaCZ$>YJl_6~H@d9-4gIyEoe0 z_O=kr;%}i{n8%K|r(=E-35g*kNtP7sFl)Q4gO~mzNOy9OL;seeht2t@kTM8nA3OVJ zE41Mg^qpNn$ZKa{L0Ifh$5u7)+PU2yMSbFfn!N7telhR%R=9WjEqn7aqpM0>z?$Jk z#0qjC`c&H3im<4&OG06~IJU@Pyf~r z{NnQIR76bFtSnBkB`fm$PxqjWP_fk1jB3v}H+@pwL7D3?$Ta9AgCO*sf$p{*Mu6)i zGLDn{y$3pm==lk6m?Yyoke9P6^$88XD`u_zhz3wy0q+)e_RQ$+ zP9<1BH1Ulwr6LjjbfxrCC+?S9vG-m9RVDS5NjW!f8nV_`l?>(AggAWSOBJg9zRDF0 zuM)V@x~KcZ?{U`$eI2$DU|mQ8c$ze&G-rf_!S<6LJI{txysEztQ3m9cUGvE>t45X9o52W71Y>wJsZsouD~p*%=y68)q9^ORxeJzNU;=i{w3=)F zPNMu8=y*`?!;oL{-oUny>F695BbI^TYEjK%;Vw`=CDqpy6RuPtz3Xch_9o?*bY8}t z-7vlt7YaF7! z-B10_c1C_wq;RH&c2@H~=2?n5(Lp2wCTkw6M;T%4PYKA73bdW>m>Zg7yXItr2uO`j zaD4dV_q~(Qn)htpnKjV@zphAZ@ycj-f{=|s1JxKbL}2@@13jCMc_aHABPL*Ig{85k zAN@?`)ccyPn2oQXyTambLAx7t8M)&Ndo<&a%n&iH7Uj3FaYaZ*Bwq80$(JJ_L_}c& zVw}zzq;ph^!GV!;%OO?Fk?fo(W-^%9L1(G#t-(SLcV9ora9_h8D9YKA9P^K=w@ z1^nu?>HWi*!E6*;x*8p{d-}ZEmMeWRkM+mkaX_cem4$Hwzm8W}3>+v?R6lM{aLSw> z9%r57YXp{8+mAif*~~hAml?geqs@)?kRp{o5LNCh9EVfPdq)0Ph#jKrq~_s&IN5+{ zryV~r{K=OufQgJ%Jf4>I-w7rJ~&yX^RpkYwAW zj(~)BWM$nA06?4QFkyeDul{KaY|ueD)9`f@2mN2MD7B&Eh0#IbI=irW1)PDEs-h=; z?K&177zC0f>d_m56G5t5cNY^qBh}w%qUV5ovXf^Xah#1Wo*vJ;;3(knA&2<{M9!XL zzHdCr${~DZ0rnjl<)vl}=+^=fK)XMJ+5W_`mx@qYbjpOi(VOgYUKF6@j!Vi1NJ<8r z0A>?ZhqYJ&Rw^o}nw(W2=@1FJ&7#{~#oedL-ey%q06E3xH>CB}8Oyk7|2aQf!WMoB znk)NXAZ6^;-yr20@%>s5;SAFTamLK}>F1L#zvUPz8N4_;t!s}}iR71r8pHnaQ*8aI z6kYKjAo{I9IzD3Y69ckXBXHqlNVcEq;EyLWQuO7}VUv*fN$3x0sC9$yu$l)euB$Nv8X-Kv^UmLUO zU6vh#-=T$PDN64WF+Bxc`ay!aW*LAaz~aA?*2S}^P6%P((_rkN|Dsdx7HE7{zMQcdPD1o0as(IVQ1Ld#!jZY<;uF#^2r@z-klB=#Y^N*Ld44IzbS1wW7;54`cSAX^XHN5{f_Yk*X4gx(ZfhDb+8CG`BTjo}8Pj zE&IWQ+|D@nGyifo*A>>NvRr4=@n9P9U?F6!<}TONq4q;tQJ0P>ys73ax~PAmN_x5s z@dc|mD=ROz*(PPS@eZ1ujnRm|@CwT48xpR((>9!Rb|7q!zc3Pr&-?D^-e9JdaM%Wc zt^&2BCnnmqVdK)gdpa(+d_V*>z@gmqM68fBzEhd2v?ti>m-v1|eqKVV%2j(7Zt&I( z^%*Xt;4D7UPxrus_iW$@!{DkoG~t~^0?QtE1qw|w1(Z>DVesSsDeFw!+06Dh-j=DY zRc#teFqyhFR2a&oN-fcbM#e5h)z+fD+M1?{mXax|mXN6>DaKL}Vzg+Dy|%;_YNXa_ zQ6`q4l}r#zCW-rI+B-APb^d|#oacGp^PF>jpWo-JSylYhB$H1&Ru`H-G(=vFuG-39 zw~teHC}eXgK3~^doi8PqyHRt69l(3|RmhF#R8WSqYzxqYbNL@)G!Zv`zkccJq1#keHp4v+L|S1F2WxfD8F{l zDu5$wR;3l?C*K~z9rZlW%>p>cSS#g{+sS7GY!k4L)cQ>?^f))+(LRcH!C zZK``7BjW>6pIxZAVC*bQ_>HKCYh>?jMHKolkg@1nciD|7@Ar`<3Qka z@^yKep8H%{;ZDjJ#zS|=MTYv?4(iMsj(z`|AXe-^v(o~fizyFWFrg|{Q3L#*To#ORPi z-9DIlhTCm}EvsqrSgtMTPF`D5QtwroY~2hAo2IlW2<|ZPeAvm^8y8-nz8oU$-Jy-q zA1ZpP;D>hNQ)igdZeqF(5ApX-cH&T_2W^vpGK$T=<`WMToUgwE?3FKXS*~lpNvHoj z!H>i>SEu?zfhtILE>th(_qVs6kWCybtECAduHIB_HoUO?(!04iDWm7;NzDu>_4`aa zESy+^^E{MlSX9z9z*1W`{(RCo(fk8T)$7?k-MExyfcxrSIrwTJ2klCSt_}Zc!mO-z zZP)t+iKL%@8b~gkM@!3msTPtk!^rW-C?Gg(-aMuUJ5^@$Wd0@*6DpFQ4l=&`iBnpy*vRO)Rwt}UNWqpZ;7P+Cg zw9D+P8Jp{dYkfwm6-BwLl6V}dV*JLhr|%HnWOg3MMs*#V8YyJ9Luv)C-55Xa)JFIj z&yLk0*P6~4qt%oE@R1RhaPHQn+pylFn;PWOvN`vo=n)%mT3&*)r?mGOMyp2K_@J#Paw=iE0qmTX@cg(Y zneyx>oYu462OC-LGy`5>g5m{mVAet@?W4{@T}$(F8Suk18?*AhK(WHhmzY9paHIWP z&?&aa8|e_==h`^BN^Ilz`{6%1*Lf&F zoc*F4Y*tn*<^+?KECGuzndO0p2;EdMoB9tVLIX@D&I}30-$b)T!7ATIvZJWE0%Zy! zvXDLFqc3pXzW^ct+yDi8&w{<-6?C|g`v{xga-s0#2ltoNm0a6ULj}uIUt%42VWsLl zf)nqjr@s4HoGm5s308x~-){ymrf;uIj+(27CFh^Ku|=s&ZyuHG_=_VQ*wUP;RW13O zB-JSI8YW1|1K6NAW++Er4TwhyB*>6}W;c6(QfnOsHwvU92oL;C@Vxk=^>jqNDS#?X zqAk=~cP`^z0H^t=adt9}+N>`*x0s1V8Gh=uh#E1l@soPJ;x6yUIKzGuCn0j4n>0fs(V z;A|{D_72mZm5VcyT0|WEGqmV)RkcO$5e@v>h5{4?R8FFWo7*Alg;67$;v^tGdJ-W4 zaD<;Fto#;peY!b7ArTw56Mx)L=Q~;af6|RuKitLwq2~n0uRN%<3I}oSj0uCx@cj)o zzIv@;wffXujIFT1S{sN`@BzXu?n&tjHdA|SQ*Dnfz1osK9g9Qoh?k-^yeV^}C zoqMa!_ur{|E;THAGkf>$UcI_|$!~S|Cnae#WI|*Z7#K8J83_;!3_KGI4BT79H_-oZ z_>+U7e_)+K(qb@WBgFgA3wU!;MNt@-${3Uc79RvLLE67?{^Q zSqV|Kulh$n-io}}TI?@x>N{wxuPCHXW9vPSEuS4mLZ$b>=;YBh3{dqN)0sp56f6g4s zEIBnjy^I*}!9O}0op|f!c=2f!UKEgR)C+!oyxn~zN6f~wo-LESo2$1cd*v3z47ONp z6D$_F$QwxKbw2xhukm0UwF9QPx%rEI068)&U3Njiz^f>x1O++?U(lK3W*^$Wz8G)y za##0XYoGIj04NaYVxffKFR}cm6vieB3L-ZVfs)++D*c9+#R`ap{Y&2cQ~H2IC5b5Z z?k^$yrCf#C(Bta#GcJBlHAu&2JCIVflss5 z9aUUDqRZ#pcheZ?huEEa848A^rw~Td?M)9CCkL!}hBVW%@g}E)`6Xb3sDPByvo}L2 z(i$Zr0xs?t@-kZ+{V{U%L!*zwI4*ZxKD&$d-s3uSJJOg2Xn)z+IV%UT3BmFbSTUsl zT$RqMlVjR_#q$!16_&zmXQ7g8W6vb$vy!}Qr$MnohR;4nVbWn$0QeQ)!-g9&v%Xcd z(<4)j9eKgSHKK{g9cWiXqPyS|x=NQJ$A8lB^B?QlD9lebbh;B4CeLDNkJpylbC?!7 zG~P%6zRE zW#Ad1fn(VLddPrbpug3k z0-nBlyhnB`$qUHqdtTD@dchQZf`9S?Nf3YWLyl&z8HeE+=^UjPy}L3%jROjE|4XP| zS?S^eDz1%^Xw3FK+m$WHtf*<6@t}`>e*Z}zBn8UAB2%G&@W+?$(xVQ)7F42)=5S@U{!GZS-~kY@fn zo=a2SrS#>e?#Yxb#xkUUyW0ALUaNfiNc zzH)1sL;7}72|Azex6QAi)E$mabF#uhYu#R~2B3gHj~My|0vW~Wg9;+%EkeEy?oMtP zF}Ihun|vMSu5Ngb{p?s-l6-4GbO|FX|5Zb@lnne%+^4II(akj&bNAZ_842+c%z;4( z1_*2hkLhiPNX*zLKLi8}gu80LPcBYRN%f35l~*55l{?G!g4%gla3$|uejkUWMxC@Cq00emai^SCHFfplr9CD4-psghf@$VW+D}ZezjpX#S(L-iJG};E=2SV1->`eXz3Y3i81pj!dvzOD}x~T8vUgK-rc+& z#?6$vGBz@~Wb2d3-P1hIws9P_A*CRDlbjEiObWT|9UgjJq)g?`YFOxwnb*@!lmPl>{?e zUH^&PY*SXm=#F74Wg=C0V7&b^nP3U~kx?TJ;>K!@3mvvwCYBEBYYwuSn9!zsyUrO4 z$-c6iwV2y0rwK&Fq!$U{N%_dZjqa#LF>0j!Ga>3?TOc)NcSHJYH8v8V+O9RGi;5)V zaU?U=Z?xmW^T(Y@h8*WQPkfz#|0WeHSw#?A(MvPEpMqF@5vO$a1;V;6Z8upKd(NR6 z9+&0Enu^rY;$F8kWg%;n#&aNp*=wT5p2%|xx(k7MWX~u>*Ae%IY4%Sm--o%M^qJD+ zUlP96Z98*(M=FfN4NylPCG%IsWzsLHu*6Y!1qX1w@wXTx&|$C}{t%DI;plC&`Cd@I z<)qWraV5-*sT4mD0W`1@@DE z3R(Bc|eNMylOP7Q@9i@472odLYjVZ*@)Ng=8an7B6Ius=m~N2aNXzW>wxTsVp{?eXOyb^6$6AXBH{f4o)mVLr`Cdl|4NGg-EoWm`lRKkIozZ&0%O}zh+`&0 ze?H>xgzkn@$F<_!uLQ^L*y^PnyRj@kUEA-IxsItBiaSs$Pr0%a>TKU*xsNOcI~2xB z*hJ){avCnSZ`G_KboCxQbE-~pd4jPN9IHXC+k$t5odr=bE@VG{&Yd2!0*KX2SU+HL z#P$m~oF#ChW|~=N<5%T{DVNMXKc@QRqpM+Z5M-4#i>$ij6^6^0gN;_r0{Esca>ERe zajbWr)|Ltr7?M&_57GkeAJ{)jabUR|mQUME5u}}w$MD3|hwh%H3Sx%47K_+krCV7Q zRgZUFoh|l{tc)uh^{1tgo~8&FX^ozD_pOh;sl%S!_t8-#%;vFLe}0bXU0LFbCV%-T zCxa#7eu|N=c*;yXUA7%|B1k*J&8cToWNyXx*>Br+v)10I7nl1FP_kz|^7dJkLE8G} zeGLg$PJ9ssqhI)b-#vr7fxAmpM3k?W#Ou*Tr9=A8bY<5;A&@P@unsHQ`FuOnqHpnL zA@PxjbDQB-#UdNAKgGTY@iloYXE99uSo)(t?a`h5z+HieKKSan+P7MTVcJ#kV_j;Q zUO}BM2dd~V#mQ(NPHrngX01kSa~7Y@mT|#K&{4sH#^noVzRVp-cTZm^&)g5~2E!tH z0hcQObJP(*G)`LO<9VB<$f&bVvyn$@VxZip7VpFHqU^$7QqJxvsVkmmtYh)btPJs> zJVe~EmE?e#n8a=Xm9QatQ-e{;iqZ3aa)9;}4c!GC#b>aZHPC{~D!}4}-dT0>^8<>@ z^p_!I3o4os;a_{wOzoxZo_>K`^?Es)-o;cBnKC#zwPL! z1Mr6JcQ@2zADlh{Eg3L}M#{MT#nR`2S|idWhcg3CuV;NCvzDy_948vqvF()@^&%~+ zA`WXdG0RBY16{kK+6k9Li@YD(y|a~((}v*yOM#K>)dcOSQ>_>7shs9N zu-6s!KJBQ?k{rcqwp?q=vyq>Of|M>39P}si zexW!<=Pas|Ow|#H?{PwEEs#Vr|U%s-%dbV0weOsI+B*hTdjN9X$ z-2fPr>nYlQK32tl$U7>sr0(-s;h>&#!&?_XeSQqO`UxGV(xsspV-2IF`qC78KEEKN zd>Z@*eJlBpy=2GDvcN2|@gmp|(oG@rP(kwo6_&ds1iT*x0=4BocPsSc5)xPm3Flk# zoJK_vF?Zb4vB=||+qA)m&A&S<@R)SltO%NfU7JA49Lv&{#_d|Sttl3>B043v>dHqU zlZ7`r`Bt3U<24qCSV158+wljiQ%l2*1`>fWt+sAmN1mKSZ+X3zKQ3{z698XY!huQL z%HS}{bry3s9mHTYkw;Ew5gEKoE#2}4=^TcFxOdu{$+RkEQGJ~NeFit~U) zL$IceV;v)CYm)Zv`-;U)r*!%B=&y96)9XIJ8eE+)rWQx35ZyvA$p-WS3<(5!B1fgiAdwfPJQd5DDt#Kp9kAgJFkx{}b1>^u}qbLAW8> zbyDd$8OptYx)~iGsUHO_9Vb+LEV&S3Y>dVbIX=w0hp+@0@>M4uYx*%rOu z43-vazp$g$ABjQ`d^|iMR^&#;&s2RVX=A$-=KOKUDGMP(ECdA+6&e0v>LLZP`E==) zcP6T(R@HCe>E3&b=#opmY&cn^qiNly7L$))g+}gZe)w?I+Yrh&SP{Fs!~Us7KYu${}{^@-khwdZ5DTIv-VxgO}aCh+Wi+o7Gjfy$p zB^T#@hKxm}^|d3bajgbW5;jB zu_tXBnLL;E;byH~XYYiqK8i5x5uZPQV3Gs{8ZL&`Rfxa#P#Pr^TgoJOuDkspBI0mao3sY}?I)Q}`p+h!;X?`WU$s2zzb3 z6x;AiJl-M!ClV4Y2AEQtdA7zihM@cFbQ z>@-BF1cvembz&+nNw-n4^LF1%-FE8Z_Y`g46zGiX&D_7z)@G%d*b$F*)!=Qt4U3HXEwT6xBBrQu4Jlig+}jlYIHKFz>pe_#tv{>#hdV(L~G%@lXkr zD+9mi&kNQ?*wIp4e1?sV?<*6S&_!4BsKS5$GOuZudXVzd+}5(3i!j1HL*Q_i5=;BEVlc2j{YqiF35Y0Hr9pP|qg1QYk?uO;4W`0lEtv&U6TP@a+_C z3aoipD@Se9dB%!ABq~8-I$R=;}93j>KV;4dT-JuLJ1)l0Pif2B*9DO_UM3M`;vjZdnc?l|xE6CmUHbLx@b3_f6 zuw4Cyi-Fp1opUMt{i}$KRFc}3>if;;n@ma(rV~eYrKB-guhko8A-2~nC-$3$-z$}e z0jyUa7Ci=#lcTEt=;1$g?6?v>&qGJ$G9gI-i=1t~_H%0Y!b+%Fm)Oe@k0sihpxb;^ z=!7D~2sAV}535!dF)CRsMYCv^X%88;v%Yr`Mvlt zJ&iukTaY2lol)dC#~3bf3X8d_S2+-G08-DK}{#w=I%- zTb?|A9AGS1^kNj4J-Fx8|Em#UYVVQObQV!2AdUQX5Us7|uMw$zhhPBI{_-}7_{5MJ zdk>kY%h@$%K0CBAqj~km*fBFE$5H-U3{&@Q`LnO--r`AIj-2G{&x!f&{>RdZU;Bp(=55H}g@U(aQNP5@!AXDN?Q?_QfhKc5-vua1In@l~7c_$Ldf%dhQ;ldk>grm=L`rK7e?O{;^Bi_`w?s z>>2^ftHh|LbbZPI6sp1PmbGbBl}2n=o@efClCuZVOZBS|6_=*yrhkzl^b1(aaD3L= zoI^BU-bFb9dTfcP6)9 z^(fTeBa2w>&ZX%8Iz!q7A5Dl$GRl3q&-PTWyy%(mS`d8Z`JFVvTUl?6Jt@B1c-ZpFoXwCC@r8@P{WK`|8j!qE z9M%IPJ43ru(WI})m%zXr^UFRM>UV8J*8=sJw@*+TkLdp)muw-k3HgY-T#NpjTym+5 zMLk<-*y@~GE-)AIyj)cQOx3W|3zo~1CZV#@lb?G~k4u-H&yy)!oN2txnORO^WR^<; zA~Cs-`9pLOpl*Ym;hp3^)v+(OxnT(>IZ?rGQAtvcbZmyoKO~j!N4_V3a>FKvgL$N< zltEklyY@1WGL$mZdKczcU?5(Hs@TTdwug{gb4bEmEjm;eY-y@}rdGl&PK&^ewpWH--ra>oHr91+X=aZz`yKcd9}UlHUIfEnBxMit-_ZG=@Rut1wF zY@q$;*V{NykVo#T6OnsT3bbR!woGfbLMF0`VA@4&%XPO>sn_ouqF zhBvTcPv;!6SR1R7JNl6R5H9|CcMMZ`2+pY>YcDhDBr$KlombXt>_@_va~cI_wf^#0 zV1hNL1cOed?=U|J{Q0X`2w=bcI%m&mJxLBK1Y3dIctv`G5T9eYs`s3<8o%`+KW80? zul*e=H$YT-8#bZC&#^0J11^yF#*aewix0x_z>j_9B7WY+;L`Pr4=uLOM6!?%kAghX z9E$&uI>#ORC^Fmy29O%Khc`o7$*`Glo8jpl`%1r${Ool$EMvAx6qJe3H3n9P&y1*h z`}giD1c;u$)3(~xWOdl7>KJX`I4e+^#8sj8cmv99ozYMKD);W4|D7Ln&g8!H3*bCJ z>!&whaV*a5G=)JizW(BqZwc{45+Ia8#X;n$cxdm>PkS<%tii|n@_Sn9TL#HxUeDxl#n2aYxf)9L%)^R6~ zJwJOkhsM`_KJ$v#Ol0*+eBBdV#m6Xn-tfkt+i*>E-!w9m=GMeo<6S6<$q)w&IUvd2DX25_G0)5p=Y@meK0I58j#N^8Z+VxEd_&$BLZJ z@{t*$j9A9oiB@mFHcgSp3!&W!a1%!jaJuR&fd`qb*xR!V?d;qCM@d=c^FN` zc;c%OF(H*0I4u~IYS+c%I9XPQdUz$BRm;(hdhDGXi&ru26p{{nNT5pq#4&pzbdugT{CaF5L>!QN)>Q$zfJm{xOESjREWQ$<6yH|4xIh!fNm_+5XkG)ur5lWZ*T~-jsvS6yh@rxo|mu92T zLYR6JGT3{lo@Z4Y9JD0yqo4xEXXrLmx(KiyLVs%9rtH0XEM;W>lqq8JGPCQLmC5rR zC>gZvr`mzJiXI%SsmFmIvBBBqTOO7_hm00g@ZvSg>^pS(`ccy1pi4hzc1?K}o))0H z@H26tet}^lG{Vx<*#>r`IN|3&zjyd6Ehra}|0=@XllW%1gQb# z$z066dKp@EO4Bl7Z~T0|UtG++Q3&4ff=%!SQlz3$k0gNPH`hmP&lU9W6lGk#Bg54T zQ{jonX;6@&OS4H(4-Kc+j9qp}PnXwc#B6-FJQ;P6*ZT=f6SG2U5W0u_gpv^@)zboU3Y%zP!MQxEN)R!Ek)?bQ5Ip`THifK#+ z4Yvg9!c;}!eh}!2N*g~Y7wO)L`SM#KOZ~abZ_0n2+ici%E6$nhhL6UK)v~aS*+@w_ zlM8dI72kv%%&gh#2cnLk|v88&UuvM$ja93S1jmvVWW`(TQGX_gR z*yqJogr`VUHC)IcorL}U8js(!wPv%2IZyP;3!XzdVtoYbp2%=}(~C;dA&hRm;SVcg zqF2samoGz?dnPxfzy0VXC)g&RjNT}dr4=J%*p63>8?@NVC8J~b#KxVkd&xkK)O1Z0 zMDY}*zKq;eE5W(B5j0gDHn=u~EEtm?$bg?d$ixG!1mE3o@!J-#diD?evekZ?F7O=| zCYS6>QxGP()m`~1e_7kP+1S36J1 zVzX1JTkTFVw_iZI&9)gDxp0dvE8xN*B)Ljn+cd*9(g@I zMM)BmwqSs$wzg*#!;^cz#oIgkZW_e{dEz8iNOntq^6Rg$nzjgsXcAbx7IA2Jc z$8tz5ks1n|So@!n)kF3qZs1#pJ3Bk>hi+Ib( z1Xgde>^E9sA$~@XL{4sbEm0-2uK3l>jrz&J-%{Py!f)!H8@dII!3C8f4HLPQLtQh^ z8Zk(SI_Aeu&phJPVO`MOh@9e^hiRRAxF;>rvZwn5Pfo4LVlg`*UpyzD>jcl%cL!$F zw)2B&NP^i9KD3=nS3)80hLn`~xk}H0>QSMKx~EM_jxn8XAN2IY-3uPWx4Dm zd_x{f(gnf7b6$w3zUxJ<4w>haoK0?-t~B2~NW-uFzAcC6nRDO7)8SD9=fbsmMaBcRSdSR$-!lci#geZHLDLlv3)rGhNr4%2KDVch9P3 zU}bp&Mp9U#^65x%H`g#?e9uwebwr7M$xYcAq5oqhr6Gj5Cp#<4e_*0KGx4b+7~j1a zzr<5tFIo6Knrn)i)xxj-3fsZQ)>90HhUOA}IR#Fk$aLSh@(g%AY~clP9pL_<@Ailv zLE1o4GCM=(m-8p((?J9&=Jp6rDtk=+%n9GNCiVlB>6P$wQqv~torneWNHV*LRx$y* zPOOp7jd1o{xBRAKc(wa>ZP5$a6T-i!1tfC#y!|v2KkAs-v=Do^3^4(fH9IyLPviG4 z@f#frY+rGdrxJUEsDfI1sX0lrkp1RgyKr9K(1u-lpuBQs{0!RIVGb-ihbjT$er1g5 z;UP`uQCr4y`DePK-egdl;{-3wK(JOb5(~16kR1;OBiramnv(XNobC2J!j3yc=`8LT z?mb2=F3CT>=@SIk=D;i(N3dSOc`}l4&0rhTdTgFt&Nt$FekaLkL^IoDVx1aWRJnQl z6j+sumhpL$L-{B9?X_z3kcmQdy}QMEf9LmZde29eVJ7p%**TkSM+!{PR>C1A3J05% z2dlz3E1y>Q+)rAjhYzIAijWfWILogE%0( zsKa+ANyLD)4-|hX-Cz3QTP~vLcO>YS6mWkD)VBF|NreUq2ns^|OE~^1Nu-d|UDSt} z;Xj5hDlke#;xui0NT|2_MZ#Z6{}*h}7>f3PquEeA2^4+tF9^oJOQr$;v_=MMf&R~S{df8B zzpe0R0|1hgBrJm|ffRy4hK``s>dE;pq}1JU{pv!kb^pJ>P#hc_m_jbDuJ`Ro0Uspd zX%scz#xX<3h5X;27r!leENbe!G|Awi8IwSrcT|QIJ zl|kL6;6@maOS-XrU}k^1MtCvLO{i#o-jBG^e3k&B z!drn5<7}DRpB`<&A;|vzJ-CM9DVw6dE8r#0LYGnMVi3nHD%Oj+Scnt!CzXDD#QCBLH+|d(p zPK`)Cs4fT)#gNigU%COH2t%=wmViQM#kc zXVKBvt806W7nKW0enN1fGV8*Wl59B1KN*y7i4Jb8=9T6PnhunRh|;{whuw>iLvC$B zt)|TJ*1ibBXC6q|RP7CbaOa@F{u>B*{A-vw|U6NU$G$k|=mgZ#H4#W@t(G8z^_*iG3k)ZPt~)=lvR6viNV;)J#qW6Pl}OMhvc-4Jp8LD_ zNgpr%_Ql{kuu(xt%FNSB&d3M^RCbcn*2azhp(6nfW6W&Kr>I8c%3U5kDUllQRDi6q z^6xFa*!0wQ2y}HeztOzjAP}rJxZS2Iu92XWdy=0&zf?NJI&H&8d7{s@#b1ww-Y{W< z=oG;f>y#*cdLO*E2rAz%(vE* z-W-G`hzRH5a*E++0q#Q@1>Y=1Er&^X5M{B%2=nA2OEzC+ zsqgK5TnK0}wX}Sqw?MrwZnPhR0w|)i5#hVGF`l9yMZfB_@)^P35*6Cg*HkR<7Jyao z+Qe84W4g2Rb;qGGwja|p43MAl;-dF*?I<667*22-gVV4!Y3ndkl|*#jB%oo8b0>bl z>yxYb;;m74GZ>my{&ge|TY?TML|rG{fY4W!;A)DD^XAo$UqQNHo3VT6Lc&bg$oU8F z7xA(X6SAoa<0gT~#@{tK$Lj4{pv`sidRz?u!0*hov-&G@VnZ!4&eA`un>l97wD49~ zy9e;4y{6U~Y{q0s)qOBBVC3R~F^N;F+>qgUO<6qj3yOvT$|0G;&+X|%{CJ&T6K z?)FwQMpc_lxwjfeejA1$wPkFZMHBLIonlbdcr$s-cMCJ^(H$9-eufK*X_U5EBj;_z zSjw~u=`SoA2?;DwwX7_|FrfIP?MUGI%cxL26>$H>4{Ke#kR+{o^r1d=H$tFmXm}*Z zoj7$8RvO{pR9X;1ceaH1wSUFq!X^cBI96{n0Sp2_UHRkoU%=Ww(ymNx!=xSeJ@7T1 z%&_Q;IC7@BY=z+PO6>KV|osz;DZ($8Ym%o1{l8b51aYgGeil`!kD5u56W zvTG*JTl7ruyG{IB0T432%GR0RoYl0G1^}VSl_pqh1|Os;IcQXp;=ibw-e5Vd&_O44*AyHYo(OV#z-o+Ny zIB}Mzr0M}KlK18?Z=l3#dYvSv=6ZHiJyTE-$+hmjR4kundEF5qGdO!>$OyER{hrvQ zRoj;2eicjhVQ2vr0Sj-L`2E*aRP>1gvtA&mXB(e5*RIjYFAf^^kwBuuPDnXII-SeQ z0iR{DSWtP3EBcJ79cv+y&91fu2HFGw=nRln#!c@~gD}RI)>(FLKGVD26@QHMxDEV* z@7y;lkCi6`c8HbaBP_0+|HfIPtn)Q}DX6qylKUfnQ!;?S4(ar(w=;W}biLc~8oBdG zvz_1j-rBDCv>&ji70Dw^OUSu0R)Chxuu5Q;G<6&>NC66JQ)oBrv{&vF{oXv_YBfi+ z!m94WG4$EGmw-n`;((Gn98fq(g3c!G_j`fUil>Nb7PfE6Z;BqjTHae~YBdf>VxIcJ zf?47&xjZY9kAJpgrcT>dt>LDKOn|9088Ghyhi=5${)pXsaTZ-iiH0d;0~fJ02(A!> z4$Nwk6&Brw4-Wc7xn-#~G}6mVp#v7UshdaYKAyG#FkUq2G%(-3Ygyj>1I+3zMM&z2 zoPHyNRrV!jkl{-}2J0!Cs(sb~A}oB!z}lL8$-Qd3K3K+W_+Uw9#f~VVN9UI+L{ph% zeY7d!(|W!UNW!*wPOioR*WElTV*M1Hh@~%3Prn0IN2n=p^Mvy@no!dmy@w7 z`)?5n_>vMz%h18baJ{;q>O!E7*Zq~k@lU$A)bGbN5_c+45GP+}b zfJoIQnpwn%!5{meB{BA)E*YT05$dkVNYs}Iu{i`QG1Zka&@#ZSR7#}`gUF!~u1}-W zoK^+-xX>MuhB{XUmGN>1JXkT*w45|W;Df({H3Cn0KDV&xfVq3uTu%L$AN~i?vmr56 zj#p5)CzTr}Y5;2{dZf>FeXh(~|DT4loh+LOLZmWFW7XFRou>s3$va42b!DLZ7y_VA z6s!7(2LHZu&b6d7NIvsvfeJ=-<K6_U2{kA|I%YjPTTK{f_GZ--csdUjxs#qhB@ z)KO2B2{kOxwp4cCmR}`d?OTkW6i^)4==-dZ)#hh)C3Obpg?YjSBQbpEN3~m&C&$li z+n$MgEIY%wGlC|YV7|se9kn+&n=O|9P8vKiX&&yhCvHL0dDW^eWBIcu_GCQW{Q7da zh>1p}`K0dPYV^=Jj0Xqbw~>u{!>~}OHHNV-;l(v*tG)=zf^oyIx(-$x2LfDG3vr~i zYmPXHdJ;cW+U`NQ!6H1yk=X*ox!QUD*V>l&tB#F3xY7E!kFuZQfIY&w4S;h#Ld#ZS zsHHL~6BJWS2K?gMsNi5!Le>?Uv`fT;c&nBRjMVZSA;quuW1BG-&8MB>KGq}YE6MhI z(?@)8dkxA}!kB7&H2wA&QQcnjc$pj>rx z{7V{!n8nVDGV)BkP{W}Mw5G1)VPUCd)JGjq?sV>m)!~|BMmQpesD`=w3XKNA``^l3 zq5b!FyYdh|M6wHUz&g32)$h*_KJd_$%b2`L`^YN?x>)#yDbQWajhW@sW2Z%Flh

(Qsw$bk!CBB^hciX^z{vII*F-M#=?_|VNw)h<(W-dS7u7AM(Ru5A71|h~eQ0`_DJMIm3z$J9 zi%@C{4*dS4W&Ix!2|pLR(`0Q#z;0%4><+!|BmG9noxLms zmj7YjAh5sJsnM3}s)eN*NPom{2&#!Ev7 z;(#xq()xNmO>)dpwF~Z5-kadzYT*zl=A%%z7o0F>9t|C;Q|Jtj+j3hSbvoPAzmDbE z1P%R~?G~RBGxVU9BHm321a_jo`cGCeK-Qs=p$@ai!Js15jl!y1-Xf;!2_FQ1*iwXc zI8z9VQ20r|)-tIVK|F4S`n#?*>q%178adhvqlN?+UN<=KiczCXuUhCcTIPvQ$QLQh zJZQigK4a3mI>TqYH7c8?tG{{8DD&cpHCHBqZ@ZZDoBLGh{JV8==UX@)895|LSh_c- zb1c8ul=4NuCOuvJOl4}4cLm&TIK)A@h!j!Kum$HGWmmsI9*qpK@ykd@(H1k~E0i>?O_E>=`0$nh8Ugkd zjaaU0``YQkBQt#P{;jJ{H*C`C2WqN;mt^~4bU0Qx-KS4m#V+tF_?A#CfUl_aI+=J~ zH-Dm~lR*-G6{2ELFW&6I-+HCTRnjS6`L*Fy-uzd+LblO}=o5veuA;rG>m&!E@*YgU zN8`572OPofM_*~Q?yw~2pkqF+ewkrIG%Z7Jv0$%`(kjjMa(;eP=eo+`7t@co65*5C zD_d9UrvjGH#i&~@qQ`WxWYJ{#aynT5QnGlj|KwnL-+&u1T`3j_lOYw!)@v^usF-H@n+fuPqawVc3=P7DiByaBMiA&nF!$ zbWm-+)*o5(FR9~58Ih;K*Q%Z!qQ8+|3ISTSm4xU(gJP>iD>Qhx8H-cTHwd!y4^kp= zla}d9s}Fu0uf^|MjA#E?P=ze(BO=ggl&NfHSS`3`lRk8`BW1flGwB-eikFoX{oOhC zS>CK~#u?)iQzf0p#9WBoIov;CqgPcjf~byE)c26SO1Eq4VG7OYIR^xqyjw={X(d`2 zFTD{?08WP<2e=<`5=EV<6kqf33{YlL)k~C_kT&vaokbV_>UQAMqbUsygzq;u?R(qB zKQzTp>HVR!5f&jU6d1$-ZNrcShUS#jwVlmfa!q^wpz~L0Wd0wIeC^Mu2;p*mca2bH zaHFqp&OBH;#CnqKCM7K*oFdAjiQe%vSx^yg#eiScz!v5D2nZ=-wJJ%-32P*B@=TQ8 z67PM$@dwYC`RtX_Ia1pU9sIbfn#y-eW(=r1|}B(Y3V_Kuw$! ziaQ@ry~0DE?+5ab)Y8;?&Dgv-W!WK(;5qs%s_`cQ#|^&$MshC;ks@$oaRzQwvQ-O% z(uNW`BcM*FLbv%8_cfB=0Xv9fmmf2`MM3(>;26d2md#8#h;YJfHmy5#8NEfIz~QPC z-gB_{O(i0@MTi4Ik`Q$&H1JO17nStatObt?G!+S#D>Ob4xu967bKAqh&WZx@%kN)Q zrcL~YG@#a?2z-U7kq{p5zfsUArw(CHk!OY+=zl(*Dd&Z~sLXtx9dw^C6Mn;Z#5w`^ zFSbQ)FaAkjz&OS46~uLHH3=)@DjTm>QgsFV6%tevImpz{+z#%W{HsJ|^%J#fAHPP? z3pvW~-#IvT>{neFI#|za71m7Bs^Mp{b?R*EYx4>+ZRS#Ssy!^F+=FSa>T_C=E4Uprq`@;cz#=g5jCzu z3EcL)v0=m)FkRnMym1q?r0CTbp$rp)21d08D?ZpC3OdBDT=TnHFMZaRwG5m1s(Dk@ z&BcHE*u`)2n@W<69NbNs-0hh*W%s$!NH5lt1ev#_v6WyHI=t)?&WuhsKk~GTY?UMn7_FTu#1^xuBJr$;^Fw_7G<-OSkQVZlh`D#>{-0F@u8PC?P){s|6(EGx*d)(g5ILl5#+x z+LP@U>EPgjL0JgGVRLQjy_YTVkE&}r#`Gj$ALmei&QS*|iZX?H!yPDK6Zflh=z|Z$ zc^8g*Yp72DVI1_Mv}GQVO8*X@G2B-2tKos83;k^18<$e2TbY$-YQ%l0tiw3zwd}rd zp(Sq^v~UjA9^|3m_~60CdsisV$>xJNH8V z0WukNqu%X#Hzs4Fn}k(&(3xGkMoQb;$HHRfOm zop-i1ng_uL_9>%-P5Q>NPeU~y1-wUK(Jh+FiLY6HPo;JjnE=Et!L+25kxx)y^I#L)(g(L%$_de9>!I#s~X(;NbzS-N7F@Cg6OlmEZqn1=ti zkmBDnD*i7%nd1Lommw494V6#F>W!T`1_wXf*W=sZ9EI%1!GkllPCBdadU7ucdoYmx zISJ&SGeID6TPzBR&u!=KHSm5z?Zpj${FPsBOeA?$B^fp)Jrj0>Z%~zY;={?X|DqlO z4fMfVX6B}OG`YFIsB_J>w{|WHg-Nt5=Lsy4p!rHE^N6lJuL%DENKhl0;1>tt1Ofd; zT-Z(f`Gv0ezg*8-2`+-mf(O79)E9x`e~&FW`y&qtQ?4(S2p9+Y_z(Q1WeZk*-v4T2 z;r!KK#G-O7_eZkf#J$?aBlKhl=-obfGA-@K1)JN8qk1Qc57a*STFmpbtatI(+kf1d zFLhhpmRY}_M{mc-4-CpET~xW%HHM;M5c`z2j*-yiHn3+&5C2k7E1EP8wOue}W@4pG zmA$C)`+6Imix$1B#3M*ky!SuYd#j+hqpnXkL4&({<3WPE1lQoM!QGukfSV!zN%AmIX8XT-Bo*c@Acp7`8_MUc>epaXKV?N_t}hG114tf zC>fmsvrcV$9bqMYm5{@Ge8dk6XSTU%nWg4O>U+7C+iPAOgt03JdoFLxLojNIPvn&I zbIJnNK7!1Cz4VAI=)0Xm?xtiYEwl2~E7IU3{?xh>yv)k1r{i;7p`5fH-I`qBQ6{9z zv`*|97J1P>wrEh*3&!8Ma!q7o8pla-JR4d#^C0V?=`3V>f)0_6z5brl&Rq?raeSUU z7+Z|#n#n4pDjs<9(l+#qY3LL1^jcx%pyT?XB4$*uo&&R5t8Fh>D-vmhp#A!Jcj*A~ zN&74wJR^mvSJgsT{m62)^$t=x@}E|{jRpxX+JA8@(Ft|3e2CB|U>}B#-CPfb*-Ul6 zpues{s9($-*QK>fuD-BNO)5#+OvU#h(}5=n4uLL@y}ylTY2(6SxV3?O4COwTLS7-T zGUDl1Rg$ejh@Qi^9dG+68DA9l_axkPpuT=Q{rTw>mONVDETok_eRkfBzoiLk$;u3C zZGVsBto)rbRH39!SJ3$aD@F(&_T-Bi$T(kpVd(;icC5@FCD3FR8#t&p zJoR*z%F_5rbhToGy;@LEXMJ1z21S57BwGGH!lD=73Yd!BD`qBn$eK1o6~B%9D}g+P zm!niK`PTDpl*XbgzK!;@xxw9KLLJXEh7o)+oT_T!Eb9&RV-u^uRi8{Kpku z`ZarjucPZTkGom2VtrR(4SDUu(X9_gCW_$Xlqu5tf&(DKbGLW%6SS34Rq47`F})^3 zX?Su(Us1nSI*g1ndN(3usRz8f5$bsTcHUnYrUtbV{Lg@21CaN8WTdQ)sLXa6n7kPt zh~a-Hq7l$Hk=1(L{IyX8q;0E7BOKYtMaLdb=-StMbuAuS*}?SVjwS$D$(VT^tgDUc z%A>*c;p17RaI>4w{UL583oqpg`oBwCqwNOQ@16pCv1kbL@-sKf+|OfNEK1sk70!+; z)*6OPhjkj*6tsV1k4{K1lq|}NGlUtyP^c>0WokXHjd4aTrB!S>zdn6#O5fAv{Zg;6jYumW=(N1W`-@Ejy(KGdhF zpWXBdhc+<*n{S&O z!B60Jt{e>JinkjT(}#KbAUtC3)HIrwhvSwXafYrlFRD9a_(yYafW{rlkRT(^LI{hi z`2^Xbtjh$b&bK>jiI4h5p<8wrQ{JGnH|WgO=JdttiS1rHzA7)?OUs!TKH~rUIpFUH zQ?!749+HyR9*F}DbFU~QL`j%iyE}eegI76`3vVmQ1luK_g+!iM47*@<#N_gylVTv9 zgZXmD5+bdJw94ghi7^qF5R>61d7Hv&F3iXjyXJKa#_nro`DNe$QYSA~D8pDS*jV0( zewXmlu2Zpp*=NCA&F}aLTo{JRjK6MRk+K**H;FbNu?3{?bM`xh#PsloterXu*)!ck zpGm#@nQAsKq+5BV$kE-2YN4F>T>32bwKrd@weK?#nJO9%BWnsWTJ%z|5q#Y6!IHp! zzkQjhJ{18t&UHOr2`Y4CU1ytlBSS9L8YUC!S$sZ36uY|EZhZV$fk$pjKy1QHj0nF& zUNUteBveD(Q0Fl7bHDY5HRcBb4~ex61-4Gbs(tjNOpcwmE-J4Biyk?;m7UkmK^6#? zF8T!9z}9*NgY9$PTX~(s*wCC7kwbSz)@v0~wDOzUKq`k`5N%`)Tg#a@~ox_X9p@IV>2P?1j?;XdiB6sbMG(_Kiz zV-F4hmS>xl$eZ~_4$|&>3TxLUQ&ksqw;W^bwy+6B;jm{E>2fkjyw@ZXGI>?7bYID% zk~!aKsXhHel&gsA{q@MnWQ9F(XyXSn+OCJciT>rIW6G^(Q#Q-u z)?uAXQ~i-w`_}kaX?htlevVIbu@{~E$8uy_5W#7a; zhEqrTk7>9DaY1X2MTw~em4pN}HC3_2fndyt^M;YXvlUtI&yC_E#n*n0{7>jT``0F5y%&(naW9zA`IcntTE&7X>H)%5(h7L z;6aI`Qz(6G(|9q4 z)&n^YFTaq%9cpfqTcpO+5Kqu>+ONan3T@rcGYU{o!9W`j{|Z6lURm-PbYcE1N7Bt5 zhP*@mo0~a9ujLowu#7A>Y1D4m;EF~_iVP&>sBbv`d6Q!G1#w60G=Yu*hy8Uyf9%iw zN}bh5N-SA3vQ3-g`7gUE{GrULUP=j2jmX7}x7!`aMIFJ!F{Wgre^a`S%KPU`liiTO z!qA^EJ(VkIAI?dP2)QKlGLN*FdOzGzYRS&;yA{kAp||%nnmvbkLO@u1 z12$fNQqAwlQ-cNpltR2A)t|6@nEp-@69oH^!tSqh+g!5M_o)m}P(O6Zm@J@BS`hPx z(p!+H&PkWr1~6QouLvRcvLwD$${Sw01zHlhI@@1OQnplJnxFfb-$dmU$Q1`;8(GMO zvA<}+d-{*MzV zd`=(9C>DhQId!AGK}}+%#U`~%f34YOrQ1mT-b?q9*s-fwU(7yTR&%=S$JGN$NIhBy zi!VX+V8XsOMYpE7Yu#H$s-7ru3THDeN?)C%?}tpZnGMRC2gyPN)8=XQW%g>U)&m!~ z4GlTzDBh@%gk8sIR?qWK(hIkCOc+7Z#EXua~14m zGxXpvx!*ig>Y#lp_J~x{E5m97b+cPA_b@a*$S zclj)jeu2awi$EV3kF#Z13=gmEx7RQlkS*8dPO^owxZb6Gq0Drq80K-#+ikV>RJ9je z5z_3yxa9F`sP0JF!&l{JB>Lx91B{tZ6}G4yaZxe;dfQl0sSyv3_s}KcfB!hf+3UBv z+b&f~T#)Xik_H3?mt14A9^bQKla&_0!apY^P~4JYFiQBCy2{WeOqj0w_`8Mu{@&u5 zf6#U`c_p;-%G2?h9fXB7N98vzhhfrBeF~pdxwUf*5oS7E{TeAnmUM>yv~NCSAuiZl z$D#Lox$k`T?H=ty*_1*i{sS3OY5a7?w#^$p^kQGR&S!;%5Ck?aF?K+Jk38q<7x)z; z9`B&9XC&Ec_Yh*G?E#aRijPu?E%yc}A+G!NRB#_Nk7i)Xee#$7#B!7GsX3D8@IZ_$ zm@B%iUnHd~hJROw#jev}>Au1p#WU>RA#K`aG5zs+)c%0nsYMgMhB|N8(Jc7auRYaF z8~L;PV>PuZX7;Ltcw>0*DjGOeSUi_-h7Q#t6fIw z$($Y~*~#MSmx$+SlLi47{J-s2_0J)3qX^+snpUV%Cd$dl^}USv8l#skrdE0VWEKfK zy^5-m5>;tXhfGWt4dxxoF^BC6+e}7Jc;fV*WP)Us=b^pMPa^1D0hBQy*N^MPEW?UJs}Fct-x1;L@bV_VfStxQO~b zQ_zJ;Jn(vd?~8^C0c`Qd4fatd{&`rJeYxVfNcbWbw@lrxDL#+9*m4ZwPeo72JVRJx zQN0Si&Sy8n9WV4xt;*(i53xheGzz`m!K6%|O~;?Y!(SQQ8|uNd2TD4B14>iE>30^a zm1EPZB&_QVnXR2c%hg!U7*#1n;}0!I2auMqg}jAMt}=$qGZo+2OPQpHtG0z%OP1;&poz=mX8o_=by^Cgs&Kt#}kVZyG*g+ z0!dTpFv75&AC7Jlt^0jPq&K`81B}2DYuXuojnxj{_+Vm-1GY&M>q4|ZJ zOPj;Vu(uQ>Pc5MlwI2|670>Fi7}K{Lfx7(j96j7rIzEDFMSriL(7~vLrH`(8c!XD( z1D;nn?0W8wI}XsQ9kslB&|54TptSraK#8t2tJ|h?jHkiuUfa36X}`&BAM5Xr70_iZ z+2W2gl2c&GxM3?MEXk{I$zUS(vx9O5wih%}+Tw3P^O}QH;%##6D8;lfb*h+s_kx%$ zGn?16iH!Yc?4iQnM#v_9Sjmj(ie}RBZR*|&c0vS)k6HCfQe&(m+9IwV%gp@Dv~mQ+ z(&nRo^T6 zwXsix{mc$1UX&CqDd<&7WUIS%6b5lTdwo%cjIQWh3p$fkpL$hyll93sY4q(OR;QOej2y(~;Zc9BM+HAy`Vx)2XTnoPx{op6K#-(lxC z!6TTBk5@W6I@6%Fl|m1o48b5wNki*o8Y4L0b)v>D2Pzpz9nV14-3X_R7eUufV~G85CPb?u>tr#GgxL28KI`dMhj za>T{ScOCkKIE@y{A-KtzG z^GI@;nX@lwPk{&#OWdVnv3T8ES!dNW7u@2K zm^N-aTpV^pkIF`-2M`Liv}YXj9=$uF;~Uj=SH8qtuKpWxjBEZ3*7KF`$jyFfq<)Fj z4-E=7HJ8IICYJ#1o3cKXlU<}OiINlN^Qi*&5+rEkQW)9v*rc4!gTc}NAnEP?XAB$g zOl<&aHB&0FUaU<|-N>?KOo5UKDB!eCid#60QqF#T7`>ecsHTorwNmXqvBAFx@eBK- zSgDBnFDnJdVsVK$#u3xdEUppmn5>SxJH}0T2vBdm$vpz2uUYK^g@^~f0+gM87=yL}Lz5aH0uUSzIMjJ&wei?XuJ5axlVP7;zGmqRD-IZ}wMDlKJ z^Dm_4GYShzss^Ke=bYjqoZ>37*7 zUjRni2=>D4^uy9bti1QKeH8BPkbrKP`!K1R!;56%sm1syd~92GVQ!@-%-QyWjEKx5 zEhv1l>X8DydgN6BoftxsIRc;IouXwE((lyA;%h^O>?BM5at|>rGesXzK>I zpoutCQy4I60nx#I-zLjl=@Uq&o`k%CALFRFK@*v7|2#A^D;igB+>&%#lH9PsE-Ezi z#%;!e^R0%P#!OGf3S$(>KZftcCfQNX8_2ZUuzUZ^lL~4Z{cA1` zXXw|ev|rMi&%=SsAO$5MrffULsT7ZNWFqKp-IS3Z&t^Ryg05rAq=au|db~%a?zzDU$FpRj%e^U2 znz;Y^8JSk*a8-;@IIyegq#;EOkGS%VZ!SvJ?GM==eNvq#o#Y#7oqk%<%Rr_#cH9K2 z=T9I-6;gvfxE!0OkNIeZI%LPbPZtk7u7yDD%+J{T{5TJ5%QK3JVS4zaD(Xa^Kmf1U z+9pXhm`dUsv>PG-Yr|6Bs6TYVjUVRvo(}V<)K}`gK(J7b6w>!w^r833ZK>w)wIqe*^>gJ|8rNxWi8fQZ{+^$Fyl zdsG~5IpT_(SZO+?LkcOEtpbtB=Jb_=}icS;rZDaAne*`D1`^tp(AWECMn^YiVS z7FgX2;e+nLSrqrA{RLE`@6<@BRw|~2zY#-c`GggUBzw6~?SGQ#lK2dEUxGQ4^g+S< zhn{)RWAmZpM+>pDSFv7KK!1BIWb*}$(ML}xxm18t*YR^3fp5!T86=bURl$AM=m`T{ z4nC8KFRgF|$74Xvr9;AbfJ^b!t6ZhR`iBN}23u8q<0m39h@cL!A4YhM?=uR@#yh79 z)o3(=P_z4d8Ukl~Ub55@As7-*ZpGm--&yne!@nLRioSG^uey}1n)!wha$38p>hgN~=c$TIcFljTjX4UeCi+2KKCa2$ za>ZiQPUEjo_0p&^@WOR#yz>k9R>v2f9`kVrQa_lzj&vwIh|y*)s8x%oi1U5G((gJ= zEHCOUEASYq`;*}^33+v^X<^Uf`lwdlQuIfJ(ezY`PaL_^o2~!gJ$twLt*jgvqe>G+OLK%&&h6_~jld-Pry z=bulZ-g5wZiQU%OgzzJL9KbRp8Q|RR;4Qwt(JQJny2enqVe~NA_w5vN$5wmg(&R4nmzTWewbRPd+REFyqWzGvcQwiM@$%D!xBqODZkPnIBk$fm6X4C}_a>GFsb!e` ztHVDlth8FMe<*6W^{~ zPT{A3S;ac@Baqoi`}t}HtD89&BAO@I!e=L*68zm<7-}#>B7B6 z%e>X;OaT@nvvu5}{?M%4y0z}_9!vek-88!-i}6_Qc)>g&ao<&oZNyLTU`oWda$ap6 zqCk*MtR7Po?&@bp572H{z9jSmUOIHspOct7!y_TkPl>Z&cwUgGS?$gDhT}a7P%|G9 zk%0-peU_)51Cj7m;NqdktSD^8p$DsS@}C4`!02BR->lx)UI$cypIwQW7RxED=YW(t z<3NezQ~;4HP2N;BBB`d22nZ%C{lPd4aZ*~%a!Wui3QuRpPeZ)n(f9jilrp)*U6mAG z4y&nLdGs&pasu;s)lC*UPCCOWtpiFg^Gr`qI+}p7S?F55-_Wek(vwa;|cXqPb0jFq_aad z1G=Q+dXee2?DF*%DMx-?RT+2$D=f=QVR+-fU5dQ13F~iv`Ictbx{DtXn=H%!!*zj` zwezW2%bD$`)glm&@)F;nEAm&e+NlfPF719;3LrkWvO`#Fs}bym0_rE$d-Y)Usb-C_ z@m?fk&&%wM_%ejS`@KS6ayz?~B$HqgyVA*&81eFYEDpev^lDV{x6%x8Vv(n+MfEsL z`Fnz}&Pr9~oIH#392OYX9*rOow@+L^z?=sGrP7-eI1(+lA5SAO{k9*c8Mc+?N?d!0)g!vg6Kj3P!v$J>MtcF?(+xR$lb` zhL%r@lzKHl505?4@=Y%O9J||eOAu%gO+;^L?%eO;@y?b>*BeVCF>4G3$hzvPeSy#} zBa`u7{?ZxPqvoRDma{oks~4O$|IE=iB$&*(q@SBEKg>ZR9lBR=+P#_GBjxWXIEW51 zca6&XYbR%%oJoz5M73+B`L^8>;|v-GPa!Mj&cTS8B+`_(P;}#m;GU+te8@a%o5}yV&AkbvvJl+ny<_HGC31ssql(aWb8uFA~PGsw)4U=R6YW#yOAJwod|6UD-o)bUx$ zG*iR1AA6|GY5!1)rT=`Wx~i1NmQu=KoV;49P_gq8?(B622@+EY@KRol8kUX30q6(-v1$HII zhESG0^J_`KqQp!Ok>F;hm@i*aD=yHhXA`&5)>re^l=EzD->)s{D4)~0ck#9%o3Kv! zF!RIatbnU?rZY2P7;s))Sx?H4<;b#S!V4*U#i79IR+S#598!XVq##H8!H?B8ONY&* z-j7wjOm}*|vJo*1h`{))XAp;{VdO^H3QYnEQ#5z)m?~d@->if2{u1^-?{1WF{3m<= zus<>6;XJkg^t-YvS_cVI|A~N#o;nAWtWj0Oz=b(GcS_=Lki~n(?Ph>_!31^-gyUKe zRt@Jv+!-{y#CF=peN@41!?rtg8f`aATzEbnL`8!z1y+SJ&X%h;t@xojuUrtx!}Arm zP$vGH&-l_AD(KEZ`20~gS)1~kcR9D9N|XXKNjd1<*7uOYs;dRtNcfKK-PH}{Ut!ZZ z-MN77Z`@}`PfU;|jy_hMa4ucbfzaWa&*7yGQp*vbSOy~(URS9|w~!U5TLUEhFyUbj zVf#Px4f&6ApOaEHDgDuCwXq_*eOrSV$5x@d{&A>_0Aw(%AZxr&aAsjG_o*2tQf1WuBR8n38Wll8LyFpPMJ#Dlx;J^Hd{AdK z(1fc6^)7JnTfZWc1Ubd4UDHHcgX`&XEgT^`vex{<{qPSZc3{)Pu7!USDa`k!wenOl z?rC$-89P5<#@!JAWj?LoM(Mf=X zxpjTXaSYLLV?nVQi~BipKeXitCpCLgwuYWQX-=!<&zjlqHt!u}mc173fRxxYjTc^hFEA~$Y^2ig&GU~?$pvpLbUl}l-3`qCgj3Mg&E)5>&$>+FJszd7F`Unsd@?Kc7gc;9INnVf9&HrK{;^NfL?(pf z_2V&XnBJwkJ>+DBbNeD92oYso>ZDnv-54uFivt-_(5)0na}6zR?cg#RWe1=#8d*ku zeal!1{eh~S2`#tmI%qT{$AM0E_3}C=(rC6i7mUb$2s$J>KE;o^5b#>H_3E@ay66)c zWPg8IxU$bcjZJ4ut>=ag^18hnicz1_X_z@*r49S}u-8Yu_>)TF-Q`tJh3clU_-t`< zLy}07tTvnTrl2{bUbTNuxKh|$;D^Dq*QiW8$-2uGrV0#{fY9HU=Mo$9wG}#CK)$=bGpGAfQWjCO+Ik~|T~6XncQbaaDu;o()lb@t3z^;(>kNUFBTW8IHve4h*M zVW4*8Z>22hqVM7K2+LoHI9Sy=w%M`sn^zd3P0o=T@iZ%j%5;UCCBz23T34_3Il8{f z{IlAz_WvUPvrbhhcEKGb%Xy>2WTI_CQgQPJ0CC5G`Me7T$e2V6^Xr}dK70-@OpB?= zYTW`5@;h;2Lhs#dc2mgiStJ7Re=xM)(pc7Io1RC`4sO4q%Q7Tgg!!L)W#BA^;H$&8RejYPr2?L7`|>c|#uZdMU#?u6 z?qKZrU!#UTz)|$OKR&#h!k*rYd;YsDBXAp;MLinsOso?cD$GN;e%vK%X%w8x!)$1M zD;y<>_0!^&ThEAu4D<+0j2x?sS&tCu9p$#|z**z<*`kkc|4hJHt~*In9XcYD`+K(C z86)$NYrIxBpP^NMZ_v!B6$xI1qrNmqdIz!vAOOJf64Omrk#6v!Dz}MoY)k#qZLf@v zicIkBH20KaGvrAMKbK|6Mp|vh4>h?E>gz>*9pbxax8qYJq_=NsZbmf-8&Ozj0#HdC z??`2FW>aC?3luFh9>k!B-QpdQH&OuvLIXNFS7dYmL~NLpDu97541{-9M}c2o*%Au_ zm1)05F}%7mandl*s}N)3;bsPMCKZ(>Nnb5H`cp|#7g5v>WNXHZ2S@FflGiRPGE(%c z@#9CHcBFpEPf{s(^XY#ol(86D@bJdcdm7C z*vD@S(6R_uOz!xblbo0wh-gv(*dZr)e)Oqh-_}!BX1xwc8n=xw9ha5+4$g~nr22hy zn6lg*HX|=17bTha{<@7vLC(giRrgFui-n6rgbNdSbBG3l7DaL+rv^}S1q+k+u9c*f zr;syn(~{6);@~3A$&SV)L_UQ;j97Kfb#q!KG00&|#YY5|_U>?fQl_pP<3dcrrKZLG z<9%XU@G|3nH6_|2!={h znsa`9A3y0jHvBf?s~Ov2T}jb^WDN=EM{+}Mc1{$40wey|%e;3?%eI?9Krt6#` zR^DBMuniA)KqDn7aZC}%M;-y?0ipLiyYE@YTa+i`dh}MTdwV;trN!~1R9fhdvnF{; zHtbI6_)bg#w7J!Q^4+<_jB!<6c~|$%hK^(MJ7(~|1`b}6r2+_$vFQE$9#$0I7~GA#wyd5= z#c8G53zFNHstg^?`ieRX6<*XN#-76Vj=8x(k7q)Kkewmwf0F&N~sNivk!1wB*kO8svRx)Ho^ zu(uU8raZ<3W_ZOWJk@pCRsf{CnTx$3#c(^>dMz^$`@fIAT7j>r_SYK7gyW<1CK(+^XGa0kR_XTV#BXta%~3zXt{UIGLdE#sX2|y%Z}$Wi4JeC z_=koBRR4v}OM^^HSWc9C4K9sKpgMvIgD}(2iG?DA$DiWv=(tiN!5^R z#GOa46Kb!aD8F8tQp8(YW3UdAYrFYP`=6zWHmVR0<7USC!t~IM9tn|q3aS8HcA=j! zOhkU6htXOjw^fbGLSpT871xMzH?hxwyygIdV7wSS#sH@k4Elt<3h)4|mjt%Kn#`B* zd*qVR8-{DhSRE}Oq!{gXIQyKyzN5qC=CI?*79RIDPF6kV?rF_3kY zg8PQX)Pvo0+#vXy#a%fi8>B&co)&O(Pi40)y!s%*&8R4 zEjA?5IE28wkojM)j?4CP9aT&OEHR6ae$K^NcztoD4IulfpPp(Al=EA0UQyOZ;%mT> z#fts$n7VFH1w*awrfke`k0G`}< zJsc`t`lmN-n$wNpDXmq*qji&9Q@n@8>e%l7{;;(slC{RZK4WmrP#^_#H@Sq*BU)Rn zm5NDryY7`21*sWpFTtpSrP<5*XrGZw;}PReqKsKh2N0VMYy0&mYl_TY#L>w+NK4(L zV#}mfOShPaFv0Mf97w!-{h+?2J8QG7i$-xq*4dj1>&(;RDpc^+)isrQ!DNkvbsnG9 zLu-$MJqFqE8u<@-f=u5DkG@vqBr*{za6pTBNslw@=309V?nGZy(I+7>e)yml$JPA9 zJ`tt7VLGvQ4`M9aXBpc2ccFTyM=6oU*%9sSA@Y2w`){IkzxM~+hm)T36o;ElnNL=1`tC5cI{@=RKJVO9oI=Ig-@y6 zp{v~wEVqS-$g0S3yBhLQ)iZLu^z2LRWBGHT4$X~ANP}|xKOy6vo?FjuH2n96`@=}S zZWJ2)qLoB*+{*x*|934()=L~v|tDePP_Fzr)=Y31~d~DZz*k6&q%-P zK8oLKd;TD0P0JG-?O{HEJBGp-EQ-_|#W=dkw0fAgEV^74VLtIst^$83LZoh?_C#zt zuFpJd1utk>eiz7N_N*YATuz@)``F(XcQkHmwolOU5cRh$=r|(BU6~$0GW_=ESY2Y~ zg5vP%spx}CxE|Xnkeabfc)c_c7r9>&lRL25yd@0@wogWOEdH4IDo}tyXFm5{6KnZ` z(HF8WSL+HO&81l6@(Xmgq1gZ+opGbgQC#g`3h_6`%hI`s^qOMAg2>LUd#JD{rzgl> zfFLeww740f0Y7I8619eh>tnlD(r&KLdE=-1{`sQgDa(cxNw3gBMw7Vno#^lM6JmZl zb=@esrme~u0tX%eAhSNnLDdW`;z#V#wkn$Q9b-DDW)yS z+Rs8mm#T@|No_57rCb<9QO1xZByNLZZO_xTGZ}`+GAL!TDoQO|9?PC+eh>KU3bFJq zP0++*$<#SA3Y%Ei5C4Ea+2QdvdEpY1=x2X0(!j)0e2~~>O>~p)*i8fjKtGV`c{m_>Dt%C%RXeae`UjDlf!Bub@Gu7# z6GMay%H0F9__stCXX@%x3pgQJ-)3jyb|>F61tH9FfyaNpR2Ruup|e>%Vmfdq4`lEA z=`$5Cs<+Bny`BG3LzfUAz9VEmZ@+*S)`*T}(u<_)&_a8B{;b|fW*-S7*FXKD6HQ72 zw1oCvDV$r73@jb?MKTC=gm+>?lL4B!(2=3S_-gM` z_SHFunwnaosj?a|zc$t;Sf0&Is#^rE&?wXfnMrwCuI>lju1wY~tmp8d8(th8t9zJl zVYO{em8GZe2eb!|G??4PB$vHcie_mcW6}4ZQSGpP|6=nlHN7^K14h)>07O+NnA=>v zVbJ|+W0SW7c@e@>qe5U)gEJ6Rq;@r-;~9NIxU%v2Bx4qE5L)6be( z>D=`Ujzz(AWCwpipV^AT!zbiR`kdnp5u`m#YGIkixF~BtHDTxe?2z9h!_g}$ z?nuP411nbw${F=bo38uv&njKX+{PwEUiEC%c8odnD)c)yuX(35K*a6 z4dm3a8}a~8t}&3DLbh(uhB2A~$ttp)D;)JS^+F9+4)<{@WFvcIFjOCg*7LG+5A}C0 zvuhz9DdDT!yOE;ipHJ~%-3nG-Y37x=LH`S^#vy8br=VnjeJb8^T5J!szAupzZ|?Pg zBfQ?Mpl&mv0h&9?o+Q;%+e`mOnldf86SFLawZ%`I!vTRof-$#VrRaEZ<^wAXjZE^X z#qW*pgPWfdu6@0;hcCQv0q4=;I!3}L7wm9r0T!x;HrPAYkWZ#Mjlyrm7yGIE^ajJ2 zaUQ#CS|V5H*u!51bd=f?-m$iw*J^UDBS5?vBeridD1zWl^b^N3N9~QK23c zLVIz-FwazeJY+tmo?APT-H+NY%*o({@sm-9^y4|5=wU@0Zg?cjHBaXFh{*|*HlfZL zQr~1&_zDzP8hcE{PzTTPEfc2XanB0(bv-CyUYvnQWUyInNNX@$hhn_n;-S8lP7}%V^sEsKMqMITQ?0a-DQt)C@MNp&rQ{LG8Y| zTup88$WhUiwC^QrZb~9BRt_jO|1hInM0&R|z%@{;<&KMEmILkcvGG10Y7!Z*L!O$r z_j<~5^)gW~@D2-b2GeOt9UC2=Lfh-heN?gLS|42oVfhdkq`-5Ps*cia*b(0u@S^d? z>A4+;_daPms7bD{7_?is5egPfrU`D27d|>T{hbS~De<9(s}F>kG;sr75UP*}^4@h_ z)4xc()Sv}ITGGyYLI<8{-_$dxG!1(Dm~JJF?4HSfLt+;}XK(65j_9|KOWXz=xte7v z-Lg1Fhuz6!nuSe59eaKK`t3MhM>%(+x<$9lvpFX=Tnr>+7av$2(BNT) z@}Ep*@qktekDp9pANU1-y%0a1YCd64A~fop88K^GEI%;w;dP#vbsHu@LOCqFs~DTL zz%u5(;e=X45vINcx!Js~z1wEM9-o|$kQaHX$ts72*Y=-!;d#82oX*7h zLKdWE-YX(RRV=5`3;P}9dDXaC@A;FLx9~^v#6}$^8?U-*;Fl8qQi~`{p_Gx$_*ZNl zd60O!u5gy7fj);W%h6^@-av=-Zo1wS@OPp6Xfly8WV#8ECN2{zJ@LZb&weTz+HY?% zws_Y;j6ov}$Vc}eky3;tglu9at}XnvEjLqts@UDRW+i6zj0V`f`t4Rh}zbCCQXBi zh10Nm`*a~#zB!kV08i7~1gvLR0+o-NQgBcflCS^$EyOlgTS=ALY||)=ZM5GUM4g&S zGHrXcC-kUE?$dCfkW4bY^|znjea*@1C;2AOqJgAr-4=i-geqoiuW)V0Gcs*0HiX79 zZn(T`d+w%ugr=7ZJ|o-tCml+jtJSW$3ET(9a#sGaM4(7(u17asvDQ{K>*t#D0J45- z)g5Z(4dB(bKfLL-ODisYRI+XQi5se`-Goh_%)(INo@9eevSEj+!QaFRt71Bt9rfl; zK%7oM;Mg*&pZs+4RDj(IV?sDn6#JdLuI3Tgx5S>;zUt-0F7hL?Y=sLD9%dP*ig1 z>9)S_k)cFn!oB)7tX;dE7;mhv)`*E0gvVzmYvc{tuZD(<`U40T;_SiNC><64($aoE zb%N#vHsQ(`OxHQp_aQ`Ow|#*n!JNH0bTa^*6RV*JvL56X$vz>{V_xrms(Sb|Lnt12 zSK)8A`Hu1bp#19p6Xo9n9ENVsW?kyG2(DGaD-PCuuM_Tj97*H1kuvHKhqwJHP&VFP zG5&HLb1`7t`9^lJ?D_ z5q{|R<8#?!B@_23RB6Oc=7t3cxP3{IKN;=f8etck`{b1aHz;F1=2>zkt)|8;QlOi1 z#6Qels%MddaL)Cy=U@mK#xtu1xtxQ7efe0BBuB6E$8xLU;Ae`&HY(U)RsNyi2>d~Zx4-+}@-D5+5LIE_Xn8RY} z=9NIiQpaDXetP{XS603bT@3!BjkT5{hg>u7!-FOD!-vkf(NLh^X?^z?b z7YHrna7RMt40kaZV_t%H9RbJU?F-+Ysh*xI2TLnEUhTd1h)OHP<(VMhZ2iIDiheU% zSp=93sD!>82^r$JF*&b$PMu8TpSO+pl>5cA;d83%A|nzK>t1SK=)K_0L5d=A_$u>_ z(VMz_kCppP*|)Hn4{%X9DYNvPFwJ5q?MllOYHz>WUYu5CL7u_dCcfG4B;| zu&R=Q6Iw}J4}HJ^7Ne%TaF8%BMUP+XFcNhLZV>LqI9cGYxj6${!kB@wHCEBn!6|?n{2fI#EM;mU|M8N-B_-W$z={9RZSu4Dsqlx%B{IEBk2YI5BA%{itGd7l28l4MG^b|V!E)WQV*^AO!HYQ#p$ZN0%Ut*xmh!v3Q{Q@ol1?|^!#ZMxMXEI2B&ba>qu{|~q=R_>~1OuNE*~6y>>E4nM>fvroYZ+mSk7liAp!@h7C5&SN1c2rl zTD`*Yc#|je@4gM*sJJpS4}TL|oA$LTdvl)JaY1$|`SDBO#&oAi)p~m`(bGKdZ&D=6 z4_W1Wa2pP1m@kS%UVN<3VrXV9rCYSXjhIc5w_ehpL~$v6vZo0GclkIOaT z4#ml>ZB$ku2pvt1yn-{*udzYnM)RpXx^agE9RA=ceN*$#ADlW!);d4$30*MM0{x9K=5)>Xa z#e0ygek86TDhDiCg2E6kkk^3~L9g)H!=SxEh}5kofRoMQzyT0vM2v>W+lWF^n`dBx zi8Jq#j?C{$5J*NB&w>LWg(k_&!W^YRUO$}%jVsJ0yPn5+&C_zUoFAXFc&j&kF0Z5* zzZq1>0#q0w4%+n=#i~wzm&v%DDJ=taJ*NpavLC*hxs+D=jL_{lh!G^57l7Gdh_Yd0Xd>ee;^=&LNq*=BpP*6 zVBqG1>}0$(j*N3>;4!!PQn=}pn_<%h6FpddnL*I#YQ=hmmRJcFjEQ7LGJJ)08vz{_ zm~&WDEIMgqB#l^Z{+da!CXq7 zP+Trw-jy``CRTA?B=f4sEJt~l=DTipM;L}()1ssM*YVu=+hDN_i6Wt!3ljR#FD}jS z#1h2SD3&%SGfqxN;1#=^1`S;^(g}39X|{<_d%v|hb?>#3KWOnVwnW^%WMdhq>7k=? z7&gx4-xa@6nfzTBXpfY!_<*ae$I3xs(wY~p6S(q+Nw)f%;TDBP9=aeC0AgB9x6r%t zc&RE7_A#awCA-F%&NMvq5jE9Q@Ov!r+Sf0KZr%vXcV3oC+X5mm^aKqETZcZjwi|ZT zWX0-fE|$eQt#yjj)(n{!jVi%dG(DHl3Iqoclh?E(*O~S`HiHUcXupQzJ}S>rB&Q*e3V9&<>;_#oFF% ze;4qCwH&wkz{8Iami{p;US_3R$vH!8U97J z3gEQ{r^Hg(jbHpay`W6|VlxecqWra`svBa&EJ)My6$jCeM88xszWT(KrIb(X@}GJ< zlN69&O|q!v<%!0+B;%zbfN^#pldjE1B%1QuQtY{sgqPF@2S{9L^w3O|I=MQb2T+Ne zQsNF-Q~R`X+FLp20EPoII4fy0(QWA$KC?QeVw)@c(Jj*bK6EC?mkP%U`oUWXDR=JH ziJps847myJo*JkbNH5@u#)eDs^ar!XW0#`CnGX^RW@__ix&$nPWd$OBfAO9{VfYOIW+?omE)Lwl_IIO_xN7!ZZ;9>Lr_=|vN)d0oY*YKbUPOM*NQ-^ z)aJ5+FM#!KCbSmJ`Nx?}wW9H#`tiXYW#i+w<3(1}{KV_92jYs)+n<-;fn8;D!bCH& zLoylbdYpySTt-Kk5;?`=?)v>LfsDRZ$e>r-*Gg^-@OyqN06ihqEzLa!Z12j{s($1v za*BTU!95xN?gRHO&ON1`{AZ&;c=?jw_0kq6O*iBjJ`EipYxNXK^n#t}i1*$FfJpF*E1_F5H#$agKLqXHcD&Sr~nT7I8kfK6!tg#Q#XuH^T&%4kWvO? zy)O@$6TT=VCrh>@-wOUVd$opOba<+L!JdylY8lN z;J}AiPdc-^6udgS1l$JC(= z&(8xE9Ofqa*tT2Lt*t#EfQMWnjHCdYytg_Y)N0;;IDpdt()5`6ZQ=Dz`jE}oF)(8k zJ}N3$9FznGfot?lBE! zL7N#LoMbTt_f`y+>)hv8*u~!h#Gg$9_E0TQIOO6L%<0pwHz;*Zr-mE6Vr=LFyQ}5B z!tyu(e?sq@iFe2VMmYhy^|Bejrg6a;XCK=hg0Cms(B|^%>S++=e6!wWN7E&50jtuF zfH$TK@mqJRArOoH=jA)+gUj705|-))kzp9Sa^cG;IVU^eLF$RuzpMZnmn^zGABKi^8KV_+(EO1ww>J; zlVEC*|C=DU4@@Ai$V@)*7IFEPpCGU6DS_{FIC0SVE)K%yt>74TK|`X|TL2DWx@sU% z_Y|xe_h&GMUyI*9?_yf&o{5Iw8qz*)^mY(YHkPtv1Bu$9Z|*@Sc)gGoYQ8HC_Rbbt}L`b3s zhdBl~F=P)tC+-ynUKxkBx^-pSu(eZXeSCp#Kih`*A8uC?A#Z+;_QE zNx@u13`*@Yc6)>_YGPWb5qxG4-a?76>4q@cW72ywqB}?7B5UQq{-+gXiY7E-bK^_A zja^4Kq^jQdtd!~IIeKlFFf1kU(|KqDt$5DBrf_)Rx?WJi57nY2m9Pt6fc$cv4%9&~ zp;P8e1B%I3i%VpT)_!1;ipyVJzz6u{4@T>kwN8x26{n(*%7I9>goLzknV*^zA$_7u z4rF~)bLrM35iZP5QkPZPy}C<6t&aJ+FZeXuZeBeB*!-UsJJ9k4fXt@!@BwTt47D1J*dQV~|E5))zCM|&hEC&e@!X%?oglmV zL95a7C{QY2kTBi0bKhT5Mcj8d>T0yTvQbxtqSUbFxRJ{)3+P@kvvxIgC%v7$xKCh= z^)o05KFff;Oj6l?Z+v~i`=n710~|+H!bkfTgi}j5&4ovwbkTl@b|)aFB4Edet^U*cFk(YDjRG+TYE~RCvEp7_09SDhq!8{UfyrAzr3iJ;vP6yheFR%FW!nY@fD8Y(fuS5WQY4OUq4 zT3dZc>J!$r_4M|DZ#VKmr@2&qybPp?)L&Bv5U=HBv~E}4o>Mol?I4MDu-*xB|Lp&@ z*HL`pCTZZ`;xI1#oJj!n`dUqUZ&@HgbkRkn0aKF*4lnFAJDs2pXgo;G3}~b<*~4+I zF*JU+HsQR&Rk09?t|RvFl;+l-Lep3Ms~I4k2blRnaDXGbs*abV$To3~9;sIak==)P z+*+hy=Cm%Z^0HB$p%EI*`bKnt$lI=->FSPit<<%X-7yF!6AFH}FbQlXP5lVK49Z{?wCLPnpEeG3Cok)d$Qr3OzOoKul>;c zt|O<)-%XYV1U}h;vFqlQ4T%Q0rnvRr5bZi>n&u5%H~(!PYgb>oV2VN^-q(?Huk#G4 z62=yO_=)^ty_8;Ha=b83Fkh+L9G+`=8VmpiTJaz5`jgw`NlJGihLbKM+Aq{=*cByA+p<$R zk-G^5KzGDv+7d&JkUZsPEd{pb%1k_*{w$WWnsk?`4T6*}n`O-?B}&A;LElM01ND>X z$duy!e`E9Rk5!VT)*Z&JB8SzQ4YJbQHZRC?o_;mD82?oX{@4wq-DZp_kpXukJ1 z9VmX68=l+bD`h&^YsW5zaYw05o@{zumdSBuZ4J0D63iyS%DXqkbMQE^QXiJ>O39ic z$U}$d^U8?s+CWv>pve?~*Sja{cMOgS9J})XgNQ?lzm5&uC}%S0d~DXP-WTVYR{lpq z>tN$vKM)Jw=kP$7Q8I^TRLo6?GE+1^w!pC8&8v&O;t_{&NKAOPkBx z$Tz9#Un7qH9u&sIc zVWg#IWaB2c>zS15*1kVF5K#%ksx_SjuJfr&Zjmoa>u2?YoM{ddraPDH<(~8E<_l+_WdBQZCOY;Xh(6suWy3#w!~? z&;Olw^LkQ{Q*YL{<0^Wd;kO`w`r`; z{>9#{%}Dbm(loNqaz8Z+Rh1XIJ|r9b^0vRE7}quNLsv$P?w+YpunRUZSeEAY6nooj z=Ys-3*c&l-1c4pMMUXq@Fx$ErXw?p&b241p=era@> zzD;=>)AIRwabdYZ<(UO6*v%*xu5XCVySegRG{UWZk_8Dzo$s-_G6KtNyL5LJXAQ{P zvQSZ5?+L@bM8F5Y)KXUUnjDJXAJsCp_>sTC)%0>}#bEt{b#_qVi(I1JGo7mo(bK}! ziC(5ptApr)v7dC;5%_8DMTPW|LC+<{d|Lc)H&F|`G27Q7zAVqE%Dep|suCqwzQO?a z+WQPKex=ok!M}JH%lI~nC{+=HW;w&>!zluPj-6qGyE}3k-^^des4VGenQcxHXqZz` z557)ML#{_4PHp<&$6@1LY5gyy{LP+b=Y=&z8Z4bd_{tZUO)VhUXcLTux7s>{r1?C_ z5Vxdf9K6C>*8$TS1ErOp>&}rEZvUAKP&i~>Q(W(7_KT$6^V?E=lrco(sgX0=-t-iX zcrZ+Ytc~4j1ttZG7-URa$Bjn2r+jx&tUYBBb#^&9vKj&3RpRdPN~2e=T1{Qu`X*ia z`4LUrm1-JDI&+s@r*`Wh@q6zv&fl^SI<_&#$_O9>jcRumJjZ6}PnmB2m#M`Y z@&pl-ME6A6dl*u_hObPq;>pCCAGA2i7PV1Vt0B3ng2vah0^Fo|(4zXTG_yDm$_rpIITB~yTy!L;g0{AB zuB-yV+0MZjcY~S)t)RFHrTfME0-T; zeFE5I-eN)KB_7CL3DZ{Z$&+kz6n&m-O=?=5y9O~yX@ucj0tn7XPhuJSTX ze3`8Ta`;C-`@#-t6HvYpvN~vycWr;Re#QFPbMFol!Pe+^>y0ydMDg{ARm?!=a*lgTE*`VOU}I z{sCiZ2S4~-R+b{FIM-PYC04X7we^bO&Zjip_Eq>W2iK|Z{jm_6g4iaoXyu6b-r7|D zSy^c|XzHhB&+8e(f7{0NlXY8t;q6AYz_Wf1JiSF)G;2lC;NQcV7sa zD7BKLbmEgqV=|I>R7fL{#}=#=jeVjqC*@`Ga=rC@j--5??}y zzt*8w6jpaT0d&lH>aYx1tI2v<6+Gu&ek^*&m(}~WK(edZEGJ`9yZu{QbR7Psxj@S4 zB>#n2yWE2ZO`V~br+bI@y%jY5_LR5AZWBn`sq*shbm*_pXvzNhr;TFE@PSfCTOlZz z?ID>FTsJlR&x6Y3_+T_i$*gw`ndx`V&RWT9FAp^SMZFs3276*P6|yRy_S=zn{7e_n zIv9WqX#3KShY<3pKfOf!Qdp~0*xYmFtq^!)a#Wmab@|+lm<+IC4@AydQ#Wwkj!MP>x#i^(`g>upUzv+C z9C01%mkV7+v3?U{0<&)cX`$6MetRuW^f&RtDVYMfpq@6&JBuoP4(&Uv9tk*3dBF8` zxF!2ovY(=$x24%VW4S57AE3cw`JSzL?ULu~wuBA$2t9Z^vvx&;HNQVKISHO&{%6#} zpyfL{s%#^(+Lcz%v)JQ>TBJqWRP7-pRlKno6_u$qN6$lxhaulv4$2Gizw3nvDSsSo zKNcU}yK7w$pnRlns7YOLh(q{92F}-3GTwq)=tgM`{_{jIX9iGhE4$YL-nGNTktfDe z+#&>t3jX&K=c^w7Y-$qw330jiG9a-e3<-z_7uUYVNe;A-EYiyVi$=Yy2=nHSFeX=Twu;AmkKsi;!G?#^?8ANxPTn*cabD2U*{S<; zfhVo!GL5J*W6t-K7W$n%&A%q$7oKw3eB+q%))Rl<9gGd7e_cKuqnEQE8A!=O{mY5k z(uP}~G@WMY6$~?y#1xZF-}%YCF5o6_{>U||@#r&nJKD@W11nU->&oVsTjQ|ihEGx|44Um4)MUlH_R{^o>yU)5X?%N*?HinLgOO5N`Y!Pbk%>?$6lgF- zVzoMi3PndB_BCR1jD%ifyoZw@O^wCxq&iqGKEuCnKfVnfzQ(PU5eRUkfEqI^XsQ1Z zZ{xZT>eWlN>$F+Fn?~W1j2UQ0o6jg`-Ktlcq**I4uS?@nws3pc_#rxFLh-(&G%Z5cG*>ZFgp5Lu$% zS1{dTh5**!E8Z)YT_r>+R{a^%%psF2sRPTet};9_D%jZClWF5oHvn!+yyY^=3DJzr zncazY?Md`55gI9QADKV?eG=`xUGG0rh#*sUCxbWn*#I^% z-F2oKNDfEb=69vqC*$Fa|H6>^r8=)OX~}R_2`O)Cdz*ap`@3&eg@EaSi^AFv-qYf9Wq^S}d;w2`VHEi!;PUOt}ozBs2#F!0P+N zK-PCR&JSc+>?2UJpMyIp3Wtn0IZTRMjJr8bZ{PQKL(gwnH%jI;+B0=nOVq4n=3#-M#Mg6u^pUf~K-#;vD z-OpVS4IWMyt+24It!={FZ7OreLHwQBWA@AQ-N=Sjb>r>EW?SdY8BdOO%_s5l3S;Zb z;f=jzwv^mNSs%)r1bX?KJFj#7r?C|#8qUnDuSMb>`PqvcXH1*#x}TFELsIg-?z~3DGq@u3)6DaA`c0-19G@bg&>*%C6e_ ztG;K|d2{H%MSrVm`p8j)*72+R0RVc`AB_|@+vs9$`n_l{S+U*|4-2Ia+rh%#e*Bn4 z!v*_ENMVh2ZdP=P;T_#O`baqjlO=S%GJ^>m0XwLThA#P<7e-yL z^dQg0W?m$=)Z}=02v56qCi5B?n0znWg4}u8cP(vl9v1E>VDrDIL)$9yyf8)Cf!gfTMH<~ zzvwRAU-zU!pkSe@j#L_C&PgZOiK)`WjyybxwXoSCLI}ft?lUk|rZ}o~asW@xzW=x( z7lZsugbtU9p8kf~$m3w}o1OSuJL@#^SalvdgUviFnH>MfuYFo}S21~LjyUA^)PjVC z^ZTX3N16C-Nd$n7&1Y5@eBWO}r*o}9xN{Ox1FQeKJbLmZnv5~Etzr_~I`~uztJ!e( zj_BRuUs<~|B75R*W?PSs?zOf4)8GDvsAVU6eFdvOX!(W#`O0t2}0%q$|^$F8o1zM3fP^pi9~1GA@Vrn^MYi3@XM{FmPE3$It9v4-u{m) zfkFMnb@LaPgjx?V=Abxe=`v?YB)0Hl;lR7rd_vpqu$*vy{Y3oJC~vPrf{TR`b!Dl) zCMDR63nZy&h@8;_9_{aGIdn7HT7CzL5NDsmrn1r)pbcfHF;bd-gd}j{r73ZVapb$* z+UcNUtjXPcBN=5jGs@)kJU1uGnF$HV(r9gGr~6n^P3(n+nug)~CT+P*-IwZQ-Shka zwLQbkkaVUO2PubF;xdIynS4rWbTPFuDP)*1lT<;_H?fw334^NF>YXzeBVCB{h%fA+ z>h2(jin~Wb&o<_k0Pi9sdh>6@2Lsgk_M3NkNr;1|P;j4{0zMs(p^0u%fgp?qzzzW= zI2N0Rf||Q$dns3X#VU|4d!N^57&XHS5z(-=ditJh@a;>WYV@+y&r%^Tw^(d41e(`E z>OVCa3R;EE^&^{{QJ`WC&@bfFR1R zMf`u)ScO#sNehL5g5tkx#{Phil76qnf7gcKG|>HHVP1>>QA4Z)$YtPPi~mu>GzKGx zynih){<}sw1Z3x7y%rSzU6cL)D4^m>_?Jq}8(%o##5~PLOEk$!%|=KUqCfT9Ii(_L z>}OPe(r~2$ab$!-)A97jO*mn!0>{0PNLW8?d`UE5(SH40O!lb9Y5S8R{Oc3yivzsE zzgvXA`~yh+pO(^p0BQfzp!DWd-hVgb!@PFizZ=BhU;FMq4|@Oob#(vTfc+29SO00C z{pbJu!T;V}^h-TX;J;J^?S(!P8@=XBwQk2pVKkFcrGmF`%5APT&vt<7y>S7wGwCIO zG}LhJ$5$j6=*^-Y^i@5@_ePTN-zl4eRV&o}d@ z>vx&lPHzu)wt7SUt-YRiXOXboU8yf*fYM?7_r(3*cnZJHnE$0~jPGE0V0gdn9s5F# zMl%>1yNryqX| zGQ!)yC_?H}rg8E3!%m^yTRfL#u2$5WB%Q+{;=9l##0Bm`4kAK_0q@t&RqE|NuNinS zOjU(2{lRCRlad$xu=nWJ0YS{=j=#|e$DAkZ-;ZwweXR8}l_YuBL=+%&B8q7Q+1t#f z;6&Jk+&6lDY0f{?vU_@NEhD}txOA%styiaCfoNsnH>M-)UaJwPKZN!l0>a4Fg)B+< zE;a}_!U)fIdh#-LgcTb>|09ooo|dtjRXsqmwCE}Tcge`ekg9icirAWD+(mL^zL?9I zE-|g&cZsS)N$T^( zM~n^w>ZtI2YfLqFwN#Z2*(K*EeEcDmz#yt2xDK-y2HEVR>c<`g<7*CtK0!gjcs(gJ z45)C07r zD+bh|Lb6jmGbxUUm}J+&Q}bf4DH{OtJp7(*wc*hBN5hN7pE~E|CwBLJMW5oP{r;lj z;18B@d_U(e1AjK4Py;V~|JWhl^>Aa85-L(}ul7zv7z^c+pSj|q*Iv`poJ*M>Q7H?r z^qN7k_ma`?!;$Pmcy6g13}yyN*lJoW>|xq@geCU}Ye9br1frYSZ}#AbkL(|$RRbX~ z&&R411TZX_%b9G4e847>2363C^KxD~KgBPM>5g)D05%Zg{VrQD25D@_kAP^D-G*)v z)xg-aNsYM7FAhBti=5(a*Eb4>SK6I+kF-KW*~&fPW9#{Lm(nk5?wyfaStZn%>0_$# z*EHNi1nhXap7}4dq@>Ag^oYagIRYEgUA`NNdN0vm_2adaqt%Jf{#ZUs>unD0u4l!( zLAjGp)!U(iQxFu_bgXZ^tO(WnuJeoT$!h;5CX35`-^jnwclabWf|$kK+i~YeFkO~l z*=(u7Kn~8|SIBDzw)=(wh;Tc-!Lar?xPeUNjPZt|lzb{mDB15t_ zNAnVqc-=4EaVb$tC=mU~C4o_K8ZNgz4w!kSH?NAmq*UvO+_%I`mLR~Ww>6r{(jLt! zu;%tr+3RwLSgChDqB%|=Q>3LZJ~Is?65{KMNV7jdx5$h@p+|&AVjXjRu^UDMXZSEQ zb&I1%_Dz2;h{x%YxjbCxzNN*M&k8)}Lp-XEzA4F67!zXs&UQJt>-x7Q4F&3vy}K8} zp{S3&8$uztGQDfw{ChSNA27}kKC{Ve@cp;Hzu&xYzS9QAJHZM!qQC4pp!p-h+{v1n z9|<1aOfwWOaCti7o=FZ0^EbEs-wT4 zx_Qf`#+y|Ul6gb=lQUUN-inY?{fSb77SPO1n+d5E#%NYxvmk~8-RzYNsAeQH++ORv z5sT$ZPZAo!3Q7(WR+x>5jC$PkEafp0ybbzy`pUQR68I6MP4Pm#xhboPy(ButK;kC) zRVCJMOvrP5XQuwQSydRnHJqLA5pS3`K%-8_q+J&>?0eVXkdOuS#h_}mA(Hydzv1f* zd~}z(4GI)k&K4j@nWh}KcTS~3?{Yr8alb*rYC5f>xz!|&H@YT{Gw4+dpsEzx+}oC8 zOzb}$Sw>iOCRN898nBn^Pkag3pfLJ%6NE{)*2rZ(rNVB{q;SSj?!l)G^h-ryXhQ{2 zz39b)UkR3cVt;hTERl7?x}2TNI9g=ARUGVb`JujAAfRWkBOj34VuoO%n2qgTwsFw+ zq1d>7dIT-h$b48Ub=ve`VC;|406WP$mkQNvzwzUEV15@9(Zy$k=X&_q3mBHYAuRgc zeEWo6s?d%e4^}N4gaa4GJfA{YZ!}%NX%C@pX!oRxJJgm3OZg--gNPg5?qKdy9ipXZg)&zhF1)uIZr2xQ zS8mhW(XG9TW^K_&SrR#-K|VzlLqy&r4?91#DDR*;e`VUr<~^(2(PB+8lZKm=g>;*^ z7)aNS6QYI&j-QJDp=ywQUCc++De+UylnNr(vk^S^KhdavD ztY4|o(-d{cnCOzoDg)#yGeR3GW$bdbTo#&Aau2@ML7<>4*u~V+s6`9ivEubi0Cul5 zIb(1rQ$ZxQgG>Zl5Kr4hyyr?ZOx& zRC)4Lv-uYnvGHPrKkS1WpwxuUweSy+N^ZFPmaCbC*%+m*xSLBw?UaS^(pkPwvmJ>5 z*Fs@T`F*$~3Gy=$il4T9=r?TDBfmtiQgVSM%)_088wLciXSX^~AFkp+I0d^$DbCZiEtq)4ZiS(^7yODP-&6sSr(K@!z+WEa+r6zxZczykVX@hKchspUHPt z1q|Z|DiGQXP=hKJ{nRpTT<^)PSylfDAk#L|e`8YU+lmbhsB~KHofGA_P=`o5G2(Dw z4ZT!%zx{IXWh8uT?gAZ=lir}3-dRJ-X;*4DIQ~vd8pAYjyp}-&UBng85Hztr8bM^C zW0p@Y9`Dad!?*i3)W7NXr@8FN3lS@D(e?Bd>2F1a@~cXzKZuyo;Ba8eR%zNhWv415wYvKTSmHw=JMhGHeApEhF<5er;AnJbX+aIlzY~(4mzx7d} zW(;C@ay+dLDS3WREcc}?Fg{KIIDXfEY8CW-K!z!!Ri7)~&)$a`D!5{X0jI)ejH1fW z`Rq`_h}`JS`*ERr<{NsC2Y)#dJZFGzWG18LiQ7LdV>8v_Ge7&W8Qj$nHWm6LgLiz7Zgm3?iX=1d5aIhdmQdjfe2Uf9$02x+U`3* z4j(o^H#*6RDkS4qRp6%KZW|r?AEbEBTl#~%NK^x{#oqwGx09ry!|*a1Zd)Il{d6i$ z2l8G@@-fEgejrvym&gC`pKru}JPN$-e)5`)+#!LSUnKtKtpQaqzXyy7UZTczAYxPN zG>=aMyv4f_(wkw}7A$$fB@WWFS~sVGva>EjRUu9vy-cfKyAnyV7KAwgu?lUOJixj1 zR!29lpTFJ`^%N#$FLx_@8vFunJ6qJ|dLs>3!Y)!`jln)7e7J|bGhK5ZNM2=%qZBP~ zOoMTWJbIv-k*NM!LKge&4|!QUVB7HGR<0PD(y7MTh~7!Y-2o(=KPL6QJ`qHNvC!^P zNh0vhixz#{|MLm3Q$py5jKP|+^iNd?qd-^PpV{zAX%#Xx8)ICRM(U5` zZ;!?qf~7m?dR|4nZM=!HydsO`=~Bi1Y!3Uz)}4C3JmGcv#aAG_RE6T={s_X zU|Y5(2<^IjLq^f9psFn7lV$VTt+<`-P7b`F8njKda5f(^XS*tUI+IRSc!PE|&x4Xp)CW zNJ0NzqADbt_LuEdkV^|(>V+i%21g$>$!v&DXbjCv$n?_#+7P1#ps6mlE3ln6LiLkP_RGW4>R4Q*)P`E-}=s~^w(#DehsUq%;$JOtoBUWW$#ozBg-cAZYC z^@&reFXxrs8)MzHLrl~Mw-N6a)f8GGV<*D@+_7vS3`&%3$GTB$dCj2}goK1X98wqIAoKyLUuzM5~}{mA;UfLCaf;We58Whv)#bqapu zbC7q`G?X<~R195*k|LdMz;x%lSkWC+cKk^kVx=D9r2Is`#fFNADacw>5z5ssLu9Yy zwq=h{s9Iggzn>!lWJzm~)!kLKHW-|JD&1)Xx`6L(eYHe}DY?h-m+TEljEmx6`JFgg z=woaX+R$b*C`1euI09s)GgWHoksk1W8%9Uyb;`GCWoUWNt%i=qIwu%SNlN2*&5M2Bu?x)ZhK!mY# z>$lqNohCSNGc~I}HpPjAu(;v8h3>f;AKt@lXJ3zrm!Hcexbr z&9rR2dvPg4S%DpxsL0pm$qnx6{vqeXqp^=rMBDR`E9~^@Pls-+2DxCv1f2}PdLsBl zao7B>2e($w5hMB75+m7hUFwDGZu#1De7tfQuKRrc2`xN2HQ77-JLxxREp)|+>dHH- zWp8+qIZ6~VnpId$Nm^*D;^1u74wOfTX`IsNPK21YKK1(IuHsc-^sQTSLyPXoN;h>c zVkD#GaeN?vP_2hDYWY@%&4&suK0(GbkUD2ZHL&2ix{^~Yl#%ZdraLp64tVk!?l!C} zddH3j_M@vuR`imX1{fX2Vng!GP7D3d;sTpBN)guM8V}By=Sg@F*f#K`@#YpylKXK5 z;Yi(mJ&H*d%>Z*(f@mkcO{XNq*T@{bQlHho=9B(nHKW15M34K+Ix;mol@CWTHPWO4obXl_@wTkkP_6jke(+Dn>wo8rTH+Zzp5#d7B+1V=*3~FbdRo+nk zbonS(FlLDB4?09OL#>XG3H4C=frNx`xsxb)Bh0Uz?>=!`U8I>Egpp(bx9WJLZE3rx z5qW_~4)WA7Up!-Ghk+3Cz4_$&zOVt zADzk7;!kKC?)Sg`fkA)o(nQi86)$XoUV0UFn~YTcrS`UBh!}lhedxj2s&ZJ$y4>j` znq8U_yles&j&`)Vcn%&;soJ7W+jn3(XndmrEiO=p2yk`wu|*DlTtW|!v-DiLm8rLg znPFGMyi+Ejrwj#+)PmeK5NK0y_tC?Tp^__ICU;*0OZ8|)X6Dt+20xi#i|y1(FhVjs zO{aD`2Qt{o(Z?jJ+Qo-k=ob)Mbe(+iCl}w`@+mKRqPVPa^#Zp=90BUIlyjUdgAe_u zD~=d0JQ79r7X;^4$o+@5tI_cT!fCfkVFyX`l}1aBrxUzZH)GSz%7&!rErlVh($Wvv zmiQ}%2GgR{2SRgnBoXCHVp%p_pYIh&W7qiVKw{8DJFv1hx>`yj=jl$bIjqQaei)%Y zH}51r$JB@JcDsa+{>zLMeuPyC{zPbFgRa)1!&Dnm9NNlZ4ieW#=j(lH1wUakwA&mI zVU`<|B;R@0N6oi(Mb&`N6}X)STBxsYmHL zRvZP{gvmbCX{UFf*$Y;c))hv2uQRORAaFDCtbfgLR)8j;%N4)|q}^P!?}ZrVH32va zyOld%-GoI%uMR>P=&Nh+)wxLa|F>84f4NHqFw%(puXNk~9|8Z%1^z!fzG-qIA+d?} zZZUs%e=RxtOmmWQvcXpd21>Mqlo;>rUdV)p|DuLVx3;D-X${y=$-Yv8r@iou*=B zh|{~*1MZZs!2*&R{{4n=e(jlxq-X?1-lG{HklM6uF}8_!o}?@%xYOxho_`->y34Iy z<2Xe{4T$sH^xY#!11+uki3Jn5VCg4_^s562mZA2Xe6`ol;M>Q!-yxKW_l zP&KV~8czTGlcg$vG+ejOlXWdcWa=!|Vo$vIcJvRDDZrT$!k{P=x##fG_CuZ5bDpEY z5Hoh5np#dk)7{$uQ*+r^-xPyfejIzhxIZs}^OnZ(#%WBe%un^C7dqbOo^}xS)Df^` z0^d2*!acf}7b!=r7f8-OhS+$jk`Vx7RnKH9M=k*a1bPd+TP69*{TT%>Dg`Ceeei(+A%Ow;(@J=4RJvuq~ zl_bqRjJ{{?iEh!nre?T*$+fE~I#Gbs}^=n`V0IX1@Gw?9qeommlVICwtjJDXR5G zV8m-RJ9d$6$XEwi9Y_z>tQS0qItl(x?7r*&&*(0$FTXN*zw4mwQPtig!|2J^bY&_I zFvU+kF)zk6HkXkK_@&)!l`ypN@QePH9W9){H_;j48iP3NDG1r>od_4O7dDj$1BM@_ zqJq!O`On{12!H5;lyCbk%$gTu3QhU1zVXYIzR3v!)%wA9Ws}n}{sIDQGQ8-p4jN_@ z<+}=1Xyj|)#igJ{p3KreP5=CzeNeZmjd`A#=(^im(Z?@yAVw}q^s1uWJ(J!SeX4Ep zxdRaUYOS^!swtpQbFi})tmd-M9l1w_?^`pho=xZ)lqxYQFcMO_O9={?R5MWgyx zHM*9H{Fr=ED$8de=}jANzA+vQ$DqC;D39s8z;{DG54bKF)x-X6KJ)jzu?i|kzqontGf-i49WR5BZTG`@`(an_>3ebl;PGCnxy|3?C7+s9 zug9dm0=&P{Q4D3aNyxY&p`>$nXqdTqj?Q+a{*w3f6@P@1={3)KUID#OCRg05)#p;0cEqD`+;6kI^`ucVUXR?v*9a42utI?xM@EbNBfck0h-IcEFVh7P*POA;?Ph%Nwc-O)3ZdaCk-x7RLK+~}3g5U+}9 zh1kY2Th($Wi%I1Wl0wLX2=~+R;t9*@aG!5HC^r|mXBr_p!_`>ahpSL4u3>EVKuBx# z*FV+28qD43WN?j8kc^BtCu>U09WPx_6!NZ-QC?axYM{KNaL=--6c3Q?(Q1g-QC?Cg1fs+e}DJhc{6MNfLUwach{<_ zQ>RWnXMgs7$Q`XGIF%}-n4mP6XTrwNPs$ft*#1eVo7!}8^PyE}1GQL0u3p>8t5n6$ zG7r_&YTh9tQ{$&&l1zF5wm8t9ZRxE;gV9?ScHaLsu(RvP!k(Xhfh~(5TJ!x>>QlZv zxqs`Ci&b2$UQ@Jk48d0-PvxMDP2}e|2%*11};;>UQo}(ACm_z@4J$ojnDj= z+FzBpGk$3Ox4a*t5`E@Gf4BDsMCamuIVxSN8GAQP;ai4|enP{nH-G)7BbCcCCKRkS zp;D#fcL?D4QAj=mAW2dxp7mWgy!Vlu#rvVi=C@Mq;kP>6PyJz{nVTPDv$LU{pPE;M z5k&0QVHKw)LkFk?iI5_MH#@{KnNzIwM6{!Hcb56vgrRV+Ntf3j0^lLzGSY{v^$?t< zHg6{Y;{J<0@u7j_`TyyaorEUkQW7>mvV5c}MJeJe;!W}tJ+_`VyyLzVYK*V2E_Dxe z23WZGVib)EJ~N?q2(1LitRJCvmRw!Q+07$NgNOCaU(8_o1^D|JDIhUd9klSf286yT z-I9k36rf#NVjft)IeXoO175lZ_v5pJP&eOZJ7JwoOD3}Ix4R<_<|Yxe-*Ik>46814 z6~Ud0{7^EchNAuaY)nmy1_z&_(*r!YWi*q`0K4Ahz3bySHcKoIX{hY~WZ-MruN^(c zO4deT-_3@gq}CT#d!S!+Ihw{sP$b))TdpLFAsdM!H@VUeN_^868poShIL?dd>geE+($$hH9kR)v%-p27}TcueL0ow{rXPam*F|?O+WGH zN2F#LuwS=qAS^Qf`|ag1|KowOi%%3cBg^O%tQm+HCeoTAO8~B&TD$H;vXPAY$8Xpk zp9oVZS<9k4F!l7HOA?Q%iR zf0z50_6Z$D2?>5uvq97IX=zdWT4e!A0?y{SLr?PqzCofTrm0SLXMZd&?cRCyELT{l zO@@S#qyBte*{!}!GUFVA+xsC?NA>{WvJ~rD|41ORIg>fx4p!Ak`-e`JJ@S`KH&f0@ zMr-5p$GPTLS}n-@4{zG^Ar*UAgx^r4n#g<%Cdm#&-*+lr1j!a`&XeqdAg#ZD-5I2h z7B|dBk3T7^`>6H-c>}!OdVDt}!fqBWNw-&ogUG>At z^+kUo=k#InWHOgv1`o=n!vr2sH5Z_L2F_Di+-;ro2vZO3@4(@} z7KE#?*5; zovim)IAYD%G)uT|!RxpBk`@j4wzIKR!C(xh*}HD5^0*NYq%M+Y2eLI|T2*-C8))C) zD;RC(t`nSUDr5a>&&q4}2%{j!%#`$f&i8K{(n+&XX-L4`hTXVokfH|e$+%+jNm*qB7jBB$RF1Og=yLS`&XX)`F~$-Iq1#* zz+@NSBA{kzvUKebPooi)w4Qu#`yv)Mb=n7yT4`ycjiKB82M*d^3!c~TmYk>s8Pvi2 z2)6rK%36vM))fd5CuRntek4`$$`G{|T>i@!%FP9NJ#OIW3p}HJL6?l3GxA1QU9B@c zK7~JB`pg#oiODjA;~&B8(~Q}EA_ zmDsG8(asQkv$e+Bh;Z-e=d$I;3Fn2LQn7*&CvB~aA(k?`j1+Dnl zrF={b`QRE9_LhIBQ~JpdXSSzN(`1(dT_4DZqK|*!Q4QaFbK6lpvN_yeSnLk2WhHO}xK(w*7Q`1;9yfsCYI)TnXFN|uoc6i&@UevCQZ zbCIbh8!*`2yU76VYsAj(6%9NejS;G(M}HipdXTxv=y_0m%y}(>gc0NuipOz^-0YS* z^QrHmPL6-u=(LD`L|4w4DWp~wmDGr-Sw<5rcZp~y>)MnK7P7u>8XE6XZ7Y>aEgf6r zW7%xv{&m$Cs(W6w*GZ1N5Iieyt2CME-~oU9JfF{`&?}#~ZY~;t`~(B0R(%`A& zThMNM%dQM-5P%eX(q}$b7pN7Lz9j_iN5*m8+Sy}KPGa;H;X(dFF4~TWufy1kwPfs* z9u>a8b-7`Efd9pwFK;N&l$k#W=r7}0Zn$jG!B@B{&f@qS6~cwq?-Q-Ep*SI|NM-Hz zM~BHRI=+dl)bfX6@A5<=1gmkqq^Z`)XorSfH^WB%8-| z7H%1G=JXt2Q4{i44SxMluQsBeLxzYAjC}XtI9)Pr%Sow*XZDcu+G)>yWWVhrnHn;g zd=FugUguX*lxo-TQagS0XXiE&lutK7?M|@BCtyRNsiK=-R8*8(ROGuG+yaP5>1384 zR&WRQW1XlA`Ebk*QJs^cgl26%=%lNr+_CyFK<2f2Z#C+SD`i^a#|UC95(Wvk$JaHF z(JFy`4+(|eFgS9eysaKqSR7d(+1?^fU(5jc84*AVF7lCgeYF6>@QX5L|xYiDB+A<{U9sCMGQ@4 zlne1sXXkq)V*WpqQ(DzuPJDI-I#y3Jw?9uN?`Zkd%43)2*W9HPFNY1}pM^{nkEn5I zG8#TxH|d959}yU)F1vec{skN4+Mzp=*zke(_K->XpEU3^kLV|L3pji>Ee^iaoB=f} zX@yJ%Tk%VW#@BJ{dbMH$0xWZc(38ybgrJ>M;^@d%nNs;N-gzE7*N2?O8pv>vjTjbP z`Pv;y^$#Mw75QT@90#sb!-%ljf{!cH$*HUUR*oPAE$5zFHX@wTai!q4`B>5CLHNm~ zH`$-TF?nwvS<*!lPr-)`p){xf6cl9XgZ=>TU$KUr=uEla|;(ZudhC%a5dA}J_^d* zfRDW(>TDKinsxv)#7ae|uSdqhih=y1Tsk7|W^J_a)wE75F$k>ntc9M{OuTj%ovwXP zVRLQq=9iB$G}sE3dj@djKh!EN46f+}{XOTBuX_oN$9d!tA{_v!pbb0YltW4W`2&@- znpp{hFRCK5q`eY{Fk2zD7p`Movl$wYnY`J*>VJ%B3*az~2HXkJIecYPkG)f`k#cjn zG_7|VUB{**3BH?-HaA&tFk$f8!&S{$CZlKD&Dp5c0&wYp#aWk^GkMf^1AL;~#9hH6 z4rX9FF~;t;<0Yth<7fQ>ZW!YJV|#z_ceQCZdNS=AJjPZQWM>DjRLq)b3o{z42<7S% zSs~(EBa$AFT=!1JFO8ai!h{(l#6Q}$bZ6ebcyiWFRJVx6J`tYAy-&&e)H;$)W?t1} zP7CVOmvQyR*H7!uGPnUrX$GT~Q(%cBRQ%EkELgTY<(#>jrt~n^46Z5w z_aXz&AiP}8Dr?UOeJz_cF%llbE|?}yb?y&Ws`(<~hF_cppdz=9UhposAD#aSFI6JG zVxf906sHHL`QJY%-hB$Tqwjwb!SjZX5n}D6RMDR!%U4t+`&Jq6B4ZiVH;YLL&J5t9 z&u~G36S2X17k;3G7t+79I95kis^c5fPgR1K_lb&oB+TEq!9Wlkm)z1LYK8T7jmFmh zV}FhYJ&tK|YNGd=bva+%syybd5=Q*g$lVJ!O6eaZ)C5=80e1egSsINVn1WIWK*B-- zR+GKHvNoA`DAKkv-dg;#r4F?IdA=C(T@gPaN1GlkIA{n;Rgvtv?Im zz>zy7WY;coZP1G#Azf9fmTZ*pbT@Ev*$11NLonTa8Wo~Zf*X~R*jt=Q|EV3*U{ljK znl1e0PPCi2kih!UIvb=06b2)=B< zph+0}atQWZ1ecq(HU*Bo$EJa4&VG^b-`FgBgH9qp`(I(Wc4&p#wUG32@#%?A=3(10 zC&`+z)$=szWy+@|;6lgoQ4&2``~p-BN$)?NaKAIo&%tqWg{^`5hHKnv)SLL%c?L8p zFH}#qGy2sD-^s`{|J^al~8k}Fs(~x~#;@Mqb0!(!GwjB%wJG0(N zg@ZH@(%66s1N#W|=)4E)K|dG(wjkCW{IIC|m(tQisTV;a7yy1zSzi+rL@#xMRaS8Q z$vF>kY_yL@3A2~#i1Fwt@NZDj7AuABPyIC2TcpBqg^t_=^sn z;4PU~bAPz-gBRuS1LE$BC+dBy$74NXz=PZ+qO)F|thgo5^X^+YhSR3q7GB9KxaO}< z!FO1ZbaD&S4+|dLkkr`4G45=)BFKJ~T=;2vX~dP_w+X)OxVgJI@P{fKgG(yY4OgwG zs`C>W7~$p3W#N{QswZ_1PBBknWVQgL=#qesqqM;sA&oNw8SipqXRxfJ#AB;v2MOxa zLY?STwftc*S2B=Ih_mW)G;O+mfn6GWDL|&QtF+Q~vh$d4t(Zq$mYm&*myFrJz@#t% zvWws@%V~^rr->>bp8ZBORwW@qn0nSucC~{AQ}EDkw814H{<1ANlWNq$_0dQ+&uYB+ zy#V=wlwTSs?)hMsG5xAA!kya!1AYb}Q#ya3^B-2c*^8q7Y|;2FMVw1YiXtTgv}u_V z-ZL@FiI^~ntb=ogda#*kH+q$D&?^3|T^BJ18fMT_q>QxypuG(w@kN!$n*|h`v@sE) z1cgVXeIGO_ys;O369z*l98DL&e9Uil?zP3R62k6?gytl4shDtAoLJ$3eXVe13)+aj zQ{FOaCv9ZUFD_?nNV4ZSYh|n~6Ep5X(m#x!H7L|$*VoGnhGf6DTIiVr9NN(W^e!%S zyzhGl@~5EGF||>WtN;!Klapd%dZvII!+sv7CY9jxQ{`_JR_NEsG^25eXGuhsot|#_ zi0nghoCwW_;{@;9U~N*t|C8^|_%^8vd{lM0dg zy)|~d*yf=|T)|?rweqC~JKfE{iWcWGTesuUhw^=iiDwr>;tS4|J9y>uhHFFDSr7Hf z#ayW(3Bd#TJcGP7_KPZ^=Dnr%q6S)ef(56XLtv9EtXdzrLmJ3hR*oMJw*=}XSkC4* zB`a|tC^Tc|ztpr{{2Gw&_})8aV*q#*$H^EloI|{awmIsOThe)B3T`5klvt4TW#YaL z!qK&M;?NHHDCek_@Ldj%9H6Zx^Db4XS}NDg-_r7@y4U=8ki8@%2I}04xPOd>W*hXM zeme@Qo#jOE095fzW7mT;Vx5DL@ZohuzsC;p*=wGbdrTKU$(H;GQ6gfS;W9tKC6Ko1 zC4JV3h2_pQ4RR+FfRbF(N4{+i@uU1~4nZ*9Go~7Vg5q6Yan`HYuhwPM`j}~4IeNd* zvPpxMc%m+%-uG%GItKPDzL}OqjY3kn3AZs#0Jk&^^igqe@TWQ@6x|O)cDu{~A1B{5 zMbya0AK96$rvyS1gKS;B_o3_22nGaSECS3BN;zOEScKLoAwuTn?2k$jXV05n1Ybr4 z_!)aZZyV6{c@ry_zR_#9ujR5OjeCDYuHHz1ftgof<9CUvoflZS_z7q*8c$rBu`z2h zNFl*uz<8I?YEmKf*X&34TJ#qE)EHmElk7$^6Qb$Su}KTr6l^qJjwN>9II6GDf zQ1BB2BVTYHnZ}JSes5`wnTvUeaY90)@n|2k%e&(>@{Ws>ap}dkhOhD=CH~ZlyV>Qh zP7b^tY|`(fF1V?Ih1(7H3;5MzdQYpoQHocRV)w6b)=*WgJW6YL)|lJ`d5}UN%n?~M z>J5*|I)|j3nbkhi^okJ>3fr}99U0DU{8_Y|XM1U8PNe9PwB=(4PkuBk`Erxp)CsLM zr1jwVM#mz<2pEJG0L= z^A?E0Exdxua!O}OiiBTp74)E0{kP=T%#CDvk4Bv$YKN((3f)Ao;T>F4 zSE@n>>DzAbAvRaR@j|ruWBcgF27dy6*u6OrAU2izXL}x2znl=?4jhrRcDT?fAG=ps z57hDfiX$EX84rYe-(A}1F;d5@dG$bv=0*q)_kvHB1^s$W<_()_v~Y!n^lrC%9qZYw zBJ`8zk{S=}yOZrC&tcOfVmZeMj_S2<_o9!(f_x{^YsBPvkoir&8``1%I%e0fNuPWA zXs@>b!f0>oG#S)qXdm#7qB^oDC}i@eP5YmF@|2DHsSkat^m=l8SuNdzuPnG(rI-`; zz4X;SDPPc0D=-Wlw<46A3(=mQwns#oDrr$T{auwvoFZ39@Df3*Rh^XgD z9-G){kZjHr)z01KWA+>s-$2-3)g0EcR1x9IyKxeksJ86Ps&uBo5ehDcQ(2syq5Qm~Kmyd5h=(%w`+8X;?htnWL({UX{*#|(4ka%PFy zYJ7!+M2kr!U(f|pA2$w;1PG0q_&T0=Oh^nVnkN0>0*&9{dY<5y&i$XiWu%iR zc)vPL(M2LvNL+ezyj#p9HasC0v#h$F6bZUa(jM`0pPp)>5^SsJb<`{^9PZ>;w^>B< z2urMnt4BLJey_laQr3ClcoXCHL?es%rh96eXh}&u^cD(f39xhP6B81Yc$wq&(%9@K zjeT7l@(sP502Ktbka`~xEkpY)2T>-yn>wE4V;+QH!Jk-b*M0_3rk|(il_7LlJ8D?F z2=ovvC_7#j4HimLN%C%&6E6Frm`%_Y%%fw*RY>(a3Sq}rKp`DOy@}H>laszZSOuuU z-9tKZGHGnd7q*cJVQn>FK94IBfLL8XKWdu*(*oodjiD7bX{h%0)lLHh1XA^!UCQ*Xu;?e_Sx^ljpfW`%&&_r$g*3@XY5FF1u)<%n# zfbjukX*Pyv7>p3^P^GI*iMfs?qPFFDG3L}k_$g(!qljwnwFx#Bw)g$j=69m{A#{l; z%>^j9>d=Vo`efZ|KVyjfc~N-&Jx15)d=3N9O&@YC`vtf4h1+AY=t#0j|$>2Wt^wy(SK@T>*{n(IiSQ z;R-=n((fsk(|sLkn}8kehtBDxIx+^b{p4|EZ1}{eG{Xd0RIR}p=J0VM^)sVRpW+Og zigOAgI@L$irmZ@6+WKzg2D;Lxo z7nQ`?9j0q|oVcZrB|4r7m6l1rej)`od0kVhg*7^kP>|Bl@+ZL9Z8|5!)`SuC3C*1c>4Ld4B! zII-Wm%kTE#GcheK7T@xzEGqqgr7D#Xz|y)7y!s`JV-xCn2T5hiVZ||pb~`b#LiaZM z?Gv&hPcWMJ^w*-{gtM7&7niKO<)BbmO4LVz&ErPJ48o-ax2g2yPoqF`K6O%T%NbMG zl$?8DmYm_@LWynzo3h!$Nn#o6eFJV6T-zHd&Oefe)53J~XqkoVqG4O&oKsYkY*mk? zFvGXCau|u5b_e2&tQR*va`u$&?-Mx>Y%FcChMtZ@m+u`$bcBnU%d#)dP5!^c! z*W3slQ)BicBOI%n4HN5h+JlD2wdI2`ipRg{*F*#yxwV_6$-7qx z?Qdt06y+gphr_BBGl6UAcw?SOKRwS%+w3o6Ask-7#<)&Juzis5@^#W&BN6akhCT2z zvQ*wfF=o!0(*ZO!3J@@Ye{Ky^#YT6Ojo`eaMK0SX*=N!w7y_4ruF)X}mR?@`afGRF2$1k7y@ z{?u7}s{eY4XG-6=pi^AJXHlPJ-II?0K^0={9HKCX$=E&|=~zN`cRtckqP#@)NkmPI zWY#Ce-jPf9=(72QqRH~Gava^!V8(=%#o;p4djnm3MJ-~h_!ohY*OO)_E;fJRA_%l~ zt>#0@x>i?LY;kKT%VIx+m*|7&ZZidMx zpq7TXd*&fZ2J_G)kGiqxK|i?|qddLij>JRhDqqY-<2TmP2$YXCtZ4~RKa;0;@1ntQ z^?hASM4VQmUVrbDz~ghi@*rrtAY@g0IZ$8l=10TRl&C~H;Z19P@NL8C?;WRa7jN}b zVgyzjgk}tO5B8Ne4t2Rv;jQ$)Wec&fNvKe5tO+GSBGAOtomWVXXFE(cQD zW839xXBpfs;6YbUQ?nN@V^Sk!$ZNSOf8*fE7J8;s&$BJ{5Q16g>}ZbF>t{8^qg(gA zB*##DNyYMyk;A1&ON>1N>32Hqeeqw(--hiiSNAQ5HaeUlJKKQssZu654g1Mo?S~pF zZ3S0c!_t->dS%kOBzYsG9qNYQ+};80e3BlVl)~#N*ndF2xUR}$>eswa=iFKTq-6Hh zU*j~*+dzSqqJI@7k$Jv@?>bPRs|50Q%+xDBuUv=?H<9;LL{cX(cs$!fVmUJ~4ttQF z*h<2>&v~n&>vWP?6qfVWOi_mC$Up+O;J^p>A$TKqh-ImEpk}0Jh zOWm34shQFY!GC&3R@U^=Ao-R-e-LgfujXsO&!e&ckn5tNgfFNZ^~r8j%LyR}S;zt4 zJE{%Y-;MF2ZFzus-y%iuD2Sz9U|fw@-8M>4DCYXpi~-5R29Ni*vokd>PwHjJBw8VQ zW9}n@&ARfh7BgZD;z?~)1jO350QRy1Z#+qcTsz%sJ#bJ|j|if(w-;oa*ICQbU*tC> zl*bP=NVe+|K-dycXhY7dw)MiIVn~X3{Z=K)%v4}8GqTV5MxLaNgi1&V5>t1h*e~Gn zr&~TVJ1WG((I{@lwB)1#cW&rG!FF`0`nk1M^)wwt?zX51tPZ7+Kg{jd7SE4@y-CP&&2?)6xAGw2kp%}2c-(Vmbg7o@-sOCrr*p|!iHyYudiJAz2^MgL!UMsM3d$b9#+ zVy*OSMq9z1?bE;5Ewb=i{!a-keD!%P?%sOddTTixV6^b^e`1BeHNsM_fp2sf{tMh* zRhiB!&eW&2zMzt7^?5_t9Hb1`{q^Auww=Jx{&(c0?jcdVUwR7F52Zs*?X+kphqe*G z`bAq5P`{J%-WJ&B^ItMiY*kRIM}BTb(SOo%sx~~7QQMdk|n0Ns?`ti%t zEM$*ACS8~1N?Tyzb$AyWt)cy$SYe~bTv}dYh2q!ef&Rz;N#*K|{tcKl`j)Q)SgaHz zTRQT6Mm#5|;bt5hBHhj$W+WTq%F@#$?FWabIdKk=-h<@!vENM`>IP;idpfi7Tp>j4 ze{azQ{ZAg&f3)$e`?0mX6u93-@)oKC8}T!N{Yn@+Yx{Xd|tP!T4q zm$xy38PR;E_{?AGDY$(zS-w46g0FC%AojO5ys7&{2J12d)( ztV?~XjIUA0sYBes1-JC0yY_p1IulI33k|TlZ6P1Rq*4p?_Ls@<1 z1C(i7q2%m?&=uOVbK(#>Mq6braaC-9PP8`S41VK}Z9n>%(GYc0jkq;*t4@Osx+TaV zz*vmrfaHO(tJ9!u#5Sgnm+e z+R(>g1TJ^lTQFmf5+46;H8W)soSgW0Zmc*4#{{|>@^a<)aseUXB5S7Ayxs3H zUe2D?22X7*04$yT%>talyBj%!#G7B4tX3@oMaUDFM}&cUZRFdkMRSNB5v*qtrYsM# zHO!nT&5&zzAn-!`I;dMlsuaS_U@$k96l0em$F+KA6L; zux{D5KC+y-t;Q$?&(izzbw9t*u4l(#_uO^pyV-hCXZ>2tLO;HR#(LM@z00y`b@(Kb`^)qQ7Ns+vd&pP+!hZM0#+( zpq6@u(!$HXrZAbIkV}?(NT5WD3avt>a`Cfv$0KWW$`U`rrp_Yx?cj4AoXLJ)WqnGk z&hyL;+&e!Q3{DSzSpVlVNr&b!ip^IrC;*_BA>ZF`Ox6D3qL0^FU|t{p8z6E!nJ8?p zQltz_gVp?%$%0r>GL9P+EO8cZ3h;{jp=DLVZgUtfO}#!NV^f>VeFd64=wlx`M{V(` z)nC1;?`WAb)|w*PP|k#qU+2jjh&Y<6> z;3T*gv=C&b);-R*XF^ZM1K?#fW7p;EEsRynzpP2Y5}o0MN&m(S!WVPxkj4x*!BhB{ zdt0l33BFN#0r^I()ty`kperhxeegqn4-_9V3unJ=M`e_R9=5zsZJX%7O+##(y-6q@ zX%vYxrITBU41K|fk1&V5x;0oz+}`cY=Av~%p;_O!7EYjRE{E!(wPNYlq1Aq3ed^KiJXLKrhudRz7(rl2<16wg@COE-S&@4^Rz zN7P*O0<`@6w5)=(d;&}y6jXo6DM(0uFi|qSJB}myw9uk#y_hXBOr;(b6_uylj$t1Sp)Ts zT&}S4*-fA>IsOv9e-=Mdr^r`Zos|^yIQiuk1$b zE_u|(v&Er)M!0c*4G^m~q2uy6EXw^7h=NHJf>_s#=&0myZPu{#<;&-tw77^0J6a73 zFC8j;OGp;@a|1nJ>}zlQt`b|#?^NwE$hzAe>86F^`E=9f>yr@S2fr}1J>Kv-;7?1gU2`V| zXkaz3XSf#h=%`Bs75|-BDBGhszVdxHurjzaKb7lqt=w5hj9D+|m`BIO$45!e>bv`s z3l69lQ;!p4lsw&Dd*71^Jd-) z3YJrF%D;0H)zI=tRSv}VfU1=uVGy?2f5@sRnf54u1Ji*SP6$k>x#nD7CAlNjSU#xv zDCxL6#iz(;=;!+h+8t94k5vGQ2 zczM)61n63}XAFZg+6l%LzuIZ{#@Dj99J+(YS{Vf`h}=RwCRuXUXs1R8yp<}#T+1Gh zj_X%YOkrAN_}N@HHYBVI)O5jnV2ay{pZ?RmTm0ucL>5tW=0IRMO2)Szf9#V|R@9uN zjK%FRevEJb*fadXLy1s|;aK+`5m-H+A{?l$BI>b2OG7brYX4vaXt9a6m{0d$`e`*P z(75BS^(Il_-Dg6`XK5(9n}mpR+wyb~=ONMMd>~A>RuhZv(MB zn0T}Fl3eM0(FRscY8ps_V$*&jMe)GH`nQu;D?oT!jwD9QvG2Noxrj4X z4^%C;%-E|wf&l&7Pudm~oWnHE6Yp#yoG zLdeReW&YAQpLrn*n@3u5^yJvMpk+<jvP>K>*k;z_3i1?^H!J(yd`?6%R4D5OtJ z0iM%gW)s-Z`@X*kU}26ozhWZabO(drJ;A%{iM?Hj1zf|&YiHZ48A0wEI&EK|W<=;} zhr$fIG*f-TarI$}s@qS+bU3S%Cum4-=xb?v4`W1m zfcXyf$sy$vL-)gJdza%#bAIg`Hz&Lqakr?gc&fTp?Zr|b{HJiGYTF&rS6XZK{z(}2 zdkLdOXC;OizuhY(9f86QEW@=-J&S0>M0&(kk^zu7e_wFE4-s#}luUxV9>%8>k{}Ut z^fpWk<})gd5x`&B=nU7{N;l{(SMWCtq*7#<{gFts{vjsJUW8Kgw>Nfd#2CSYV}3E1 zYjkInPl((Gm+kCtEo2MyCCt1CZthM+VgUeA?J4J1-9)o7dOtwm~)m=tBu(r5*uTxq0!BkSXO# zHYq*5X0K=U#&P`w*1PDM?J+wrRjd9ts#3LsUJE{?y>r7u*~S^n)-B4D|7op0MbzH8dUD8FyP+YxjY0B>P;@V?+n`SR9!&EQ^QwQQ^#CR+ z44vu=tl1}bur-QNR6grtw7pTmIEf!Lhps{Axg8FdBu|Y%e;e<)o?$hw4 zyM`MaT$rbA=!#O+-!;of!N`X1=j6zsA6&#;4^u%ULu|o%qr2!=Q7sp=>6o;EBiI*t z0n63(n6$|>%4fs%68Tj1^lK2iTSI0Q!{pvAi}*JBZdAIyy)7i3#4FF_H=QQ2S z88lL1M%w%r7sCvullmZ~3i3O>W7d1cm=kTiWH6|MJ@}n@_&o3VRa->X^dQab=a|8t zJY18^*NY4lCNlnm>53~)Ygggn<-`7Um8DZFwD{3r(t1#xz{$dCjM9<%f)j-0S(C3l z8ZO^?c$kxTZE0ilFeTkK4YE>E&32}rA#Y`g9?=KP2278#sz&xiV(WMje<+Q%1?Lv+ zBCjg1(mPoBC^Y4ZGs4JAK*P4mP?zrp1?x;?kn5T<{98d zrh>1+8#hh)1M+T2%pdbtpzy)PwDNkTr~dxv1bwn7Nj_f`-l_%Ue2s`%*~4n01)ba# zGtLjE3*(>_GaZC2NnsM6-IDh8FD3srb34}5DpicW*XoO(t{8cU5kl()vYMb}lAu(O z1}si#Mj>AEh6s}oJbidKjj)+}m5iQP-}0!JtrZ@^xJwFrPRRNjp{3lhEqf2gr}N^@S!) zZm314=ZCOC08EBKZ|VtVfK4&NHB&{v%W}OBJ7iw1!-ru|suVH%A%mYV2Uo?M;oQ)T zyJM{2fq8~V26UlGF$;1a)OWrPf8i)|t7+qf8p98#g6L}*Pg0cVr}DjZC-L%${dXy1 z*@jA^zNhy7;h$Os$kw@VkPdT#agH0{O92~j%*oT~`LH-`1YAEFSK1;sgUsxZx-e?h zV-x^N3wIJFUQ(*NCyVFU+H}DfN4&*Y& zFNpi%q~Q+`(+VBlH#(O#aUj^-=-CwhI;^eK1+in%C~CJj?2Pu&tLge;$L~(4PJ+c9 zeP4gU)Xl!@dEl>=@y0?LA%r2vf|m~1kXZNFT5xT%M7v7@Kh!3Pus9y4SI%j5{i`J1 zGoNAd71yJ(UD)U1?zfdZLipg6vaj!Eq zpnVYOE;JneCJx}`P-BvONtrhzfULa`0^5bsTkgG(l?XZ7%t_hGL#$VCV;iz0|7m?3FYS4m^!-bTpPyIOin?5Ap z6I{Hx+fMP)z8)gRVRh8_y%(N4H^V#L2B4H_1JFxbw_P60Zo7E>c}Ig`2JrY>k6ZOF z@>UyI@_|Z^_5{OD*0Qw+?W7)w8|&@vPx%1=`!Uufj3cZ!p?~OXF?A;(Vk^eyt1l;e zTYApOf80p7Z>Wx6yvom&3+__n@nl@X=beTy!S3G)1ybA3T?IzF{xm(3J9r6n^$~Pc zBOTo3#%d(&Y767H3XWbeI#|r|f06Dt+@W>_J1xg)6z8i&+<8hno>}X+E9GJ_aXYpQ zePF3c0x<1az>zaT$b75d2sX_%yj z`Ac=pk5>XJ?7=HEPGAk@ltT&I;LHx&0J>;=;}7C_JR95~1o-tpqzNxD3CQ#2+$dkKfJ`Cx7%E7;0Wc$+vwR zQVFf_pdQM)t-|%hGc`_(_#inGtiD0|*3#+{xcyE#&a$Vedn)0jIg_xsp5$H23m)eu3pQA86A7xSNDldzni`sf*BcUmjHwN|O-g@b^eYRq#&ptW?IE;; zvFV&NhM-0-a7}=L;FAyi&s_9sN$u9M)U`(tg!RE!)&6Q{ISUr{W{|FS7m{C!H_Sos zor*7gf=06&;%G|Hjcp_~@5WFsYTXZmT*=C&$ahSYPNxOa{&ZV}PnIb&aDI+3C_4GC z;E%IMEiFG`o5!|g{GPYg-C;vOf6WC>$$}ZnV;Q1$pRQw2+&W43Ir_mc>>d(dp*`5c zMr>)&_aNHQYVoE6i}LJ%>{8q#l^G>#BRpKwj(Oau{Sy}xDa8eDsJdPJYk?N(S@coF z!FPfw#osIIsG**&NY>7o?fH{W?B?{f37Dv?Q+Q`;3Cyq60c*}CckQwNS@Hl}roBYg z!q$mtZwtEa1nu|xkL*Rpe_xr6#z-T7Uh&nF(a-E0G?>nRSd%}Dr3!o>#vMJPw{bB^S6A8Z=*zc_&FhKi!zF^_Ed6(0jZn% zYPyBPkl_k*IB>XlFjL|+jM}s?kmV9%1F+jffeqk=wftyB%4Bd`_OByD3}kG}iGKv? z-a>qaV%oR(>vEPcTP>Jid#L7l@9Krh0mV&nN7XB$FGc6_a50M|_%@qnk63&r4SUoX z*)LTT$2U+cR1HUUrnhOSvOwoVt!;`e6%4#;RAAK^RZ0L8Lb&{8EkM34199p-Nwzb&O3bR&V|w{wh7EYBg9u-{DR z{l!l8U9H1i=zG>D)CP4U#+lqG(qaq&R5lHo-jn!;l!*f06{t;dZI9rbBev`xjVL}L zn(C?Pw+MA8N}B9HD$P)&{J8~%n9)wIT*7G(sySZ2UAS`OASF&n(DcE{W}Fn;dMg`Q zbyUJrDTD|^MF8W{+fh%d!J<>83@YXCw`iZ_3M_;gd3HH0KQ4jF9*S8t; z{6K0_ixRJwW4YS8DnD9b04L@MVa1h)zKs8sB97KUCyDX0w{VC-oE@qiU?+_!1NN+Q zO*{H;k$N*^w8MRM$BEtRj@XR-^&i>oB+4s_w>Ri5`ZBFKToC>GQ3FoKSP4@A=Uo;l z1PU)&X?Fb7_>NlU@&*eTmojilBEST5{O_C(8r+nJD>~80KBXWD?flg8w-dk{w7Bfy zEva}W;4*o4obH;MeV%{KpY4rx&@nwS^I%hc|&SOU9JU^ zm{oKxSD;|P9qOd+rJ`>Ip}RHFJge0RW=1*8ft!R+?fvH+DUM`X_%uS(?MRZ`OG=>~ zkqLKMESA^Glmqg7E{i$A>`*AJD9m24WbbKS7>IlFRzCEfa>>6A>f8O3UT6w;a0p2( z@f6rBXRUqeH&={oHno0td|Rxj$D1o#LEHD~PVb);!iQVg6H)SclaB7vK9HNAPWI^n zc2%WmxstD@c=|AmWKpF+k69k+7tnY_M);Pfs8<|Vq|EOsI$_0Lpn#A=0-{@cSh9geX8g~#XvaI~vnW2vc*d}1*TpeBm7hVr^&$Sdg{ zK}P#CD1{k+5=a89oA7cJa+N8!!fD7w9E}(Z7>C1i} zO`ZCW*YoxpOkf>uA#6K_l?TkpPaRKu6F5_v!3(O_>iv0O1xZZyz6)oT55$g|lj2?- zH@;|k|mkm zo~7YV9-M?Jg!8}ge*K3xOQ@8IR)aIm;+F4UYp&^WJp0a3^JIrua-9VDYu+v$i(ZVD z1>5c5Asza#(G{bFA$LYb-mCX>{J!yxu|6VmZ9RSQlfqLh-1d@2?a_NQ3-n6>(k>X*a}y!`EBS*<@tA_SSu!NbhGQx;7w&|{z=u4`9GC)5W#w#ln(xeR_E-O z4H!o5ue&OGRu1NyWaX=mRBtk28C35bwPf^42jD)w77Lkw5T${NRaXaUj%`yKM-XHFrFEr~${g6Ld z3hn)X*$xS3g;dCIjMSZzYF6#Kzfo^w6TaukDye@R_-`QU4$VLwen334lAsCy#+&b=^#6>6wPNG?yfv*shf?wZRLWlV&6mDs2ji# zUa{Nz#=F+$dm$#yYpe2&wH#)=e?GUepq3-bq;t9PzR3Jr-$jL% znfNIysK9ybQ)2n-s}u=mktZE19AC9c<+q9QO@Tyc`%HclF__~;y0t$>QLIDhYq<+a zn_MU)ajs6Acm_Im>-p7DO-P)>tuKwhvd7PfgIM%2<;?oT5F3}URxH`@M@>_ zgKNorld*KH&nJkz6*9SVxgcKt8Gr_wlI__tK<71|op>w6XxIBfXt+fW(dxbYpRo!_5U^MuzwByr&PU*VF?NmCqxW}5 zIbLXT%S?Tv(-UJZ8iLkZG%aMWw_2g{qN0=KKDe2t3rsD)faVu*j&M0xVo6T~!L^-q zUz09I>VBZ>?WSYBDLK7tA7E^iY$W4WbUtiKv)D;?F=IVXvPp8A8gsClg~T#>2{kpk zOrlPS!L}UirmHjFZDTPJ(I!V=7yx$b8g5SRd>V=ZmYxFNz&@ib6n5)L)>I}ajHd0T z4@chR=iNwBztP>(lHr}*9zUo!?pf*c1gTn!6NqU`!w(l7 zSRB*gyI{dVYwz0o24Xp@Lu!(O-*zHED%@&KOuOC2BZkp=S6ReVE{TArn#JRDK16u& zAt}r#&u!Y88<JNEgQ-jrl4DqJYfBb@vf~ntq)q zS__gBe{6Z>CxUq3ol45YjTjbauoPZ-b5i$sco9-H&b0&ukPct}IL&HW!$fY@v}a>n zo8P+SA7hkl%Jgg-17(C-Uw{mgGIFG%bzUAi=>SKF0oWK!t@y4utPz?1i-s?izS~P4 z{eQBw$o<{7TscbFo7M5?rkm2WM#n{-8WYpIE+^B9Nv&&BJMcCuhoP=JJl=#nHJEyi z#4P0V_Knt`nCi$1yK*R<`LOPkIzw|t|460ZwTEagg#hW`{+bZ30tpV8*Nud7>a31_ z#W}n+ua$#bu7Zh{g`kXy?+N7$sK^g!6_Vx@awV}vy)1=OfWuL%fj|wL9L+3CMF5r* zSnfKA=Q`3gT3B4Swo%;=(AFd&Dgvj_R`LexE^cvbG}2o>0!3te8N3neyzaU)op!xH=+ zvJXyMoxsSZ>k<*JIP(^) z#^s#QM3bfO_`{!bPg-ceBS=Qv>;Eq*a&ot9XrlA(-dt+RS)^ufX@ zf;`bY9^mM4&$% z>MplbWakX+9V0)kaw0233}oTlBqT>z&!7Kr>YqbLQI)PEGiBr$eg@C%j$xm7&B|{u z`9IAS2n$;et{mnhF3o&K@d#UMMMUK1?8rLENmS89x_;>&(1D597mK^RGMEg@T9#?B ze=_Ka-4(*BB^t!3_|OE7&#p6lFu#v6soMO*C8peJ=yGy-OUpKy`f`p@?T{R(FQA{S zG9*j*wr_jA<96{R2wm;n?3$ra-udtq9pz6RWQkl?QlmjkjWpWLbX zeA~&AU3r6Zj~Ww!d$**~rKvFux%3Xv2eFQe7lVt1T}{V1Q|@aT<4>OWU)`CayxN}c zq{Ag5V!Dam`ZH0^I=}&HbT{ScIAj|0+3u01wDmv!15?1-m>pYZ|Pm5{eW&OL4Zf@rqnGa(W^_0~f1mFEnw8l8VM zXyQYKK3}Vifj^ilqOjS8(O+<0+p~D=RiO_@E!I(<#`r-PE9+CRFO#Q_1srjUKGi(ldWvjXR>jhG!WJDk3#|cFrdNbWDtR*vaESqWp5?=F%-N;=^z0r2kh2i?MJpXTF6`{AQ#*X5Bg-ND%f z3gEDQ%0OPyPMr>Cmr;?4$$-3!ms4OIC5OYuh;YP32)D!4(R?uGnv<~w3Cjpj$h|Bx z*byO8y@s5q?|PBG<}BG2KP@W^v9sBH1n1FZ?fP?FIDV<$%oUEdR{juF>8;_2;7Xy6 zW~{$GE@#=qXDgsu0ZFe^0T-oGG1|9XEpMrm!lABcgkdadgPxU`s;!Wkx?7UVkd_CB^2hHLc`J<8O`f96KkBsNGI zTYH7$)j6RP1~hZjyt_D)&b2?kze#AN^@BXUazwnE>MXNwdjV|>G2)abL5j2<2m|jQ zFRL*suM&4${5E0`OcQRE1J6I_3sg93xPf*wu7~j*Qr#d?Jdi$e$o=rxN89g>aY`Gr`U$X ziM|(M&rDftjoStAq&^0A3Wd@J9+6@>Y1m*J`#AF4>`n)&-10b^@2vk?n46o(6vyRb zps8Gl0s;fi|Ei|?2EGLFDr(AAxiCMmY{ar9ZObPsymp0LM?dTtQRNFP+$@lb0%ggJ zOhT(Nu#QRNKLkO#4qQF!m;g-Fy9x^Uwn7+FPDM?<;2eiAzy6}&dioCHrk1-KMmw`( zyQd}YyfS%*Km+Z3Xl3fk8EMytVIu6LQU45aNqa3sV1gAW97$`#`LFrCg#Ht3~i}?&zzH)1u;+TDJ2s z1C)K2@6$X06)dM54SN~jVy2@LU)>-%wT+zkJ)?iVAT3GYexZ7X1og}LoH!Ip)65j7 z{1ra&ky?anZ@uI(zjFKK4Q?)*&esbLKMVH+-scL1aKoz@iG$ZatUNSzG!Ih#ov2ra zS2Pu6dDpJ@u}YlADW0S~Va(AUtBPlZErDLndNS_At%Bd2)Cuz7 zij8`k1pyD%59w@9K~aMdx1ZR!>EeFFqMc|q)ycl3wuAW?*}7%ZQ_;+^UZf3f`o-3c zCt6Mt^?Juc1Wd$G`=zATC;W*mD)8C#4GEfR8DHF+@VIS8RU(IadJeg1!34CRriHtc z!zBmL2}V8-XLHck$&zuV#xy7Mxh{gR3BC*KZ7&5y-EU8RaSSkjH=W=E zX+#U?B^wB6iJKHTpYm1^wwKKap47#4rS4s!UQ=XB1%u>WN^{uk`FLGUXJN27N>qv4 zSGyeUvO3-KsU2*y9MNF9sX#u>2cbFqzs?q=3*6o&G!imjo-xs@Nd z>HOkT@hnZWF^)T^CkO|t$hzkH_WQO?N1N9oZ~JZtihHn=V(U&+qW z))1kwKZ*w7FG5j=A~u|*;2Jk{s#gy58Ix*cwe)WZVq!>>=pXj_nQ8EOkdW~!`&#t*V0_q+YC|4>QSR>+}c~;jUeLoN{#u7}y%Hji}>An^uF)KA> zcy zS!;D<(VvppbLG%w@Ajng^BR!}uaCUtsWrNuOpW9fZXIHXiDrw>|2TC;jtFb@aWqnM zK+WEu^vvSA1MHZD$G}aeba#i0q=B_kqaDAVx$>Q4nkDL|-T3!vRREk7H1>N!49;BJ zA7SrN%yhk+X+!VUieQTi2)MugK_=eXWvOw#3Sg{ouLZxq z((#T^edXb-9K^HEob5It04L+k+D8lj7!NA42Ug(R=x6K z+tg*Gd%p1e{19Jx*f*EnysAIw9f#_=zQC+(Gh66H9%VgKEYI&^z5AQ+C~{VJci$)C zs+WovbB=&rse21+i}$l^-;zzu`O@dX~OZ$;DsZ_}S3>Xl`HqkgA|tyU#7hrlEx@xMCK{%V+E`_CcTl*VA z$vA;}I(W~w6LlDNFF9YGEEDyp3?V}BOoHknK7o^(G$wZK;kTIpW{-pQ!z}Qr_#cZd zhb)UbTgJv1+VS$JaNCg6A}kd6)(U}w$muXzCPVXo?l=`EX5EfSP!}31AmqQnMfi4C z52!mjd75-pibrbb(PtKV!=uxA?r{vBLLaH;bV2i>L=1e3Bkeze09fk+5rG30a3Tkt zbLS}0V%q+D6+>vYj9&S8pZ;(zGjA=rRt@M!@bb8xLc(!prIw`P4U<S9qxO$ai8hbTH272Xl5RjreY(x5_{1PcM~fkO3>qNfsW1?A?UW?pXRC zBSf>QBJ$fa@!FngrS=)PG?;M;J1wRMu&LnY&LhCA6>iQkYuYwdDIAD7E=KZl6V`}NI*^jRpr%L_46ds zSUTgthEb$m}wxh;g^af;5i`ZV$=H|`;5XNZiNyBE+? zkG{qCRk)t41y?3lODu}8+q?*w8uec2W2kLC75$e3NCKAyFab$I$cDo(R1Z^Tb0 zv^BpipE_||Jd1N$)%R~1n)r)V&n@RBVl_VlOe7bS|KU3z>=#E42E3A&Edl_gx%4$m zDb#Q;qB5j;;%kh*Jfb(??5F{le-9M@ZUGm|MB6p9pBY#`^Gf0B0;hND!tYf{hWOLs z3)AT+b!|y{n*75M{Ckl4Z!7hG(5{40|9{Q4qp=bb2iDbSk`PvzOdc!10OjdjU8$46{(T-)tard5|GVSUJAkzHe=h(;>3^pXeXkgn_|FIeb7U|K?mrWQ4O2K7;(1N z&V~&2rvDoJ*Gc5>Bm?Y3fP>$ETEqWv8zKHKEB{Xm{(m^4{2%PH^GrzR$DMjnWQ>G$ z)KJEAeScJc?m4jK=sm|twWNIF;du^zFH#PAar^B{L}#6U$mLBaD+6jb(iW{va53%XR(Lf`H+nM~$IBM~V zLdxS*%p&|bRre-xBn0pz{gw{pJ9}EFqWZ<5Syvp%tGzRN=zW0my>9Y|g%1!E3B6HM_=wCPzBPK~a|62M_3;>so#lu~GMhf{V0=*1~p8lWuPY96T%7!*c$YuG4od0&Kn#PII{o| z@mURP(GC{WC|$FuHtKoJeCPXRnfU`mDFy21b9N97dirC%1zg^j*HI7!6YPzKSGAK=4fNb-;M9_xTM8e0)23UxT z5c-El32_LhEwrQqyb(Tgi2b--4+AVHrP8<@ouOQEB)>E6H<5EJj5l#0#n*ZmVl^6` zjv& z;6%TAgTHWya)Um4MG4AIFzSglRS`QF!|J}HIr<`)O7UTHDYT^LKIIb>tLaVaS$pN8 z`%EnVNwt|UN#E0_4|w(Ok6ejiH#<7>+fX6Y?H?MC>_jS5@W)gaT_$b6-4BPawE;#9 z>$Vqk3`IMWOMsX^*h_ga58AL$ki;A9f-zSsYPc^Cb^8TXG8`~T;V^ygbf9UEA>c;? z3(yJJsFygW+?!u7?Yzofsvm43y)Bjt%x2uZsF*O;Wg8J3hXE<^30WvF=jaTMmp^Sq zFKz6m(*^4j5JD^K@z^@@o|~D_wL7r*FrBMGc5l&)Gf={@!|Z95tJHs9C{y+}Wi{cU z>@_1G8DW09hSN_}`ag?LsGQb6wT%aWj$t{)!*9GxLwTrAz3VTD%Da?6q8DlM#(58r zmB)zCr|I)$&tLOH_aSf7#A_=h$=QEr4sG&>2Y>F3x?8d?v!x8s6+$%v-lv#LM`W%# zfRtF}OwI9xlaIx6gProTDj)P(v$=SvLNEg$Mi~<<*r3|D)R2O-_x2L;ov8V=bZbnM zDnYu-veSZ=v131~iP$+PQCdo-*Z{@H~G$j?h zUz!eUkdYKkDy0*>Z5D{b+V|spd9I|@W2uQrVtC8(&oaNME1ddRQB?;EY8kpFGVk>8 zz(IiutcOTN>ZV?+Fl5C5T@Ver@$u(K`&_wU_S>`|ddNDPBnC19 ztMt9oH7@XeWf1WZ1Kj=XwNxs69B%J8%91&lf7njI@B7(eoxt?a2}k?O=i8H;N@i`pU!FU7FA>>tgmJAd7}eGd=36=Df9rK^at-mWw>tw@OKR4MF^Xc zaANs`8p`2)BY5$d!JkjD-gm;sx5H#7)9y+kq((5ErvVn9yN2 z7a@%N<0E@4yX;5^Aq8f=*{+a`*FzmPAJBPHN%?NAc83FX^?P>+6})NYrmkKKx2LID zOrCNqv-%WoUz?8Z{*@$V!~C{l!INrM51TOH+RlAhaCS+4)OKr7TatLDjSc>Ip)B!u z-Z}(9UcFezt`%^y?ID2MnHqoH-~Z;vgMXJDdVMi{b(LI5Hs(kg146QxEqUXewVTx{ zx^oL9#sD-*`xlOwA(~agLqmpP0T;Lv1L||xGq~MrV!Vx8wD8&QVv9%~G?rLl{W^9{ zfY4OUh}!!PLAH^;fpEw#qm^(TGnzFgdPk%LTxL_`W36h73jdJe6>^nn=~$JABq&yE z3Yh9;lN;G3vI0W)88fA*2glSXFlEkvSxTUoqD=#-rSDo|CRjlvtmQWghqN93CE*wz z2AjTECi9WJ@14GER={EC`UP^5-KtUQog!uysx5wFZZ&tpg1QO@wj_v)2)q%R$OB#> zw*9?M-SZirerCwDnBK9?rmFo4J1`X_xjCN2tl?x%M5>rnQO_!D5a53g;fs|E+YmCL zG#J()`=L8Zf%sO_M>O-5j!9HIYq5XglyrJ1F?<2A^Q|GXWNyaefqidG2w@lcIc+wb zvLyI>R^#D&Kki%L`O{~h>gC!k-N$w?%frpp7B!ghoz~^0eN=yiMSOv9InIo7N}<$df@PP_Yylu2%sq#X^m&LS|M?4&#& zlj_N2JmHIuy0o8IaV!YWEcEqYdlaCq5`Vjnb{mR)LWGiSLl)`Be{$2`%*wLDhBwdq z>#dU8QlkVitfzvSE>|WO+C92==-6{`R7oSmmxWr zwK}swBuaT0kYH2w(|%rC*IhT+I=Cd0rq@8BQz}gQ-TZ3sO+MQeEx71$*KqmVib-v< zB2|#tqcv;fl)|p;Em<>m*(Yzj&-w7qOL;19n6!PV z!Si=VggSltgeSvqh&>>;%P$hrICMpR91QR7Y#Q41IU8DQP$rs$LSZ?qz&%7{+*JMy z$@ep;g~NECKvetF)e{us1XE|LT|d+j^KQlPn+EyM+ti`;OYwmA4&LIR@2}hYn<`~v z63m+7KCM^}rTCvdwips)?#G8fZQGYDO!Q(S<+LoN-6@)Aeb2=*V~SDM?ot4%ZZ;+e zeXMxQ!Tj;tHlCAn6Q0bBlpi6u+pXV0DIGSy5>i!(XcB+rzmfzpp;lsK=Yu>4f`n_D z(SR$nK89b(D2`7UvXkIrO`YNN5RqD}bRrtK6Z13L_p^(dJH{axPOX_T4nMcBBX%eU z!%1NCE|cqh+3kGozAHrvW_?QVsGvDxQjZPtT8UB*40%B% z^yOiaIj?DyMf%3&xGqJ*$XqZP_F4Ebh1G)*YP!iR`PW>#5Mdfh#?;(|*2u3AiAUEK z8*C`0X1BY?wcV+Cf_r+um>=Kh^y}u2{(PgiWKoor+Zf`jo5dj9?QY6S&P1lGU~eK~ z4d}HdHzgU_AFY&pDlD1d=1ULPsg_79xta+2r|J_y_a3vE%*(>*Jj$m5^*W$Zz;N>= zZf)l(Bw)~kiuvg|_{*|88txEZstoF`(sEdU8fgG#P{UyFD-Us?i!|RF^+lsoHx3Wn zp0zBmYAMHup6C9*7i;7xvAun-OcUjyzhJml9bEj1Kq&jIJs>WYKM+*lD=2q15rl+S z2#4Kx*eU^dBh{sQ2EAiDSqtDlF{$3YhAHP0)r5cM@uLZz2Gljq{v0Es@ps?+U1EQg z@AU1)>1uM$nA)4qPr$XuN*AMod-!#&#Wdu^GABF@T1ff&kH|1N3!HcpW*<`Ahl*RU z4mApO1;lCnH~=(?vD06Wb*YlyzqRP@fjfdH?Sqi!e&x%QkKf-hM&FNo?_4g7LVr^A zYC64C=aMn%W5w6I$?xap2^&zpDmPkU!S6E?_F?j`Kr~sBhew~e{6uD7qeyk!0SsPnoBScpZ4)uaLYs@`FM0F4ZA~c#skY+zSw# zfXY@s!R2`o!hDW&_bi7GVj`=@ZGe_JaFU4Fu$kCcg&|@<_S~xjagQHc3C{11w}!0I zLbXg4<>+3;nJ#Vz#`k09oQ>1Qt%Ah)p+^iq|6oCqy#|zG20#y{>xBmPtfHcs-z&y7 z3nh$9h&Oz(N|m4wxA(Jsf&|Nk0lAM{WTsfgX^D*@Am_5V+srfnst_!LoPDndSRX#i zMRryG>X4i=nX=B6{HXAlT72FYX8U3svlJG9r{`d~BK3!t1MR5O?NKs9SlntB zSqRm2NpxV?UA*JET{t4}*l=_a5Qg<+>K6wSYo}~AZrVLia65mQ!`)FN6iUCspmcRD zI|0v$&X<%zN#fhWjrAwsOT`~xQY$5|EiCzu?;bm$8f!;p8=Gt3wJ#_Olz)X41bd4< zs&Th*V~=y4)m&gTw{QW^rWdIA0}Seycw2KLeVh^f@rIst7xsBy6)iv%ct2;Lt|Yc! zo#>oh5a`CBo3`*cwo5-JJP@$a`s$mb5vlHu^clPu`3u_oGfPae@=K$!k*|KWV(=Md zk%#f#4l@K9oEae20g1w0-JyCE&$|(fRk|TE`Sue(Q5{wCRM-2pRBuS5jEXl)pI53Q z^0Euc=|lB862w%835xG`dFeG2%8)w1X(RG+LimySiqWYNR_LBkEq44)$%(!tAT*oeAmNNfllY^Ww*r(e#m;VW8?iL15iqX8 zHZ))6KL)^$pZBRc&(%4=$&MKYtp+6Ys|hUpX@Oe#fLAH`C-VE1c0LP>IiDQ!=_6k- z^Iq;16yij3@LU^$JNte5dDw{+r`P#0Z~em9=`@@V@_b3@cib$}D5jUs@W#sUp_?FY z4hhaXVrJRNlD>DD>gF!%Be#_del$ja#kPz{l}zedH7(S%+e|w2{wi7*H<(F?GT;%Q zq67;P&ey4-b-%M4PBjP*79wFEI%rhCfjW|$_z);K4i76xk_hFquZ^~csG;dx6(smt zp`EXDitT5%zkt6iM569?k|ajrK?%j3Ro_|(@ASdy3lRkO(|Gmu7?EF$AT1sGgJI=% zEeqT)sA3o-!1qpC}L@q(<2<;s(O*2g$uwS6C1s zN~xP4s2>OvB&3}IMoOPHKtXDodmC>j1LHJcms$k~1~u4B)<`3j7+m_QN)nqDR?GEt zQU|ne+}84ZaEhp!AwD#?TSGyGD|h$1|DdF+dB?l!sfo4ifuI*bnH@Z<)k~3~feW=bMyyBkA zZ7s&NFA*=PVez%av6MAj?Cjs|l(%nr& zo_vGuoPITxK>d*Sd{{yE#F#gPQv^nXs9{-#r~j}F+ro7#Gf*!G-0>TM%SS%9Us5WQ z*hbFX;hjBZjc~Xwu`}C*G&54nxNFRSZI87sIxr00R(yPzLaxTUrcineKr9li#r#r2 zBM;Fi6D%21)DEeQO8WShv4B-!BK;%?iwVhiC`P>E^MCxLJ zvxyK=Nxs*c`auv(HImgSBy|JRVuw9au;76n!#{T+n%p3$Tw*ZxnaT^S)&T>tZ%H5u z859L5Pwh`6G2Yrk%`XnDv$<8BnNq~CK+R?D;ovxsIi)W^5s2l_Yc`2rPyAGiLBMbz z<8YH#i#q&fe)F^f+Tn(}G+%gbcW@UXjBFnhe{}u*5!x4XU3~(sIY2PsvFT_)Ep}b@ zE#rrE$>s9o{JI0`QH#xKv@HJ>n%kCySQ*xPJUzHy4&_7ov#){by3iNP9$_3?bA0N1 zE@E{oGoe3Z7gWXBp@$D|(rU#Dn5YFlBEA)2wT2cMc!`(yn;K`~480UIGyN&wa4BFiGj9C}vrf60{j!|Uhv@*)r8&Du@Z zyVm8Cd zC~=Nl^Z25wA+ML$9Zz&h4CZ90yq@{!^nVnQ_nuA$Y?&tXoY=Sw4RF@f{8`AoascFu z+30v`tdb=pNHwm(V{gyV4HyCxz-1&V*o75q9UN}=Q-wqV4)VyE(7<@Db)9q&KJTAp z(K-!0SZuPGXMy>ipvvScnD$0>*IYTwn*griPI>-LtL*kdq}K8lN`Q^s1r_((76Srr zwhMX16VH5hi0aBo*8rn!_G`lEeubn?5*Inyr=NXegM;HRi_42Gt*$|$h9NT!sllU= z0*f9?+>0$@_YzcnQa>s8_xCC9R{~rY^9x)|zew-xvB8LC{3hOvHb<}xx4l4+3$eX= z3<$LDflr-EUF0F<{`7NWa4$ce7@=Ty*WoHF;{N;W!-ao+W+&_?nPEwZYT-_;+QLeU zl6qbGwDA#1L5%DSLQBgH1I_5)uJrUBe(Blqsc4(nC%ePVI@rnIVXI9ol^zK({JsP9 zTtjLS%(c^X-YdO;cMgaVU!%dIlhg(MFr+D&{Es9g%Jw;wLEr#psQP;U`qL+QIOEsC zqHA2ya|u|G;m=JB4tV%WKS4{YwTx8=MOJp$___d86N&7*TeV}tBsJX4(D%-pS&Q>y z+@o9m9fdJo1hy?led}(j=`+0z@ zpMi3!`#l3(9@MT{?DLlra#ApC?!9j`g{lOOK!B+Iv9l@WQc9?WJ z9p2cbTQb2=*Zfy7&z8uSd!Bbe7SReNeH-CY#NLV{G@%GH7=1ZhCKB?qsWGvAYgiM~ zQ9)b$UXH>eHM1Ry5hr;Cdml~rd!E08oIwa_f1D)nu32VBIAIXOb(+T}f_d_u7aMoC zcA~Lou0~2Qc9pvTsZ4R2M;_jmOFgK>mWLo}vXrY!3^rwQRB#nC5g_LE*}G+2E>eWq zgUd^FBxdIXm$9D>1Fe&Y5!sXd#P*cr)|B2YVT^ColSGe=Cew4h`yAatbYH1T}e8b2O4Gm=pP3y;% zJ?X6I4DTfU1nO@LhZciw*T<=w9 zi>VsC+Ilw*b~|gGXc!Y8nLb&Jn`LgYXDse7vf~b1`G~m>XqBP7upF1eGwO|Ou`am> z03(CIR1ZMtwzHN1I{&+*2f*cf6zl&Y^8Nq@N&^ibp9+5g_n5yz#{aYw5CHfy_b>2H zit?XUF6Lh~*7tu8ME`Bk{;j8g_b*~JHkx9e;E<&Ds96I9kM>2&noFRLg`EB>I*d#7oxv~(Qh-_&IO z{nh)J%3+cEz&p-n>-Ht7E6bRg5CuVF3J0I7o|j+^d0rFZSafoFuk3%W<5~|YpyA{b z;G<&XW+P>9PSIN*)@tV}<`N*MrJ~|5%2-^y_M|G7RGUx+X((l6CZzsKl9rs1{Uz?Q zqk!JCv%#D)srzze16tf6yxqi3!e$* zhVPs@;%QuTx58I~bd~*J7s>n(!Zs$e(B4RO+OcREhl2!}Uk51a_0&W%I{Bp$t|mdO zoY(p#o^!=Uoyd_f(xSv)D`4 zM=uFiHx{2cUs8JPS1?t1qgqNPSe|YRJ&xsMpEhb_T3<$Z@tXR_W4r=W8G}5|0Of$& zFfZ-gl^i+*fAgQnDA@k)vGhhVl!=L%2WhyiZ$S}pLeK-f(CL_};>KL< zD*23_1Ro(mnGzyPD)FG}#E19o?Rr)(&LUG`MhZnWc|1m@V(zBU8dL3C!Rt9`d0;L_ z`*3sRF7K@D2C`i2Uhrrc=_;dgo-BvWm}A^C13CKc~#g+lpe* zT8v`0`e{iuQiF^tQcEcSD^aqooxlj+OEo>VyJ52g@WdV zq&;)>wLQZR&cc-H)xF9V1evQk@*%-o%!Ju!-uBh_%rS|mDUz4UqeAkOowoAyn3Oaf z-&dC0hLR-yxtCaoaruUiNC}m8EB-URP4p@-k0w!xpt!q?xKgEKqujA}N z@{{o^QBYd46IFP7c@%zW)q8QLOuh=)4Ws5HqAT~5kpiru+=zujL}aR9d0a*Gl%9hTxhv|$ z-PO4MxV++n(8vp&lS?qEPd?jLr3zrvlsWxlMhj6TrL>BtAn@QEdrg#~iMWHnPl{7} ztm-!~(sgnAC4F0qFi2j!U$ad)U;@~yp<9Lz3Yg_Zd*{gALjt_JeU>_{kU#}obo^JF zmFa^7H;uD%>?Y;#wKc*bB5xHADTHk*)?!pQ=kxj@gP8oEeXD#2Qw7gWRIX$P*{GI{ zHo|fdhd3;z1ZSP!smG!OE?A4j5iJXn5Zq;Ew~rF(mDuWBz5VvX+o7}GhNaF_wUX0r-n^-`w~KqJx^c0M z!{iX!g;TC@X(*-x+q2Mco~ah~j@OLX@14i#MknpaR|)eL4`*tnzKYg*7KTl=u-WgH zr_r-9x^|_kbTECdifeWn7^EbM1Q(+~R#r1(r4VEE+x}SAytazL5j|3*dj031h!k#v zF+;Cp&FDDh6OrN17q5Thy6Ltin5Pp3JlQ(!==wWr z={S4bYp55rFmBsUV;XA+gi?iQ>h~64*nBMMITFS-XoL)-b@PXTsvKewrPR(FxL=qx zE(m(A1$)P{6l7C^R^gjNEqZK&gyf~}Z=0s3?Iwc*G?H@WolY>nK4`QRPplJ|ih0E8 z(mndURwpNh_^hG+?T&B2R32$rqUKr_#=+UK&PitaXWvI5}Qojd* zsGRVEkSd#w^fp8`qSIJ=Ayl}H;EwunUF_T9~J$vM&KQK1B`!NQ>I|AhL2Xz zN<-1rIdAiaCWI<`I&t#JKbhyLT+mG?BrZ#dgiRyU#a+E4IDlE4AF!5=}zOj%w?pvbtnC#*icH zm!Esx%F5iS&jcDv9l2?LE%o1}ll&UYNlt`-ufHTVR6cj)U%xv1|0D65hkpeyV7}m%BL&mI=ph1?vz`?A!w}w zkTagM=lRBO~Q13_@13(x0cq+`jI_jiQ`Kr^-)U` zlfTxv>(j$vDp~FX@W8$#~cGQUQIm} zMMGV{nM1=aYV(%0xH-8Z>?iQ!gQVy^jggz0{IzODG)&A0mH5{VIu6IalnoOy6 zPg3cyf$03C6o^wHNhH^HUN}=BNX9p|W=)#n6!3kW&ud<)q>o_|A-BsJx!ZQE!zdVS zv%?3~IYeJrZbwFKGtct0dt-hRTz+PW^fFsY#>TqJU5tS{(v=+D)v;|OQ(V$L}x z>q^lr*feF$eDhjS#PX_V(4X?GBP0I6q!zp5SHTP-+>a*r%2=s=-}5C9$yl}^ z+F$h}DQdexIe4Ki{F@3p>Lx6`C+a5jZn6f(3j^Bb@({TAzU{Ya;LkzN0WTQ(r(Y#4L{ExXbfat{w}su(CWDADOCLxOc7Oi@W=l-?~>XrcgGbc zKd~9mn0<11{qk77e_kLHB*&Ccch^lg_ zP0%L&!R^)~SATk+d55q`evY?Xp~Mv@CJyMu9|zCZP&+O#&W7TusAPt{o8kQ)I)?G< ze9UNw&#&e7d>P)?b--xeagBwUfB0jmkV%hRLC}waFWlMp{ZdiUHEYp&x&~KWJsvjt zi@KMrbaA%k*Ef+Eq70yM-kskWV>^PEg(30VO|aK6q2D-gx%Hcr6{JBskixZC@X<&y zbvQ?NRqP2;jmsR_BRJ^n{tnu1gTlXtkt0j0$L2`TUm&8}@BPjaCcaibIe4?QUw=yaF_J>o6xBto; zl;t(bhGd%4G7JhK8GR(}IEv_tCi@_%XJ&ptVaBCVSF&TRbQhKoQ49~UNOiwvG*=#+ zi!udfr7d8i2F%ogRNb|&y`i>sFr`7UVw&$a?2|KjXVt@S71LNHKW7S% zPhLaU8%g`vO``}n4oNseJMF^9Jxj*?g3e^sVM7VE|1#y+PKk>haMGE45K z&Yug!!~tRA`BPVGg1(lx>4Z#`f8JcRe$8mQMGQi=Dz{x-W$A29ByQP0jxtVI)Y<9lGzyk2^A`IeeQ9H}v&pRWXWqAl08m@~E))6^N<*C`UcOn93b=J%n1;oPNg>J?j5!KKqS0bb2< zK6El=0b(Se@q9i-2U@V216D z#i?J^WogCwdA74NslF5DU;+CM6-&-V>SuhH+3Vv9w}K*hWr#tOFJk%JR&8^o3GU8H zy+#j0x5j6tL}!lfD_G@2?JW^Cqkay!MgwIUn8^$klZ=+v!`3%XX0OOK;M+7Q)jjoC zOpGB;J*&p^wo_A6Q~d*0guS^jv~(U{G?#kfT!Br#S&G1@%Rd2Bl}FK!hFjC(G#3~M zSh1e~xzA>Kla>$3#4f*tSXfxIJv4RG--aLEZ^(a3?gO{j)njW7X?>`U2~nZY!t2a4ZwW51^04}S~%OshRM>e=udwXHb`z3B+L zWj1*Jfv_k11C4A9seDM`uJvQii+;|5*MEJ@0&I_ve{V>XD7v97jR$e|cd&iV49Y&& z;%{Be+S2mtE-2`h4Ed<{QBQxD?2TzrTQi2Z0!f4&#k*$TzwaOqPya2N87m(fdu{i+ zUj=1V8Hy)0yuh81*37}Yp&JRFeh!)6LmU9_C! z_Ld<~Bqc)kg=_#m#u<=tW157wJ>U$GKY6>Ydng^T{A-?G~%kdgFs1kAzKY z)NOZ6(RKOI>%yIb2yJ=WFKoiZxYS2B1gJ*+3-gSrbf}(&4Twsvh$d#7lal@Ry@Nox zS3&S5Z2Poo6-C(cYZrR24+cW-`*RfF``IeY^8qfsiTIC#8}LO6;MurypmKGJqlvd2 zR|7F@T+7Mf-G-(KVsJ>6zCb_8d-ogUA;09`ezR7O4TfcEpiIU<+T}%gx&rH%LGQLN zVRG~IOh1ktweoAd(LY~-?>Oj+pqFwrI!&hs;atdCTY-n`!YRrQtAJ`s)Q_awOxG<( zHte1Pgpaq5akV#wG*_M8IeZn1_cxuGH)uxdtgl(1r(btQ)J4~$-JcMfI7d6Z%>Y%ha_fK2GAcn2+;8t8q)NI5UVpsa7&)d&o50$pA??YQ05DW)x3 zG0@n)?+#II(fuL633Um$fnu;BP12*|-bER`h~cLA5?WPf?#_>#ijr+%08k6-tIC># znW{}w6mG-x;`e5FKmATfv6DTWdmijMv}q@W@gqlIHI~1y^2w;xr-0eP&K&l9MYEu0qFW=SS{e3RSa{#;d+dwnn zS6N0WcSDxKi$ZbByh*XukR1KnM1n4G>Re}3)*1M|F6P-MLhq?z+k5+v)O%fr*kbkgtP7&{fN`m3uH(Q#rEjeYW|r@upe=oQ&flasf8?2xA*Xvln5rZ zLc;QBJxLDL8%}=>?B~#>Iw>rL>dEjamN5JVt1jE!aA|RRJ=9?H{5Y>xxd7sVtzQ)~ z+}h4wVg=!nw+a@$;yDR(X0wN3b20x<2@N;9W~4Ey1idaXZ~!Y~@P7VsUr_%O{ku7%% zCnqaHji)isr>GUsbNQ!D$fVLF!viMI#0d!JF?3!s;Wt5gqEvMVqzqH#K#nCH}a}oYex)Mkh=- zhBbP}o{n@YX?A;>J}~rD>aqCQ7}!LCjI31&bCi=bTwq}Zym9^z68Cp&%#KFLlYHYp zuB&|=w)?GLhgj6G;eVP55PUlC<=>4PXBQ8B-H2#FT=)*fKRYtX_ZC{+Kai6BkgGt2TV}3$ig$ zdfOwVzIoN^TpRQvVl$_~iNOU@?Q?rJ;zfdQL~GRT@fp@^kyTrH-iMrA^?!h&j$18;muyAGEQ zKqs`pyqF!;UMEH7Ui6Hfjsa!_XXDcOs)^mL%%iE%I^1|o$d?>22^;eVy%s~@QP6~W;sc6H5 zgDm=IPz8b$=Lk4Kj9Qmd;Yi3r=^fc92vYl^Z~+5#{OqN+;!9}6!tiq*jwFx16;g>H z@piP_^%#NDXY3HEQ?sQk6iDu%JmdlU=}sA@DLJA2kc@NCLZ$*+lkgm;qy09)gtLS; zI{T}>xPa?VuWgh)i(X2H5x_vtTjdjP69z3)0#7ZPOxuWdruJT7{?O>xkAYjTukK9y zA}LDqK3NA|`A}i1QQ_tg$W8OA%z>$f^6CJYlsNOJS$W9;Me^h8Vb{7!+AB;&c@`z+ z{4~pb#DSBs34rBPWDG9kI^b{aP`EKaON;=&W3kxBsY9XpmkPKVX2j0L_1iZ2EWWz_ zzx&CrMi=}tL2GU|dTwe=*S9FQ#-V$Bt_0Y!Xx-sQ<=PQCXwr1xR%M7Ia%8&mZhchO zg3{_fV@pP4qvZ+Cm9A#2A&q%RuOF_BICS#SCd&coH{eKkf-&p#z(QLR8cu_bt$sDt zkijy#o@|9)lW;`k_^Qjk`DTksncitA;lfAbMAf-w_E~*u4)6OaV^A_4CQA z0N(TQlvfr{RNeVl_zj)+!P~WMu5x@7L>J4CZjVZ2MWcldQXfN9jx}aIwsxPtmd@66 z+jTVtB(=Jp&s2y9)QHmBa=4|DDrPxZHBv5PV%%+{maT+S7nN$olFRC;ah~NeWYtiG zI!Jp|KoS>2r9rxoTwj0YJX+oG&VFAwu3NYEb>OX7eEATsnKdT- z9>xNEy-N(w`{^3KE^Fo*eS8OUk`7`@Ny$Eonnb2@n#P08d>{3Rp8)>hGQIM$t!0Aw z3zTi*_)pnFbnpR%>$!I-2Mbu^Y?p49y&*mpJSsTGC7gJu3^lULcYH7ZzykBx=1*UD z*L7Yjh`ei-n29z_)iRAWXU_xyCX# zhLkix`j*ZZcYGW%Z3#`#F9c|APaH|^QRr1Pn9W3fRH*ZbH~Y=6_~bZ`8q>kY0~msuDOmP4-sEzE=m$^) zr`uWjKEIHUS3V1)XYJ#>L15`Iu0BWAMNOCY@|&osY`do z`#t76xy%pw;+AWupS}D?J2!Guk=f+ehM1!E1xM9272`f9xR@N2npjPVwcye*(2Ynw zkB$w?j53rS%b&H4`;LbvB;rtc?-`qkl8b*aVb6~-E9}Ngk0oToC!k>O+cV5lmZDj5 z6;uv*t|fSj{>=1z-lQSobuA=5g&O>(ux!vZ?u_#CU^qkB5+=v7GQvPlU&5?{o4jAN zr<>~Tb-bov#Wdfs6Tme&I?gyYD!gIftKwHw|Bw5iYZu=2M6J$3=yo`|FE*Ix!vb&} zw~0&l(cmIoCx4X1{n1N#R#j0KjvK>Ts`xDgGA?6(y1I^#dH(bf=RfohEZEm?$Mdn# zajfUsVLy$C1k-G(Z{@*`)@v4n7lu08c9#b=; z(-;}pZ-U3njc7hMCJGApC%`RBOz!5Co;4!w2r zfkZ(zhdWev__wq$RJrx6q{Wb|;S6-kt*`7E7IRXEPu{U^0G))7(#Z|^o2ozd^t=ci z5`Z3xOtaB<%@pGcAKpmE2Dcxx4&vec*d_d@Q3hm>fA-(a`Tc6o}3h<*A;KW#(A4eRt_gXQ_O*_#%64b`65 z2GNEEz<)V?ll!joMOAgqd29j9YP4K?c~(kCB1yWqW*cImj}#z3_@uRA&&+FOYWkEm~S{d65X^m!xingfZ?L9Kc=SCSdVK8U$Cm~G$!V(xMfbi zm2q(-R>zdb^5jHodg^WL72`g&uz4xuBFohDz%*nsb0Z8W;c6EF1YQV0qEG|k)_UTn z!t-J;!VktdGFrMCuA3+0kA9ySg`>7{+A&%Rh#Cb@w7U6OMfKnNrJ8ALUi7v*)7~17 z)*mnJuS+(oo)(_#@!<0>yKNA)W%N=f<4ESvqM6dxjGoefBr_{$?amr5F-Foh@BT6t z9b7m4-objaTg#aCy4H^Z^Af6y7piuUiT&KxsiREc>o4HD5v5*ZVHKe^cP-}4>17I) zj*_DZg|Pygfkd}4u(15cY=F+%lp5q&2Krt*8OwB3teH?Urt($`pk3W`#dMefyHWdy zbEiL_y;T@D#>OTxxC-+Ylqh2(*UXLHzLH8D!cNKp_X2j;YbiB0igsn;T+jIP$vTD!XNEge4Poc~P29lCEdm z_7e|=z3Il{?|DFKW~v#)5`**CR4&jhcPajxG<; z@5x|w$g-5q_nXp_3xkL5TOoo%IACPVcD^{G`WT%u*6mq9i>Vjo6Ta`LTdawDNvbFau<`{V*WYt zZJ%7T+g4V#3kg2~w4vE8eEXvWPBH!yP)I8RB8xJ%v~_5pMu(ca=QOHD%3*w z<#g!{OUao1o&0^#02mT18l#D6&JJ~WvB!d&(boD}f*qE2pB6d-Ui8A(g%FUgLx-=1 zKVKpg%Z}<=s|#u?8ZYtpml$roe+HBvJnbRh0>vi@+Z3 z-_FnS;h9Y?3ry??dVczyXy{d`>gW_c;*63b+c`+%-QbVH>tG!%1S;QD8->> z(TLIcR;h`YuFK=C>G7fTjc|wb&!A7g82lQD*Za9v@efkdD>m_K)}O?6k20cL*3J`L zonFx!M4x3AT7v-m8pm!5nQ=P9Z1AK9@y!%LTcrHuX{BasF0Hh`nhZUiM{w2}<^phg z#76DRvGy|5L{_t2@W)2SVMq{n(0)-|aTtC%0u8hVbEhkU>BCTNc$0+igvw%qWFwcJ ze2zb_aoEid)PZhSr`zbh<-rzu0D~XT>sqO#q`6wsGe-0lnaAj0a0cvZySi;zI7{yVwPw$~_@2Pd~2tV3vQ0Q0wzI)7x z$H8=wS9f2zW?Y5ZexYWzt%17lLCSJ6ozH*%#Qh~`cnMRXs12dw^F0a94*wx6AWlX5 zci`ts5J>o2LBgb&%=JvH0H2pP#{HyOhC3YsYcg-SP|pq0lNnd7VF1Q9=lZ8fB*F7Y z_0e$OqevdIK(i-cTK#vr?xolA+t@iOEaqXgv?Du$iypX>4j~T3vLNz<=i;@s^H_op zBd>YktCSRS{6dw)d%bdlOGWl601#2YrLenvoNde76#60fsEqT+`EkciT7qY^$)Vom>cbuZStG z9|yE?RHn?Su3pYrt_IGvW8E`sln*L+gN0j6wV_TWQ`byrerf1OcJ;HH*|z+0Z>aec zpa={s+oxKMI8xZJ2`4ExCjEN$PL28IPH|(XJruXzhNTZ8Iq}I*WR~|!xn26_{%Z@r zNTxeic!Btl@y}mWJnl+IArbuylPTqc8^SRKGlMk*Ps?X(TmY(jiiz^XJpAaT8~6T~ z9%LX4JUiejjMsHpG)dWDPFOcm5XSJ}eT=?(rcPE`xIgyHA#nrQ@AIQICfNHfY*m$* zQDK|Mfl(zX3<>&Tb$hE$;CE5}KT!A7zfh}b5jDKlaE%A33`xK%Mg~7=KfzP3xvg}i&+9%9pa7;wbLA3x|LA>4uDwEjzKkUd!n(2oA$R$hjDf$mt@CUvgLF9j83GD)uaUynv;o?-j`?Ixw zK{jwzBM<*C zG8s%c~O#uh!4J6->p0{(A&OlLEIJVMmTIzb&&OFFA{FU=R+{5GdiXqmJ0Ohda2;({_N(Qy1u8e_)JIYCDrIl{juI5w`jcrV~vUOO%NrYL(@Va89``66b~wi8}+M)P;m8* z_*p}ST$1mC&0=``Ma+*BFY2^7zIsEDK3d~PlpXYk`6hgY`fy;Bn`2Mr^vD>LoYJ2M zSGA}JrJitncgLU_oh8e@M!iA8yu@Z@SB-XOXpX9n^F=RgzLSCXQ{ommH!ScU)?FWq zDIN96T-Pa`m&)o+e={?hRa*?B^Xy)H!{m;Y|nQ`Lj!?wL`ZZ{JKUbc!ba zj-yQ%@L$Q__^8KX z1xw3#8q>AqvwI5pI?T%R3oqXDYjF_sfCi5`poFD^!eFgaZ`D)B`unf;=&eK>Hc!Lf zPnNW-zqXyFGyc5!bd0ZRM`S)n;%)kt_}4s`&X7e0DR+8=Ad_xqllSgyDbuF-ZqobZ zRu~}huw!(S+A~u=6Ngj313ImrQ?$|iC^Ro#H8s1dbKFlkb>TZ-JGwuSd|zmf2F}Ph zro5_W*PRx4-znKd=~IzM+*hDXoW=PAr?Ii-l4$@{-JIGfs++3w(Jm&h~J zjP|Of%JE zwK+$5!DT$rf)^9tYkJ_w7{S#L=+Ah@m^9>2XG&FksquUubE^^Bqe*qTm73Q>kQ7rD z!yrN`h0F4LQza5YfF991qh+&eNlgnc6>s5&wakMis@A>rhVa+Fx#0S(o|{#7Sn1j^ z`v)11JkBu^Bz8w0sI=X}W4$obPsfOT53!(mNTdO}N#p zos`~L4_%S-*(c>KD~cXh^yuE={=!lso29@n-)L~I(6nOB)$)U%PVydqm&%?>WPeOw z!siE-PV+OKNj&cm(692pkqmkOuC18(&q-Q^nG? zI<7X@ag>|%POp0BO-hdcLXg0JS^j{?!!_%% z$xW~vp^!uQ_&yaY*8CEy4l1N~$po=8@+YMd0UcHtCr^KN)R+W;Cp6*+N@|y?^;dSB zh=oYsFx(m)?Nv7o`~>dZVc+?YFMwl8NF1j7H@p=%C!QL;Z5MqWO@i9Xl$^-0aS+o` ziyuooM2P~BDMA$$4Y-An7m!KydracIG1LB<-~}W>PQ|KSx1{)u!%JJ8xHnPSfjN#K zT#F-32`p(t*9-Gq{TqAc3OefD!b6%9CV`)UF>uKwv}-{vU<&)xZSTkNGPkHwA-J%P zK0RtG9=5Jb6Z6T9j37$ao2KThscNJl3_S_76b_RirvIv5rI43Yhw+*5)np9b^M(O~ zFpktHhB6mNyD4ts#XLQq%2e~^tR2JHY(D**U_qVIWC9KmR+suDH~6sfow8>8NUq5Q zrS}kf=j}kJfwBPhv)wt0S*SSWJZ=%j5&^9G$U(yD;eP7m`503s6$CzvxB8qB^G z39s3z(iUh93>x>1WwUNYqm!5jI8-37uV9TzieVEDrLm8AjaKk0Jdvt&Uf&*I_)B=q zc(s|PH`je8KAF~rfZ+z0_@UedRv0hJ5kEApB)^(~$lUTxzXUd?rZl&#Imn5OXsOJ8KOWVVNPM9mzOu%cIex9kM!sge=%`zoR^^hKHHbX~q7I>#d&P>`C`Sr6*`V(;A@)A#J z2B$`*agA^^V~Oi`swJ)T25BNDpDSJVNO1vD#>)H`D{dJ)`?1=}BMQ6MBDVQIzKFi3 zJU*baP8P6K*2Gkgo=V6Inbn_Xk!+)@X#V4>p;d4=bigo$U8hJ)tMRu2`Dl!QmR2Pq z0-}b0b<6OdjTor7STgP_8MLx?=e*6i@yG2B{KDR+JAy>LU8C~5tRQPciDH1sdf67% z1tzGaCH05^yoFDAE?~dTkm&AnHu}RMBilVK{pk37C*tVXX4MA41%}1}w$@*1>(K+7 z72C@C^Qd0>_~oSg0gQ`w$6jEN7s^O^W2^Rhk=YK-T~x48c#A)-aT{S_7ST=bW|}X` zGQFIM$YarsVI>~l+M))VgiW&mC4FF3JE2C*G*qU17b7vR&!fh2l%y0QM2GdAC#MNd zft{4u?NK1cX2IYHeNpni_OMDRM7^cG_mF(RbEiU#AqkEF5T&=a%VmHNA44=3k&{DJ zQOvDFKQ|18&JcgjNF08|WgU;HeI!$l!|MSw0(DWSHw=aq*+vH}!;*)%q38lUj*0#@ zG%`mKS75$}Qwcfi4E%BL?U@S#b!Bz_Ge0+^pNtWaHm2b#J{d4SrVTxA}4@TjkFqDH>^cvLdG9TQ^4i8j)~?j8{p*Uig1{ z=Y(#0<$ExjHItu^DrPX!1>t(T&_C}2`vrssL&b4H)=O-!ke&jz|~HDze_oRk7Bkla9kaoUf|oa=#@ z)}c7S5u22jzlVaqEm_aaeD*+vD~=-3Oz?QaA_oLXhq)5JycivtG9RG zOr7;)6cB{fP^iA_E8NA8v@vp*`Q zQE;5m1iA-yGiaj2zQ{wNrt6=Rv0%$a6&DgMSh^us-%ajAKeWhzQitJ5#6exR-t({^CVj`KXB7#dSL6YI8be z9Mr5r&wjFC9ZoEU7j(mM#X_%->a!BY0^$<*r;54w_x%Lj8BH3@Fwm;RHK({GO+Tzo z*1TiiuV<<$GA%OD84E~7%#oYD=+#1c2SK_O z&y(lDO*+<}a+ty8Wp$NrSnPWdp<%0I6XpIy!CwVK+Moj1#vf*|tVkFV%=m7<7erONwFp!u12!(DnwAa3kTo z@1G~z#z1}~l}r|m^I-ZjLPmRrJo!~zst~`*=W!VJ4vHk7Q+X>G+N*P#qpa90 zoYBS}VY7{F3MXb|hj_m#IhOXrbt0R~n%3l^-^&}?Ff2Es&NpuJ&|@`x+!r|%F9^f} zhK$J zd|U1@sKRQVG?dEXONwlC5iMoD)o%fxUC3}C^M+V!I7~%orJsfVPI-Nq>W-q(?`?bC zuV~g%U#bFvnRW0DD14U}OswEpqgoXQn=2ZnFn+A}$=8eW8xf)Xe2VX&bC_K~p({LW zZpgmn`9(OQKrxfz?0pj(L8Kr?0N)Ay1H-Nks=<5K4#YbyQ_PU)xhDGBlz+cCR4V(_ z4oC5YmE>l(lDVR0R4pK=ppSP%rea7{)FD$k6OPRyukN(={L3VKRu*R^sb*d7IXW~C zht)>G_^arBI-{F^ThX0eImSbFN7M2dKuHmbccOJAgKbugv)#mZGmBy87!nM>a-ZFJ z9ukI6HJXw?BT`7dJ$y$30*1DY^UatXM}4Ik8QmTdzoVJOKgXzQzWG*0o#=D~sX_+I z<_TAS=bhNaZ9p0K(e%Ee;1*nhmPv@XX9Nk@6AqJYqV1CAyfNi_fLQg3CVDg)aq-}V zsQ6E!(y6ThA+R%5UmR~-i)V_9{;O_td42+}w5LCC!Q%LR$~C}U%2B_+kO|8*!eQ!U z*?M6T6>t5keg^4AH)BldpP-3m#rsdjhyBgc0 zoPxacVm)opFxe+MebOYH79kSJ#q5sVWA|+A(EVUP37HpR5*hi&Ke7TeTCj+qdQSpI zU~h0+1(^_e5|4Mxq&d8c^>@z%#lL$_$-i;6VkyB!u$+aQkM7cSS#2a3KY9$+F_FWH zC;YSG8;CzAr=c9~I{$HvoWPN<@$) zn{egdms-q z5_np@-xw}n>X|_)RB!9YdTN%V9PXLHohJY}MvU3=EBiYn8V&Bw4R(F4A;%^Y$|m;s zAO*&FY0fw&v4*n$3W@-KfFYGl?KWVdWy{S+erPX{MX3lRo5EEquf<>Vb5`F~D$0@P ztaP)mORTBjz`*uH-Ih$##i;*pbQ-NH$NB)mZwmET+cYxo+5E8lkHGU_$nfS5;OEb# z!N*ZcWx)$FWa4Q2(5yQrTMB}Ow`P)HCYUGtb66o2pt?@TX~F7{o3tHGly%RTg|1EP zaOqN1%3+b$bz}Mm;Mq?K+(Up15!M5VwyhK~pnG`aOb^!fp#)#W+KCggWly;Wa+G$s zCa;skw^TIBKX(knsgcO|%(?r|wiacM98fp`*Dm?S<&bS{h`c>C)TX(54OVSE1jeO? zD>sfGpt*s@5VOCQj)6^nP9c&eK9X1gv@sGWzxtE4*3nByCi0+NjpVT9V12~s3+0d* zvAwYVUUgpcX-+9pOp{tna#%#hXYBF%V1wQQS}=w8 z(uG=xkOxy!mgf+%D39IChaWCtoqEvRxNdnrSyDrlpD`d!uE z8SI1^;sGLRXas_xKSMym(>GT&^i&2i)3fZ~{W0$ZP>Yn&w?yCN4`(Z1{6|L~gXnA} zFbANuP^aHq`h2=%yV8?6?C^crUDj(T1~8w*dn%s4AG@~g-?c?*ZT>uWh5-R`SYX2x z^uGbe(xDkrpZXIfA-iHq;(J-{IW0EzO$$q0TFB{O0tGj2E7?$&K;6Y3QU0W~Jn>Gk zgk@{=3&h77En79^v${Tgt|+_j>ft1x+1+7zb`w+evb3kiL#>c`&%qzK9=W4}%5;D7afP+S zF(E-sV>oviT?GqsqMPCG*_tY^V$FQ7tcnxIE{~Uhtmo`%9_Lukc^oDb(|IFgq zLb6LRm=w*&JYabvrL^engw88U-VzCNm?kOS-6~u~`2L;~SnQ;7aq$_^Wo+&A7t8DV zNvKi4q@7~LyvqyyED^>~H(doMiY1cE8OZD1?W}`c4s8;w=$mrI!%8*>T%QqW|GUKS zu{)?y!Bf$e5w{cDU+l*jH&+gRHakWe>5Y$<{j}jYgBtNdF!Am9qh;#=+IB**w!WiObPB4w3)CxU+<}rYU*~vVy z0=p3(8%@OBVMxLFk|6hX47%sXV8-JKll!#R8mS1H|#NW7Cp?biOL&x8pupYP{H4&69BWM5Q{wyodoU zd}s*yiF~dB(HgL}g*U)=kYyCs6D~9m((5*Os;?G}a7dWpj zY*VwO5i(`W$%oIMQG`=VXgaM4T$epVi2*ER z@D&!&cVy|6gQ?y_!QO%EjSd(?YAz@5ORY>ZAqnYIeY#qo>$?Q!n8glhlttlQp#O1A zFG{z~1QCdAG4Tv+LV~|%$WD&B&frEaC(Xq4()QcUsOOkXM!ECRXA^tLe;Y{pH`qB^ zgza{3_$(%|`SF;Zxd_>;MY+OOmvn>stn-7j@paFd*E4nQ&q$TWjxN$R=dyxujF|FM z;OXcVUD7`Iij-9HQ+{N#yZi05Lu`F)`dUa(lpaRQF(B%yqXC3Nw zGleCY!SvY+`h=ey9KCugsM3voIECusxeqEqJmM?Y{iQrK-w`Ai;(0?O9m-q{FXhJQ zyG%(u?PmHs@yz-vt{f)frv*S|Jvj zwcS{>nHf^B5S+*BW-Rmd#f5k}na%qi^%oBf*#kD7U)zdL$ntJ!sS_l405=J^zg+UQ zZCx>BAx`G2ifxMx>E?1YgXG6O5sb1{d&{=EN}%4pBxypo?#rO)u6yE5{rltY1tc?Q z>5Q;qNJXqiIB~){red_zr>F_(3V4bU-XOSWJ#WSNOpIsf=kVty8@j9X^%tc|OS2`kYA?Lc-no z?@rFH`F-fK>n=CclJ?7Bw@gq7H!Ohi=?s~;mx{e;o}OB;GvGbaZq%yXyCc|0DJJu~ zIs#A(0!>+#-QKx>rYRW=TE~iYyCEe?m}I~#4>g|AOh75&(WI-UoF7CwjEYUhGpL$( zUCC=Wa|4_`{$075f2{Fm+HK{3TKSaV-X-Xe^Y=d(#f+{x5|%Xwh2{xE^M<=;0eG$z zJYm`uOm)oN{W+xape(6|b3|k*{=4Wt`A9<7kG%w92P7?d>m`iiUEV8t;**g5?A|9y z^6rRz^&!~o^UERWQ&PCjWi=S7I%KbMPU^eW%DFI>Udk=HOixHOyxCL)mqiar=ejqgl(Itb@sEBZ1@;@N{g=m-UK z-~h@g2T@W}q}*7s`dezQc_Y>(NXI@Bh#YYodMIa$E+vqfecG!P%k0vr!W;YdlFU$_ zg)b$rEbc&0;bO^WX1_clJWGsvL-k*KFj;RTzom_K%HrL8sF@HC1;|qS%n1^T9{Q2l zV2LrL2XXbRJC(|hd27VPkQ(1D5y{Pne3L7h$Ygi94h+lV2~#bqO6%Obca@_5sH}E` z;E&y#wu6xj<6?P@yt1vogt-9k-Q0t?zVf=w(B8v$rE@ym-~}rEu%S(D%7z!_MX8VLBgH zAoUw#yuG3JIbEHHb#q2P-_8M=H0OaJUp^(Fk719kWJZG}dU7XcJ0c(s`vB*Z7WWf8 zv96ELrgO28ETj*gf$Ix@qP`X+L$(W|LZFKHVbzIO2-B~j@SD(eOj+D=$spP7KCGHJ zaQWzk^w2Tl?^%h;7phe+*3uUUoF3{Pe5z!SSE4e=q|0kLf1zTgW4G=T+OkrYR)IkI z<@De+J7$a$a4m3YS|K&FzW#Ojs7=#rf4^8rDX|;@exRIHrRJi_z-c;3VPE5R^!LZF zq|3^oKWZLAfcUqhixrAe!&o;xMd5;U%Iosb%gRu(o5XS{0!;_bd0{}rZ6*2XP#aww z;ZCT7?@UUp`63H-nC~~?Xx#40o({mwA!G#RMymg8b02p8X>~>%?M+Rq+-=oF3GrIt zS{X?5b;vE=B1$08=?||?=7F$gYX$PEdE}WR3No)wk09|SkWx;wC6Ia@jP$$!@<*ej zs4qwHkBwnEV3z587MUr?ONr^#qF6~YPi;t?epw` z+|FX-P^oq>TT#r!BX=z95E$6|@}1-3Ha^DJLJ-4d`8sd!Ls&QtMXrkQ3!Z_Oz@by9 z3_T>EIcckGMg6g??xl5auV;5SlmhusEX zGT3Hxxf@5RD|!b`CmcW9@wZ8OtD}O%KiQ6Dxj0vcw|aa~>{9!p@wtyZY5bZ&H&4tD zGSf+`7dEOq3Q-MNry4m7oU9nS-Hl0-d4dPKLr}hU`r-_p;Jd8~`P}LX$-fzV^PWm1yn6oK;6Fm#@f7S=Eu*fAQ=e##Ys*H&-K4*N z(-jUy0-G7G^Y0G_%wNJIX#v(oD(of>B>R`W>8-8-9kBezj>>0jj&@F4oZC?y`zI8V8 zreQdZ0$`Z$ys`mq9M-|sK;;c+sORLV!P}j19f-fB1fRm%$e}!18AubX z4_{69|9|@(sqk2goOR=mlbbB0w?(c0-1PdKCeZY3ATew^MnhV40tZa zzl4@s#yezOO1#+@6Oz@FW1<1kOHIjJd+ZbV%2yNi$o3nvEMg?=TN)sa)fCYl_^yrB zbNo_+S<$E#knRf5?Awc7{ih!q!p%FbnIB(o*!=0PMv?gHM%XYdv@2dzrP3ML4&+-; zpo6SXGT5w3fO&+nunh{MP@OK(AujNg3J%A00cjW_E|`OYqx0XO2u&c=*jq@2b4_`d z@j_PkRr~6WluObKOEX7PgXWeSquTwvs#ky~BWkG2&^)IoqFu(ajxf!$OrT69d`Fi2 zlz5(X`C!i8`sC*k5MaK6zZpqg%QW=a?PZayS_d|Hn}R93Q3JWJ)S;#mc`OMvl>&RohnjGpjCc6GsD!HP{vG7LM0 zmQ_K^(VYuLYab3dPRSZ2%9MzL+Pu;tw!9DH8wRJZ=ut%+7b?>uqFYtJ7h3@sKINi4^d>p^_inE6G(9R{Y48py;xl29!(V6>C z%erAhTR(>s%9ShKe@f3D_1EnCXbCRf1754#_6zcim(j0NXV?^8MQfV#H5yhKwEicOW?gwvcvzBdh>lk zctLTLoQLOc_YTu?tKXve?l&KX6NW6&^w`dq5x7+vyJy#tjEE7`%JY;Wj<8*xrm-yM zN0*@P7pxT;?exNT0|ARkQ?5sT+^e6z*|D@k^;1kliCUw@JDl(?y>UP~G>bEFz;81u zQymrQ99HJzq_I@DF*t$6lXCNeR%|+I^Bpz@LxqC5%|K9jVQ#)*B^7v!P;Wv2hTv^a zA}m8Nl%zTDJ12gwAt{Te9&i0AFOr%9Wn#g`#VT4HAwpKhR*^1G*!7uT6Hjq;rtvr?kGT{wc0fVjoJst_Awajo=|ukAGcrI{>r1@2wTy7 ziHTo{(4Bu>f{@&;J2OCv&b{_gl=8Ere#wsWQ!0hBw~Rr_^_|s}2i>O~;-E z<_exCzX{~&zCANaD$A{*&%>H$L~p@Z7hL$J#Tqz=`vCR2`Q+HoSev87wA)#rFg|)T zT%7bKO+kjxpIDLj30`j=$nA_Rd7>T^=)Iq%V;Ygj!u?GUHd8&bfL2O&_7GEuKP=0( zTTTP1xHHeiY8oK45HZvrvlv5IX2M{tdGPK(arT2(7fMG+rV=RpL*Mb1W7Wj9Y4vty zJ7Kfvz6?R%l~ZH25YTOH%2sQG+SRAI|M+}Qj=9vnG1j#Vkx~gR`<)lz8OviKrJlpe zygXN~@OmHc>`@w0iW+_LphT0#efV(HeCExdo;6`6y(aS0-Rk*H|AzTi7@>d|%j2$k zF-5wA#wL*Kb-QkC(`{Tll=d}J0xZDHJXqhHphoY3rq1L8WZjW7q z*LmF0KUUEf zMx#!FozZ?>LSOJo7LECXft8eF6uwT2ArlYw07nLMG4{>C*W5SW zcez7jmUKe~%)8|?lNs8+S>WtVur|JN8a(Qx{hT?E&t+)GTxteBorLAHe+8ifv1C|T z!JtXngm&A*<6}MzTTj~FmD;rBe1z?luivay$5LzNLc7f^nL!iQ2YyX2N2D1xvzhM_ z!oqe=_xD-zC-t_{NF}C-j#4hkqzSzk1Qp-;&g1Qwf1bvZf{teW;}jh}xLXmr$T1or zHiI+(8nL1?^``_}?7t*q4Vzo8e+Ks^myAPxzRekb)1DD49#L7e*rS4Nv1`l#n*Hy9Lt(sF`A4#Z&FP{09|W=_TN+%XAWLl>#I$V8w@O)SW95{^6oLVM z3T~Zr9bQ+ZhkM>-6UN!u^u?0d3Z|xD7UyMP;m6o=Pi+@znFRk9pl{c0Aaxp^nBb|B z)k9YxH`lD%fy?o1QB_t@gupv;&jpsHw4W>LvE*8tkbK!(Ffa#;sp2q3Pmj}s^l`g3 zDcx{V8MG2p^$!Ez2JhLTQIG4-TlP-3b^_MLeg6(nxxS^FTO8s;VWqW`F`)Y)7dQOw z38CQ0Lh~8gIy%Eh!X-|N)DJK$P6494p$aET-xsbH+hT87lKGYbFZaD63UDr+JFyowPa} zvhCuI4Ea}wddYa1fz(LnI20W4Qui?Qo1x{tEnnvFDdM5{RkOYw`81q z+M3_~&d+&I3)XD(FbBHf=#;adN7C3gu%@uBG?f}@7T&_4bIxhes)nK1I>w6(bXGgm zxKl`f4k74Vh{pfgpCp)4v&f;u_^iydztkKHr{j!~!|%*8WIPzt-LpjhyrLpuM|#_8PRTm&oa*V-Tb-$;(9B7!6MtFocLq6zRAxi_McA!|1(q#-!VzyrncOywq?w1e+u%0ujTsEc6tYz>ABZ zGn}fIhMRxOO^YC1T-ld{Wl1o6Awi;*JyF}#Cdm>=3rgIph+jmtNX}6K8f=F=6;cg{ zq-Gm8Xz5V|h;p)qT>qRpp2oE5e9Q=;_^W^50SiCy1t-uxyI^##%hKRW!Y6|bD5hKR zTaW<>ixu5WH`$qKCli%=shNC#6=c4L?U-j4bFliEfyr^d!5w><%24C2=0>GU9Pcrm zCH}GsA^-?ggLmRd6-Hr^`ry6-{WZYgBHdrOOp0PSzDv_b_%Qcvsns`N&iz^x^1@p9 zH4`=Ql|Jz_#HPWgai8ouZ0GLcNR2(JD{D+W8OvBCfT@l3>I|YE3gP`O;s3a%{Y>>P zXn(XNKp^px4ubjjyfKTkLRXDkKbkc)Ox?tpvHN$L1r3djp1&n>L~yhcC>5N!_${~U z=L9L+e)zTK;P-^4XX1W8f;4@k3ydf4o)GNwJGoV|^}be8jM39)IcefHw0$j%i5!>f zqXzGd%~x{W$&R7#PCR^2j4D5o<0xp5zT1k1Zuz1T;0Awl%+;{wGV(rA_X@eM-OA3& z*=#~BuK{8^kDtLO=%TbyMcB(87TU5RYAO&0t-)(X;BywmbRn=pu z)V`iiI-y|kEEWQYew)(5^^kJ!kyX)iUUA80Pq@`iXmumv<6sqD%TK|^1hFIUCcnB3shCwuwJ2qxb+*%*z0Eur-&x43ago@m3#>60_15 z=tk^gVaP>Io>8Si*#3(`7SM=`51{RMJqVyb$PY)-j&xHyU>{T8c3<>3>8Av#dUiP@ zL$^Fprsi6k3tmYJ4JzwP{TRRkBY(!WOG{#O71NAQi9c9Lur{-KeTQCt|NHW|d9Y+J zriIEU=Q{R{DACT+w<|M@l3b&0&GSCJ41!6OeCjS{1g?T zfJ6NJ7A|quc9^M_aQ8=rc=s*o@?|TYmP4!$WRT3K72wlD|JmTM~EbGYQ4dc2>gAAF9uUAqXz z5_>KbysG{s*0w`rtACKM>JcFXQ`^6}k?5P6B%gx817YRq{2TPAZ_w%fB%9cxhYbb} z8+(A6Sv7psnuptv5>Ax#$>Y1@x_z`r7*ex#H$w8(QGB+5P2{h?_O~4260h?-8=Tp$ z2>sScSALFW&QQxC(eNr{Trf1BnNo40Z5;8=deaTNPp>>^GZHnOrP5-PjR-y+*Pg}> z4xU{FL}>)QX}k}or(b}-;Tym_7fGQ@K-0qA3w^AKd*9N(e_BV_by<$rClG7GaA~ZT zg~h^w>A2dgMVYvE4tbaxwI#b9s8#LFv69;PkyagXKLG$t$q+XAfa%a?mvk6b>Fv^E zSLnHGiT|yKffH=3rd|lcnDRGy$u`YcY=RL7cuh~cGkDOVx2{|yB9)_bs*>dFI$-BJ?~NQ_QtUF-8cW2eol@H z?7{Xu9!HETj`#7%*atw$QyfG>YbHe>F(U6Iyz({*8O33#^>@v!RkBQH9o2Y`id+&4 zruXj)zORz_w_D7%$b@bqdB7meGV^2p>578C2k)*B4JT8#x#1ZLSTS?*&1oT<24HJ# zhWvlsZ4%!E9T%ezh;X%ht!GKFAFj(C`@hyI?TCn98;JkMhvq--GedznoL?jB7I`0* z)*58|4W9GoyWTBB9l&vYg4CpDuzD|j*L6-Sd!0M?h5HXV=>KTT98q_M=@PX9V;Hga zUuRu!C_&eUvkLc_q!IFd&lkXpejewQ6d@lSqSGM$xIdW}a?T?LN-fcCVm=b32OM}n zF#r1Wb-`E2vi-k%NVZb)2*ITP{=Dh~ZT|1$U@ox#q2m3|pLGB6@cEw|M<~Ee=zn(F z0T%ZE{lou`TGC>uP5GaGg0Q(B)<91FpKcQon1RT^?!4J&6ijL$Dk1S6x~9G!^OYLt zjk*4}+D#6tp&|&uC4E1YG82SRi1;a=l|YhIua8G8b3vcA(3F&vo`G&`V`XbAK^hbk z)UysF_8A)RJo^IGLjr8}EG*yxIo?=;fBlfJ-{w*AzPoGT?H_iW%fI-d|9t%~^`!dp zHW*dNrWkXVst{)}KfVMbf*?0yl8$aXOYoC6c^DC;+0x$i_SpOAS7xQklv_}B9O)VY zpgJd?7nf2jd}=wNlfE73xXid zPAzM5;ByKseq9;(@s$}J++i$#nILSIa|;^k*EPU7k(hML`S;l!q&8jDgA;`-susma zRsLLpir&z@Yd{e%RCT%*^HcRQ`(3;Z6vCfhNf^+70p=RWhp}&EiL!RQ>q8p1Rml6= z-7#ZMSLx#>iTicT%R0ZgCH~O$@CSQQwC7`W*UKMztI3d~b2)NjK|3q_js;5MozG(7 zb09(VyX!3Ur>6pm1Zj#w1kVVA4q9lTo8?`Xh5sd$xLcnO-Rn3eQ0~jE1YyNAz?=54 zQTz2qm4cIqrGg@Yr>9&Ot1B6=UbOIx*dQ4S)XyxE&lM`z-p*#x>M(V|%Et6?qVSJCmN*$nD3-S$-}uH4(ij)Tml3uEs?;cNiq85BYEa7GFL(Jvg** zD8Yz@g@h&O7tO{5d-`z?J=kn++;(lEz5O|i9V*_OHd$jxLp@zD9WMkQns}r=$J}fi z%T)mh(KQJpxFhEt-pduh^)o@gw zMIR7E`$V94`NGp+N)~JS!`IR#N49zm&dHm$*{XW+w^5EPT&*Mpk*k@ip(e_@F!H_< zYbKD|6k0H-r$7aT-g{|AeG*nJ*G*i0tu!zehXUc}!Uk2RVE_1fe{O`(Cm_g|;O~#~ zix;y{Mkq+My`2~yR)!jrwS`I+9f7|}*zqSn)7eAUD#3oR~|#rXu@96H7;NV*E3u%)mo!u+dH0B8Ul zwJI(C{x)$)O8b{>TE@g% zosMp-Z@T(j%zd{?axEFCghGS^Wp>C+g)CuV^2>sZc-UV#H~K@yF#VF@D9N2da{o}6 zS}Kx$3z@=mNJS ze5gx3i(K_nvna$wO40tzM+gh?%ikf&6uJSB0XPO-#YXX0UkFWV435(649rfx7x&(@1_XhtS{c-f7i4NIR$%0zY~T zi1|VA4XeJBV!osBT+{W+EGMHOh95TmKSHO&`{mz@1NK6mC0A!8LSEoH06TLo0pZK?q!^JYmMLCoIPD{@+2;FTq3M|FJ~YnD^u-Yi z!9y=rTrTg9i-#FaE{&EXcc6fiu`X`ffg?-!bZf7$oA7W9e31UIv0d{n9m;`2Rf7TT z*eC{|=;hM-3(Xj~)rZi~T*W0(SlaxMgUUs5s7cEM=M>`(A7ezD=4KDZ;Fh&>dyE7eYD(cSG<3a&odZnY&E z56M(HNVU2hFPq(eB(m4<;9{7{x2Xb`)Lj9B>quumdO~f$W@U+tV~;aycpUuE0d`9} zbt2NIZVD|I+ve+?NE}WAe5j>|gVLswM0bmlh0}`Bs=okX6jSH)Gi!Z>!iO`7C3nIu zRTak~;#UsuDSibA6Y7sR-*&9hb!=$uMkyJ`JNk-j_8&w9V-g87(du zYisUW<$QTK1Y<(q$kT>jn+-nrk}-rEnd9Om_44L;{J9|P?* zuZ>`q{kZ;#-yhn&KBJlVfPz$Q!!y8z0-)=S?IQ>IO}Qv-sr^)y$p^wG8_^o97L46m zoS@~JVJFG$o52rgD;Vd*p3DHJ7@IrIEXED50-?$HNzQhoOhTOmb4S}KnT#CwtIqs zbx>(7s#=Wty9Zf7Inqk>_3ikg)_tATwq*l0d3uN8YE+3U)+?7A3g#ZsS#+4fQ2?J# zC|`!zBR0cKhT89_V?EfQnX0>@h_)cUi6K~h|6yBwl{0Zt`s@}|!LbHn@iPbp3(!Se zL?})L#XB5B93uE7oU@%X`uT=<(wm5&E)k@;t! zF$_&Z8P?+VR;&$|?^c^rzh+VFl%4r%J|Y1gT6yEP8Qu=F6+>VARm1a8?r6#1bTsA1 zM-7i$W{`y{2OOqtIDO2efa@cAcSjYHv;Uq~7B>r6S8jWaFjbX-#s~@fnW-#F8idz$ zdIb(eW}n&@x=UO5W(1kw(r0{Dn1S#1qo)7;K%$+fBAE|ZMuu(L_2e3D%%KD-;`m1* z!jJQQ=AL)veygdsXZe{2-;PT6&de`}XTs%nQeS7! zxShb|Ux^6ZLXB{8+}J-xnV#vo*ng%F=o5Y%d6xPVegh4`Z+vWk_2n?Un0D?x!`q!2KlqR=gZn&#N}`Ja6Aiw)F*A1F9$QJnZOMxAKi4pJj= z6@0zyDS{u)&H&l47R2BOk8R*-o;du`gJ#Pt?kpF^S8|o4la1VQDCS(yFi|jGc#g<$ z87(W=s`)er8p6pfd%m2{7lNumxyabJndOm!*@U)Pb)c zo$d8u79#sAC{$PBN8I{SEZ~KKmmXEZU^;!}`YAye9m9_lf|oZ3+UoU*d;?!1dY{f02POSE1pf$VY;RSAkrk3{k5A9TP+nLdp6-4 z^M(JB+a^*~bJ+zMT8@qxa*^a{VE1l%a2K{fJE-1zr4)~Sen00ADiA2`(Y6oD`kjAn zBF{jRC3)oVCG~ro7F_lXXPHs!Q`VhEC&wU7SV3O~0admiY$Uvmd73po-bt>nLXrOT z^2ihHU2Hj>S`ug`rNd++azcuUlQBWfcw}xL_wj`g%OkfLDJog&vsR*yEXfJK$5&DO z8DiD)TgsB&XS^ppt=PIEv*P!OX?t~t`*T3{dGD-MjFjIaUMZAE3qhPYszUbQMC$G? zrl-eHhVjgu^_lI?#E8n~H5hEImh+ihM`T;TEJ99qEH6lL5ok2*IyFmC1GSHuoPFXr z?ynCL%T=8kVqs0@06wKy*|5POHo=kc@SSegGTqF#OeB(h)bLyob8eSvuB$&?n{v-9*cesLGYhU*iJGZmIh;F*KkEt? z6~<6{E9eE&^`5KzotNF#zG=(s%i_0@AZ-xFgA3A|7;zZ~!fj*ueJD(EVW1QlS3lG1 zKIO%cv?)nGR-;08EzsJz0>zF_%W~rsD`Jg^S?>^n`Q&d8!Q1mwC4cA{ALukWmv&$< z=i97ZQ&tYrT(!Z&QS~-Aa(m;dG8|JRvLp=3En=jX#6rW~hhMMr*zQr4Neu%up5RMN zXP$uxlUf)R2vBD#XvLC47JJm&mJOHY(|R@edSlt2^Rt|j!?&gCR9Q~1*3vEN zE*OV`v`q$A{`Lb;HBT!kN_>aEbqk2l)Dhp+jHIZu;&cOXY78@g8!6RL`P{Xd8_4}t zRQRcWJ)Viv-G9^G)bLgc9y?;@?)f+egis;d+xVUhS}Sbw6K$y8wszwBlaj=Fv(&}9 zQ`KMK<~kp){*Ww*5-|nXf4ye2`GbW(SuUG#)P(veM@N*1eud`vv7+UxKP7|skVFs` zUhN+#lZ;-Ls=h$Lu1bgCpy1-HOM=ueaCYlz2^dK05Kfyw2GE7a46B@YfW=S7emPv1 z7!i$M%GG@ze55+KaQNKZL}GCZMk{ROnWsWF&HlHvT?&4bWt>&d>93O21{?-oL&}Fd zyC z{3Ft9W8T|9T-k)SEPG-V`$5-*@JUvM75x&p=90B;4DanG(cW9nd!1w3qfeYvAlXqs z*hu&Z{V?52vE_;UgolBXpU=D} z1FPrtX1Df5KO$rdEIpT=U{{sR3P%AVr!|jh$6aZZIy?X+Z_tMz)N5y`fe zrW^}Get7Xs+>bvfe&%TbD|~~w$g%;v$;XARPNyII-$F$LJ`0GLC7Y64&>Z6+g%nz5 zG2<_Y5#5exC6?e)Uu|CS0f^YD*U4A+bhH_?H1u~t6}YR2&=0cLfXTt{K~FK#-lO@0 z`~JK9E^MVmn-4*S8g0F3Pw$}FTJOgCm{Okz)Ro)ooJnCWfkIGc7c+Ha9)L8q27&Bs z(RZxj+XXxica)i_?Rda{(sHFBFP42*&7}gMLoNI3BAAu4gDDsDcy|bArs~EGWl4^h zy(CD($oBFb9Ygs8s-A!{w1#~A5x3Pg3y{a3tw~{AsCciSSb`BpfTW@7*|IE&@YM6m zM9P?!XNg3|ERQTn!3~5I)C%-){e1Jk$X0MJlc?sFGd()EcL!OSAu&^O>2 zZ)VD}lWtnZt|9zg5{VdTS{BJ!4?nh9R3H4nci{rSj3Xfep9K3s%E?X-uQ1L$cE=Lqpy(_-Je9C*4Jot#*@eF{|-%XV zIRchPM02>`9O4;=T~7Dsf;w4FeZH4?W{h77Y3sD6aDbjb`C2~DZYRzog#Zf-w2Cti zX7fx4Jr+?SyHDy2NqcJQZWxES^p98vrW+f+Alb@-$}uvlr|8pv$Q8C;g>+nDt`07h#i zAf0*S^IKSNgn*UWXkX_%)C^+tGW(OID5;3wVqU;j?HOv2`n-7v6SZeq4%@SKsN5})gSdo;XGkAc41EKJ)33+Lz z^zGBuKo{p}=+K<-neUJQ@}ZL^;PAkz7;qZ06|rU*XmvhZY$!p5yc`=U>ee9rPnw1D zwF@Hq4kpRPymJdX{Y}S^lK?hI4=JkZa_U>Y9zx$+-!TCJoa^B|Ec8RCgDrwt!Ka?m zU)L2TKNEz5#D|JovFL`Ge#eIMj~|th`*Xf*&>$2#Z*}X#F^fGmlU#wI7xPlE=*;Bn z@=)q_-X{tl`YpeMw&oPAdRd579lYMqSG#LHs zhB2g~fYd1SI7v9018jFauizf;0|fJF8Bukpr$z7J1POPB;16=nV2@@@Xf@l}_FkNI zaUu~Ohmh;M7EQz;Go1AgpGKm7z3uLa)Jk68I=%?NK)XNRdpZJd=&NE;Qskq%`z}ZX z2TYPx9ogXmWyw}uZYza9?!s45(g}%9UJ~dJos9#lMwG>I(jeIoA7HMaW6=qhL#HYO zRfH-I*r+4W%9@Z*=&y2Xc4(9{LqwOskQogeB0ikq&^MNk(!jSYrG> zGtm7G;J)Idxr_g`w&Ro-zV~xj+igEsGmcb+Pxq=`*E20K9cAbCw`)I)PAW3L>s?j) z(d-<8Q=nX2;`S;J4n9Msbr_gLqqWA*vcwpsZm?aZTBsde(AVEH5dSkQCuU``nzdoK zlN=*m+0fHt;|X<@@1GzHRyi8IdFLh>#xa*A_Gk8t4Uo<((?!d1GYri?-G{Ofm%I^| zgz%k2MbOi_$0PHH8|82sF$ZhoCk>&_567R9rc+Ub=WU~%rDQ(;Az^cfF!&w$KGdc) zzK1%q2@)a-cMZlt)%uD^QkY+I)lcm=y1_vmV^rFS!H`=%ADbhj~Gembhx^D>8>2(#6wVsBlQSs0yN|Oi)l>| zOe+ek%47ggjo<={f7a4vkO7baLL5LB69Wyu+RdqJ#5l_)$iSzqd@Wg5WV(pIR0cZ>hTh5ovA6A zY8O!<@{RJpwez2PGAK+iX3z4BYi9*tkJ5)v4T$w@&Z|gQOlZ`ztJPKn#g#MCsc0!a z)BIa-HUT25EG|3n33a0QKxNZ4R4NoY>MA3qcuH-GI39iaG8!?o=#1lku3|tLWn3t| z)rX!aYm(Ep7X;|&k|HNL80%(O(k8NhNa=Z9{#QTt8v-DxlL)1f*EM}M2|?l25vro! zV-n@vG>;NzWXE#{*^Owh}X zXVpn;YZpB}IZ5r;Gw?J-%p{UQ1##z1uTxfqklms!BB}amzTOD@LMH}9WPAL zT8x|j!0iNNC^8YS#bHIosI(A6$0V*|=D<@u>KjI`drQnMm61^P^f~ zzCugd!rb|^+R23PSc^F6;J89l_N^qY1yb}n!eR~T)LaXNooFV!xq!@v(bPg| z2J{0nOfOfQ8UI--=oc1D>@IHkOO79lzHv=WTEnlad%mu?)U#(%K_MS_-hJ*K*?xXc z8RwQ)NC*(HQF4|Dd~}axzN}tHNPfZk5N*ie&Gw4GksKn>3@#ypPc!K0XVu_5V9nE!y~!>yZy}-u7?^re1a@J#AGy+c6`8Y@T?KfLO>u4T^A*% zHEN`QJ&e5XsXMcQ9Cc!1@ZF1P7qSvfZufZ#BVzzWlF-+rMjenh+wc^ne5?oCN2ah{ zqRm|y88CBT9>qN&!|IHS&~Zz8Zi9AW)Ld4MA-Gf_h*4o5z)=ho99gSnYB-(9aZu&s z1$oD1c+@~r^ULaLbz?wVo>f1)Y>vsuWYqN}Vtu}6KWc{7wUOtGEiRG8>5l<1LrfFB91`LuWA@>is2TO-!|9cksDHdTy^pvxtQ z?EQ&8NVcszTKLEnbQpnw-G#O($dV5c%ToQRAF;kk&ZwCLXd}ERK_zzZJ=1~j>!}3z@}^o*R^F+?$_t* zWN~=|VwNxq1ndQ+#58CYM1fULa*(P7UN=a&-VT%EhruN-(}fHTSf$pFgQ44}9C?aL zp;Av-JebjNujF>*lYXG!#j!fQqlb(1ldKu_ZoA@2Rq>hnCVG0$jVd&ZGbG^2-=+>L z3TyF!lky3t-06DFz@FI)urgY1@b`&qU_QcA&<`3W57##hwBvIe(%TxHQuIRkd44Lr zC1Z!j?e{Y;QqnaEOpqAWNY0S-*LlwWcRYt1YW>ueA`3l}*Z@`*|!~e(8SA!vmNcSto6|^U$>Xe8A zU&P{v)z||P@f4P)3Bvg!$s|2Pzgz_3g)4GQwEVESsi@Y44z0AJa3gV^^|mc5A&k;hcQR~2ef{^n=(U@Z zkoxND{lT71`4!%>5G!i|X{0IiWW%if26?~gb`OBvLHs`GUI@_>$)xwZVO@hZTtoiL zLpPU5V+NT6hlOJ1z)}-DAp!_YFB1#kTSi#qZr>dSpl8RuYIgX);(Hx|&91)WE?eo( z@!K)QAXHX94RGoSyIPIvpB6J%By#~i;qD0+V+_JG7*N#Fqmo}bPLIACILEV?lIKBM z-eE*ag}iF5TmZ|3o(uz5jMPk-jXA#xcPh)vqeovxb?muIPmAjsy_s%!o`}p6!G3u?~#31p9FUAdMDUAU(ANgsma;d;r0sjN`uw*#sSJ;2V*fc zIb?Q*8}lef=9j$J8S0ZKB4nPO+?Gqup^k>?Ihs{|l-Wg+9vBNjlXL+` zUUNS-tgJF+2Et_TV+9)9s1%Ooh&q;>_QjCu^M&MqGtn_Hh%>;~KNh5xzpliN(bjpz z7lgnOt(xq^y!CbQp&N7F=g(EENPe%oE&>-RN=JUOIOe;SY{;bdSj_3t@NsOI&s*G& z9N9Eo*jW&q2)0wWHv8tq>fzlVV|?5YP6Qb2#-?EJP=;!ay_#*TOf_Jyw_x2n?lyXU z0gPNo#$YQ%Ns~86y0gN6g!4y5BcUC(sKO~YcqqR{qZuSjMCA$o^6ods!rZQb9{$aw zNyt#y9!zd$P~)yGhsHheyY~&}8@X~=KNcoi5g2v+Y!35gseN$Qh&LJO12!ew2K?YukU6ZG;4J+SRBwY_`Bog78Fkn7x44(a;qj4r4tb!Ml{-W^y5 zbsaFcr>x+ev7ugqCSUs1;&bawl|cUD}V1)(sQJmwsA%%iSGuz6y$-~Z4?@3^`fO$n^T z-@lLA2Tn)}?@P^&MX3`=N{c5l76kAh;_wOYqwl{jyyEOwVD0WyAC8B(Ez~o5<*%o6$;#Wh8YDVpeDoW9W+qoE@9-oai6<5S zW8&=Qo$Lt^5Pi0y(yluMd_Ib(q+~%YVfVR7Bi&=UKh?Say3}2U7JyAdEw7-!zu&6k&#sFC#repux+UfINe`QA1?n3idC|^aL?e_NodClENfJ&WDMHg#1wC$wV&T{44 zJpDv4X2P<|!^!fZ;pP+DazkC)D<=wE_djx+#%LVv!S)awK+y`Rf_ z)WvzF!7bemcclEyZ=cMr7*WmnlUD?E<2Z{O4yw8yV)1JnyGvpQ4>yq~B+WeF`cSR; z^r1;q$HoXe@U}2{MH_jWWABTk~MJd=Bhwbh@XPTDVrO_jd zMq0O=7o{PuooHEXO4L{YIrwz<1LEWp+er^l0J5|*8rImsq(Qp^mB+o22SbCkR(9Er zY2rj_Cm)^8+qnPYcs%T!W$;!r)Aif}S^1<>^2qBFia?Kl5{Jgg$T|f8;i^ypXXXK| z&0Z+Nb_}1xE=N7UnfI}ij{B^L9SQnkf~g{)tCcc05pQj=3r~I7dw^)F$39$G!QNw^ z{PtSAlpIR#WeoXzZ-8mHMDWuvL0Z3d$%@Oex@7e2hVO!Ex-A+BD?pej$ueUB6Y(P@ z2-nM8i?Ifd!*N`bs;#@hL9^v72f#mZGTalR37Z#Vna~yc`H%_zpjy0G3|?M={wT*D z-tmVtp&v(CR#8dKSS7%AYJI`a&}sNa-jQ*2ePx&M&TmGte?kUp$0W3?S%!ehGn+kS z_@hRE7H{P$w(M@CDs;8{MH8o4D!X%jUS46qOO;fLxVnx3RwX*+y9<+{YG>-c#H z+^$n?K}hFx?o5)#T?*a42oJYk)VL>M3)<6b^X8g~1*T5}zyx+UE1Oo(pk&iquX>H1 zkhx(+m}>1VhFy5S$af>cuAWdgn5gvnmgJ9myqU%Q1UF~?ROiF>cvY-gs{m-$ zPm;`Ec9+q+KoBUhEq&Ad54~2U3<+I5#?S^3xoTuT8+3$7AR(T5m-SPDE{G@Ck#r^;DL$vEQp1;YJVJwt;+OCbD(m2Py3SPT zx*%OJcCb?8@BOiyNj6he8uoD6&qz>nt|Jb1#NeE{PZES^HOT`peRS0y<g>WNIt*dcIq+E&Rk4yNX{;L&IDvH}B*K^?QxWY%2pi4@-Kh$2WRh z4ySZ^-;0^-rd@+1)(p?wCO8D2Whlk#O9K~7v>z8)yp3V`8XpN=hYcuY*!0v2c1u_ z$x~a7m~$g6^DErR6^rv}da(`qnA6r9K@}0V>_o?x$=gv!f2u5`l1?EPd>rLcfB5P& zb9$|k&&m9ZFEkQNrFKP0U2lmpn(QYmG-kufA}mr*yHHQ3wO|h?1)2j!2{nd4bN7UM z9&*_XZEIWP;XEffn>Zz5YN0XB8idT9B$xaS6aBTH*XzS&&*l+E27{hVH8x{l@(+a8 z>j>WR?zc6+)dPOAyJmau6^BV}k2uj>#$lzpZI%0F+!%Fd=y2z;yL0$=SwTb77x_Ad zy~-5RBcFZ&Vc~*ZQrcmK*rxAcXi!tNTlqZsQsc9qHs9w1a;;GAcB;8wu4`;I&=Dk+ zG|XobjAcp6IB)=T4%o(S#)!gir5eCF*x0IwlCpXCKSz}Oii*+h^ynKoQ5|fbI^GT8 zcl#=8u@9N%w+C_7|o8lKc9?(E#(kA7#8o;a;+Vc}fnYgxGiv}u|o zXT%GhhP3M_Uua5iK4q7d`Pl7!z%l&V@&q7*x2o5FoLbkV<-HwlY0$(FgpZe(Fo(A4 z=Rfc?qq}akcg&aCXLFQxL>)$4lwr^)t6Cd&nU=3hD*3u+b!ptB-xS5xu`u?EmA`q8 ziqurkgKkClb^5a}MRkUhzww3g6Y6o<_l<4%FTU?%E1RcGy|v-rTSeg$6w|C7g$$i` zHcXMsKG;s>YMU-5`DZraFIZAOy57jePUz2BNljiIPx^Fbsaz0rad%I*iYQ@x&qT2-r-q zluJ;bSb0Y?Yst-vV%D(-Lq^%GwVQvVCx46i?x+Vu&##;}Vn>y@*d@8A5Me`l@A zj64}9PE%Tv9aY5)`X8*n$N;W4G6jE`X=KuVTGN?wj^Uti|N%vE?(k#Q!_W6LI7gVA29b!d; z&mBSvEZdGLPQ%?K3qw!jh$spdAa z)(k+1kGjSmEGSN3>RJS$do2#M*+osldLiYdHh_e zSmIV{f;*;jr|2CQ`J@2GsI~w$i`cCFueF^=5g@3|`u2$R2Kx-7R;UQtw{*{twb^(F zi2BdJxzc~Dw{}7n%%%auBm8D>UiB%3zdyFXJ_zuklMBYJV(& zt<;|;9_2z9G-$CYg>%qdR=84kR0ZmVR}<@|_0leyFF9&9Jy+-8B725htm;(!Xb{G- zY5>$~{Q7ewaTn?`5b}EQWE~i%2{&~-I%jD`r{pp58gX2<&Hf$-**9%uxlW(cQ-fHl<6) zCRXN51Au~&8{%t|1`8oM{Tq5qy!{+Vl6)y+<>&ZYpnI*dQ+Cxa@QQSL=BR3~Id59N zg$a%m-_sUyt#fdAqjr3~;jk4;@$a03dHgY4z^%xi~@nW@+>37`QFB9UoP4+Pt3G*5n zA)cA;Hp5=K?mEzth3wK{<9W6dI74Ppy*hvFRPi6)g+8F_Y}0eK6;SC`8S)(aqtUR| zjFlcH;!6|oS*-wexc9w>jE&7;npP8SKU{1}bpDd=4WV*^3AyJKL~E})Dm2=zWg8=@ zk}lg-I}iBgJXr&VUaOT&eC5}y-6hsWGl>(*&+R^SwVfNL^6X~qtk#1BbA9#MIPBWU(^L$^bZV&C{k`SIQZzYCKofsJ{i&mxFmG@i^;ZmMW$7 z!ck#IV*Y_RPDwTE&>lc&r-GJ_~*8H$?iz%?kPgN5wTPpv-uR3`ohT|R&l|(YK2T2Q2sEwei~h~I z86Z0iK9kE$b98U|B-dhcgwGpf&g_ns_C5wjep~`Y;-%#@1JOT`MKeuaH&(!`tW=0( zm@vD|+4(9@QoR7>K@s5x>UfZhpq&>u#h<(r!nH5KNUGQK>(e=Q)RAIR`FlNgf|J1R z()evJ(L-Gwwn3Bc#n;JLJ!&hk~InHjm%0ce;|-Kb?s5$rSqV-ChPk zlCBT82so^1VlvHAAP4V>e{|w$x=X!Ofi@cTVA4ku^lE*LMww3GoI$fo0@_Z2Y#dk8 zyWEeN)qK_VDxRc~r=!FztP^FNcTJBzocA5#;&6WcA+sZ{hQ|8__h+<{NCV(f#2LqN z)v8a+3t=*~^I?fmK#SOCL#ecj0$oa$(uER)Ts?nUr|zfWA;!+vnbZjfFPusNR!RmT z22xrU&&%*QPa*{g8qVrpE^f@Ko!_(%w)-JfDw`vzlX)*tkg%e$&#ceHfG4o?J4P3_sf5^;3UDVJRX z&Fus4zzw?o`(z`S!;dzx4$x-Z+>@p5P0n*R`aSaZp4vqaGZ)s%0FfRwSe*&0lxN_xJp+glb1<}FRcJj|PYr`2BsiJ1-Z8ePPn zB-Ad|zNJZVs|5{y2JztIw_JgFA-%rYf#I7occc}%hKe6;5=bP$Bgl{Cg}gni;FPg@P>fi*8U-noid9O;k zz%(t{Lf@~2RyyGQZW1S1p>k-QaP!Xl$v3}< zhYoZ8v7j<`MlY+m?F`hK0P#SH8s49(Ib}ZN zw0VL*Bk`9b*7(-PY0SLTatAl&hBb814beTFDdP+Nr4zhq^hz)GIgpR3ct5q9(Z&Z?M&yppBOR8%b0NCH6;Hkm@VSqZ9 z6Ce^o!RmWW> zt2y$du}<)bA4S@y)$fQXs{MkIrBeMr0-<@Wl5D+dF)?%!n$TWXAZ;OZIZ(%29lW1c zz%vl8IQcNi%L~EEsKT8PXO2ZR7NdczVC0rGrec6GH(>pXgp0L%|6M+rz6g>#eYa4I z0N$dH#ZR~1*_(C%>rC#CN#DG(FO{9{{GA)dSGIQT!)G%d)bWc8PY_r&%2`3F=J{G2 zYu)i7VnG;?ZKD4&@FnC9>kKm)20iX}LZ2LdnCE zb*AQ0;>bC@8pFGUmnWquE#6o_iGkFNrzs}e%7bfxq$Off-Lzd@-J3+dB1m2;gOZ@*4@$6cEq}?%o1;OwYkE#sAMZ1vpH7Iz{j0FAce+HBtPu% zh}7+Q=;ox1r20vATd;Ac$hU|kalogPuEkq5;T+&~DU}oHq_e#rI;*t4gG%vM|BIkd z@*h+}YSz3UZlg!jdm-h63L5Le*`Aw#V7Jo(jB*M-@p_5~GsdYtE%3Cuke{!hKSA5D zWs5X;tfJ@$q);!vL@;{e^2R5kT=O9!yOsjT93{v}_@WTW9qoO{EOk01fAs%rdx?yaW%;EDTHk?IKTs!CqaFerTjptMg+0?b1$ zgIV*PkGd)_@P&v-UjNH8QBc~}wSF|zb&%d6k4QL`8muJm-qI5sv9m z{41g`jOv&2>LztgjJBZ0-ZCp_Y%ieI9e92ypHs(qaa(_wsrLhTntdgQr13C*G`8yL zRbwHK1gR$dZZNf(bkhDud znEJ=0wJh8z4g7drwvL{42dEUfOVmqUG}8Bj zmVHX@$*TnyaZpeExRUqZ(6#s5yN)c;2Sxxo1ySF4hpAFQX_4B#$6jo()?a&>rEE=) zP@3v|D};pk=<@3M#LuEL#+T53PJyyN0kZFzi0!uxvTnh86@@gG#6WGS1w0rP(Zx&D zp_(Af-Wi&R&7xg%^4Hee8`JiF#gipzmOjChW?7Js=-(mYxsC&-^v8$|vA|CC9KP1i zpdT|gWudc-9r_C?Hm;sJ8A>5gGvKIOLCz7KFCM-du}$}0o+fOMP%cf^21ns|LcShY#rNnaz>tR zRk9l4j;v{Q*M?ug6L^Eytv~wL5?PHm#Oul0wcw(`6{veF0;tb zqlga?ig*21Rl=w44c?@FUddTZu8{-r%cPm-nlu@N(CvIgVML{2NjobPgKohYsUbp-y4|kb1FE}#4;@+r@H@m)YZSm^s3lAO%b;+#6L!_#H=khwi>K8| zfO}|q4f1Lfb+j2M@)+gKsM357qEElAKZ}>vXaAfjNv<)y2$5F)kRNU&14f1Ia6d^g z5!+>!{oe}Dd9Pwaq$0skY-cXg@r%FA0@e_thFzZ|A4^JP)(0CdAsshM+nb;7Wco7_(%f^@k;z(?(Y4^lP|%AL{D0djh~Tt=8d7@f1{# z(Crz)>Uw}x88z*-%Bp?k+K=;b6M6%KKvU|&dQ(p z`s$vK-#d*)imIfl>Y!R5kBD5St!%9+9M?Da^g>Bh@h{>LFDNVt-HJVu2sXpyXdkU_ z8wHYwoyOA;?shl6`(A=rKWv+`um_DY*Cud_7pkvJbgflIm)#K##oO8vyvAs){;B>G zAkN6R#gUGqN-;mOeL>DBFX>1uk8O-$h6Ogqhf1kVa$&_m1|Vt%nQ-s@&V!b%NqXVYq{ge& zjmz!~%u)s^dF0hy_ZtXAvf7fmMV5Ser2@&Hsy|sgFKY79IxRHaWv2I##YM|st5qyz zxv@F4-xx9_rs46%f5Hi5p%T57qzVW}7v{Ect!R5xA9Qr_yDkxR$J}T>8ktv2!&kUr zXAt#Rg$n%1t3~D@aC1RY<5j!F*$y0_T*KJ(1P{-BtQ@WaCifR@<`|$tXT-U2+^aSX z;~e&QPJQ!=5gvFPE=SKu?+w$lzL4Z_pa5}s@4Kmd>H1{x(so)jCP!VCEfqb=Ljm8V z(25|6)wU_6W2`UuF@MrdcKPcc-IyLz@2R!BGxkXhg4^|B1B8$K39VN2$Ep={t$^)H1 zO!0}+JQwPobm}i_MkyVWHspTx_J-)P5uk{>4e>IEo7He|eQ%d})juyDy-B?vMijx=5QJ1}#L&P8q1feVMSA&qtvn*Ni2!aZ-T8rmGSHCEH8i<`P{yV@`6!=YBle$7<|?O@@e zkL@Ka!efsd`A&BAyN?xj(VtEF&}WffuzOXuz$}SU?Y+LcjK5e{@c(fp1bh`5`E$OQ z>4(X_^SN;PFI1^`t#~XD*PYpa?vY&u`MfbraBuLbozk*SJ5{Szp`x!*@b>UiQKBU6OoqZNBWV zgY?BG@7F^O4X4e_WMVAu;=y9SX_(Jr)J%T1EaOdlHjkdYzs_Z9+Mv; zk2!y2zkTc2Dj^b-7g~Q_vTNDL@vxAVkwELqXy-sa<}hzMK+WGS>5ziM6SWxErU0hn zQ_bELr|@%3ofqaYc?Na7VY+-KhTpz@b#hL=j^bk!KOCA3tf`}U6<#IJXJ3_i`}$Uz zP&6i=O(mF@vdj0LMnL=|Nc(dyS%>K(>?|Y2sNuRXMo!Na=I0td{7%k){+n1t*8yq| z_$>B|ev2rEvGwL-obwvm3TaJiYkJlc)hR34?bf89TGUFZu>=G)icBKpssXFQc0fb8ech9MM6n8uE`v;~I zhvn%P|Jdd@^!S6Wh=dA8wp2iTV;+t~2ymnx+;n6i|2`T%&2?)Eo$M zx18m<>Io4dtJ{1+fa9^u7$(Qa*v5y*&LdQwH+7h3-}MO_Jc!f`jgKGDCNVt*(cr}q zF8=)zkn~d22)|ho!&1W%GrqRr%#2x#<})%v;}j7FZeW*ZS;Gxp3o}XgwfE8%NV-)_ zBd;(Zmvi8Llaz`(>-%0;=2oSP2%%LVsq_WQfaw`0Fy_-3zsE)jN?slx8rS8-(!u6> zbxr0AJu?z7$Lme-hj%fOZco~f;wX&X z(`r;6qU)D0LiInzgjGh|PHug0l6QzdC456;+xmV!7Gq-7+=kj?J9IbgM*K)HafkH@ zU{HixV}D7LyK0AExBn#5p5>Qn5p~zdanzY3(rp`I*u)MBC_AAXwMhT+86}O_=5jI! zv>3!K=8Zs>$W2tHRg3vd=^Ab{rz)Xu{#!&izmMKA(Nbt}QF5VC!VVW|o(osa(EdA}$_eblTB&EtzT``#w~WMB`M1BMMYkP|urlU3*%&;3bg6f{ z&9I^CXA70oZ`_}RLt?gP|5+Ya2ghIXFK~Er;;$KefDn#-)IdEvgh(c+&R3P#)B%X! z=_d>vC)c`v&=}}&ELj^Oe2f}Vqr2gb9+)uz4P;Dh%iTc(CW2hST=TxWo;e4+P@*pG zDtB^SAhJj*PFc;!68RP?-H>T!38-ui_20fuxDHEFSU4ozED8^jG&nLOVU`l0uuDUx zYSyJe4J&e>+emt)UbrD~_BtJq$SCNHW)9kkr9J4`iXq9{7D4<<67nb}O1oer%64_c zxz&Bw>fa^yc>jjvN8EZe+#$|3^|DO=(x;Qiqq9cn%b{CA*mWH#3$e}iM`7UrOHD8f z;*)h%n@g~cU8+uhIwi@_blk_h3nN4EpGHiNV`hR@9|H%V@GkUPmTSK}u6NY3}m7Jy7oKz0P*^ zQz556UWshr@J7*DjAL~x7n7UksvW8OVOXYaFF6P^7a|+Vwm|!*AMb5}Afldrh}4Vi zoDliv@S^cb4Ri9>zVH7Scuh>*bz;Vi3r8aU*dDLcBG}9tePUAAZNaA4_<~t!U~%A& z^M&02VebI3nV z9tG%$FTuJ>k9g_DyFxamSF;iLy)Y{UwV65ftENQ^-8#B2h}jw|&?;9>4Q_K=F=GT4 z^L{^pGBET{hk@o7Cx zc4XJL)+?QrIjrM1Us+p?kB}QVMQ{kX{IjKEdc%I)Y3Ap80h&X^f zsCbR?X?gqx6D6InNHCefS4bi5Vdkg;dfEUA{4-eR92HjSKg~*k&^Mj*cc+fhJO|&? zP=HGC36Kh7RtVDmfL!(XBR;$M||+V%nEQf-sjOu_{tYcO$u zZvmJeJ4yxFc~UI-)e<=y9<)`*dhKf$TZn~=g{4#nA6dM)r7AnpUiNT)eqoqDPz%6w zbOwNQ;^5NKdT~W6qOn1STSi6}2QL+@7NECx=yPV{@)Jn!VfttrAc+Pc48O0729c}$ zzg>}V@(sx0&Eb^ZB?#TV%f0n>-wDRO`N|U13_ZQdT1SeKMj$;ppM z$;FZ}v$J-#RCR>#p?Li7&iW=&{J;9`n~21JKjr`NK(I;r-)_VD&rtu5iS}Q;_@8@^ zG5^Pe{XcyGyYub8`sqLS@_+*X?y~X- zyZir&@c+l&)f2Y#T;M;tL7qAr=H2p&Q|=A^fD`+k>Nn^?A>{}svl{^GNBMsSTa4!+ z4=1-v`WM1C9%5V=emTa2fGwsdDyjkBo*!96RD(|o&J3yGUHX5GTySVNh4IfyU&=sZ z>2n~hrxOZ>`^F#tou+fG$qwVHJ$rE2_Lxt~mVWW*xqtZI)KSjqpV}CuxNi~>$loge zSKNc#V+YC;yM^3(i(-n;v6WPiab8ycYqaisj|Vgct9bO~pQ#7>Xul?X==ty`9t9aO(E$KN+)fKD226YOuN?t5PuT5FWn0qo=| zZu@(@@puh8!rM_eE10TNhXcFHs8h-uGQbyBVM&>RL#kwk=Ik#YSM9K zeQbzN86WFRSdd=fk>j+lJ_s{o3$IX&cF$sFf|Arb0h@MX<98SsBHkhvITUc~68rV% z=(w(|g(r#@)8m{*KK=1KyjCsS-PvPpr``+Co2pe+Mh-}EXw&tIN6{OCka2*6mDD*= zh}C~>sSy^V?X!3mqlbD`)T828_2ZyF%j@lQ7|P z3i9uS%@o!D=2WW})3B%I-b8i#?V~OGswaPe0)$Snxe7Twdez$)joX6K%kxRebZVBJ zQ!C`<%enHA!5zA@KxY5vy|EzaU|l3@(Qp5h=8(XwI#BTR4L(g0ybOca5;9}zjJJ%L zo{4v^oXR6dX!)k0rUU#>IMK?h%D>AV`2NC5dyM{(OE|A-%)zhYmVQHRgl|n-OSRf+ zLh{Z!Tw)Jx(TY&IHff5nDYuD44N;0l;I;Xjx~j1VwS>`_8T0$XIwp0zbefZ}q-OR= zb5s}2MeMx(kMXdJ%Tl#_jr&%?Y)moB0hZE!>G<`$wfO@p!Uj>I7CfE^T)FgBUZU!$ zm3P!6E$3w}LY>;O1rtFb-Ifn4RSZp)bVapCkdm8b>T0|Fk}`f&fC;B$0zgxkz?c&` z)560lZ=OF3KW1(gjb#txBUoGk@y|kHL7sXM2g|*b7{%ydkTY zHi|Dd_G0H!FlpAZPd&!bpV;(=f|)$k*!YTQ12o2EqiNo{O30qZUEK&i0?K2#4AJlI z!JGrJYjvlN-?WWf;M*UDKL2?j&G7@+*JBF93=y$3xO3KQMb-}7R|mFrtR&{b4;%dr zY5Io&o)*q)BfM;}%*JGiK3a7Ie^SRsc{9+@uW)M18sDK=yHn)bnn`e2%Ouw7{;9{w zXW-^VA{~2N|9RM~ra|l5rf|udy{?xKh*pBy8ubu;gDi4(JY_Y^gy zf@6R4)kP$$bTdzE>+L}|XVq(d*UP1PC7Q=i`yjMU*sBomdCt*Qw`1+^;S94={z1|> zs$Fvx6!fBXuj^vuU zH{}swpG0_w>OtnSJA?6&?-2^1fLY&?yNc86bPz&Vy+I42lx7wCcc@YOcnV;44o4tP z=7p#11FUf^d2Qm%#^ylQw7Z|4cFyPkTJQx{+a1i~(&a~Eqabil0rsC@g9AEz{03&J z7pPX_@-p}>G-o8ALfx6k_QmUj1`wT@{}-{ivm`uM&YF6T83nAytagRqO=;UX4fS5{ zkx?j#C?4=Ip^Gdn*OviG{qt()l=6+(AgiFR_`x|2q!S5nm-rgPnA-cP){~M5a2zqe zFfiS-KQ#CaRo~3xTxHNAcfq4*nfMigbamru5Y^^kQBGJevE|n23??kdJ-}TEgv--r z;EAc~@TwjGh%sLJ{#XC*9VL?KOu$5xce0%Zh@Dm?N^6?p#GBDVSrXvdqC_Y5Y3870 z(z*n(@LUwTW}%bnK;W9qs1eB{D3kD_6C@cI4gLbxsXhZ^YvGDr<)2%MHtFh0c_Hxh zma`*3QGJz(SxOD;GoEtkD}5u5Q&?(D!W_MxjadZ@@3l`mw1A?Y>NnTO-voc?f(i}= zP`FD9TpYFz1F3(M7t1l7jrLuw%rBkT7{Deunaswz-r8(e^Lx=$wp|x2mS6-cQp2RY z^Jw@-_5EoD?~#MJ!}Dk`x`~>Y)WHl1{A}--chTQeu|s<%5gyRM;yMqeW}lWyf26}~ z1q~VvYkTCvs#{A=Jlkf zgLZc-=oG_i{s1mjmA*}p4!n%tEU}Dp2$puIY)OXlFDp6pVit~ApWl?0$XA*lZlqIc z&Tdi-E}2y-q9$qRtSzWSDS>X46~~eu?h2&P=nzDwv@;m5c&y%&3ixj#5o{{*Pidv3 zY2e{$6d=y92%PPg1Xns7W-8$HX}k&){u&c+$EV0>g2o7cGPdds4wOyzk`vG39Z=nI zTRAa7yH=IbVT1L(O>g>&eY27Prqi=f*5;+uZr=}{{!A!Kx;@NykO8+Bl|*!w=AhAW zYR2umZKtzA>$v)>ezA}h{a62b1Eu)=2*#kNaH-ARn1Xjz=q;>-cqM*mQa_w?XGYD{ zAN9mx7<^AbPlavu5BoExt*P#Tgg#V9#Cn%WWrS1FFXo2>v7+13O!#ueiuYIfWIKI6 z#*l=O-=QZjx2T~euc8IMsTa|d=AwaQ)s)UYFSM_$ToT}Wnxq(y=BZFyot)aPLch`N@Otl zCcR!fKr<(Uim1fO(gRDcV2OCLDnuQ?g8D&qNmkv zUKJ;s_-xFv@+EO?zz)jA^G(X)%@_`Yh0jb6FMi8v_KSE9SmW8<4w*3pl{YD3! z4qF4lDpU1hU0Jc!Y2BnZy+_(qusbmvDIB`z>AE$xKYqXJBH}muP|wBUYB&o^D|$gv zBk+7?2HLxGw9kH~;`JTIeZ>_V5j~k}0_69b!wVi*N6{#nYW5Wq81V2pU8p5@y zUeBNBb@0f!t5qkgw_etqM{AFlr{C9N4(bk@=pOZ6-FHu^06zuqq%q=hYpwW^zboiN z)tDjQeA=T0bt{j{FIVtI-I|SntMDr36nB3ei6r@6*)lgnVXf9CF`M7(;WUbZYl1^~ zhhHaprzIG{cTu#D=^wU=9xBA*OWE;+PI!;SP%)o_dW*#h@ltO4JB7D!vEDgVOO!X8 zUu?$R9iPmJu;zJU_WVLB?Bh-zEy|;zc>!4YY=)XTUR4z{Jm@THG1ehz%7rY^Iu1~x zGBRa}P|+3V4yxcv(1_|wZN%Bx5N^Z#IR@2-Vn&)7}oD2!@hwLI=t1nOY zzl-LtRo7u3UYqw^DodK~+)g>=56 z>Uf~pXne0N?z*_5vI-|J-T%!0j6FwrI}!&zQ&JPR&i(QR)JC;VOOqOINlzlzekLz)+#jAO$KlB-sQ0B9L5PuD?wx z%mMr%{uEi&&2tB*9ty)2xma;F61uv*mSWzTSt{=DLti3gc2d0a9>Ywl=8Cm`MHEgg z0^4s*dE9e8VnJ6b;Ay?$7#gc|V->60<^&gM?T>EyR?gC5hC3MQm`^2Fdwf@Z8pISn z{mm~)tr{xS|L}vUZX!QMDib~e)6YS%I@g6^@y9U2S#bc@)*aJFn<#UO_uE#GxzWbM zXSYw6A1ye)aWVSJkwchJU+=P;yw)p1kyY_{aG`HEj=JBkA4D{UqZ0^pRYGX)PI^C; zuWpQoELTIYb>u33`?Dz}$wm#d ztzt!<*29U+9c?>a&GXV^-fU8SsnW9CagjJKA`N9Gou>nWi1P%B@?Egs8f@fk%oIXO z5FbWw7$w*1&tZ`2@vIecC@(fD%doSD!qV?M%K{>?cEw!ZoUnH;4#=tF^%SqaEY*%0 zpj`;C9rX)|BY)?z=z(pCfg0!R5o$`E(y11UdHVq=(dR?wz!&AnP-a_^|KOylxvGmh zLZb?F9pdpNdLmsPHVLd`ioLH3S$$!N9O|ibb099#evhjuD=n%!=3XDh=I6&9iJob= zn_xYNtm$_ku47H^5z3>n(za`mnyJFf#YYFD1u_oA>3zG~sp)|V<*T=E#{mPh84D6= zBkw&65oQX+N&fte{CRVXWafXgb~df$>F{aRx?f|qyvJTUu8y|;No1}dZ$`)!s4lAh zRXzF87WeUIqKxc7?NVd60`Ring8KZ_sk>TPymc4-aOAY=#@9H{z4(y%YB`c;MNF*0G-s$&jTbtvV?P&h zaGFRsJVS-Wk8?Byy?HRcD*`5B@gS>K2?p_sFQLmQhb zE*i?Skz2Avsn7%lgq%4UE0`m&@-93}dHYg0|6p%LVfv*ul>u79{l^OW9*n1JJf(x9 z-Pkq%x6_guVw9$%eH!k){WP|{a@z3zN~FlI`%{bP{mkv?t?IYWu|7R_6Vwp$voAb! z>rnzr5fsyK%E3DC(~KAWi+Xl+0Q2=hkKU)hYen}|gOVZ{;(+(MeR}^9$yn|y;F=j08)J1^W1!ctoTnACa`lMY%q`#uuF{cLyC4j*J{RpW$FOGM~E?K*n z_+G~hnKh~RyHD$aH`ew+-I3~2ar3ws@SPGjzaSoAsQ;dn{(J&h5I{(JYuH=TNM|cp(g`s-Ebc~Unz8vh{TbTuW z&grwk=}f{J^rMR)wzaJhh64Ez8a>K|S}EZXf?MPC44{2gB4g%-Z4n2!&9I}lDg4Is z14wjH_y(nW&=keN6M?>>-FdRfgT|1c2pVe>f{QpP2s21SbBY+X(t~jm0qqM4Q=1)H z#~w8{04)E#>_QktKPmRu&A@wI#vr72_MpR&N|z5#B_#mtFa(8V)pV0GIrK$A1sm&u zOGK0!{TNSw7dUCl{dm4h#^G5k#ebZGS(G39|gq({+%aCge;Jj{natg-+vgSPvtkzybg=7G>#Xxc%-3G;=4Ti-Ok!aJZ5q{Vr}& z)so1fg!Hx;18}2shUVk($Ih^s6=o4VEg?bIlJX{1#ulOeSsK3|a3`-)02&i;8?r;C zGEYKNx{}YP^8(}xvKT<`+I>mCP;DJHvd2bo_O^~wk!qHo z?P@N!p2CjQkqn)HTDBi7Ay5ssV*;<)uGa%~Lg?8MpVE7TM zyHw!G&{FG&55ca(*yod3mmqOir=5eJW8CaJ|AtJBepVP^_oB4@P`_u(5LWej1;HJU z?Zm#_0KYF|jfWOEC(nTFt}N6yC^37|_nW=4P;$p765~Bi>W#tp*?UuHw0Vg==2K=| zzE4}exFD=)H(;mis0ua${rFij5%2P#c;0%)q1`**)8fp*@XA=tO&C2|8&&E;0%Vc~^|@Pn(cEBW>Pv%q zU@*x&wfS`T|GgICnDK4_!_U2J!PzPjcg-Wkto_lZR8T_p1GW%1wd%5P4<}7|^Kuh= z)khhaCcK8K?ACOLx`^Sxa&sY#R-p_0>Sl~Q`Mja@&6IpNTf5nq&c12zaz}gDYEV}w z7625V+ssjMU$jygPE=AJ#Q*dJ#A%sWX%-ILQ`4$ z19{2u?vxdg$!!J`YE6Kz0_F_0qBDT&900^L^RcboxfYP}3{hi3jnW*mVm<8TsUoYf zOQQIQ@2^zOu;sga5-%d<933{KFW4OMav4n;np#wKUut-MQ$*mq413FAg=}SsqVfFY zQrc9XTy@&oLONSB^{-IUDR%9hbX+wwW>GO>g2Zt!fV5-W``)fEPkut<|oM zJr-=64&R{Thc6d`zZdfTeqDARfq{-!U7NXNvQ-CR3i9T7EB!RhTZ-{{coSQIR3uV$ zxk!xiH_X{NeYH>f)h6pr&vnms$~%g@YYD9X<#5nYot&yi}lasHmu zuS&)3;?mef6!xv}bku6+sAZWJCD7#B&$9R9v9yVXq~>`L<6s-X^E4|tKP>Bk+Aq)a zZPI9^jNHsaG?1^1TNKQ<8UZx3luSVJ<>zzb zEkQP(%MnBue?>oiU&?P|oX=;vs4*B6c5Av=h3GnTCx zk=(~0b>YuaI|mRPHB2?{XP!rc4_cm{PeUAt+tSmSVqJ4r^wxd#(-XHZ6wL_@zGwH| zj36b&!b?dbZp-BjBM!Qu+C>EA+w;yZ;iQQYD0fGvJ<$pT^L!wF+otnjwDD z=6&MLLJ{1*dltNHtm*jI@*`-){Wb)wE**3@>iCsn08d*_8Z;w4F;0t#D(rTKkzY^G ziNX^LQ2A*^CZ*YW>slDbME-{At7~)qJIE5an{0!?ZytQHC^3;{?PE^#hrYYQhgt;V z65u?#?JkWL^t!cfEVI?2wHF~ri2_WI0{{^jl6kiFM1+S@UW3sg?maG>Xst`ve9^o6w%X>7hZ_b*qxcYev%dR6+Sf>UJN!b|2c@P4IKTEl>AN47G=TTs`Zd}j`7-24 zg1LIdA*elhzIX@LMCCEpvvRd4tpY*zW<>rEzcJ-*SkiiBz<$1D=~6z-`tXrA0q%(M zjU!h#Lc>>g!ss5_Krbq#H&`SK3gaL1gI|CWa|mEDSTsdkbOxdZom?0%A`~@M#-C`1 zd_*54&oLkU*~9&06YbGKWBTqHbC2ec{)c}L;q0mXsxYa2&l5a0UAo5ZOX)C%Wxfk; zw_jRqX#GSBvr)YL+AHhzY`4*dl=wHRm6D&W6y$?Ciw7R~vER~~H`q~R_GH)Ic$5kN z{$qSQ6+9A!YpAaoK$z^tb<$%Ykjc^TYd)rN{@-|jEY-m*HD#iafxC(6FI6z#`84qu z3z38kfqkQj>z6HyXBQS<4$n0o<- zvI-FW1StU7sE3;9aXV?QvoCMLETkd*JcrHkfIQH?wqu4Fz8nD}WLgJ@%31=^x9Y~Z zJZki0(*fuR?#}VkW6#P`<>s`if8l>vAY-(%^f`p=H)JE;e@@soxfQ|=IRqUkAvLc! zt9d|Q2}m3{o3$tXl}ZYqmsvpEm^N2BFLjz!DGD_dqt`A8MRR4Y<;&aPodciab20$O z_5uw_C|0F1U1fIreeSQAF`%6qfFOe|EYnO)D9GpC`b!^injW9bXqrI(jwM}8H4v5T z`Cr?fr|^WL8mQZYqj#1`i~Q*D68*ZDrB6o?|Tdl&W6d~7FnI$Zzk?;Q8p z@1)egqUwvGE$sf~CKauMu+=wm(a4UeCtZXtCyrn9G6>@HDu?cepbG62Q#)W(9HT&mNAjj=kO)^>C7U+B4 zJSF&6W6tLA!`S;S^k+i^y*hIe~A;(<@Wq{FQt4xKGrM&+JCAJ=c3xy zf|bGLFn#-?6QDy&t)!!l4s*6#@k{42qjDKL#n!owQ2mYl$_J zdcr<$UKmY+rE$xOKTT(pOyH#y-QZ=wn^@v~y5 zE_-o(hY3|R1~=pEzNuAknLX`DCfhFQ9Y@~2qwZ|6C@7x+e{J{?J*2jvcLTa z?cxBDuVKq@kk8kFevd>yP#)1@pH@T1>Xb}Y<#j)xF!n)SpYH;oEBSSgTSw?-3|hu? z_!-W0av`Ybh9tl>H5{+WN2lQq+xr)qusDbd={S=5cI}6_{=6ooZy#hkt8J}o!=K~F zHkTnag8xA*&;A}AX0xxrqv!72{`}lML5xcTlx4KjUIz1eEdmJWU*_5YSgk6*dyyf9 zQ~cV$Tx7Kgrl$eyP6jx;bPlPq|2HQ6;GYLSYNNNr@HB0)m*A=M? zyY>;bfcNKnIH`F>K(+Vni&DX2J3x5czWpSBDuPo-IO~L=gkEBrs5$p_@USu#AoB^2 zGSOF zG&D_;s`>e2E`i#m?`d52>kCWZw;XRP&&F`i3G!)CNFt?=Rm-6-_vZ|^QT@%Cg0i4} z@g4cVEsH(wbii(rj3q%sVx(Y#vpdd2jy$EN>m?csS~uSljnupX_MIl0|5;^_wT?vu zCbK|NThqY?4T&r$aY(Pv9$szD(G`6dnI*{9K!6sIT6YXvHoQq?mkdB|Lbf0`97iBl zDwI^lkm7Fe_jR7-7vr<+5c_i@!I1v`%iG<$T5=+g-kpV|-*I%p9QaKj7;6_VA_1^Q z;R8xP$H|}*H7^*c3@9LViDpHL<9li3{L;DCVMy)dXC1}(e#BL{@svP7_}y-1m45q1 zopw6d-}^3VdwkRFN!7^pu6^YH>h7$c+S;Nvd@r=Plw!dl6bUZHDIOe(1b25WUMQuw z7MD^8P}~U)K?;Q;!KFAwf)=+M^vnJ9fB4QXXU@#ov*+wNYxb;nz0Y2fCU-uZ(4SDY zx-Fi|)|mpgD_uW|fShA#s}~1U+}{DWNm5pF=lCP1<9(~To#O0?eUswz-d}j_v7YYO zT=(LeuKQw~^Eq%%UK!$d@q=_S!=%kJr$gO|Vz=furiC4?u6I4wD;;bV*rt5DurQq- zf{)3Yo|b}W)`|#?y&TSVlciQn!!jhsXqNsHkgD{HCRx}(cidPJi6PkeEO0~Fu}oc~ zAVHg?j-224O4cCzyZv6E;=R~YHW^7zOKp`$Y%gV?kjFY!4V!uST&o3cH_c{@bo;6b z`kT)O3t(wE&u{pB*z<-<4m#Ga8tQ{y-}N_g?sFlC3X$=9ceRc>PmHa0IDZDj!{-ZkY>QyJ*ty(0p#8BcKoNY zHwHq0Y?+|oY%Gstd7?OIUVLyu4O=0^!8W4N` z;2eg|`zqxhED{sBKmb2L=*%gw;w9WT4q_L;x@uZBboi~N1#fuE825Fb1ru1IRbNsZ zo$61fB?AK+Gz;_n;zB4Sau)k!N(uDngk&)1H*%+7^CO{~&`Z&6Z^QGMOKX7gat%lb zWjF|y97|Mn47AsNu(i-GA7jkltlp=o2f z0Byy?aT|r$bs#G|_kK~Qm{l6<*k-_WNe2Eyr&yKj?;EQ+dmPO6fT_S``}b%qfLzIn zvHfxv+p!XVW<%KD;|0FWt<3PRR{6B@du>XueSbeyq|MU!*kfXT)Z%!YsG7XA!CRmGzSudl#%2 z2d$us*^L-AVmDb??wt79wh`#$VMXHao|nE>-P5$O0*s z@j+WJj&hFYJ;$@ca$9Y0Mx?+VO9wI1>|k$&Gjv1rscB^SMc(W*20`4PaHdXu&T}%i zR@674O6o7=gVgG|RNp)MY00A}OgS@w02=b=eM+a}VN+Bh;tw5{7L4FH=GI-T$$5Sy zxwshfKS9(@c=J}xleEV+YY=Y0(7_Pm+gK^KL%JuY;1a_;Nlx;*fR;s3MFWNWWk)oB zsgHd04BDw97`~4m2=KLHTlx8N-2Wq$C&O0sWz^k2&cE9{6svke+ROsdHS~%F@N+r& z+iy~T%h0b$>?B0sqqnSU2^;L-#0U$5)CWyPOx&A1>8!jXH^IO!L3I{xC;DFlz7x#C z*bI*rh928|HUUB>t`qDDCVeId3l4DG1nh$ZX4sgHg7rAwCod^0q6@liOLBp_@(oit z_-uc0&SKi#Qb+GqChnbK#NCoOogY_o{hWLXQ3;N#7T~?pn-8$14}WK^>=fd#JT7%u zjsWk2pdnmxp>BCZCciy#DS5o`GRgiW)YCtn62{vzLbK@O3JN2$j`rnm)^j4{HHIGSXZ~0rZx=fRrI#Gnk4fWui`o*Z)yjuQe zr+c4xf)VOESXn#9%U*W#AcI%O1Xv5dPoDjYxV=hkH7@gekohq5j9{l~^C5+Bj-|e# zCjNsw$-MbS3~xg<6FeLpL$7!TiOntNUj$7GdrYblu15CqV<>IwuO}yu)9y&v)$%+h zjBPjFo=78Fxed$Ez?*@+1XMyTD=HJ1TUIm~m|M%N6`ZDeVAYL3Mj{Qb7s%`0xQ;3r z+6r-Q8~nWfiwdEdBI23NE3b+(@`XR{xcYjf15GzDaPYm=LOmfbP+hy#3it{zHiGGb zo`^8b5q4{sT7>4|&AiD4b_q_`tzw>mfC-&Zxatqyi%f*BLY_UEO!!aF`!OIUZ3>P$ zfe1fhhKCfB?Z@!i4Zr-KK}FAlLYQvG{^IsWS9jvzNB8KeH|(Qo*G8A(x|V%RT>dew z4YjUI9?}I8dRWHXKW>B+n-x5fZy9Wi9@-0BH}fUdeH**iZgFWo7pWQ~O<+WyZ9X~@ zVW2`X%OrGly+PxmNBH_OJw3b6$0xyI!rT@v?|YP3o_fF)WFLABoLydCSoj_g+t85d zO1w72@cue^PUmY~^xk;)1aXv|7Ai~bM%3vh+2|y2lsUs%x{OEG&ul<29k#6Ca_zds zGK9s>iNC`u54w{}wel2#sD@~~R$a8?k^zlu-4zyi{2ZfW>;ZTgbU+t^n5BhK_PT4} zbXagLxoWJF%`JGM+~K`JIgwJ|P0&#A8=sEMhBJXuc4~YYn-d4~jkC6Ghh5!COAYpr>MWtrrwhC@c-k1o-+DhH!o)_Wg2W#+nV%PVz zK=Y;nNXh+O2FOGP*p+j#VVhOr776h!J>^d7lR@i|D(J0!BSV|b-q zUF@}5DW~JG#*a3$_XoHgcPuwE`DCD%edWI@-jb`+$BMhuQ|%)@@oQ+ko2(ZLX3mgk z2k0vK4tI6I-l&(2^~Hz>aFT<4n!1_cG;kG=j!9Aq#dZT8R#A%~X*glFAy@dF7F7)) zW}%4VTqas8cQr#hK^hN%1jU6F#gc-w$Nh3HAcF0G9=L89uSG!M`hR$aga1&4jB5pc z8cEl#Hu+`*n^jO-wjEn6?{7`B{QJ*EB{?*!-jjpMbETd$pa13x{E= zzVC|1A=X1pam?QHTmO>jXI&LGlRfx36ar=qo+xJ_L+n;r&Rr6MAC^n%8L=GoL?;0O zsMPdcLcZj%esu?~6XqS4g-;D0qS5LF0Pll8fi9>(-$5)8=!-XC>Kz&-5f8i!7K8YrA9^un} zuIqk$N%oHF;RlIeOz5fK-*`4swR4#yoEW>upTR^~^L5CJXUn{jgL+LiPKeU!kKD$= z^q*0K%z%rd$r5%Xy+1YxUiv9tu+*!krD(UfB>M&Pah@%G91cbE(hP|8h~f*_F4%%c zgGTB&X>dlW?`tKL=HrO^$(k?V#>B%Emh<)xy}JuVDgE(e*V{H6?)$^88!gf*wLfWj z4l(UPGIcB#!STJ^g_~JqI4{u|h@5ufl@MUgg=~?ikg7fCYFn?ip2$HzPT{yud2bpH zx4cl1$oF>;td@6KvriDe-U8O${$S!#46xjxoKI+oN1+~w*_g0nd1+Or^U16%rM!mh zrVxg|grTBv6CUxzD!nH?TxO1fv3BDK{}lB9pIu)pLkSo<&0hiBxemQ(BW}jM=1Xo& z24(~*!$y-eHv`15u;kW7D^-7{?=`4nV{Q7doG}Wv{!3q zJ=c$r$`bjZKXLPm7)b4Yr{)d8VJ#_vLq{i_#+Z6f3>TzhSJ`xrmRplSQ?P?Y8dRYAvuBk@j;E?R=k z3*?#(BP&!{dUG{<4%MD^JR$@DxQW4{d&AC89?;hO>Hzr7n$lep>cbs})_oA3PAB|D0^!U+jc%d1v&Rg1m@ z7c+pDnD6nsA3v}>Znu;>SPTkj-fHOwCh)U9Dcg5~cZ-z+d=~>}EgyMjrcyur@n4eI zMjulUMF1UPckt0TM0W>E<)!VWQO*MTUNs{JsN_=0`RZUuQqsic4Br8&#Uh}Uxt;t) zA(d|i#LnE_*xcG$DvIg7NqGxbkHFjPudi%Xh7kyMo^cJ%A$ipwPUYa#Pk$r}`RbZl z@;eFF(M~e*c$l|91l2&Z1`^Rd(1AyCt}@1@fA$+;xP;Bp6!h#=3B?cxR z@ck3pR32id=S7dFwgGGcnn7|>GID~nz7Kezl<>!IC5LQ}DdFm*suf)0U=aI9CT13H z;u6Taxk`8EY8j9bTHjV4MvSu8s$Ddyi50}?*o&>pg4|l|i&!`=V1hdBuicc@<+hLl zxvwjtR3WUKAW+^Np+Tm$mbpnE3I|dS^N{^IR(F_8k6YQ@u3TP{OjDqa0Ki9h6j#k*6u*rAw;lTlhmp zg_jFKM&2(TcRso=D#QZ7jqQV@TV>r3Upa>u$@`L2GmDhrd`k++t$;CBh>DQEG1f9p zbhOTO#VVQ0uxF!;!N!v}wzg*V-m^rXl4}N*Wv$h;{yGUEFU>%D8@*1`hU88xaVYuP z$cxnqv%R4i&OuUc(CxB-bk-NN63=wAq0#%@ijv}AsGT>Y@DzXmW#5a@074C_-(W|C`QATSnHlmLuH6~h~_E^rN0cGjuDbBTzDPT|=(y^I2> zc2uMfXY<#r$np#pqkW&V3<$sA?p!8ifjB6z1XR>A@#|0(HiAE`rK9McvfUx4-kC_E}mc4Z~$B1nHa9~ZR3D@*3-41?#tg;Jv2H5l3j1e(`8Wwr2rzGP$-|LK3Z6|XfqP<(&_Y|0(d_xq$B^l zmS2!xP=c9Zt2xT)^Fh%i4F2l1habtqfzC3~MsHtK-gM(+DtR3`(Wk9nu&=qt!E45(VZG3xl}FZkX`-$Z@>lFXTfc`%MKix`VqM{Tj z!ejz)F)=X#%F4<(HzHv&$$#l6C@MzXh08E1|K8lhxbgbu)auv+BaHF;@9*JG&!@T2 vP%cK84C4#*ZKEz6y{P~F5O!+NzxBW%vph9aam57u3w^18H5F>*EI<7Rew_7e literal 0 HcmV?d00001 diff --git a/configuration_guides/use_legacy_string_literals.rst b/configuration_guides/use_legacy_string_literals.rst index 0720de8d4..164801084 100644 --- a/configuration_guides/use_legacy_string_literals.rst +++ b/configuration_guides/use_legacy_string_literals.rst @@ -1,7 +1,7 @@ .. _use_legacy_string_literals: ************************* -Interpreting VARCHAR as TEXT +Using Legacy String Literals ************************* The ``useLegacyStringLiterals`` flag interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. This flag is used to preserve legacy behavior in existing customers. diff --git a/feature_guides/concurrency_and_locks.rst b/feature_guides/concurrency_and_locks.rst index e18dea015..bdff2235a 100644 --- a/feature_guides/concurrency_and_locks.rst +++ b/feature_guides/concurrency_and_locks.rst @@ -99,9 +99,4 @@ In this example, we create a table based on results (:ref:`create_table_as`), bu 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | globalpermission$ | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | schema$t$public | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - -For more information on troubleshooting lock related issues, see - - - + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 \ No newline at end of file diff --git a/feature_guides/delete.rst b/feature_guides/delete.rst new file mode 100644 index 000000000..24ab5a218 --- /dev/null +++ b/feature_guides/delete.rst @@ -0,0 +1,214 @@ +.. _delete_guide: + +*********************** +Deleting Data +*********************** + +SQream DB supports deleting data, but it's important to understand how this works and how to maintain deleted data. + +How does deleting in SQream DB work? +======================================== + +In SQream DB, when you run a delete statement, any rows that match the delete predicate will no longer be returned when running subsequent queries. +Deleted rows are tracked in a separate location, in *delete predicates*. + +After the delete statement, a separate process can be used to reclaim the space occupied by these rows, and to remove the small overhead that queries will have until this is done. + +Some benefits to this design are: + +#. Delete transactions complete quickly + +#. The total disk footprint overhead at any time for a delete transaction or cleanup process is small and bounded (while the system still supports low overhead commit, rollback and recovery for delete transactions). + + +Phase 1: Delete +--------------------------- + +.. TODO: isn't the delete cleanup able to complete a certain amount of work transactionally, so that you can do a massive cleanup in stages? + +.. TODO: our current best practices is to use a cron job with sqream sql to run the delete cleanup. we should document how to do this, we have customers with very different delete schedules so we can give a few extreme examples and when/why you'd use them + +When a :ref:`delete` statement is run, SQream DB records the delete predicates used. These predicates will be used to filter future statements on this table until all this delete predicate's matching rows have been physically cleaned up. + +This filtering process takes full advantage of SQream's zone map feature. + +Phase 2: Clean-up +-------------------- + +The cleanup process is not automatic. This gives control to the user or DBA, and gives flexibility on when to run the clean up. + +Files marked for deletion during the logical deletion stage are removed from disk. This is achieved by calling both utility function commands: ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` sequentially. + +.. note:: + * :ref:`alter_table` and other DDL operations are blocked on tables that require clean-up. See more in the :ref:`concurrency_and_locks` guide. + * If the estimated time for a cleanup processs is beyond a threshold, you will get an error message about it. The message will explain how to override this limitation and run the process anywhere. + +Notes on data deletion +========================================= + +.. note:: + * If the number of deleted records crosses the threshold defined by the ``mixedColumnChunksThreshold`` parameter, the delete operation will be aborted. + * This is intended to alert the user that the large number of deleted records may result in a large number of mixed chuncks. + * To circumvent this alert, replace XXX with the desired number of records before running the delete operation: + +.. code-block:: postgres + + set mixedColumnChunksThreshold=XXX; + + +Deleting data does not free up space +----------------------------------------- + +With the exception of a full table delete (:ref:`TRUNCATE`), deleting data does not free up disk space. To free up disk space, trigger the cleanup process. + +``SELECT`` performance on deleted rows +---------------------------------------- + +Queries on tables that have deleted rows may have to scan data that hasn't been cleaned up. +In some cases, this can cause queries to take longer than expected. To solve this issue, trigger the cleanup process. + +Use ``TRUNCATE`` instead of ``DELETE`` +--------------------------------------- +For tables that are frequently emptied entirely, consider using :ref:`truncate` rather than :ref:`delete`. TRUNCATE removes the entire content of the table immediately, without requiring a subsequent cleanup to free up disk space. + +Cleanup is I/O intensive +------------------------------- + +The cleanup process actively compacts tables by writing a complete new version of column chunks with no dead space. This minimizes the size of the table, but can take a long time. It also requires extra disk space for the new copy of the table, until the operation completes. + +Cleanup operations can create significant I/O load on the database. Consider this when planning the best time for the cleanup process. + +If this is an issue with your environment, consider using ``CREATE TABLE AS`` to create a new table and then rename and drop the old table. + + +Example +============= + +Deleting values from a table +------------------------------ + +.. code-block:: psql + + farm=> SELECT * FROM cool_animals; + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 4,Elephant ,6500 + 5,Rhinoceros ,2100 + 6,\N,\N + + 6 rows + + farm=> DELETE FROM cool_animals WHERE weight > 1000; + executed + + farm=> SELECT * FROM cool_animals; + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 6,\N,\N + + 4 rows + +Deleting values based on more complex predicates +--------------------------------------------------- + +.. code-block:: psql + + farm=> SELECT * FROM cool_animals; + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 4,Elephant ,6500 + 5,Rhinoceros ,2100 + 6,\N,\N + + 6 rows + + farm=> DELETE FROM cool_animals WHERE weight > 1000; + executed + + farm=> SELECT * FROM cool_animals; + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 6,\N,\N + + 4 rows + +Identifying and cleaning up tables +--------------------------------------- + +List tables that haven't been cleaned up +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: psql + + farm=> SELECT t.table_name FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + GROUP BY 1; + cool_animals + + 1 row + +Identify predicates for clean-up +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: psql + + farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + WHERE t.table_name = 'cool_animals'; + weight > 1000 + + 1 row + +Triggering a cleanup +^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: psql + + -- Chunk reorganization (aka SWEEP) + farm=> SELECT CLEANUP_CHUNKS('public','cool_animals'); + executed + + -- Delete leftover files (aka VACUUM) + farm=> SELECT CLEANUP_EXTENTS('public','cool_animals'); + executed + + + farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + WHERE t.table_name = 'cool_animals'; + + 0 rows + + + +Best practices for data deletion +===================================== + +* Run ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` after large ``DELETE`` operations. + +* When deleting large proportions of data from very large tables, consider running a ``CREATE TABLE AS`` operation instead, then rename and drop the original table. + +* Avoid killing ``CLEANUP_EXTENTS`` operations after they've started. + +* SQream DB is optimised for time-based data. When data is naturally ordered by a date or timestamp, deleting based on those columns will perform best. For more information, see our :ref:`time based data management guide`. + + + +.. soft update concept + +.. delete cleanup and it's properties. automatic/manual, in transaction or background + +.. automatic background gives fast delete, minimal transaction overhead, +.. small cost to queries until background reorganised + +.. when does delete use the metadata effectively + +.. more examples + diff --git a/feature_guides/delete_guide.rst b/feature_guides/delete_guide.rst new file mode 100644 index 000000000..24ab5a218 --- /dev/null +++ b/feature_guides/delete_guide.rst @@ -0,0 +1,214 @@ +.. _delete_guide: + +*********************** +Deleting Data +*********************** + +SQream DB supports deleting data, but it's important to understand how this works and how to maintain deleted data. + +How does deleting in SQream DB work? +======================================== + +In SQream DB, when you run a delete statement, any rows that match the delete predicate will no longer be returned when running subsequent queries. +Deleted rows are tracked in a separate location, in *delete predicates*. + +After the delete statement, a separate process can be used to reclaim the space occupied by these rows, and to remove the small overhead that queries will have until this is done. + +Some benefits to this design are: + +#. Delete transactions complete quickly + +#. The total disk footprint overhead at any time for a delete transaction or cleanup process is small and bounded (while the system still supports low overhead commit, rollback and recovery for delete transactions). + + +Phase 1: Delete +--------------------------- + +.. TODO: isn't the delete cleanup able to complete a certain amount of work transactionally, so that you can do a massive cleanup in stages? + +.. TODO: our current best practices is to use a cron job with sqream sql to run the delete cleanup. we should document how to do this, we have customers with very different delete schedules so we can give a few extreme examples and when/why you'd use them + +When a :ref:`delete` statement is run, SQream DB records the delete predicates used. These predicates will be used to filter future statements on this table until all this delete predicate's matching rows have been physically cleaned up. + +This filtering process takes full advantage of SQream's zone map feature. + +Phase 2: Clean-up +-------------------- + +The cleanup process is not automatic. This gives control to the user or DBA, and gives flexibility on when to run the clean up. + +Files marked for deletion during the logical deletion stage are removed from disk. This is achieved by calling both utility function commands: ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` sequentially. + +.. note:: + * :ref:`alter_table` and other DDL operations are blocked on tables that require clean-up. See more in the :ref:`concurrency_and_locks` guide. + * If the estimated time for a cleanup processs is beyond a threshold, you will get an error message about it. The message will explain how to override this limitation and run the process anywhere. + +Notes on data deletion +========================================= + +.. note:: + * If the number of deleted records crosses the threshold defined by the ``mixedColumnChunksThreshold`` parameter, the delete operation will be aborted. + * This is intended to alert the user that the large number of deleted records may result in a large number of mixed chuncks. + * To circumvent this alert, replace XXX with the desired number of records before running the delete operation: + +.. code-block:: postgres + + set mixedColumnChunksThreshold=XXX; + + +Deleting data does not free up space +----------------------------------------- + +With the exception of a full table delete (:ref:`TRUNCATE`), deleting data does not free up disk space. To free up disk space, trigger the cleanup process. + +``SELECT`` performance on deleted rows +---------------------------------------- + +Queries on tables that have deleted rows may have to scan data that hasn't been cleaned up. +In some cases, this can cause queries to take longer than expected. To solve this issue, trigger the cleanup process. + +Use ``TRUNCATE`` instead of ``DELETE`` +--------------------------------------- +For tables that are frequently emptied entirely, consider using :ref:`truncate` rather than :ref:`delete`. TRUNCATE removes the entire content of the table immediately, without requiring a subsequent cleanup to free up disk space. + +Cleanup is I/O intensive +------------------------------- + +The cleanup process actively compacts tables by writing a complete new version of column chunks with no dead space. This minimizes the size of the table, but can take a long time. It also requires extra disk space for the new copy of the table, until the operation completes. + +Cleanup operations can create significant I/O load on the database. Consider this when planning the best time for the cleanup process. + +If this is an issue with your environment, consider using ``CREATE TABLE AS`` to create a new table and then rename and drop the old table. + + +Example +============= + +Deleting values from a table +------------------------------ + +.. code-block:: psql + + farm=> SELECT * FROM cool_animals; + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 4,Elephant ,6500 + 5,Rhinoceros ,2100 + 6,\N,\N + + 6 rows + + farm=> DELETE FROM cool_animals WHERE weight > 1000; + executed + + farm=> SELECT * FROM cool_animals; + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 6,\N,\N + + 4 rows + +Deleting values based on more complex predicates +--------------------------------------------------- + +.. code-block:: psql + + farm=> SELECT * FROM cool_animals; + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 4,Elephant ,6500 + 5,Rhinoceros ,2100 + 6,\N,\N + + 6 rows + + farm=> DELETE FROM cool_animals WHERE weight > 1000; + executed + + farm=> SELECT * FROM cool_animals; + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 6,\N,\N + + 4 rows + +Identifying and cleaning up tables +--------------------------------------- + +List tables that haven't been cleaned up +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: psql + + farm=> SELECT t.table_name FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + GROUP BY 1; + cool_animals + + 1 row + +Identify predicates for clean-up +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: psql + + farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + WHERE t.table_name = 'cool_animals'; + weight > 1000 + + 1 row + +Triggering a cleanup +^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: psql + + -- Chunk reorganization (aka SWEEP) + farm=> SELECT CLEANUP_CHUNKS('public','cool_animals'); + executed + + -- Delete leftover files (aka VACUUM) + farm=> SELECT CLEANUP_EXTENTS('public','cool_animals'); + executed + + + farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + WHERE t.table_name = 'cool_animals'; + + 0 rows + + + +Best practices for data deletion +===================================== + +* Run ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` after large ``DELETE`` operations. + +* When deleting large proportions of data from very large tables, consider running a ``CREATE TABLE AS`` operation instead, then rename and drop the original table. + +* Avoid killing ``CLEANUP_EXTENTS`` operations after they've started. + +* SQream DB is optimised for time-based data. When data is naturally ordered by a date or timestamp, deleting based on those columns will perform best. For more information, see our :ref:`time based data management guide`. + + + +.. soft update concept + +.. delete cleanup and it's properties. automatic/manual, in transaction or background + +.. automatic background gives fast delete, minimal transaction overhead, +.. small cost to queries until background reorganised + +.. when does delete use the metadata effectively + +.. more examples + diff --git a/feature_guides/flexible_data_clustering_data_clustering_methods.rst b/feature_guides/flexible_data_clustering_data_clustering_methods.rst index 87ba7e5cf..a9667b920 100644 --- a/feature_guides/flexible_data_clustering_data_clustering_methods.rst +++ b/feature_guides/flexible_data_clustering_data_clustering_methods.rst @@ -87,9 +87,9 @@ The ``CLUSTER BY`` statement splits ingested data based on the range of data cor For more information, see the following: -* `The CLUSTER_BY statement `_ -* `The DELETE statement `_ -* `The Deleting Data guide `_ +* `The CLUSTER_BY statement `_ +* `The DELETE statement `_ +* `The Deleting Data guide `_ Inspecting Clustered Table Health ~~~~~~~~~~ @@ -111,7 +111,7 @@ SQream partially sorts data that you load into a clustered table. Note that whil For more information, see the following: -* **Data Manipulation commands (DML)** - see `Data Manipulation Commands (DML) `_. +* **Data Manipulation commands (DML)** - see `Data Manipulation Commands (DML) `_. * **Creating tables** - see :ref:`create_table`. When you create a table, all new data is clustered upon insert. @@ -177,7 +177,4 @@ Unlike node-partitioning (or sharding), chunks are: :: -* Compressed individually to improve compression and data locality. - - - +* Compressed individually to improve compression and data locality. \ No newline at end of file diff --git a/feature_guides/index.rst b/feature_guides/index.rst index 7a7309733..948915df4 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -12,13 +12,14 @@ This section describes the following features: :titlesonly: - xxconfiguring_your_database access_control + delete_guide compression - xxflexible_data_clustering + flexible_data_clustering python_functions + saved_queries + viewing_system_objects_as_ddl workload_manager transactions concurrency_and_locks - concurrency_and_scaling_in_sqream - xxinternational_languages_and_character_sets \ No newline at end of file + concurrency_and_scaling_in_sqream \ No newline at end of file diff --git a/glossary.rst b/glossary.rst index f6dfc1f76..546476e16 100644 --- a/glossary.rst +++ b/glossary.rst @@ -3,30 +3,33 @@ Glossary ===================================== -.. glossary:: -The following table shows a glossary of commonly-used terms: - -+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| **Term** | **Description** | -+=======================+============================================================================================================================================================+ -| Authentication | The process of verifying identity by validating a user or role identity using a username and password. | -+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Authorization | Defines the set of actions that an authenticaed role can perform after gaining access to the system. | -+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Catalog | A set of views containing metadata information about objects in a database. | -+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Cluster | A SQream deployment containing several workers running on one or more nodes. | -+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Metadata | SQream's internal storage containing details about database objects. | -+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Node | A machine used to run SQream workers. | -+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Role | A group or a user. For more information see `SQream Acceleration Studio 5.4.3 `_. | -+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Storage cluster | The directory where SQream stores data. | -+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| User-Defined Function | A feature that extends SQream's built-in SQL functionality with user-written Python code. | -+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Worker | A SQream application that responds to statements. Several workers running on one or more nodes form a cluster. | -+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +The following table shows the **Glossary** descriptions: + ++-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| **Term** | **Description** | ++=================+==============================================================================================================================================================================================================+ +| Authentication | The process of verifying identity by validating a user or role identity using a username and password. | ++-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Authorization | Defines the set of actions that an authenticaed role can perform after gaining access to the system. | ++-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Catalog | A set of views containing metadata information about objects in a database. | ++-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Cluster | A SQream deployment containing several workers running on one or more nodes. | ++-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Custom connector| When SQream is integrated with Power BI, used for running direct queries. | ++-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Direct query | A Power BI data extraction method that retrieves data from a remote source instead of from a local repository. | ++-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Import | A Power BI data extraction method that retrieves data to local repository to be visualized at a later point. | ++-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Metadata | SQream's internal storage containing details about database objects. | ++-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Node | A machine used to run SQream workers. | ++-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Role | A group or a user. For more information see `SQream Studio `_. | ++-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Storage cluster | The directory where SQream stores data. | ++-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Worker | A SQream application that responds to statements. Several workers running on one or more nodes form a cluster. | ++-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ \ No newline at end of file diff --git a/installation_guides/launching_sqream_with_monit.rst b/installation_guides/launching_sqream_with_monit.rst new file mode 100644 index 000000000..b8dc4f1a6 --- /dev/null +++ b/installation_guides/launching_sqream_with_monit.rst @@ -0,0 +1,290 @@ +.. _launching_sqream_with_monit: + +********************************************* +Launching SQream with Monit +********************************************* +This procedure describes how to launch SQream using Monit. + +Launching SQream +==================================== + +After doing the following, you can launch SQream according to the instructions on this page. + + + +1. :ref:`Installing Monit ` +2. :ref:`Installing SQream with Binary ` + + + + +The following is an example of a working monitrc file configured to monitor the ***metadataserver** and **serverpicker** commands, and **four sqreamd services**. The **monitrc** configuration file is located in the **conf/monitrc** directory. + +Note that the **monitrc** in the following example is configured for eight ``sqreamd`` services, but that only the first four are enabled: + +.. code-block:: console + + $ set daemon 5 # check services at 30 seconds intervals + $ set logfile syslog + $ + $ set httpd port 2812 and + $ use address localhost # only accept connection from localhost + $ allow localhost # allow localhost to connect to the server and + $ allow admin:monit # require user 'admin' with password 'monit' + $ + $ ##set mailserver smtp.gmail.com port 587 + $ ## using tlsv12 + $ #METADATASERVER-START + $ check process metadataserver with pidfile /var/run/metadataserver.pid + $ start program = "/usr/bin/systemctl start metadataserver" + $ stop program = "/usr/bin/systemctl stop metadataserver" + $ #METADATASERVER-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: metadataserver $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ #SERVERPICKER-START + $ check process serverpicker with pidfile /var/run/serverpicker.pid + $ start program = "/usr/bin/systemctl start serverpicker" + $ stop program = "/usr/bin/systemctl stop serverpicker" + $ #SERVERPICKER-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: serverpicker $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # + $ # + $ #SQREAM1-START + $ check process sqream1 with pidfile /var/run/sqream1.pid + $ start program = "/usr/bin/systemctl start sqream1" + $ stop program = "/usr/bin/systemctl stop sqream1" + $ #SQREAM1-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream1 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ #SQREAM2-START + $ check process sqream2 with pidfile /var/run/sqream2.pid + $ start program = "/usr/bin/systemctl start sqream2" + $ #SQREAM2-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream1 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ #SQREAM3-START + $ check process sqream3 with pidfile /var/run/sqream3.pid + $ start program = "/usr/bin/systemctl start sqream3" + $ stop program = "/usr/bin/systemctl stop sqream3" + $ #SQREAM3-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ #SQREAM4-START + $ check process sqream4 with pidfile /var/run/sqream4.pid + $ start program = "/usr/bin/systemctl start sqream4" + $ stop program = "/usr/bin/systemctl stop sqream4" + $ #SQREAM4-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ # + $ #SQREAM5-START + $ #check process sqream5 with pidfile /var/run/sqream5.pid + $ #start program = "/usr/bin/systemctl start sqream5" + $ #stop program = "/usr/bin/systemctl stop sqream5" + $ #SQREAM5-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ # + $ #SQREAM6-START + $ #check process sqream6 with pidfile /var/run/sqream6.pid + $ #start program = "/usr/bin/systemctl start sqream6" + $ #stop program = "/usr/bin/systemctl stop sqream6" + $ #SQREAM6-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ # + $ #SQREAM7-START + $ #check process sqream7 with pidfile /var/run/sqream7.pid + $ #start program = "/usr/bin/systemctl start sqream7" + $ #stop program = "/usr/bin/systemctl stop sqream7" + $ #SQREAM7-END + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + $ # + $ #SQREAM8-START + $ #check process sqream8 with pidfile /var/run/sqream8.pid + $ #start program = "/usr/bin/systemctl start sqream8" + $ #stop program = "/usr/bin/systemctl stop sqream8" + $ #SQREAM8-END + $ # alert user@domain.com on {nonexist, timeout} + $ # with mail-format { + $ # from: Monit@$HOST + $ # subject: sqream2 $EVENT - $ACTION + $ # message: This is an automate mail, sent from monit. + $ # } + +Monit Usage Examples +==================================== + +This section shows examples of two methods for stopping the **sqream3** service use Monit's command syntax: + + + +* :ref:`Stopping Monit and SQream separately ` +* :ref:`Stopping SQream using a Monit command ` + +.. _stopping_monit_and_sqream_separately: + +Stopping Monit and SQream Separately +------------------------------------- + +You can stop the Monit service and SQream separately as follows: + +.. code-block:: console + + $ sudo systemctl stop monit + $ sudo systemctl stop sqream3 + +You can restart Monit as follows: + +.. code-block:: console + + $ sudo systemctl start monit + +Restarting Monit automatically restarts the SQream services. + +.. _stopping_sqream_using_a_monit_command: + +Stopping SQream Using a Monit Command +------------------------------------- + +You can stop SQream using a Monit command as follows: + +.. code-block:: console + + $ sudo monit stop sqream3 + +This command stops SQream only (and not Monit). + +You can restart SQream as follows: + +.. code-block:: console + + $ sudo monit start sqream3 + +Monit Command Line Options +------------------------------------- +The **Monit Command Line Options** section describes some of the most commonly used Monit command options. + +You can show the command line options by running: + +.. code-block:: console + + $ monit --help + +.. code-block:: console + + $ start all - Start all services + $ start - Only start the named service + $ stop all - Stop all services + $ stop - Stop the named service + $ restart all - Stop and start all services + $ restart - Only restart the named service + $ monitor all - Enable monitoring of all services + $ monitor - Only enable monitoring of the named service + $ unmonitor all - Disable monitoring of all services + $ unmonitor - Only disable monitoring of the named service + $ reload - Reinitialize monit + $ status [name] - Print full status information for service(s) + $ summary [name] - Print short status information for service(s) + $ report [up|down|..] - Report state of services. See manual for options + $ quit - Kill the monit daemon process + $ validate - Check all services and start if not running + $ procmatch - Test process matching pattern + +Using Monit While Upgrading Your Version of SQream +================================================== + +While upgrading your version of SQream, you can use Monit to avoid conflicts (such as service start). This is done by pausing or stopping all running services while you manually upgrade SQream. When you finish successfully upgrading SQream, you can use Monit to restart all SQream services + +**To use Monit while upgrading your version of SQream:** + +1. Stop all actively running SQream services: + + .. code-block:: console + + $ sudo monit stop all + +2. Verify that SQream has stopped listening on ports **500X**, **510X**, and **310X**: + + .. code-block:: console + + $ sudo netstat -nltp #to make sure sqream stopped listening on 500X, 510X and 310X ports. + + The example below shows the old version ``sqream-db-v2020.2`` being replaced with the new version ``sqream-db-v2025.200``. + + .. code-block:: console + + $ cd /home/sqream + $ mkdir tempfolder + $ mv sqream-db-v2025.200.tar.gz tempfolder/ + $ tar -xf sqream-db-v2025.200.tar.gz + $ sudo mv sqream /usr/local/sqream-db-v2025.200 + $ cd /usr/local + $ sudo chown -R sqream:sqream sqream-db-v2025.200 + $ sudo rm sqream #This only should remove symlink + $ sudo ln -s sqream-db-v2025.200 sqream #this will create new symlink named "sqream" pointing to new version + $ ls -l + + The symbolic SQream link should point to the real folder: + + .. code-block:: console + + $ sqream -> sqream-db-v2025.200 + +4. Restart the SQream services: + + .. code-block:: console + + $ sudo monit start all + +5. Verify that the latest version has been installed: + + .. code-block:: console + + $ SELECT SHOW_VERSION(); + + The correct version is output. + + :: + +6. Restart the UI: + + .. code-block:: console + + $ pm2 start all diff --git a/reference/configuration.rst b/reference/configuration.rst deleted file mode 100644 index bf487496e..000000000 --- a/reference/configuration.rst +++ /dev/null @@ -1,5 +0,0 @@ -.. _configuration_reference: - -************************* -Configuration -************************* diff --git a/reference/index.rst b/reference/index.rst index f1a4a600e..dc8e2e22f 100644 --- a/reference/index.rst +++ b/reference/index.rst @@ -14,5 +14,4 @@ The **Reference Guides** section provides reference for using SQream DB's interf sql/index catalog_reference cli/index - sql_feature_support - xxconfiguration + sql_feature_support \ No newline at end of file diff --git a/third_party_tools/client_drivers/index.rst b/third_party_tools/client_drivers/index.rst index 2df0a1811..d9ad66a26 100644 --- a/third_party_tools/client_drivers/index.rst +++ b/third_party_tools/client_drivers/index.rst @@ -4,9 +4,7 @@ Client Drivers for |latest_version| ************************************ - - -The guides on this page describe how to use the Sqream DB client drivers and client applications with Sqream DB. +The guides on this page describe how to use the Sqream DB client drivers and client applications with SQream. Client Driver Downloads ============================= @@ -20,7 +18,7 @@ The following are applicable to all operating systems: * **JDBC** - recommended installation via ``mvn``: * `JDBC .jar file `_ - sqream-jdbc-4.5.3 (.jar) - * `JDBC driver `_ + * `JDBC driver `_ .. _python: @@ -43,22 +41,23 @@ The following are applicable to all operating systems: * **Tableau**: - * `Tableau connector `_ - SQreamDB (.taco) + * `Tableau connector `_ - SQream (.taco) * `Tableau manual installation `_ + +.. _powerbi_connector: +* **Power BI**: + + * `Power BI PowerQuery connector `_ - SQream (.mez) + * `Power BI manual installation `_ Windows -------------- The following are applicable to Windows: - -* **JDBC installer** - `SQream_JDBC_Driver_v2020.2.0.exe `_ - Windows installer for JDBC driver, with Tableau connector. - - :: - -* **ODBC installer** - SQream Drivers v2020.2.0, with Tableau customizations. Please contact your `Sqream represenative `_ for this installer. +* **ODBC installer** - SQream Drivers v2020.2.0, with Tableau customizations. Please contact your `SQream represenative `_ for this installer. For more information on installing and configuring ODBC on Windows, see :ref:`Install and configure ODBC on Windows `. @@ -81,14 +80,12 @@ The following are applicable to Linux: :: -* `ODBC Installer `_ - sqream_odbc_4.0.0_x86_64_linux.tar.gz -* :ref:`Linux installer for ODBC`. Please contact your SQream representative for this installer. +* ODBC Installer - Please contact your SQream representative for this installer. :: - * C++ connector - `libsqream-4.0 `_ -* `C++ shared object library `_ +* `C++ shared object library `_ .. toctree:: @@ -110,4 +107,4 @@ If you couldn't find what you're looking for, we're always happy to help. Visit .. rubric:: Looking for older drivers? -If you're looking for an older version of SQream DB drivers, versions 1.10 through 2019.2.1 are available at https://sqream.com/product/client-drivers/ . +If you're looking for an older version of SQream DB drivers, versions 1.10 through 2019.2.1 are available at https://sqream.com/product/client-drivers/. \ No newline at end of file diff --git a/third_party_tools/client_platforms/power_bi.rst b/third_party_tools/client_platforms/power_bi.rst new file mode 100644 index 000000000..da788cc6e --- /dev/null +++ b/third_party_tools/client_platforms/power_bi.rst @@ -0,0 +1,143 @@ +.. _power_bi: + +************************* +Connect to SQream Using Power BI Desktop +************************* + +Overview +========= +**Power BI Desktop** lets you connect to SQream and use underlying data as with other data sources in Power BI Desktop. + +SQream integrates with Power BI Desktop to do the following: + +* Extract and transform your datasets into usable visual models in approximately one minute. + + :: + +* Use **DAX** functions **(Data Analysis Expressions)** to analyze your datasets. + + :: + +* Refresh datasets as needed or by using scheduled jobs. + +SQream uses Power BI for extracting data sets using the following methods: + +* **Direct query** - Direct queries lets you connect easily with no errors, and refreshes Power BI artifacts, such as graphs and reports, in a considerable amount of time in relation to the time taken for queries to run using the `SQream SQL CLI Reference guide `_. + + :: + +* **Import** - Lets you extract datasets from remote databases. + +The **Connect to SQream Using Power BI** page describes the following: + +.. contents:: + :local: + :depth: 1 + +Prerequisites +------------------- +To connect to SQream, the following must be installed: + +* **ODBC data source administrator** - 32 or 64, depending on your operating system. For Windows users, the ODBC data source administrator is embedded within the operating system. + +* **SQream driver** - The SQream application required for interacting with the ODBC according to the configuration specified in the ODBC administrator tool. + +Installing Power BI Desktop +------------------- +**To install Power BI Desktop:** + +1. Download `Power BI Desktop 64x `_. + + :: + +2. Download and configure your ODBC driver. + + For more information about configuring your ODBC driver, see `ODBC `_. + +3. Navigate to **Windows** > **Documents** and create a folder called **Power BI Desktop Custom Connectors**. + + :: + +4. In the **Power BI Desktop** folder, create a folder called **Custom Connectors**. + + +5. From the Client Drivers page, download the **PowerQuery.mez** file. + + :: + +5. Save the PowerQuery.mez file in the **Custom Connectors** folder you created in Step 3. + + :: + +6. Open the Power BI application. + + :: + +7. Navigate to **File** > **Options and Settings** > **Option** > **Security** > **Data Extensions**, and select **(Not Recommended) Allow any extension to load without validation or warning**. + + :: + +8. Restart the Power BI Desktop application. + + :: + +9. From the **Get Data** menu, select **SQream**. + + :: + +10. Click **Connect** and provide the information shown in the following table: + + .. list-table:: + :widths: 6 31 + :header-rows: 1 + + * - Element Name + - Description + * - Server + - Provide the network address to your database server. You can use a hostname or an IP address. + * - Port + - Provide the port that the database is responding to at the network address. + * - Database + - Provide the name of your database or the schema on your database server. + * - User + - Provide a SQreamdb username. + * - Passwords + - Provide a password for your user. + +11. Under **Data Connectivity mode**, select **DirectQuery mode**. + + :: + +12. Click **Connect**. + + :: + +13. Provide your user name and password and click **Connect**. + +Best Practices for Power BI +--------------- +SQream recommends using Power BI in the following ways for acquiring the best performance metrics: + +* Creating bar, pie, line, or plot charts when illustrating one or more columns. + + :: + +* Displaying trends and statuses using visual models. + + :: + +* Creating a unified view using **PowerQuery** to connect different data sources into a single dashboard. + +Supported SQream Driver Versions +--------------- +SQream supports the following SQream driver versions: + +* The **PowerQuery Connector** is an additional layer on top of the ODBC. + + :: + +* SQream Driver Installation (ODBC v4.1.1) - Contact your administrator for the link to download ODBC v4.1.1. + +Related Information +------------------- +For more information, see the `Glossary `_. \ No newline at end of file From 85a916b03f048a86cc629259fc7f7615fb4f1ecf Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 13 Mar 2022 18:41:15 +0200 Subject: [PATCH 207/300] Redirects Redirects for 2020.3.2.1. --- .../aggregate_functions/index.rst | 21 ++-- .../aggregate_functions/mode.rst | 65 +++++++++++ .../aggregate_functions/percentile_cont.rst | 64 +++++++++++ .../aggregate_functions/percentile_disc.rst | 62 +++++++++++ reference/sql/sql_functions/index.rst | 5 +- .../user_defined_functions/index.rst | 25 +++++ .../user_defined_functions/scalar_sql_udf.rst | 101 ++++++++++++++++++ .../simple_scalar_sql_udf.rst | 51 +++++++++ .../window_functions/cume_dist.rst | 23 ++++ .../window_functions/dense_rank.rst | 23 ++++ .../window_functions/first_value.rst | 24 +++++ .../sql_functions/window_functions/index.rst | 16 ++- .../window_functions/last_value.rst | 24 +++++ .../window_functions/nth_value.rst | 74 +++++++++++++ .../sql_functions/window_functions/ntile.rst | 22 ++++ .../window_functions/percent_rank.rst | 28 +++++ third_party_tools/client_platforms/index.rst | 8 +- 17 files changed, 616 insertions(+), 20 deletions(-) create mode 100644 reference/sql/sql_functions/aggregate_functions/mode.rst create mode 100644 reference/sql/sql_functions/aggregate_functions/percentile_cont.rst create mode 100644 reference/sql/sql_functions/aggregate_functions/percentile_disc.rst create mode 100644 reference/sql/sql_functions/user_defined_functions/index.rst create mode 100644 reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.rst create mode 100644 reference/sql/sql_functions/user_defined_functions/simple_scalar_sql_udf.rst create mode 100644 reference/sql/sql_functions/window_functions/cume_dist.rst create mode 100644 reference/sql/sql_functions/window_functions/dense_rank.rst create mode 100644 reference/sql/sql_functions/window_functions/first_value.rst create mode 100644 reference/sql/sql_functions/window_functions/last_value.rst create mode 100644 reference/sql/sql_functions/window_functions/nth_value.rst create mode 100644 reference/sql/sql_functions/window_functions/ntile.rst create mode 100644 reference/sql/sql_functions/window_functions/percent_rank.rst diff --git a/reference/sql/sql_functions/aggregate_functions/index.rst b/reference/sql/sql_functions/aggregate_functions/index.rst index 5f38ac1c5..17d35a46b 100644 --- a/reference/sql/sql_functions/aggregate_functions/index.rst +++ b/reference/sql/sql_functions/aggregate_functions/index.rst @@ -1,22 +1,24 @@ .. _aggregate_functions: ******************** -Aggregate functions +Aggregate Functions ******************** -Aggregate functions performs calculation on a set of values, and return a single value. - -Most aggregate functions ignore null values. - -Aggregate functions are often used with the ``GROUP BY`` clause of the :ref:`select` statement. +Overview +=========== + +Aggregate functions perform calculations based on a set of values and return a single value. Most aggregate functions ignore null values. Aggregate functions are often used with the ``GROUP BY`` clause of the :ref:`select` statement. +Available Aggregate Functions +=============== +The following list shows the available aggregate functions: .. toctree:: :maxdepth: 1 - :caption: Aggregate functions :glob: + avg corr count @@ -24,8 +26,11 @@ Aggregate functions are often used with the ``GROUP BY`` clause of the :ref:`sel covar_samp max min + mode + percentile_cont + percentile_disc stddev_pop stddev_samp sum var_pop - var_samp \ No newline at end of file + var_samp diff --git a/reference/sql/sql_functions/aggregate_functions/mode.rst b/reference/sql/sql_functions/aggregate_functions/mode.rst new file mode 100644 index 000000000..a6d46e114 --- /dev/null +++ b/reference/sql/sql_functions/aggregate_functions/mode.rst @@ -0,0 +1,65 @@ +.. _mode: + +************************** +MODE +************************** +The **MODE** function returns the most common value in the selected column. If there are no repeating values, or if there is the same frequency of multiple values, this function returns the top value based on the ``ORDER BY`` clause. + +The **MODE** function is commonly used with the following functions: + +* `PERCENTILE_CONT `_ function +* `PERCENTILE_DISC `_ function + +Syntax +======== +The following is the correct syntax for the ``MODE`` function: + +.. code-block:: postgres + + MODE() WITHIN GROUP (ORDER BY column) + +Example +======== +The example in this section is based on the ``players`` table below: + +.. list-table:: + :widths: 33 33 33 + :header-rows: 1 + ++-----------------+----------+-----------+ +| **Player_Name** | **Team** | **Score** | ++-----------------+----------+-----------+ +| T_Tock | Blue | 13 | ++-----------------+----------+-----------+ +| N_Stein | Blue | 20 | ++-----------------+----------+-----------+ +| F_Dirk | Blue | 20 | ++-----------------+----------+-----------+ +| Y_Hyung | Blue | 10 | ++-----------------+----------+-----------+ +| A_Rodrick | Blue | 13 | ++-----------------+----------+-----------+ +| R_Evans | Red | 55 | ++-----------------+----------+-----------+ +| C_Johnston | Red | 20 | ++-----------------+----------+-----------+ +| K_Stoll | Red | 25 | ++-----------------+----------+-----------+ +| J_Loftus | Red | 22 | ++-----------------+----------+-----------+ +| L_Ellis | Red | 7 | ++-----------------+----------+-----------+ +| G_Elroy | Red | 23 | ++-----------------+----------+-----------+ + +The following is an example of the ``MODE`` function: + +.. code-block:: postgres + + SELECT + MODE() WITHIN GROUP (ORDER BY score) as Mode + FROM players; + + Mode| + ----+ + 20 diff --git a/reference/sql/sql_functions/aggregate_functions/percentile_cont.rst b/reference/sql/sql_functions/aggregate_functions/percentile_cont.rst new file mode 100644 index 000000000..115101a1d --- /dev/null +++ b/reference/sql/sql_functions/aggregate_functions/percentile_cont.rst @@ -0,0 +1,64 @@ +.. _percentile_cont: + +************************** +PERCENTILE_CONT +************************** +The **PERCENTILE_CONT** function returns the value located in the selected percentile of a specified column. The required input is a number between **0** and **1** that represents the wanted percentile and the column containing the wanted percentile. If the selected percentile does not have an exact value, the PERCENTILE_CONT function extrapolates a value estimated from the existing values. + +The **PERCENTILE_CONT** function returns an extrapolated value closest to the values in the requested percentile. If you want to see the closest value in your data to the requested percentile, use `PERCENTILE DISC `_. + +Syntax +======== +The following is the correct syntax for the ``PERCENTILE_CONT`` function: + +.. code-block:: postgres + + PERCENTILE_CONT(double) WITHIN GROUP (ORDER BY ) + +Example +======== +The example in this section is based on the ``players`` table below: + +.. list-table:: + :widths: 33 33 33 + :header-rows: 1 + ++-----------------+----------+-----------+ +| **Player_Name** | **Team** | **Score** | ++-----------------+----------+-----------+ +| T_Tock | Blue | 12 | ++-----------------+----------+-----------+ +| N_Stein | Blue | 23 | ++-----------------+----------+-----------+ +| F_Dirk | Blue | 45 | ++-----------------+----------+-----------+ +| Y_Hyung | Blue | 19 | ++-----------------+----------+-----------+ +| A_Rodrick | Blue | 37 | ++-----------------+----------+-----------+ +| R_Evans | Red | 52 | ++-----------------+----------+-----------+ +| C_Johnston | Red | 43 | ++-----------------+----------+-----------+ +| K_Stoll | Red | 27 | ++-----------------+----------+-----------+ +| J_Loftus | Red | 8 | ++-----------------+----------+-----------+ +| L_Ellis | Red | 13 | ++-----------------+----------+-----------+ +| G_Elroy | Red | 31 | ++-----------------+----------+-----------+ + +The following is an example of the ``PERCENTILE_CONT`` function: + +.. code-block:: postgres + + SELECT + PERCENTILE_CONT(0.18) WITHIN GROUP (ORDER BY score) + FROM players; + + percentile_cont| + ---------------+ + 12.8 + +.. note:: The output value is an extrapolation of the halfway point between the values. diff --git a/reference/sql/sql_functions/aggregate_functions/percentile_disc.rst b/reference/sql/sql_functions/aggregate_functions/percentile_disc.rst new file mode 100644 index 000000000..e5c1fffc3 --- /dev/null +++ b/reference/sql/sql_functions/aggregate_functions/percentile_disc.rst @@ -0,0 +1,62 @@ +.. _percentile_disc: + +************************** +PERCENTILE_DISC +************************** +The **PERCENTILE_DISC** function returns the value located in the selected percentile of a specified column. The required input is a number between **0** and **1** that represents the wanted percentile and the column that you want to rank. If the selected percentile does not have an exact value, this function returns the closest value beneath the requested percentile. + +The **PERCENTILE_DISC** function returns an exact value based on the closest values in your data to the requested percentile. If you want to see an extrapolated value in your data closest to the requested percentile, use `PERCENTILE CONT `_. + +Syntax +======== +The following is the correct syntax for the ``PERCENTILE_DISC`` function: + +.. code-block:: postgres + + PERCENTILE_DISC(double) WITHIN GROUP (ORDER BY ) + +Example +======== +The example in this section is based on the ``players`` table below: + +.. list-table:: + :widths: 33 33 33 + :header-rows: 1 + ++-----------------+----------+-----------+ +| **Player_Name** | **Team** | **Score** | ++-----------------+----------+-----------+ +| T_Tock | Blue | 12 | ++-----------------+----------+-----------+ +| N_Stein | Blue | 23 | ++-----------------+----------+-----------+ +| F_Dirk | Blue | 45 | ++-----------------+----------+-----------+ +| Y_Hyung | Blue | 19 | ++-----------------+----------+-----------+ +| A_Rodrick | Blue | 37 | ++-----------------+----------+-----------+ +| R_Evans | Red | 52 | ++-----------------+----------+-----------+ +| C_Johnston | Red | 43 | ++-----------------+----------+-----------+ +| K_Stoll | Red | 27 | ++-----------------+----------+-----------+ +| J_Loftus | Red | 8 | ++-----------------+----------+-----------+ +| L_Ellis | Red | 13 | ++-----------------+----------+-----------+ +| G_Elroy | Red | 31 | ++-----------------+----------+-----------+ + +The following is an example of the ``PERCENTILE_DISC`` function: + +.. code-block:: postgres + + SELECT + PERCENTILE_DISC(0.15) WITHIN GROUP (ORDER BY score) + FROM players; + + percentile_disc| + ---------------+ + 12 diff --git a/reference/sql/sql_functions/index.rst b/reference/sql/sql_functions/index.rst index 5d02b27a6..bb2e581f6 100644 --- a/reference/sql/sql_functions/index.rst +++ b/reference/sql/sql_functions/index.rst @@ -382,6 +382,7 @@ Workload management functions :glob: scalar_functions/index + user_defined_functions/index aggregate_functions/index - window_functions/* - system_functions/* + window_functions/index + system_functions/index diff --git a/reference/sql/sql_functions/user_defined_functions/index.rst b/reference/sql/sql_functions/user_defined_functions/index.rst new file mode 100644 index 000000000..7f45e637e --- /dev/null +++ b/reference/sql/sql_functions/user_defined_functions/index.rst @@ -0,0 +1,25 @@ +.. _user_defined_functions_index: + +******************** +User-Defined Functions +******************** + +The following user-defined functions are functions that can be defined and configured by users: + + + +* `Python user-defined functions `_. +* `Scalar SQL user-defined functions `_. + + + + +.. toctree:: + :maxdepth: 8 + :glob: + :hidden: + + + + python_functions + scalar_sql_udf diff --git a/reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.rst b/reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.rst new file mode 100644 index 000000000..de399c3ff --- /dev/null +++ b/reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.rst @@ -0,0 +1,101 @@ +.. _scalar_sql_udf: + +Scalar SQL UDF +----------------------- +A **scalar SQL UDF** is a user-defined function that returns a single value, such as the sum of a group of values. Scalar UDFs are different than table-value functions, which return a result set in the form of a table. + +This page describes the correct syntax when building simple scalar UDFs and provides three examples. + +Syntax +~~~~~~~~~~~~ + +The following example shows the correct syntax for simple scalar SQL UDF's returning the type name: + +.. code-block:: console + + $ create_function_statement ::= + $ CREATE [ OR REPLACE ] FUNCTION function_name (argument_list) + $ RETURNS return_type + $ AS $$ + $ { function_body } + $ $$ LANGUAGE SQL + $ ; + $ + $ function_name ::= identifier + $ argument_list :: = { value_name type_name [, ...] } + $ value_name ::= identifier + $ return_type ::= type_name + $ function_body ::= A valid SQL statement + +Examples +~~~~~~~~~~ +Example 1 – Support for Different Syntax +############ +Scalar SQL UDF supports standard functionality even when different syntax is used. + +In the example below, the syntax ``dateadd`` is used instead of ``add_months``, although the function of each is identical. In addition, the operation works correctly even though the order of the expressions in ``add_months`` (``dt``, ``datetime``, and ``n int``) is different than ``MONTH``, ``n``, and ``dt`` in ``dateadd``. + +.. code-block:: console + + $ CREATE or replace FUNCTION add_months(dt datetime,n int) + $ RETURNS datetime + $ AS $$ + $ SELECT dateadd(MONTH ,n,dt) + $ $$ LANGUAGE SQL; + +Example 2 – Manipulating Strings +############ +The Scalar SQL UDF can be used to manipulate strings. + +The following example shows the correct syntax for converting a TEXT date to the DATE type: + +.. code-block:: console + + $ CREATE or replace FUNCTION STR_TO_DATE(f text) + $ RETURNS date + $ AS $$ + $ select (substring(f,1,4)||'-'||substring(f,5,2)||'-'||substring(f,7,2))::date + $ $$ LANGUAGE SQL; + +Example 3 – Manually Building Functionality +############ +You can use the Scalar SQL UDF to manually build functionality for otherwise unsupported operations. + +.. code-block:: console + + $ CREATE OR REPLACE function "least_sq" (a float, b float) -- Replace the LEAST(from hql) function + $ returns float as + $ $$select case + $ when a <= b then a + $ when b < a then b + $ when a is null then b + $ when b is null then a + $ else null + $ end; + $ $$ + $ language sql; + +Usage Notes +~~~~~~~~~~~~~~ +The following usage notes apply when using simple scalar SQL UDF's: + +* During this stage, the SQL embedded in the function body must be of the type ``SELECT expr;``. Creating a UDF with invalid SQL, or with valid SQL of any other type, results in an error. +* As with Python UDFs, the argument list can be left empty. +* SQL UDFs can reference other UDF's, including Python UDF's. + +**NOTICE:** A function cannot (directly or indirectly) reference itself (such as by referencing another function that references it). + +Because SQL UDF's are one type of supported UDFs, the following Python UDF characteristics apply: + +* UDF permission rules - see `Access Control `_. + +* The ``get_function_ddl`` utility function works on these functions - see `Getting the DDL for a Function `_. + +* SQL UDF's should appear in the catalog with Python UDF's - see `Finding Existing UDFs in the Catalog `_. + +Restrictions +~~~~~~~~~~~~~~~~ +The following restrictions apply to simple scalar SQL UDFs: + +* Simple scalar SQL UDF's cannot currently reference other UDFs. +* Like Python UDF's, Sqream does not support overloading. diff --git a/reference/sql/sql_functions/user_defined_functions/simple_scalar_sql_udf.rst b/reference/sql/sql_functions/user_defined_functions/simple_scalar_sql_udf.rst new file mode 100644 index 000000000..1a78e2e8c --- /dev/null +++ b/reference/sql/sql_functions/user_defined_functions/simple_scalar_sql_udf.rst @@ -0,0 +1,51 @@ +.. _simple_scalar_sql_udf: + +************************** +Simple Scalar SQL UDF's +************************** + +Syntax +~~~~~~~~~~~~ +The following example shows the correct syntax for simple scalar SQL UDF's: + + + .. code-block:: console + + $ create_function_statement ::= + $ CREATE [ OR REPLACE ] FUNCTION function_name (argument_list) + $ RETURNS return_type + $ AS $$ + $ { function_body } + $ $$ LANGUAGE SQL + $ ; + $ + $ function_name ::= identifier + $ argument_list :: = { value_name type_name [, ...] } + $ value_name ::= identifier + $ return_type ::= type_name + $ function_body ::= A valid SQL statement + +Usage Notes +~~~~~~~~~~~~~~ +The following usage notes apply when using simple scalar SQL UDF's: + +* During this stage, the SQL embedded in the function body must be of the type ``SELECT expr;``. Creating a UDF with invalid SQL, or with valid SQL of any other type, results in an error. +* As with Python UDFs, the argument list can be left empty. +* SQL UDFs can reference other UDF's, including Python UDF's. + +**NOTICE:** A function cannot (directly or indirectly) reference itself (such as by referencing another function that references it). + +Because SQL UDF's are one type of supported UDFs, the following Python UDF characteristics apply: + +* UDF permission rules - see `Access Control `_. + +* The ``get_function_ddl`` utility function works on these functions - see `Getting the DDL for a Function `_. + +* SQL UDF's should appear in the catalog with Python UDF's - see `Finding Existing UDFs in the Catalog `_. + +Restrictions +~~~~~~~~~~~~~~~~~~~~~ +The following restrictions apply to simple scalar SQL UDF's: + +* Simple scalar SQL UDF's cannot currently reference other UDF's. +* Like Python UDF's, Sqream does not support overloading. diff --git a/reference/sql/sql_functions/window_functions/cume_dist.rst b/reference/sql/sql_functions/window_functions/cume_dist.rst new file mode 100644 index 000000000..1af80bb78 --- /dev/null +++ b/reference/sql/sql_functions/window_functions/cume_dist.rst @@ -0,0 +1,23 @@ +.. _cume_dist: + +************************** +CUME_DIST +************************** + +The **CUME_DIST** function returns the cumulative distribution for each of your partitioned rows between the range of ``1/n`` (with ``n`` being the total number of rows), and ``1``. For example, in a table with ten rows, the cumulative distance for the first row is ``0.1`` and the second is ``0.2``, etc. The cumulative distance of the final row is always ``1``. + +Syntax +------- +The following shows the correct syntax for the CUME_DIST function. + +.. code-block:: postgres + + CUME_DIST ( ) OVER (...) + +Arguments +--------- +None + +Returns +--------- +Returns the cumulative distribution for each of your partitioned rows. diff --git a/reference/sql/sql_functions/window_functions/dense_rank.rst b/reference/sql/sql_functions/window_functions/dense_rank.rst new file mode 100644 index 000000000..d9aabf5dc --- /dev/null +++ b/reference/sql/sql_functions/window_functions/dense_rank.rst @@ -0,0 +1,23 @@ +.. _dense_rank: + +************************** +DENSE_RANK +************************** + +The **DENSE_RANK** function returns data ranking information and is similar to the **RANK** function. Its main difference is related to the results of identical line values. While the RANK function proceeds with the next row after providing the same value for identical consecutive rows (for example, 1,1,3), the DENSE_RANK function proceeds with the next number in the sequence (1,1,2). + +Syntax +------- +The following shows the correct syntax for the DENSE_RANK function. + +.. code-block:: postgres + + DENSE_RANK ( ) OVER (...) + +Arguments +--------- +None + +Returns +--------- +Returns data ranking information. diff --git a/reference/sql/sql_functions/window_functions/first_value.rst b/reference/sql/sql_functions/window_functions/first_value.rst new file mode 100644 index 000000000..07708872d --- /dev/null +++ b/reference/sql/sql_functions/window_functions/first_value.rst @@ -0,0 +1,24 @@ +.. _first_value: + +************************** +FIRST_VALUE +************************** +The **FIRST_VALUE** function returns the value located in the selected column of the first row of a segment. If the table is not segmented, the FIRST_VALUE function returns the value from the first row of the whole table. + +This function returns the same type of variable that you input for your requested value. For example, requesting the value for the first employee in a list using an ``int`` type output returns an ``int`` type ID column. If you use a ``varchar`` type, the function returns a ``varchar`` type name column. + +Syntax +------- +The following shows the correct syntax for the FIRST_VALUE function. + +.. code-block:: postgres + + FIRST_VALUE(Selected_Column) OVER (...) + +Arguments +--------- +None + +Returns +--------- +Returns the value located in the selected column of the first row of a segment. diff --git a/reference/sql/sql_functions/window_functions/index.rst b/reference/sql/sql_functions/window_functions/index.rst index fffba9a0a..4061ad239 100644 --- a/reference/sql/sql_functions/window_functions/index.rst +++ b/reference/sql/sql_functions/window_functions/index.rst @@ -1,7 +1,7 @@ -.. _window_functions_functions: +.. _window_functions: ******************** -Window functions +Window Functions ******************** Window functions are functions applied over a subset (known as a window) of the rows returned by a :ref:`select` query. @@ -10,6 +10,7 @@ Read more about :ref:`window_functions` in the :ref:`sql_syntax` section. .. toctree:: :maxdepth: 1 + :caption: Window Functions: :glob: :hidden: @@ -17,7 +18,12 @@ Read more about :ref:`window_functions` in the :ref:`sql_syntax` section. lead row_number rank + first_value + last_value + nth_value + dense_rank + percent_rank + cume_dist + ntile + -.. include:: /reference/sql/sql_syntax/window_functions.rst - :start-line: 9 - :end-line: 100 diff --git a/reference/sql/sql_functions/window_functions/last_value.rst b/reference/sql/sql_functions/window_functions/last_value.rst new file mode 100644 index 000000000..3cadaa9d1 --- /dev/null +++ b/reference/sql/sql_functions/window_functions/last_value.rst @@ -0,0 +1,24 @@ +.. _last_value: + +************************** +LAST_VALUE +************************** +The **LAST_VALUE** function returns the value located in the selected column of the last row of a segment. If the table is not segmented, the LAST_VALUE function returns the value from the last row of the whole table. + +This function returns the same type of variable that you input for your requested value. For example, requesting the value for the last employee in a list using an ``int`` type output returns an ``int`` type ID column. If you use a ``varchar`` type, the function returns a ``varchar`` type name column. + +Syntax +------- +The following shows the correct syntax for the LAST_VALUE function. + +.. code-block:: postgres + + LAST_VALUE(Selected_Column) OVER (...) + +Arguments +--------- +None + +Returns +--------- +Returns the value located in the selected column of the last row of a segment. diff --git a/reference/sql/sql_functions/window_functions/nth_value.rst b/reference/sql/sql_functions/window_functions/nth_value.rst new file mode 100644 index 000000000..a2c1dd9a6 --- /dev/null +++ b/reference/sql/sql_functions/window_functions/nth_value.rst @@ -0,0 +1,74 @@ +.. _nth_value: + +************************** +NTH_VALUE +************************** + +The **NTH_VALUE** function returns the value located in the selected column of a specified row of a segment. While the NTH_VALUE function is identical to the FIRST_VALUE and LAST_VALUE functions, it requires you to add a literal and whole ``int`` type ``n`` value representing the row number containing the value that you want. If you select an ``n`` value larger than the number of rows in the table, the NTH_VALUE function returns ``NULL``. + +Syntax +------- +The following shows the correct syntax for the NTH_VALUE function. + +.. code-block:: postgres + + NTH_VALUE(Selected_Column, n) OVER (...) + +Examples +--------- +The following example shows the syntax for a table named ``superstore`` used for tracking item sales in thousands: + +.. code-block:: postgres + + CREATE TABLE superstore + ( + "Section" varchar(40), + "Product_Name" varchar(40), + "Sales_In_K" int, + ); + +The following example shows the output of the syntax above: + +.. list-table:: + :widths: 24 26 50 + :header-rows: 1 + + * - Section + - Product_Name + - Sales_In_K + * - bed + - pillow_case + - 17 + * - bath + - rubber_duck + - 22 + * - beyond + - curtain + - 15 + * - bed + - side_table + - 8 + * - bath + - shampoo + - 9 + * - bed + - blanket + - 7 + * - bath + - bath_bomb + - 13 + * - bath + - conditioner + - 17 + * - beyond + - lamp + - 7 + * - bath + - soap + - 13 + * - beyond + - rug + - 12 + * - bed + - pillow + - 17 diff --git a/reference/sql/sql_functions/window_functions/ntile.rst b/reference/sql/sql_functions/window_functions/ntile.rst new file mode 100644 index 000000000..d40b197bf --- /dev/null +++ b/reference/sql/sql_functions/window_functions/ntile.rst @@ -0,0 +1,22 @@ +.. _ntile: + +************************** +NTILE +************************** + +The **NTILE** function returns an integer ranging between ``1`` and the argument value, and divides a table's rows into ``n`` ranked buckets according to the following: + +* The selected column. +* The selected positive, literal ``n``. + +Selecting an ``n`` that exceeds the number of rows in a table outputs a result identical to the RANK function. When this happens, each ranked bucket is populated with a single value and any bucket numbered higher than the number of rows not even being created. + +Additionally, if the number of rows in a bucket is not exactly divisible by ``n``, the function gives precedence to values at the top. For example, if ``n`` is ``6`` for 63 values, the top three buckets each have 11 values, and the bottom three each have 10. + +Syntax +------- +The following shows the correct syntax for the NTILE function. + +.. code-block:: postgres + + NTILE(n) OVER (...) diff --git a/reference/sql/sql_functions/window_functions/percent_rank.rst b/reference/sql/sql_functions/window_functions/percent_rank.rst new file mode 100644 index 000000000..9f1120a46 --- /dev/null +++ b/reference/sql/sql_functions/window_functions/percent_rank.rst @@ -0,0 +1,28 @@ +.. _percent_rank: + +************************** +PERCENT_RANK +************************** + +The **PERCENT_RANK** function returns relative data ranking information and is similar to the **RANK** function. + +It differs from the RANK function in the following ways: + +* The output type is ``double`` instead of ``bigint``. +* Shows ranking as a *relative* rank number (for example, a number between and including ``0`` and ``1``), and not an *absolute* rank number (for example, ``1``, ``1``, ``3``). + +Syntax +------- +The following shows the correct syntax for the PERCENT_RANK function. + +.. code-block:: postgres + + PERCENT_RANK ( ) OVER (...) + +Arguments +--------- +None + +Returns +--------- +Returns relative data ranking information in the form of a number between (and including) ``0`` and ``1``. diff --git a/third_party_tools/client_platforms/index.rst b/third_party_tools/client_platforms/index.rst index 3b1fd8207..4575bb430 100644 --- a/third_party_tools/client_platforms/index.rst +++ b/third_party_tools/client_platforms/index.rst @@ -3,7 +3,6 @@ ************************************ Client Platforms ************************************ - These topics explain how to install and connect a variety of third party tools. Browse the articles below, in the sidebar, or use the search to find the information you need. @@ -22,6 +21,8 @@ If you are looking for a tool that is not listed, SQream and our partners can he :caption: In this section: :titlesonly: + power_bi + sas_viya sql_workbench tableau pentaho @@ -30,10 +31,7 @@ If you are looking for a tool that is not listed, SQream and our partners can he r php xxspotfire - sas_viya xxtalend xxdiagnosing_common_connectivity_issues -.. image:: /_static/images/connectivity_ecosystem.png - - +.. image:: /_static/images/connectivity_ecosystem.png \ No newline at end of file From 4f490deec28da2d1acba4e29445069035bec6261 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 14 Mar 2022 10:35:12 +0200 Subject: [PATCH 208/300] Redirects Added and modified inserting_data.rst. --- data_ingestion/index.rst | 6 +++--- data_ingestion/inserting_data.rst | 30 +++++++++++++++--------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/data_ingestion/index.rst b/data_ingestion/index.rst index d626dcd22..8ebb646c1 100644 --- a/data_ingestion/index.rst +++ b/data_ingestion/index.rst @@ -3,16 +3,16 @@ ************************* Data Ingestion Sources ************************* -The **Data Ingestion Sources** provides information about the following data ingestion sources: +The **Data Ingestion Sources** provides information about the following: .. toctree:: :maxdepth: 1 :glob: - xxavro + inserting_data csv parquet orc oracle -For information about database tools and interfaces that SQream supports, see `Third Party Tools `_. +For information about database tools and interfaces that SQream supports, see `Third Party Tools `_. \ No newline at end of file diff --git a/data_ingestion/inserting_data.rst b/data_ingestion/inserting_data.rst index 93200d927..660cd61bd 100644 --- a/data_ingestion/inserting_data.rst +++ b/data_ingestion/inserting_data.rst @@ -1,19 +1,19 @@ .. _inserting_data: *************************** -Inserting data +Inserting Data Overview *************************** -This guide covers inserting data into SQream DB, with subguides on inserting data from a variety of sources and locations. +The **Inserting Data Overview** page describes how to insert data into SQream, specifically how to insert data from a variety of sources and locations. .. contents:: In this topic: :local: -Data loading overview +Getting Started ================================ -SQream DB supports importing data from the following sources: +SQream supports importing data from the following sources: * Using :ref:`insert` with :ref:`a client driver` * Using :ref:`copy_from`: @@ -35,10 +35,10 @@ SQream DB supports loading files in the following formats: * Parquet * ORC -Data loading considerations +Data Loading Considerations ================================ -Verify data and performance after load +Verifying Data and Performance after Loading ----------------------------------------- Like other RDBMSs, SQream DB has its own set of best practcies for table design and query optimization. @@ -55,7 +55,7 @@ SQream therefore recommends: * Data types were not over-provisioned (e.g. don't use VARCHAR(2000) to store a short string) -File source location for loading +File Soure Location when Loading -------------------------------- During loading using :ref:`copy_from`, the statement can run on any worker. If you are running multiple nodes, make sure that all nodes can see the source the same. If you load from a local file which is only on 1 node and not on shared storage, it will fail some of the time. (If you need to, you can also control which node a statement runs on using the :ref:`workload_manager`). @@ -93,19 +93,19 @@ SQream DB's :ref:`COPY FROM` syntax can be used to load CSV files, bu - ✗ - ✓ (Python, JDBC, Node.JS) -Unsupported data types +Unsupported Data Types ----------------------------- SQream DB doesn't support the entire set of features that some other database systems may have, such as ``ARRAY``, ``BLOB``, ``ENUM``, ``SET``, etc. These data types will have to be converted before load. For example, ``ENUM`` can often be stored as a ``VARCHAR``. -Extended error handling +Handing Extended Errors ---------------------------- While :ref:`external tables` can be used to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options, as well as extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. -Best practices for CSV +Best Practices for CSV ------------------------------ Text files like CSV rarely conform to `RFC 4180 `_ , so alterations may be required: @@ -126,14 +126,14 @@ Text files like CSV rarely conform to `RFC 4180 Date: Mon, 14 Mar 2022 11:27:10 +0200 Subject: [PATCH 209/300] Update index.rst --- operational_guides/index.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 8de3e83c9..b7ea1502d 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -12,11 +12,10 @@ This section summarizes the following operational guides: :glob: :titlesonly: - access_control - optimization_best_practices creating_or_cloning_a_storage_cluster external_data + external_tables exporting_data logging monitoring_query_performance @@ -24,4 +23,5 @@ This section summarizes the following operational guides: saved_queries seeing_system_objects_as_ddl configuration - hardware_guide \ No newline at end of file + optimization_best_practices + hardware_guide From 90dca8d48aadae1c2bb78610fe3568bc6b76a09e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 15 Mar 2022 16:45:12 +0200 Subject: [PATCH 210/300] Removed duplicate files Removed admin_flags and generic_flags folders. --- configuration_guides/admin/admin_flags.rst | 44 ------------ .../generic/generic_flags.rst | 18 ----- configuration_guides/generic/spooling.rst | 69 ------------------- 3 files changed, 131 deletions(-) delete mode 100644 configuration_guides/admin/admin_flags.rst delete mode 100644 configuration_guides/generic/generic_flags.rst delete mode 100644 configuration_guides/generic/spooling.rst diff --git a/configuration_guides/admin/admin_flags.rst b/configuration_guides/admin/admin_flags.rst deleted file mode 100644 index c4c170841..000000000 --- a/configuration_guides/admin/admin_flags.rst +++ /dev/null @@ -1,44 +0,0 @@ -.. _admin_flags: - -************************* -Administration Flags -************************* - -The **Administration Flags** page describes the following flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: - - -.. toctree:: - :maxdepth: 1 - :glob: - - bin_sizes - check_Cuda_Memory - compiler_Gets_Only_UFs - copy_To_Restrict_Utf8 - cpu_Reduce_Hashtable_Size - csv_Limit_Row_Length - cuda_Mem_cpy_Max_Size_Bytes - Cuda_Mem_cpy_Synchronous - cuda_Mem_Quota - developer_Mode - enable_Device_Debug_Messages - enable_LogDebug - enable_Nv_prof_Markers - end_Log_Message - extent_Storage_File_Size_MB - gather_Mem_Stat - increase_Chunk_Size_Before_Reduce - increase_Mem_Factors - level_db_Write_Buffer_Size - machine_IP - memory_Reset_Trigger_MB - metadata_Server_Port - mt_Read - mt_Read_Workers - orc_Implicit_Casts - statement_Lock_Timeout - use_Config_IP - use_Legacy_Decimal_Literals - use_Legacy_String_Literals - - diff --git a/configuration_guides/generic/generic_flags.rst b/configuration_guides/generic/generic_flags.rst deleted file mode 100644 index 879e2eac1..000000000 --- a/configuration_guides/generic/generic_flags.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _generic_flags: - -************************* -Generic Flags -************************* - -The **Administration Flags** page describes the following flags, which can be modified by standard users on a session basis: - - -.. toctree:: - :maxdepth: 1 - :glob: - - flip_Join_Order - limit_query_memory_gb - log_Sys_Level - max_Avg_Blob_Size_To_Compress_On_Gpu - spool_memory_gb \ No newline at end of file diff --git a/configuration_guides/generic/spooling.rst b/configuration_guides/generic/spooling.rst deleted file mode 100644 index dcf1c775f..000000000 --- a/configuration_guides/generic/spooling.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. _spooling: - -************************** -Configuring the Spooling Feature -************************** -The **Configuring the Spooling Feature** page includes the following topics: - -.. contents:: - :local: - :depth: 1 - - -Overview ----------- -From the SQream Acceleration Studio you can allocate the amount of memory (GB) available to the server for spooling using the ``spoolMemoryGB`` flag. SQream recommends setting the ``spoolMemoryGB`` flag to 90% of the ``limitQueryMemoryGB`` flag. The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. - -In addition, the ``limitQueryMemoryGB`` defines how much total system memory is used by each worker. SQream recommends setting ``limitQueryMemoryGB`` to 5% less than the total host memory divided by the amount of ``sqreamd`` workers on host. - -Note that ``spoolMemoryGB`` must bet set to less than the ``limitQueryMemoryGB``. - -Example Configurations ----------- -The **Example Configurations** section shows the following example configurations: - -.. contents:: - :local: - :depth: 1 - -Example 1 - Recommended Settings -~~~~~~~~~~~ -The following is an example of the recommended settings for a machine with 512GB of RAM and 4 workers: - -.. code-block:: console - - limitQueryMemoryGB - ⌊(512 * 0.95 / 4)⌋ → ~ 486 / 4 → 121 - spoolMemoryGB - ⌊( 0.9 * limitQueryMemoryGB )⌋ → ⌊( 0.9 * 121 )⌋ → 108 - -Example 2 - Setting Spool Memory -~~~~~~~~~~~ -The following is an example of setting ``spoolMemoryGB`` value in the current configuration method per-worker for 512GB of RAM and 4 workers: - -.. code-block:: console - - { - “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, - “gpu”: 0, - “licensePath”: “home/test_user/SQream/tests/license.enc”, - “machineIP”: “127.0.0.1”, - “metadataServerIp”: “127.0.0.1”, - “metadataServerPort”: “3105, - “port”: 5000, - “useConfigIP”” true, - “limitQueryMemoryGB" : 121, - “spoolMemoryGB" : 108 - “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” - } - -The following is an example of setting ``spoolMemoryGB`` value in the previous configuration method per-worker for 512GB of RAM and 4 workers: - -.. code-block:: console - - “runtimeFlags”: { - “limitQueryMemoryGB” : 121, - “spoolMemoryGB” : 108 - -For more information about configuring the ``spoolMemoryGB`` flag, see the following: - -* **Current configuration method**: Configuration flags -* **Previous configuration method**: Runtime global flags \ No newline at end of file From 667bba9621d01f078484fc466a7dfa77b594437a Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 20 Mar 2022 10:37:26 +0200 Subject: [PATCH 211/300] Restored Tibco Restored Tibco. Was accidentally removed from index. --- .../client_platforms/connect2.sas | 27 ++ .../client_platforms/connect3.sas | 17 + third_party_tools/client_platforms/index.rst | 2 +- .../client_platforms/tibco_spotfire.rst | 387 ++++++++++++++++++ 4 files changed, 432 insertions(+), 1 deletion(-) create mode 100644 third_party_tools/client_platforms/connect2.sas create mode 100644 third_party_tools/client_platforms/connect3.sas create mode 100644 third_party_tools/client_platforms/tibco_spotfire.rst diff --git a/third_party_tools/client_platforms/connect2.sas b/third_party_tools/client_platforms/connect2.sas new file mode 100644 index 000000000..10fcdb0a2 --- /dev/null +++ b/third_party_tools/client_platforms/connect2.sas @@ -0,0 +1,27 @@ +options sastrace='d,d,d,d' +sastraceloc=saslog +nostsuffix +msglevel=i +sql_ip_trace=(note,source) +DEBUG=DBMS_SELECT; + +options validvarname=any; + +libname sqlib jdbc driver="com.sqream.jdbc.SQDriver" + classpath="/opt/sqream/sqream-jdbc-4.0.0.jar" + URL="jdbc:Sqream://sqream-cluster.piedpiper.com:3108/raviga;cluster=true" + user="rhendricks" + password="Tr0ub4dor3" + schema="public" + PRESERVE_TAB_NAMES=YES + PRESERVE_COL_NAMES=YES; + +proc sql; + title 'Customers table'; + select * + from sqlib.customers; +quit; + +data sqlib.customers; + set sqlib.customers; +run; \ No newline at end of file diff --git a/third_party_tools/client_platforms/connect3.sas b/third_party_tools/client_platforms/connect3.sas new file mode 100644 index 000000000..c1bf11dcf --- /dev/null +++ b/third_party_tools/client_platforms/connect3.sas @@ -0,0 +1,17 @@ +options sastrace='d,d,d,d' +sastraceloc=saslog +nostsuffix +msglevel=i +sql_ip_trace=(note,source) +DEBUG=DBMS_SELECT; + +options validvarname=any; + +libname sqlib jdbc driver="com.sqream.jdbc.SQDriver" + classpath="/opt/sqream/sqream-jdbc-4.0.0.jar" + URL="jdbc:Sqream://sqream-cluster.piedpiper.com:3108/raviga;cluster=true" + user="rhendricks" + password="Tr0ub4dor3" + schema="public" + PRESERVE_TAB_NAMES=YES + PRESERVE_COL_NAMES=YES; \ No newline at end of file diff --git a/third_party_tools/client_platforms/index.rst b/third_party_tools/client_platforms/index.rst index 4575bb430..1ed2874ed 100644 --- a/third_party_tools/client_platforms/index.rst +++ b/third_party_tools/client_platforms/index.rst @@ -22,6 +22,7 @@ If you are looking for a tool that is not listed, SQream and our partners can he :titlesonly: power_bi + tibco_spotfire sas_viya sql_workbench tableau @@ -30,7 +31,6 @@ If you are looking for a tool that is not listed, SQream and our partners can he informatica r php - xxspotfire xxtalend xxdiagnosing_common_connectivity_issues diff --git a/third_party_tools/client_platforms/tibco_spotfire.rst b/third_party_tools/client_platforms/tibco_spotfire.rst new file mode 100644 index 000000000..4c032ba84 --- /dev/null +++ b/third_party_tools/client_platforms/tibco_spotfire.rst @@ -0,0 +1,387 @@ +.. _tibco_spotfire: + + +************************* +Connecting to SQream Using TIBCO Spotfire +************************* +Overview +========= +The **TIBCO Spotfire** software is an analytics solution that enables visualizing and exploring data through dashboards and advanced analytics. + +This document is a Quick Start Guide that describes the following: + +.. contents:: + :local: + :depth: 1 + +Establishing a Connection between TIBCO Spotfire and SQream +----------------- +TIBCO Spotfire supports the following versions: + +* **JDBC driver** - Version 4.5.2 +* **ODBC driver** - Version 4.1.1 + +SQream supports TIBCO Spotfire version 7.12.0. + +The **Establishing a JDBC Connection between TIBCO Spotfire and SQream** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Creating a JDBC Connection +~~~~~~~~~~~ +For TIBCO Spotfire to recognize SQream, you must add the correct JDBC jar file to Spotfire's loaded binary folder. The following is an example of a path to the Spotfire loaded binaries folder: ``C:\tibco\tss\7.12.0\tomcat\bin``. + +For the complete TIBCO Spotfire documentation, see `TIBCO Spotfire® JDBC Data Access Connectivity Details `_. + +Creating an ODBC Connection +~~~~~~~~~~~ +**To create an ODBC connection** + +1. Install and configure ODBC on Windows. + + For more information, see :ref:`Install and Configure ODBC on Windows`. + +#. Launch the TIBCO Spotfire application. + + :: + +#. From the **File** menu click **Add Data Tables**. + + The **Add Database Tables** window is displayed. + +#. Click **Add** and select **Database**. + + The **Open Database** window is displayed. + +#. In the **Data source type** area, select **ODBC SQream** (Odbc Data Provider) and click **Configure**. + + The **Configure Data Source and Connection** window is displayed. + +#. Select **System or user data source** and from the drop-down menu select the DSN of your data source (SQreamDB). + + :: + +#. Provide your database username and password and click **OK**. + + :: + +#. In the **Open Database** window, click **OK**. + + The **Specify Tables and Columns** window is displayed. + +#. In the **Specify Tables and Columns** window, select the checkboxes corresponding to the tables and columns that you want to include in your SQL statement. + + :: + +#. In the **Data source name** field, set your data source name and click **OK**. + + Your data source is displayed in the **Data tables** area. + +#. In the **Add Data Tables** dialog, click **OK** to load the data from your ODBC data source into Spotfire. + +.. note:: Verify that you have checked the SQL statement. + +Creating the SQream Data Source Template +~~~~~~~~~~~ +After creating a connection, you can create your SQream data source template. + +**To create your SQream data source template:** + +1. Log in to the TIBCO Spotfire Server Configuration Tool. + + :: + +#. From the **Configuration** tab, in the **Configuration Start** menu, click **Data Source Templates**. + + The **Data Source Templates** list is displayed. + +#. From the Data Source Templates list do one of the following: + + * Override an existing template: + + 1. In the template text field, select an existing template. + + :: + + 2. Copy and paste your data source template text. + + :: + + * Create a new template: + + 1. Click **New**. + + The **Add Data Source Template** window is displayed. + + .. _creating_sqream_data_source_template: + + 2. In the **Name** field, define your template name. + + :: + + 3. In the **Data Source Template** text field, copy and paste your data source template text. + + The following is an example of a data source template: + + .. code-block:: console + + + SQream + com.sqream.jdbc.SQDriver + jdbc:Sqream://<host>:<port>/database;user=sqream;password=sqream;cluster=true + true + true + false + TABLE,EXTERNAL_TABLE + + + Bool + Integer + + + VARCHAR(2048) + String + + + INT + Integer + + + BIGINT + LongInteger + + + Real + Real + + + Decimal + Float + + + Numeric + Float + + + Date + DATE + + + DateTime + DateTime + + + + + +4. Click **Save configuration**. + + :: + +5. Close and restart your Spotfire server. + +Creating a Data Source +~~~~~~~~~~~ +After creating the SQream data source template, you can create a data source. + +**To create a data source:** + +1. Launch the TIBCO Spotfire application. + + :: + +#. From the **Tools** menu, select **Information Designer**. + + The **Information Designer** window is displayed. + + :: + +#. From the **New** menu, click **Data Source**. + + The **Data Source** tab is displayed. + + :: + +#. Provide the following information: + + * **Name** - define a unique name. + + :: + + * **Type** - use the same type template name you used while configuring your template. See **Step 3** in :ref:`Creating the SQream Data Source Template`. + + :: + + * **Connection URL** - use the standard JDBC connection string, ``:/database``. + + :: + + * **No. of connections** - define a number between **1** and **100**. SQream recommends setting your number of connections to **100**. + + :: + + * **Username and Password** - define your SQream username and password. + +Creating an Information Link +~~~~~~~~~~~ +After creating a data source, you can create an information link. + +**To create an information link**: + +1. From the **Tools** menu, select **Information Designer**. + + The **Information Designer** window is displayed. + + :: + +#. From the **New** menu, click **Information Link**. + + The **Information link** tab is displayed. + +#. From the **Elements** tab, select a column type and click **Add**. + + The column type is added to the **Elements** region as a filter. + + Note the following: + + * You can select procedures from the Elements region. + + :: + + * You can remove an element by selecting an element and clicking **Remove**. + + .. tip:: If the Elements menu is not displayed, you can display it by clicking the **Elements** tab. You can simultaneously select multiple elements by pressing **Ctrl** and making additional selections, and select a range of elements by holding **Shift** and clicking two elements. + +#. If the elements you select originate from more than one data source table, specify a **Join path**. + +5. *Optional* - In the **Description** region, type the description of the information link. + + :: + +#. *Optional* - To filter your data, expand the **Filters** section and do the following: + + 1. From the **Information Link** region, select the element you added in Step 3 above. + + :: + + 2. Click **Add**. + + The **Add Column** window is displayed. + + 3. From the drop-down list, select a column to add a hard filter to and click **OK**. + + The selected column is added to the Filters list. + + 4. Repeat steps 2 and 3 to add filters to additional columns. + + :: + + 5. For each column, from the **Filter Type** drop-down list, select **range** or **values**. + + .. note:: Filtering by range means entering the upper and lower limits of the desired range. Filtering by values means entering the exact values that you want to include in the returned data, separated by semicolon. + + 6. In the **Values** field type the desired values separated with semicolons, or set the upper and lower limits in the **Min Value** and **Max Value** fields. Alternatively, you can type ``?param_name`` in the Values field to use a parameter as the filter for the selected column, where ``param_name`` is the name used to identify the parameter. + + .. note:: Because limits are inclusive, setting the lower limit to **1000** includes the value **1000** in the data table. + + .. note:: When setting upper and lower limits on **String** type columns, ``A`` precedes ``AA``, and a lone letter precedes words beginning with that latter. For example, ``S** precedes **Smith**, indicating that the name ``Smith`` will not be present when you select names from ``D`` to ``S``. The order of characters is standard ASCII. + + For more information on adding filters, see `Adding Hard Filters `_. + +7. *Optional* - To add runtime filtering prompts, expand the **Prompts** section and do the following: + + 1. Click **Add**. + + The **Add Column** window is displayed. + + #. From the **Select column** list, select a column to add a prompt to and click **OK**. + + The selected column is added to the Prompts list. + + #. Repeat **Step 1** to add prompts to additional columns. + + :: + + #. Do the following for each column: + + * Make a selection from the **Prompt Type** drop-down list. + * Select or clear **Mandatory**. + * *Optional* - Set your **Max Selections**. + + For more information on adding prompts, see `Adding Prompts `_. + +8. *Optional* - Expand the **Conditioning** section and specify one of the following conditions: + + * None + * Distinct + * Pivot + + Note that you can edit the Pivot conditioning by selecting **Pivot** and clicking **Edit**. + +9. *Optional* - Expand the **Parameters** section and define your parameters. + + :: + +10. *Optional* - Expand the **Properties** section and define your properties. + + :: + +11. *Optional* - Expand the **Caching** section and enable or disable whether your information link can be cached. + + :: + +12. Click **Save**. + + The **Save As** window is displayed. + +13. In the tree, select where you want to save the information link. + + :: + +14. In the **Name** field, type a name and description for the information link. + + :: + + +15. Click **Save**. + + The new information link is added to the library and can be accessed by other users. + +.. tip:: You can test the information link directly by clicking **Open Data**. You can also view and edit the SQL belonging to the information link by clicking **SQL**. + +For more information on the Information Link attributes, see `Information Link Tab `_. + +Troubleshooting +------------- +The **Troubleshooting** section describes the following scenarios: + +.. contents:: + :local: + :depth: 1 + +The JDBC Driver does not Support Boolean, Decimal, or Numeric Types +~~~~~~~~~~~ +When attempting to load data, the the Boolean, Decimal, or Numeric column types are not supported and generate the following error: + +.. code-block:: console + + Failed to execute query: Unsupported JDBC data type in query result: Bool (HRESULT: 80131500) + +The error above is resolved by casting the columns as follows: + +* ``Bool`` columns to ``INT``. +* ``Decimal`` and ``Numeric`` columns to ``REAL``. + +For more information, see the following: + +* **Resolving this error** - `Details on Change Data Types `_. + +* **Supported data types** - :ref:`Data Types`. + +Information Services do not Support Live Queries +~~~~~~~~~~~ +TIBCO Spotfire data connectors support live queries, but no APIs currently exist for creating custom data connectors. This is resolved by creating a customized SQream adapter using TIBCO's **Data Virtualization (TDV)** or the **Spotfire Advanced Services (ADS)**. These can be used from the built-in TDV connector to enable live queries. + +This resolution applies to JDBC and ODBC drivers. \ No newline at end of file From 6f5cf93dfec0d65ee9ea3087245ab65f412257cb Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 20 Mar 2022 11:05:34 +0200 Subject: [PATCH 212/300] Update current_configuration_method.rst Added All Configurations Table --- .../current_configuration_method.rst | 353 ++++++++++++++++++ 1 file changed, 353 insertions(+) diff --git a/configuration_guides/current_configuration_method.rst b/configuration_guides/current_configuration_method.rst index 9bd214b7b..f86500972 100644 --- a/configuration_guides/current_configuration_method.rst +++ b/configuration_guides/current_configuration_method.rst @@ -281,6 +281,359 @@ The following table describes the Worker flag types: * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` +All Configurations +--------------------- +The following table describes the **Generic** and **Administration** configuration flags: + +.. list-table:: + :header-rows: 1 + :widths: 1 2 1 15 1 20 + :class: my-class + :name: my-name + + * - Flag Name + - Access Control + - Modification Type + - Description + - Data Type + - Default Value + + * - ``binSizes`` + - Administration + - Regular + - Sets the custom bin size in the cache to enable high granularity bin control. + - string + - + ``16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,`` + ``131072,262144,524288,1048576,2097152,4194304,8388608,16777216,`` + ``33554432,67108864,134217728,268435456,536870912,786432000,107374,`` + ``1824,1342177280,1610612736,1879048192,2147483648,2415919104,`` + ``2684354560,2952790016,3221225472`` + + * - ``checkCudaMemory`` + - Administration + - Regular + - Sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. + - boolean + - ``FALSE`` + + * - ``compilerGetsOnlyUFs`` + - Administration + - Regular + - Sets the runtime to pass only utility functions names to the compiler. + - boolean + - ``FALSE`` + + * - ``copyToRestrictUtf8`` + - Administration + - Regular + - Sets the custom bin size in the cache to enable high granularity bin control. + - boolean + - ``FALSE`` + + * - ``cpuReduceHashtableSize`` + - Administration + - Regular + - Sets the hash table size of the CpuReduce. + - uint + - ``10000`` + + * - ``csvLimitRowLength`` + - Administration + - Cluster + - Sets the maximum supported CSV row length. + - uint + - ``100000`` + + * - ``cudaMemcpyMaxSizeBytes`` + - Administration + - Regular + - Sets the chunk size for copying from CPU to GPU. If set to 0, do not divide. + - uint + - ``0`` + + * - ``CudaMemcpySynchronous`` + - Administration + - Regular + - Indicates if copying from/to GPU is synchronous. + - boolean + - ``FALSE`` + + * - ``cudaMemQuota`` + - Administration + - Worker + - Sets the percentage of total device memory to be used by the instance. + - uint + - ``90`` + + * - ``developerMode`` + - Administration + - Regular + - Enables modifying R&D flags. + - boolean + - ``FALSE`` + + * - ``enableDeviceDebugMessages`` + - Administration + - Regular + - Activates the Nvidia profiler (nvprof) markers. + - boolean + - ``FALSE`` + + * - ``enableLogDebug`` + - Administration + - Regular + - Enables creating and logging in the clientLogger_debug file. + - boolean + - ``TRUE`` + + * - ``enableNvprofMarkers`` + - Administration + - Regular + - Activates the Nvidia profiler (nvprof) markers. + - boolean + - ``FALSE`` + + * - ``endLogMessage`` + - Administration + - Regular + - Appends a string at the end of every log line. + - string + - ``EOM`` + + + + * - ``varcharIdentifiers`` + - Administration + - Regular + - Activates using varchar as an identifier. + - boolean + - ``true`` + + + + * - ``extentStorageFileSizeMB`` + - Administration + - Cluster + - Sets the minimum size in mebibytes of extents for table bulk data. + - uint + - ``20`` + + * - ``gatherMemStat`` + - Administration + - Regular + - Monitors all pinned allocations and all **memcopies** to/from device, and prints a report of pinned allocations that were not memcopied to/from the device using the **dump_pinned_misses** utility function. + - boolean + - ``FALSE`` + + * - ``increaseChunkSizeBeforeReduce`` + - Administration + - Regular + - Increases the chunk size to reduce query speed. + - boolean + - ``FALSE`` + + * - ``increaseMemFactors`` + - Administration + - Regular + - Adds rechunker before expensive chunk producer. + - boolean + - ``TRUE`` + + * - ``leveldbWriteBufferSize`` + - Administration + - Regular + - Sets the buffer size. + - uint + - ``524288`` + + * - ``machineIP`` + - Administration + - Worker + - Manual setting of reported IP. + - string + - ``127.0.0.1`` + + + + + * - ``memoryResetTriggerMB`` + - Administration + - Regular + - Sets the size of memory used during a query to trigger aborting the server. + - uint + - ``0`` + + * - ``metadataServerPort`` + - Administration + - Worker + - Sets the port used to connect to the metadata server. SQream recommends using port ranges above 1024† because ports below 1024 are usually reserved, although there are no strict limitations. Any positive number (1 - 65535) can be used. + - uint + - ``3105`` + + * - ``mtRead`` + - Administration + - Regular + - Splits large reads to multiple smaller ones and executes them concurrently. + - boolean + - ``FALSE`` + + * - ``mtReadWorkers`` + - Administration + - Regular + - Sets the number of workers to handle smaller concurrent reads. + - uint + - ``30`` + + * - ``orcImplicitCasts`` + - Administration + - Regular + - Sets the implicit cast in orc files, such as **int** to **tinyint** and vice versa. + - boolean + - ``TRUE`` + + * - ``statementLockTimeout`` + - Administration + - Regular + - Sets the timeout (seconds) for acquiring object locks before executing statements. + - uint + - ``3`` + + * - ``useConfigIP`` + - Administration + - Worker + - Activates the machineIP (true). Setting to false ignores the machineIP and automatically assigns a local network IP. This cannot be activated in a cloud scenario (on-premises only). + - boolean + - ``FALSE`` + + * - ``useLegacyDecimalLiterals`` + - Administration + - Regular + - Interprets decimal literals as **Double** instead of **Numeric**. Used to preserve legacy behavior in existing customers. + - boolean + - ``FALSE`` + + * - ``useLegacyStringLiterals`` + - Administration + - Regular + - Interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. Used to preserve legacy behavior in existing customers. + - boolean + - ``FALSE`` + + * - ``flipJoinOrder`` + - Generic + - Regular + - Reorders join to force equijoins and/or equijoins sorted by table size. + - boolean + - ``FALSE`` + + * - ``limitQueryMemoryGB`` + - Generic + - Worker + - Prevents a query from processing more memory than the flag’s value. + - uint + - ``100000`` + + * - ``cacheEvictionMilliseconds`` + - Generic + - Regular + - Sets how long the cache stores contents before being flushed. + - size_t + - ``2000`` + + + * - ``cacheDiskDir`` + - Generic + - Regular + - Sets the ondisk directory location for the spool to save files on. + - size_t + - Any legal string + + + * - ``cacheDiskGB`` + - Generic + - Regular + - Sets the amount of memory (GB) to be used by Spool on the disk. + - size_t + - ``128`` + + * - ``cachePartitions`` + - Generic + - Regular + - Sets the number of partitions that the cache is split into. + - size_t + - ``4`` + + + * - ``cachePersistentDir`` + - Generic + - Regular + - Sets the persistent directory location for the spool to save files on. + - string + - Any legal string + + + * - ``cachePersistentGB`` + - Generic + - Regular + - Sets the amount of data (GB) for the cache to store persistently. + - size_t + - ``128`` + + + * - ``cacheRamGB`` + - Generic + - Regular + - Sets the amount of memory (GB) to be used by Spool InMemory. + - size_t + - ``16`` + + + + + + + + * - ``logSysLevel`` + - Generic + - Regular + - + Determines the client log level: + 0 - L_SYSTEM, + 1 - L_FATAL, + 2 - L_ERROR, + 3 - L_WARN, + 4 - L_INFO, + 5 - L_DEBUG, + 6 - L_TRACE + - uint + - ``100000`` + + * - ``maxAvgBlobSizeToCompressOnGpu`` + - Generic + - Regular + - Sets the CPU to compress columns with size above (flag’s value) * (row count). + - uint + - ``120`` + + + * - ``sessionTag`` + - Generic + - Regular + - Sets the name of the session tag. + - string + - Any legal string + + + + * - ``spoolMemoryGB`` + - Generic + - Regular + - Sets the amount of memory (GB) to be used by the server for spooling. + - uint + - ``8`` + + Configuration Commands ========== The configuration commands are associated with particular flag types based on permissions. From c0b674d01dfdf10c5616276f69a968a9ea7f34cc Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 20 Mar 2022 13:37:57 +0200 Subject: [PATCH 213/300] Update tibco_spotfire.rst Updated 4.5.2 to 4.5.3. --- third_party_tools/client_platforms/tibco_spotfire.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party_tools/client_platforms/tibco_spotfire.rst b/third_party_tools/client_platforms/tibco_spotfire.rst index 4c032ba84..b98ae0825 100644 --- a/third_party_tools/client_platforms/tibco_spotfire.rst +++ b/third_party_tools/client_platforms/tibco_spotfire.rst @@ -18,7 +18,7 @@ Establishing a Connection between TIBCO Spotfire and SQream ----------------- TIBCO Spotfire supports the following versions: -* **JDBC driver** - Version 4.5.2 +* **JDBC driver** - Version 4.5.3 * **ODBC driver** - Version 4.1.1 SQream supports TIBCO Spotfire version 7.12.0. From 8ff6cef37b3fadc83018df3b47c9d35c392b864a Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 22 Mar 2022 09:46:56 +0200 Subject: [PATCH 214/300] Update php.rst Removed line with broken download link. --- third_party_tools/client_platforms/php.rst | 72 +++++++++++++++------- 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/third_party_tools/client_platforms/php.rst b/third_party_tools/client_platforms/php.rst index 16dc89fe3..4410a8e0a 100644 --- a/third_party_tools/client_platforms/php.rst +++ b/third_party_tools/client_platforms/php.rst @@ -4,43 +4,71 @@ Connect to SQream Using PHP ***************************** -You can use PHP to interact with a SQream DB cluster. +Overview +========== +PHP is an open source scripting language that executes scripts on servers. The **Connect to PHP** page explains how to connect to a SQream cluster, and describes the following: -This tutorial is a guide that will show you how to connect a PHP application to SQream DB. - -.. contents:: In this topic: +.. contents:: :local: + :depth: 1 + +Installing PHP +------------------- +**To install PHP:** + +1. Download the JDBC driver installer from the `SQream Drivers page `_. + + :: + +2. Create a DSN. + + :: + +3. Install the **uODBC** extension for your PHP installation. + + For more information, navigate to `PHP Documentation `_ and see the topic menu on the right side of the page. -Prerequisites -=============== +Configuring PHP +------------------- +You can configure PHP in one of the following ways: + +* When compiling, configure PHP to enable uODBC using ``./configure --with-pdo-odbc=unixODBC,/usr/local``. -#. Install the :ref:`SQream DB ODBC driver for Linux` and create a DSN. + :: + +* Install ``php-odbc`` and ``php-pdo`` along with PHP using your distribution package manager. SQream recommends a minimum of version 7.1 for the best results. -#. - Install the `uODBC `_ extension for your PHP installation. - To configure PHP to enable uODBC, configure it with ``./configure --with-pdo-odbc=unixODBC,/usr/local`` when compiling php or install ``php-odbc`` and ``php-pdo`` along with php (version 7.1 minimum for best results) using your distribution package manager. +.. note:: PHP's string size limitations truncates fetched text, which you can override by doing one of the following: -Testing the connection -=========================== + * Increasing the **php.ini** default setting, such as the *odbc.defaultlrl* to **10000**. -#. - Create a test connection file. Be sure to use the correct parameters for your SQream DB installation. + :: + + * Setting the size limitation in your code before making your connection using **ini_set("odbc.defaultlrl", "10000");**. - Download this :download:`PHP example connection file ` . + :: + + * Setting the size limitation in your code before fetchng your result using **odbc_longreadlen($result, "10000");**. + +Operating PHP +------------------- +After configuring PHP, you can test your connection. + +**To test your connection:** + +#. Create a test connection file using the correct parameters for your SQream installation, as shown below: .. literalinclude:: test.php :language: php :emphasize-lines: 4 :linenos: - - .. tip:: - An example of a valid DSN line is: + + The following is an example of a valid DSN line: - .. code:: php + .. code:: php - $dsn = "odbc:Driver={SqreamODBCDriver};Server=192.168.0.5;Port=5000;Database=master;User=rhendricks;Password=super_secret;Service=sqream"; + $dsn = "odbc:Driver={SqreamODBCDriver};Server=192.168.0.5;Port=5000;Database=master;User=rhendricks;Password=super_secret;Service=sqream"; - For more information about supported DSN parameters, see :ref:`dsn_params`. - #. Run the PHP file either directly with PHP (``php test.php``) or through a browser. + For more information about supported DSN parameters, see :ref:`dsn_params`. \ No newline at end of file From 6e1c883ce4eeb465f385a2ff35a9e0af16c864eb Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 22 Mar 2022 15:31:16 +0200 Subject: [PATCH 215/300] Update create_table.rst Ticket SQ-9989. --- reference/sql/sql_statements/ddl_commands/create_table.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index b660e442c..9000e8310 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -74,7 +74,7 @@ Default Value Constraints The ``DEFAULT`` value constraint specifies a value to use if one is not defined in an :ref:`insert` or :ref:`copy_from` statement. -The value may be either a literal or **GETDATE()**, which is evaluated at the time the row is created. +The value may be either a literal, which is evaluated at the time the row is created. .. note:: The ``DEFAULT`` constraint only applies if the column does not have a value specified in the :ref:`insert` or :ref:`copy_from` statement. You can still insert a ``NULL`` into an nullable column by explicitly inserting ``NULL``. For example, ``INSERT INTO cool_animals VALUES (1, 'Gnu', NULL)``. @@ -82,7 +82,6 @@ Syntax --------- The following is the correct syntax for using the **DEFAULT** value constraints: - .. code-block:: postgres column_def :: = { column_name type_name [ default ] [ column_constraint ] } From b4fa3723b202ccb74b9ec237d65e38285c43877e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 23 Mar 2022 13:55:43 +0200 Subject: [PATCH 216/300] Updated System Functions Menu --- .../system_functions/explain.rst | 59 ++++ .../sql_functions/system_functions/index.rst | 20 ++ .../system_functions/show_connections.rst | 78 +++++ .../system_functions/show_locks.rst | 79 +++++ .../system_functions/show_node_info.rst | 310 ++++++++++++++++++ .../system_functions/show_server_status.rst | 108 ++++++ .../system_functions/stop_statement.rst | 77 +++++ 7 files changed, 731 insertions(+) create mode 100644 reference/sql/sql_functions/system_functions/explain.rst create mode 100644 reference/sql/sql_functions/system_functions/index.rst create mode 100644 reference/sql/sql_functions/system_functions/show_connections.rst create mode 100644 reference/sql/sql_functions/system_functions/show_locks.rst create mode 100644 reference/sql/sql_functions/system_functions/show_node_info.rst create mode 100644 reference/sql/sql_functions/system_functions/show_server_status.rst create mode 100644 reference/sql/sql_functions/system_functions/stop_statement.rst diff --git a/reference/sql/sql_functions/system_functions/explain.rst b/reference/sql/sql_functions/system_functions/explain.rst new file mode 100644 index 000000000..e9b7e7ee9 --- /dev/null +++ b/reference/sql/sql_functions/system_functions/explain.rst @@ -0,0 +1,59 @@ +.. _explain: + +***************** +EXPLAIN +***************** + +``EXPLAIN`` returns a static query plan, which can be used to debug query plans. + +To see an actively running query or statement, use :ref:`show_node_info` instead. + +See also :ref:`show_node_info`, :ref:`show_server_status`. + + +Permissions +============= + +The role must have the ``SELECT`` permissions for any tables referenced by the query. + +Syntax +========== + +.. code-block:: postgres + + explain_statement ::= + SELECT EXPLAIN(query_stmt) + ; + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``query_stmt`` + - The select query to generate the plan for. + +Notes +=========== + +Use dollar-quoting to escape the query text + +Examples +=========== + +Generating a static query plan +---------------------------------- + +.. code-block:: psql + + t=> SELECT EXPLAIN($$SELECT DATEADD(hour,1,dt) FROM cool_dates$$); + Select + Specific (TTNative Gpu) (dateadd@null := dt@null, + dateadd@val := (pure_if dt@null "0" (addHoursdt2dt dt@val "1"))) + Table Scan + public.cool_dates ("dt@null", "dt@val") [] + diff --git a/reference/sql/sql_functions/system_functions/index.rst b/reference/sql/sql_functions/system_functions/index.rst new file mode 100644 index 000000000..a27dfda62 --- /dev/null +++ b/reference/sql/sql_functions/system_functions/index.rst @@ -0,0 +1,20 @@ +.. _system_functions_functions: + +******************** +System Functions +******************** +**System functions** are used for returning system information, such as version and node information, and for maintenance operations that are not regularly accessed from any interface. + +The System Functions page describes the following: + +.. toctree:: + :maxdepth: 1 + :glob: + + explain + show_version + show_connections + show_locks + show_node_info + show_server_status + stop_statement \ No newline at end of file diff --git a/reference/sql/sql_functions/system_functions/show_connections.rst b/reference/sql/sql_functions/system_functions/show_connections.rst new file mode 100644 index 000000000..1bd320a4c --- /dev/null +++ b/reference/sql/sql_functions/system_functions/show_connections.rst @@ -0,0 +1,78 @@ +.. _show_connections: + +******************** +SHOW_CONNECTIONS +******************** + +``SHOW_CONNECTIONS`` returns a list of active sessions on the current worker. + +To see sessions across the cluster, see :ref:`show_server_status`. + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + show_connections_statement ::= + SELECT SHOW_CONNECTIONS() + ; + +Parameters +============ + +None + +Returns +========= + +This function returns a list of active sessions. If no sessions are active on the worker, the result set will be empty. + +.. list-table:: Result columns + :widths: auto + :header-rows: 1 + + * - ``ip`` + - The worker hostname or IP + * - ``conn_id`` + - Connection ID + * - ``conn_start_time`` + - Connection start timestamp + * - ``stmt_id`` + - Statement ID. Connections with no active statement display ``-1``. + * - ``stmt_start_time`` + - Statement start timestamp + * - ``stmt`` + - Statement text + + +Notes +=========== + +* This utility shows the active connections. Some sessions may be actively connected, but not currently running a statement. + +* A connection is typically reused. There could be many statements under a single connection ID. + +Examples +=========== + +Using ``SHOW_CONNECTIONS`` to get statement IDs +---------------------------------------------------- + + +.. code-block:: psql + + t=> SELECT SHOW_CONNECTIONS(); + ip | conn_id | conn_start_time | stmt_id | stmt_start_time | stmt + -------------+---------+---------------------+---------+---------------------+-------------------------- + 192.168.1.91 | 103 | 2019-12-24 00:01:27 | 129 | 2019-12-24 00:38:18 | SELECT GET_DATE(), * F... + 192.168.1.91 | 23 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | + 192.168.1.91 | 22 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | + 192.168.1.91 | 26 | 2019-12-24 00:01:28 | -1 | 2019-12-24 00:01:28 | + + +The statement ID we're interested in is ``129``. We can see the connection started at 00:01:27, while the statement started at 00:38:18. \ No newline at end of file diff --git a/reference/sql/sql_functions/system_functions/show_locks.rst b/reference/sql/sql_functions/system_functions/show_locks.rst new file mode 100644 index 000000000..d5e7c02ec --- /dev/null +++ b/reference/sql/sql_functions/system_functions/show_locks.rst @@ -0,0 +1,79 @@ +.. _show_locks: + +******************** +SHOW_LOCKS +******************** + +``SHOW_LOCKS`` returns a list of locks from across the cluster. + +Read more about locks in :ref:`concurrency_and_locks`. + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + show_locks_statement ::= + SELECT SHOW_LOCKS() + ; + +Parameters +============ + +None + +Returns +========= + +This function returns a list of active locks. If no locks are active in the cluster, the result set will be empty. + +.. list-table:: Result columns + :widths: auto + :header-rows: 1 + + * - ``stmt_id`` + - Statement ID that caused the lock. + * - ``stmt_string`` + - Statement text + * - ``username`` + - The role that executed the statement + * - ``server`` + - The worker node's IP + * - ``port`` + - The worker node's port + * - ``locked_object`` + - The full qualified name of the object being locked, separated with ``$`` (e.g. ``table$t$public$nba2`` for table ``nba2`` in schema ``public``, in database ``t`` + * - ``lockmode`` + - The locking mode (:ref:`inclusive` or :ref:`exclusive`). + * - ``statement_start_time`` + - Timestamp the statement started + * - ``lock_start_time`` + - Timestamp the lock was obtained + + +Examples +=========== + +Using ``SHOW_LOCKS`` to see active locks +--------------------------------------------------- + +In this example, we create a table based on results (:ref:`create_table_as`), but we are also effectively dropping the previous table (by using ``OR REPLACE``). Thus, SQream DB applies locks during the table creation process to prevent the table from being altered during it's creation. + + +.. code-block:: psql + + t=> SELECT SHOW_LOCKS(); + statement_id | statement_string | username | server | port | locked_object | lockmode | statement_start_time | lock_start_time + -------------+-------------------------------------------------------------------------------------------------+----------+--------------+------+---------------------------------+-----------+----------------------+-------------------- + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | database$t | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | globalpermission$ | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | schema$t$public | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + + diff --git a/reference/sql/sql_functions/system_functions/show_node_info.rst b/reference/sql/sql_functions/system_functions/show_node_info.rst new file mode 100644 index 000000000..345d16440 --- /dev/null +++ b/reference/sql/sql_functions/system_functions/show_node_info.rst @@ -0,0 +1,310 @@ +.. _show_node_info: + +******************** +SHOW_NODE_INFO +******************** + +``SHOW_NODE_INFO`` returns a snapshot of the current query plan, similar to ``EXPLAIN ANALYZE`` from other databases. + +The snapshot provides information about execution which can be used for monitoring and troubleshooting slow running statements by helping identify long-running execution nodes (components that process data), etc. + +See also :ref:`explain`, :ref:`show_server_status`. + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + show_node_info_statement ::= + SELECT SHOW_NODE_INFO(stmt_id) + ; + + stmt_id ::= bigint + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``stmt_id`` + - The statement ID to explore + +Returns +========= + +This utility returns details of the execution nodes, if the statement is still running. + +If the statement has finished, or the statment ID does not exist, the utility returns an empty result set. + +.. list-table:: Result columns + :widths: auto + :header-rows: 1 + + * - Column name + - Description + * - ``stmt_id`` + - The ID for the statement + * - ``node_id`` + - This node's ID in this execution plan + * - ``node_type`` + - The node type + * - ``rows`` + - Total number of rows this node has processed + * - ``chunks`` + - Number of chunks this node has processed + * - ``avg_rows_in_chunk`` + - Average amount of rows that this node processes in each chunk (``rows / chunks``) + * - ``time`` + - Timestamp for this node's creation + * - ``parent_node_id`` + - The ``node_id`` of this node's parent + * - ``read`` + - Total data read from disk + * - ``write`` + - Total data written to disk + * - ``comment`` + - Additional information (e.g. table name for ``ReadTable``) + * - ``timesum`` + - Total elapsed time for this execution node's processing + + +.. _node_types: + +Node types +============= + +This is a full list of node types: + +.. list-table:: Node types + :widths: auto + :header-rows: 1 + + * - Column name + - Execution location + - Description + * - ``AddChunkId`` + - + - Used during insert operations + * - ``AddSequences`` + - + - Used during insert operations, with :ref:`identity columns` + * - ``AddMinMaxMetadata`` + - + - Used to calculate ranges for the :ref:`chunk metadata system` + * - ``AddTopSortFilters`` + - + - An operation to optimize ``LIMIT`` when used alongside ``ORDER BY`` + * - ``Compress`` + - CPU and GPU + - Compress data with both CPU and GPU schemes + * - ``CpuDecompress`` + - CPU + - Decompression operation, common for longer ``VARCHAR`` types + * - ``CpuLoopJoin`` + - CPU + - A non-indexed nested loop join, performed on the CPU + * - ``CpuReduce`` + - CPU + - A reduce process performed on the CPU, primarily with ``DISTINCT`` aggregates (e.g. ``COUNT(DISTINCT ...)``) + * - ``CpuToGpu``, ``GpuToCpu`` + - + - An operation that moves data to or from the GPU for processing + * - ``CpuTransform`` + - CPU + - A transform operation performed on the CPU, usually a :ref:`scalar function` + * - ``CrossJoin`` + - + - A join without a join condition + * - ``DeferredGather`` + - CPU + - Merges the results of GPU operations with a result set [#f0]_ + * - ``Distinct`` + - GPU + - Removes duplicate rows (usually as part of the ``DISTINCT`` operation) + * - ``Distinct_Merge`` + - CPU + - The merge operation of the ``Distinct`` operation + * - ``Filter`` + - GPU + - A filtering operation, such as a ``WHERE`` or ``JOIN`` clause + * - ``GpuCopy`` + - GPU + - Copies data between GPUs or within a single GPU + * - ``GpuDecompress`` + - GPU + - Decompression operation + * - ``GpuReduceMerge`` + - GPU + - An operation to optimize part of the merger phases in the GPU + * - ``GpuTransform`` + - GPU + - A transformation operation such as a type cast or :ref:`scalar function` + * - ``Hash`` + - CPU + - Hashes the output result. Used internally. + * - ``JoinSideMarker`` + - + - Used internally. + * - ``LiteralValues`` + - CPU + - Creates a virtual relation (table), when :ref:`values` is used + * - ``LocateFiles`` + - CPU + - Validates external file paths for foreign data wrappers, expanding directories and GLOB patterns + * - ``LoopJoin`` + - GPU + - A non-indexed nested loop join, performed on the GPU + * - ``MarkMatchedJoinRows`` + - + - Used in outer joins, matches rows for larger join operations + * - ``NullifyDuplicates`` + - + - Replaces duplicate values with ``NULL`` to calculate distinct aggregates + * - ``NullSink`` + - CPU + - Used internally + * - ``ParseCsv`` + - CPU + - A CSV parser, used after ``ReadFiles`` to convert the CSV into columnar data + * - ``PopNetworkQueue`` + - CPU + - Fetches data from the network queue (e.g. when used with :ref:`insert`) + * - ``PushToNetworkQueue`` + - CPU + - Sends result sets to a client connected over the network + * - ``ReadCatalog`` + - CPU + - Converts the :ref:`catalog` into a relation (table) + * - ``ReadFiles`` + - CPU + - Reads external flat-files + * - ``ReadOrc`` + - CPU + - Reads data from an ORC file + * - ``ReadParquet`` + - CPU + - Reads data from a Parquet file + * - ``ReadTable`` + - CPU + - Reads data from a standard table stored on disk + * - ``ReadTableMetadata`` + - CPU + - Reads only table metadata as an optimization + * - ``Rechunk`` + - + - Reorganize multiple small :ref:`chunks` into a full chunk. Commonly found after joins and when :ref:`HIGH_SELECTIVITY` is used + * - ``Reduce`` + - GPU + - A reduction operation, such as a ``GROUP BY`` + * - ``ReduceMerge`` + - GPU + - A merge operation of a reduction operation, helps operate on larger-than-RAM data + * - ``ReorderInput`` + - + - Change the order of arguments in preparation for the next operation + * - ``SeparatedGather`` + - GPU + - Gathers additional columns for the result + * - ``Sort`` + - GPU + - Sort operation [#f1]_ + * - ``SortMerge`` + - CPU + - A merge operation of a sort operation, helps operate on larger-than-RAM data + * - ``SortMergeJoin`` + - GPU + - A sort-merge join, performed on the GPU + * - ``TakeRowsFromChunk`` + - + - Take the first N rows from each chunk, to optimize ``LIMIT`` when used alongside ``ORDER BY`` + * - ``Top`` + - + - Limits the input size, when used with ``LIMIT`` (or its alias ``TOP``) + * - ``UdfTransform`` + - CPU + - Executes a :ref:`user defined function` + * - ``UnionAll`` + - + - Combines two sources of data when ``UNION ALL`` is used + * - ``VarCharJoiner`` + - + - Used internally + * - ``VarCharSplitter`` + - + - Used intenrally + * - ``Window`` + - GPU + - Executes a non-ranking :ref:`window function` + * - ``WindowRanking`` + - GPU + - Executes a ranking :ref:`window function` + * - ``WriteTable`` + - CPU + - Writes the result set to a standard table stored on disk + +.. rubric:: Footnotes + +.. [#f0] Gathers columns which should be returned. This node typically spends most of the time on decompressing additional columns. + +.. [#f1] A GPU sort operation can be added by the statement compiler before ``GROUP BY`` or ``JOIN`` operations. + +Statement statuses +======================= + +.. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst + :start-line: 67 + :end-line: 84 + +Notes +=========== + +* This utility shows the execution information for active statements. Once a query has finished execution, the information is no longer available using this utility. See :ref:`logging` for more information about extracting the information from the logs. + +* This utility is primarily intended for troubleshooting with SQream support. + +Examples +=========== + +Getting execution details for a statement +------------------------------------------------ + + +.. code-block:: psql + + t=> SELECT SHOW_SERVER_STATUS(); + service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart + --------+------------+---------------+--------------+------------+---------------+-----------+--------------+-------------+-----------------------------------------------------------------+---------------------+-----------------+--------------------- + sqream | | 152 | 192.168.1.91 | 5000 | t | sqream | 192.168.1.91 | 176 | SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | 25-12-2019 23:53:13 | Executing | 25-12-2019 23:53:13 + sqream | | 151 | 192.168.1.91 | 5000 | t | sqream | 192.168.0.1 | 177 | SELECT show_server_status() | 25-12-2019 23:51:31 | Executing | 25-12-2019 23:53:13 + + +The statement ID we want to reserach is ``176``, running on worker ``192.168.1.91``. + +The query text is ``SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1;`` + +.. code-block:: psql + + t=> SELECT SHOW_NODE_INFO(176); + stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum + --------+---------+--------------------+------+--------+-------------------+---------------------+----------------+------+-------+------------+-------- + 176 | 1 | PushToNetworkQueue | 1 | 1 | 1 | 2019-12-25 23:53:13 | -1 | | | | 0.0025 + 176 | 2 | Rechunk | 1 | 1 | 1 | 2019-12-25 23:53:13 | 1 | | | | 0 + 176 | 3 | GpuToCpu | 1 | 1 | 1 | 2019-12-25 23:53:13 | 2 | | | | 0 + 176 | 4 | ReorderInput | 1 | 1 | 1 | 2019-12-25 23:53:13 | 3 | | | | 0 + 176 | 5 | Filter | 1 | 1 | 1 | 2019-12-25 23:53:13 | 4 | | | | 0.0002 + 176 | 6 | GpuTransform | 457 | 1 | 457 | 2019-12-25 23:53:13 | 5 | | | | 0.0002 + 176 | 7 | GpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 6 | | | | 0 + 176 | 8 | CpuToGpu | 457 | 1 | 457 | 2019-12-25 23:53:13 | 7 | | | | 0.0003 + 176 | 9 | Rechunk | 457 | 1 | 457 | 2019-12-25 23:53:13 | 8 | | | | 0 + 176 | 10 | CpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 9 | | | | 0 + 176 | 11 | ReadTable | 457 | 1 | 457 | 2019-12-25 23:53:13 | 10 | 4MB | | public.nba | 0.0004 + diff --git a/reference/sql/sql_functions/system_functions/show_server_status.rst b/reference/sql/sql_functions/system_functions/show_server_status.rst new file mode 100644 index 000000000..f59f79ccc --- /dev/null +++ b/reference/sql/sql_functions/system_functions/show_server_status.rst @@ -0,0 +1,108 @@ +.. _show_server_status: + +******************** +SHOW_SERVER_STATUS +******************** + +``SHOW_SERVER_STATUS`` returns a list of active sessions across the cluster. + +To list active statements on the current worker only, see :ref:`show_connections`. + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + show_server_status_statement ::= + SELECT SHOW_SERVER_STATUS() + ; + +Parameters +============ + +None + +Returns +========= + +This function returns a list of active sessions. If no sessions are active across the cluster, the result set will be empty. + +.. list-table:: Result columns + :widths: auto + :header-rows: 1 + + * - ``service`` + - The service name for the statement + * - ``instance`` + - The worker ID + * - ``connection_id`` + - Connection ID + * - ``serverip`` + - Worker end-point IP + * - ``serverport`` + - Worker end-point port + * - ``database_name`` + - Database name for the statement + * - ``user_name`` + - Username running the statement + * - ``clientip`` + - Client IP + * - ``statementid`` + - Statement ID + * - ``statement`` + - Statement text + * - ``statementstarttime`` + - Statement start timestamp + * - ``statementstatus`` + - Statement status (see table below) + * - ``statementstatusstart`` + - Last updated timestamp + +.. include from here: 66 + + +.. list-table:: Statement status values + :widths: auto + :header-rows: 1 + + * - Status + - Description + * - ``Preparing`` + - Statement is being prepared + * - ``In queue`` + - Statement is waiting for execution + * - ``Initializing`` + - Statement has entered execution checks + * - ``Executing`` + - Statement is executing + * - ``Stopping`` + - Statement is in the process of stopping + + +.. include until here 86 + +Notes +=========== + +* This utility shows the active sessions. Some sessions may be actively connected, but not running any statements. + +Examples +=========== + +Using ``SHOW_SERVER_STATUS`` to get statement IDs +---------------------------------------------------- + + +.. code-block:: psql + + t=> SELECT SHOW_SERVER_STATUS(); + service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart + --------+------------+---------------+--------------+------------+---------------+------------+-------------+-------------+-----------------------------+---------------------+-----------------+--------------------- + sqream | | 102 | 192.168.1.91 | 5000 | t | rhendricks | 192.168.0.1 | 128 | SELECT SHOW_SERVER_STATUS() | 24-12-2019 00:14:53 | Executing | 24-12-2019 00:14:53 + +The statement ID is ``128``, running on worker ``192.168.1.91``. diff --git a/reference/sql/sql_functions/system_functions/stop_statement.rst b/reference/sql/sql_functions/system_functions/stop_statement.rst new file mode 100644 index 000000000..30efc25b5 --- /dev/null +++ b/reference/sql/sql_functions/system_functions/stop_statement.rst @@ -0,0 +1,77 @@ +.. _stop_statement: + +******************** +STOP_STATEMENT +******************** + +``STOP_STATEMENT`` stops or aborts an active statement. + +To find a statement by ID, see :ref:`show_server_status` and :ref:`show_connections`. + +.. tip:: Some DBMSs call this process killing a session, terminating a job, or kill query + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + stop_statement_statement ::= + SELECT STOP_STATEMENT(stmt_id) + ; + + stmt_id ::= bigint + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``stmt_id`` + - The statement ID to stop + +Returns +========= + +This utility does not return any value, and always succeeds even if the statement does not exist, or has already stopped. + + +Notes +=========== + +* This utility always succeeds even if the statement does not exist, or has already stopped. + +Examples +=========== + +Using :ref:`show_connections` to get statement IDs +---------------------------------------------------- + +.. tip:: Use :ref:`show_server_status` to find statments from across the entire cluster, or :ref:`show_connections` to show statements from the current worker the client is connected to. + +.. code-block:: psql + + t=> SELECT SHOW_CONNECTIONS(); + ip | conn_id | conn_start_time | stmt_id | stmt_start_time | stmt + -------------+---------+---------------------+---------+---------------------+-------------------------- + 192.168.1.91 | 103 | 2019-12-24 00:01:27 | 129 | 2019-12-24 00:38:18 | SELECT GET_DATE(), * F... + 192.168.1.91 | 23 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | + 192.168.1.91 | 22 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | + 192.168.1.91 | 26 | 2019-12-24 00:01:28 | -1 | 2019-12-24 00:01:28 | + + +The statement ID we're interested in is ``129``. We can now stop this statement: + +.. code-block:: psql + + t=> SELECT STOP_STATEMENT(129) + executed + From c40428fd72c9a0c462127b84b02c157ec3f9419d Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 27 Mar 2022 18:09:51 +0300 Subject: [PATCH 217/300] Avoid long topic menu lists. --- .../aggregate_functions/index.rst | 38 ++++---- .../sql_functions/scalar_functions/index.rst | 95 ++++++++++++++++--- .../sql_functions/system_functions/index.rst | 19 ++-- .../user_defined_functions/index.rst | 21 +--- .../sql_functions/window_functions/index.rst | 35 +++---- reference/sql/sql_syntax/index.rst | 26 +++-- 6 files changed, 137 insertions(+), 97 deletions(-) diff --git a/reference/sql/sql_functions/aggregate_functions/index.rst b/reference/sql/sql_functions/aggregate_functions/index.rst index 17d35a46b..5d3dfc125 100644 --- a/reference/sql/sql_functions/aggregate_functions/index.rst +++ b/reference/sql/sql_functions/aggregate_functions/index.rst @@ -6,31 +6,27 @@ Aggregate Functions Overview =========== - Aggregate functions perform calculations based on a set of values and return a single value. Most aggregate functions ignore null values. Aggregate functions are often used with the ``GROUP BY`` clause of the :ref:`select` statement. Available Aggregate Functions =============== The following list shows the available aggregate functions: - -.. toctree:: - :maxdepth: 1 - :glob: +.. hlist:: + :columns: 2 - - avg - corr - count - covar_pop - covar_samp - max - min - mode - percentile_cont - percentile_disc - stddev_pop - stddev_samp - sum - var_pop - var_samp + * :ref:`AVG` + * :ref:`CORR` + * :ref:`COUNT` + * :ref:`COVAR_POP` + * :ref:`COVAR_SAMP` + * :ref:`MAX` + * :ref:`MIN` + * :ref:`MODE` + * :ref:`PERCENTILE_CONT` + * :ref:`PERCENTILE_DISC` + * :ref:`STDDEV_POP` + * :ref:`STDDEV_SAMP` + * :ref:`SUM` + * :ref:`VAR_POP` + * :ref:`VAR_SAMP` \ No newline at end of file diff --git a/reference/sql/sql_functions/scalar_functions/index.rst b/reference/sql/sql_functions/scalar_functions/index.rst index b7befbb28..bd05f9bbe 100644 --- a/reference/sql/sql_functions/scalar_functions/index.rst +++ b/reference/sql/sql_functions/scalar_functions/index.rst @@ -1,20 +1,85 @@ .. _scalar_functions: **************** -Scalar functions +Built-In Scalar Functions **************** +The **Built-In Scalar Functions** page describes functions that return one value per call: -Scalar functions return one value per call. - - -.. toctree:: - :maxdepth: 1 - :caption: Scalar functions - :glob: - - bitwise/* - conditionals/* - conversion/* - date_and_time/* - numeric/* - string/* \ No newline at end of file +.. hlist:: + :columns: 5 + + * `AND `_ + * `NOT `_ + * `OR `_ + * `SHIFT_LEFT `_ + * `SHIFT_RIGHT `_ + * `XOR `_ + * :ref:`between` + * :ref:`case` + * :ref:`coalesce` + * :ref:`in` + * :ref:`is_ascii` + * :ref:`is_null` + * :ref:`isnull` + * :ref:`from_unixts` + * :ref:`to_hex` + * :ref:`to_unixts` + * :ref:`curdate` + * :ref:`current_date` + * :ref:`current_timestamp` + * :ref:`dateadd` + * :ref:`datediff` + * :ref:`datepart` + * :ref:`eomonth` + * :ref:`extract` + * :ref:`getdate` + * :ref:`sysdate` + * :ref:`trunc` + * :ref:`abs` + * :ref:`acos` + * :ref:`asin` + * :ref:`atan` + * :ref:`atn2` + * :ref:`ceiling` + * :ref:`cos` + * :ref:`cot` + * :ref:`crc64` + * :ref:`degrees` + * :ref:`exp` + * :ref:`floor` + * :ref:`log` + * :ref:`log10` + * :ref:`mod` + * :ref:`pi` + * :ref:`power` + * :ref:`radians` + * :ref:`round` + * :ref:`sin` + * :ref:`sqrt` + * :ref:`square` + * :ref:`tan` + * :ref:`trunc` + * :ref:`char_length` + * :ref:`charindex` + * :ref:`concat` + * :ref:`isprefixof` + * :ref:`left` + * :ref:`len` + * :ref:`like` + * :ref:`lower` + * :ref:`ltrim` + * :ref:`octet_length` + * :ref:`patindex` + * :ref:`regexp_count` + * :ref:`regexp_instr` + * :ref:`regexp_replace` + * :ref:`regexp_substr` + * :ref:`repeat` + * :ref:`replace` + * :ref:`reverse` + * :ref:`right` + * :ref:`rlike` + * :ref:`rtrim` + * :ref:`substring` + * :ref:`trim` + * :ref:`upper` \ No newline at end of file diff --git a/reference/sql/sql_functions/system_functions/index.rst b/reference/sql/sql_functions/system_functions/index.rst index a27dfda62..ba99610ba 100644 --- a/reference/sql/sql_functions/system_functions/index.rst +++ b/reference/sql/sql_functions/system_functions/index.rst @@ -7,14 +7,13 @@ System Functions The System Functions page describes the following: -.. toctree:: - :maxdepth: 1 - :glob: +.. hlist:: + :columns: 1 - explain - show_version - show_connections - show_locks - show_node_info - show_server_status - stop_statement \ No newline at end of file + * :ref:`explain` + * :ref:`show_version` + * :ref:`show_connections` + * :ref:`show_locks` + * :ref:`show_node_info` + * :ref:`show_server_status` + * :ref:`stop_statement` \ No newline at end of file diff --git a/reference/sql/sql_functions/user_defined_functions/index.rst b/reference/sql/sql_functions/user_defined_functions/index.rst index 7f45e637e..028e35a07 100644 --- a/reference/sql/sql_functions/user_defined_functions/index.rst +++ b/reference/sql/sql_functions/user_defined_functions/index.rst @@ -4,22 +4,9 @@ User-Defined Functions ******************** -The following user-defined functions are functions that can be defined and configured by users: +The following user-defined functions are functions that can be defined and configured by users. +The **User-Defined Functions** page describes the following: - -* `Python user-defined functions `_. -* `Scalar SQL user-defined functions `_. - - - - -.. toctree:: - :maxdepth: 8 - :glob: - :hidden: - - - - python_functions - scalar_sql_udf +* `Python user-defined functions `_ +* `Scalar SQL user-defined functions `_ \ No newline at end of file diff --git a/reference/sql/sql_functions/window_functions/index.rst b/reference/sql/sql_functions/window_functions/index.rst index 4061ad239..e949e0e3c 100644 --- a/reference/sql/sql_functions/window_functions/index.rst +++ b/reference/sql/sql_functions/window_functions/index.rst @@ -4,26 +4,21 @@ Window Functions ******************** -Window functions are functions applied over a subset (known as a window) of the rows returned by a :ref:`select` query. +Window functions are functions applied over a subset (known as a window) of the rows returned by a :ref:`select` query and describes the following: -Read more about :ref:`window_functions` in the :ref:`sql_syntax` section. - -.. toctree:: - :maxdepth: 1 - :caption: Window Functions: - :glob: - :hidden: +.. hlist:: + :columns: 1 - lag - lead - row_number - rank - first_value - last_value - nth_value - dense_rank - percent_rank - cume_dist - ntile - + * :ref:`lag` + * :ref:`lead` + * :ref:`row_number` + * :ref:`rank` + * :ref:`first_value` + * :ref:`last_value` + * :ref:`nth_value` + * :ref:`dense_rank` + * :ref:`percent_rank` + * :ref:`cume_dist` + * :ref:`ntile` +For more information, see :ref:`window_functions` in the :ref:`sql_syntax` section. \ No newline at end of file diff --git a/reference/sql/sql_syntax/index.rst b/reference/sql/sql_syntax/index.rst index 4b6b66aaa..9e0422db4 100644 --- a/reference/sql/sql_syntax/index.rst +++ b/reference/sql/sql_syntax/index.rst @@ -1,21 +1,19 @@ .. _sql_syntax: ********************** -SQL syntax features +SQL Syntax Features ********************** -SQream DB supports SQL from the ANSI 92 syntax. +SQream DB supports SQL from the ANSI 92 syntax and describes the following: -.. toctree:: - :maxdepth: 2 - :caption: SQL syntax topics - :glob: +.. hlist:: + :columns: 1 - keywords_and_identifiers - literals - scalar_expressions - joins - common_table_expressions - window_functions - subqueries - null_handling \ No newline at end of file + * :ref:`keywords_and_identifiers` + * :ref:`literals` + * :ref:`scalar_expressions` + * :ref:`joins` + * :ref:`common_table_expressions` + * :ref:`window_functions` + * :ref:`subqueries` + * :ref:`null_handling` \ No newline at end of file From 4bbfaf05600b1a74c860ec1611f87e06475b3838 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 28 Mar 2022 11:16:38 +0300 Subject: [PATCH 218/300] Update running_sqream_in_a_docker_container.rst Removed dollar signs from wget lines. --- .../running_sqream_in_a_docker_container.rst | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst index 7f698ede4..3f1060ab8 100644 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ b/installation_guides/running_sqream_in_a_docker_container.rst @@ -27,6 +27,7 @@ SQream recommends installing a clean OS on the host to avoid any installation is .. warning:: Docker-based installation supports only single host deployment and cannot be used on a multi-node cluster. Installing Docker on a single host you will not be able to scale it to a multi-node cluster. + Creating a Local User ---------------- To run SQream in a Docker container you must create a local user. @@ -121,6 +122,8 @@ After installing the recommended tools you must update to the current version of SQream recommends updating to the current version of the operating system. This is not recommended if the nvidia driver has **not been installed.** + + Configuring the NTP Package ---------------- After updating to the current version of the operating system you must configure the NTP package. @@ -199,7 +202,6 @@ You can abort the above but-reporting tools by running the following command: Installing the Nvidia CUDA Driver ------------------------------------- -**To install the Nvidia CUDA driver:** 1. Verify that the Tesla NVIDIA card has been installed and is detected by the system: @@ -517,17 +519,15 @@ Installing the Docker Engine on an IBM Power9 Processor ---------------------------------------- The x86_64 processor only supports installing the **Docker Community Edition (CE)** version 18.03. - **To install the Docker Engine on an IBM Power9 processor:** You can install the Docker Engine on an IBM Power9 processor by running the following command: .. code-block:: console - $ wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm - $ wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - $ yum install -y container-selinux-2.9-4.el7.noarch.rpm - $ docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm + wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm + wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm + yum install -y container-selinux-2.9-4.el7.noarch.rpm docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm For more information on installing the Docker Engine CE on an IBM Power9 processor, see `Install Docker Engine on Ubuntu `_. @@ -572,8 +572,8 @@ After configuring Docker on your local machine you must install the Nvidia Docke This section describes the following: -* :ref:`Installing the NVIDIA Docker2 Toolkit on an x86_64 processor. ` -* :ref:`Installing the NVIDIA Docker2 Toolkit on a PPC64le processor. ` +* :ref:`Installing the NVIDIA Docker2 Toolkit on an x86_64 processor ` +* :ref:`Installing the NVIDIA Docker2 Toolkit on a PPC64le processor ` .. _install_nvidia_docker2_toolkit_x8664_processor: @@ -664,7 +664,9 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System $ sudo apt-get install nvidia-docker2 $ sudo pkill -SIGHUP dockerd + 3. Do one of the following: + * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 `. * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 `. @@ -791,8 +793,8 @@ For more information about the correct directory to copy the above files into, s For related information, see the following sections: -* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. -* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. +* :ref:`Configuring the Hadoop and Kubernetes Configuration Files ` +* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters ` .. _installing_sqream_software: From 1ac826a8dbf85484adc6c1ea94f807795ee3ad79 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 28 Mar 2022 14:22:32 +0300 Subject: [PATCH 219/300] Update running_sqream_in_a_docker_container.rst --- .../running_sqream_in_a_docker_container.rst | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst index 3f1060ab8..8e42c910d 100644 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ b/installation_guides/running_sqream_in_a_docker_container.rst @@ -1,7 +1,5 @@ .. _running_sqream_in_a_docker_container: - - *********************** Installing and Running SQream in a Docker Container *********************** @@ -597,10 +595,9 @@ Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System .. code-block:: console - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L - $ https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ - $ sudo tee /etc/yum.repos.d/nvidia-docker.repo + distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ + sudo tee /etc/yum.repos.d/nvidia-docker.repo 2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: @@ -650,13 +647,10 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System .. code-block:: console - $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \ - $ sudo apt-key add - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L - $ https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \ - $ sudo tee /etc/apt/sources.list.d/nvidia-docker.list - $ sudo apt-get update + curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - + distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list + sudo apt-get update 2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: From b4564182f1b8d17b721ddfb62ed48efb0715eddf Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 28 Mar 2022 15:17:03 +0300 Subject: [PATCH 220/300] Update running_sqream_in_a_docker_container.rst --- .../running_sqream_in_a_docker_container.rst | 218 +++++++++--------- 1 file changed, 104 insertions(+), 114 deletions(-) diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst index 8e42c910d..e85eac925 100644 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ b/installation_guides/running_sqream_in_a_docker_container.rst @@ -3,7 +3,7 @@ *********************** Installing and Running SQream in a Docker Container *********************** -The **Running SQream in a Docker Container** page describes how to prepare your machine's environment for installing and running SQream in a Docker container. +The **Installing and Running SQream in a Docker Container** page describes how to prepare your machine's environment for installing and running SQream in a Docker container. This page describes the following: @@ -34,19 +34,19 @@ To run SQream in a Docker container you must create a local user. 1. Add a local user: - .. code-block:: console + .. code-block:: $ useradd -m -U 2. Set the local user's password: - .. code-block:: console + .. code-block:: $ passwd 3. Add the local user to the ``wheel`` group: - .. code-block:: console + .. code-block:: $ usermod -aG wheel @@ -62,13 +62,13 @@ After creating a local user you must set a local language. 1. Set the local language: - .. code-block:: console + .. code-block:: $ sudo localectl set-locale LANG=en_US.UTF-8 2. Set the time stamp (time and date) of the locale: - .. code-block:: console + .. code-block:: $ sudo timedatectl set-timezone Asia/Jerusalem @@ -84,13 +84,13 @@ After setting a local language you must add the EPEL repository. 1. RedHat (RHEL 7): - .. code-block:: console + .. code-block:: $ sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 2. CentOS 7 - .. code-block:: console + .. code-block:: $ sudo yum install epel-release @@ -100,9 +100,9 @@ After adding the EPEL repository, you must install the required NTP packages. You can install the required NTP packages by running the following command: -.. code-block:: console +.. code-block:: - $ sudo yum install ntp pciutils python36 kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc + $ sudo yum install ntp pciutils python36 kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc Installing the Recommended Tools ---------------- @@ -110,7 +110,7 @@ After installin gthe required NTP packages you must install the recommended tool SQream recommends installing the following recommended tools: -.. code-block:: console +.. code-block:: $ sudo yum install bash-completion.noarch vim-enhanced.x86_64 vim-common.x86_64 net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix @@ -134,7 +134,7 @@ After updating to the current version of the operating system you must configure 2. Configure the **ntpd** service to begin running when your machine is started: - .. code-block:: console + .. code-block:: $ sudo systemctl enable ntpd $ sudo systemctl start ntpd @@ -146,15 +146,15 @@ After configuring the NTP package you must configure the performance profile. **To configure the performance profile:** -1. Switch the active profile: +1. *Optional* - Switch the active profile: - .. code-block:: console + .. code-block:: $ sudo tuned-adm profile throughput-performance 2. Change the multi-user's default run level: - .. code-block:: console + .. code-block:: $ sudo systemctl set-default multi-user.target @@ -166,19 +166,19 @@ After configuring the performance profile you must configure your security limit 1. Run the **bash** shell as a super-user: - .. code-block:: console + .. code-block:: $ sudo bash 2. Run the following command: - .. code-block:: console + .. code-block:: $ echo -e "sqream soft nproc 500000\nsqream hard nproc 500000\nsqream soft nofile 500000\nsqream hard nofile 500000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf 3. Run the following command: - .. code-block:: console + .. code-block:: $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.zone_reclaim_mode = 0 \n vm.vfs_cache_pressure = 200 \n" >> /etc/sysctl.conf @@ -194,7 +194,7 @@ After configuring your security limits you must disable the following automatic You can abort the above but-reporting tools by running the following command: -.. code-block:: console +.. code-block:: $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done @@ -203,7 +203,7 @@ Installing the Nvidia CUDA Driver 1. Verify that the Tesla NVIDIA card has been installed and is detected by the system: - .. code-block:: console + .. code-block:: $ lspci | grep -i nvidia @@ -211,7 +211,7 @@ Installing the Nvidia CUDA Driver #. Verify that the open-source upstream Nvidia driver is running: - .. code-block:: console + .. code-block:: $ lsmod | grep nouveau @@ -221,7 +221,7 @@ Installing the Nvidia CUDA Driver 1. Disable the open-source upstream Nvidia driver: - .. code-block:: console + .. code-block:: $ sudo bash $ echo "blacklist nouveau" > /etc/modprobe.d/blacklist-nouveau.conf @@ -231,19 +231,19 @@ Installing the Nvidia CUDA Driver 2. Reboot the server and verify that the Nouveau model has not been loaded: - .. code-block:: console + .. code-block:: $ lsmod | grep nouveau #. Check if the Nvidia CUDA driver has already been installed: - .. code-block:: console + .. code-block:: $ nvidia-smi The following is an example of the correct output: - .. code-block:: console + .. code-block:: nvidia-smi Wed Oct 30 14:05:42 2019 @@ -310,14 +310,14 @@ For installer type, SQream recommends selecting **runfile (local)**. The availab 2. Download the base installer for Linux CentOS 7 x86_64: - .. code-block:: console + .. code-block:: wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm 3. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: - .. code-block:: console + .. code-block:: $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm $ sudo yum clean all @@ -333,26 +333,22 @@ For installer type, SQream recommends selecting **runfile (local)**. The availab 5. Enable the Nvidia service to start at boot and start it: - .. code-block:: console + .. code-block:: $ sudo systemctl enable nvidia-persistenced.service && sudo systemctl start nvidia-persistenced.service -6. Create a symbolic link from the **/etc/systemd/system/multi-user.target.wants/nvidia-persistenced.service** file to the **/usr/lib/systemd/system/nvidia-persistenced.service** file. - - :: - 7. Reboot the server. :: 8. Verify that the Nvidia driver has been installed and shows all available GPU's: - .. code-block:: console + .. code-block:: $ nvidia-smi The following is the correct output: - .. code-block:: console + .. code-block:: nvidia-smi Wed Oct 30 14:05:42 2019 @@ -385,14 +381,14 @@ Installing the CUDA Driver Version 10.1 for IBM Power9 1. Download the base installer for Linux CentOS 7 PPC64le: - .. code-block:: console + .. code-block:: wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm #. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: - .. code-block:: console + .. code-block:: $ sudo rpm -i cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm $ sudo yum clean all @@ -408,20 +404,16 @@ Installing the CUDA Driver Version 10.1 for IBM Power9 4. If you are using RHEL 7 version (7.6 or later), comment out, remove, or change the hot-pluggable memory rule located in file copied to the **/etc/udev/rules.d** directory by running the following command: - .. code-block:: console + .. code-block:: $ sudo cp /lib/udev/rules.d/40-redhat.rules /etc/udev/rules.d $ sudo sed -i 's/SUBSYSTEM!="memory",.*GOTO="memory_hotplug_end"/SUBSYSTEM=="*", GOTO="memory_hotplug_end"/' /etc/udev/rules.d/40-redhat.rules #. Enable the **nvidia-persisted.service** file: - .. code-block:: console + .. code-block:: $ sudo systemctl enable nvidia-persistenced.service - -#. Create a symbolic link from the **/etc/systemd/system/multi-user.target.wants/nvidia-persistenced.service** file to the **/usr/lib/systemd/system/nvidia-persistenced.service** file. - - :: #. Reboot your system to initialize the above modifications. @@ -429,13 +421,13 @@ Installing the CUDA Driver Version 10.1 for IBM Power9 #. Verify that the Nvidia driver and the **nvidia-persistenced.service** files are running: - .. code-block:: console + .. code-block:: $ nvidia smi The following is the correct output: - .. code-block:: console + .. code-block:: nvidia-smi Wed Oct 30 14:05:42 2019 @@ -461,13 +453,13 @@ Installing the CUDA Driver Version 10.1 for IBM Power9 #. Verify that the **nvidia-persistenced** service is running: - .. code-block:: console + .. code-block:: $ systemctl status nvidia-persistenced The following is the correct output: - .. code-block:: console + .. code-block:: root@gpudb ~]systemctl status nvidia-persistenced nvidia-persistenced.service - NVIDIA Persistence Daemon @@ -521,7 +513,7 @@ The x86_64 processor only supports installing the **Docker Community Edition (CE You can install the Docker Engine on an IBM Power9 processor by running the following command: -.. code-block:: console +.. code-block:: wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm @@ -537,13 +529,13 @@ After installing the Docker engine you must configure Docker on your local machi 1. Enable Docker to start on boot: - .. code-block:: console + .. code-block:: $ sudo systemctl enable docker && sudo systemctl start docker 2. Enable managing Docker as a non-root user: - .. code-block:: console + .. code-block:: $ sudo usermod -aG docker $USER @@ -553,7 +545,7 @@ After installing the Docker engine you must configure Docker on your local machi 4. Verify that you can run the following Docker command as a non-root user (without ``sudo``): - .. code-block:: console + .. code-block:: $ docker run hello-world @@ -593,7 +585,7 @@ Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System 1. Install the repository for your distribution: - .. code-block:: console + .. code-block:: distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ @@ -601,7 +593,7 @@ Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System 2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: - .. code-block:: console + .. code-block:: $ sudo yum install nvidia-docker2 $ sudo pkill -SIGHUP dockerd @@ -618,7 +610,7 @@ Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: - .. code-block:: console + .. code-block:: https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: [Errno -1] repomd.xml signature could not be verified for nvidia-docker @@ -629,7 +621,7 @@ Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System 5. Verify that the NVIDIA-Docker run has been installed correctly: - .. code-block:: console + .. code-block:: $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi @@ -645,7 +637,7 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System 1. Install the repository for your distribution: - .. code-block:: console + .. code-block:: curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - distribution=$(. /etc/os-release;echo $ID$VERSION_ID) @@ -654,7 +646,7 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System 2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: - .. code-block:: console + .. code-block:: $ sudo apt-get install nvidia-docker2 $ sudo pkill -SIGHUP dockerd @@ -670,7 +662,7 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: - .. code-block:: console + .. code-block:: https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: [Errno -1] repomd.xml signature could not be verified for nvidia-docker @@ -681,7 +673,7 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System 5. Verify that the NVIDIA-Docker run has been installed correctly: - .. code-block:: console + .. code-block:: $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi @@ -698,7 +690,7 @@ This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL 1. Import the repository and install the ``libnvidia-container`` and the ``nvidia-container-runtime`` containers. - .. code-block:: console + .. code-block:: $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ @@ -716,7 +708,7 @@ This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the containers: - .. code-block:: console + .. code-block:: https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: [Errno -1] repomd.xml signature could not be verified for nvidia-docker @@ -727,7 +719,7 @@ This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL 3. Install the ``libnvidia-container`` container. - .. code-block:: console + .. code-block:: $ sudo yum install -y libnvidia-container* @@ -735,13 +727,13 @@ This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL 4. Install the ``nvidia-container-runtime`` container: - .. code-block:: console + .. code-block:: $ sudo yum install -y nvidia-container-runtime* 5. Add ``nvidia runtime`` to the Docker daemon: - .. code-block:: console + .. code-block:: $ sudo mkdir -p /etc/systemd/system/docker.service.d/ $ sudo vi /etc/systemd/system/docker.service.d/override.conf @@ -752,14 +744,14 @@ This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL 6. Restart Docker: - .. code-block:: console + .. code-block:: $ sudo systemctl daemon-reload $ sudo systemctl restart docker 7. Verify that the NVIDIA-Docker run has been installed correctly: - .. code-block:: console + .. code-block:: $ docker run --runtime=nvidia --rm nvidia/cuda-ppc64le nvidia-smi @@ -828,13 +820,13 @@ The **sqream_installer-nnn-DBnnn-COnnn-EDnnn-.tar.gz** file includes the f 2. Extract the tarball file: - .. code-block:: console + .. code-block:: $ tar -xvf sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz -When the tarball file has been extracted, a new folder will be created. The new folder is automatically given the name of the tarball file: + When the tarball file has been extracted, a new folder will be created. The new folder is automatically given the name of the tarball file: - .. code-block:: console + .. code-block:: drwxrwxr-x 9 sqream sqream 4096 Aug 11 11:51 sqream_istaller-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64/ -rw-rw-r-- 1 sqream sqream 3130398797 Aug 11 11:20 sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz @@ -845,13 +837,13 @@ When the tarball file has been extracted, a new folder will be created. The new 4. Verify that the folder you just created contains all of the required files. - .. code-block:: console + .. code-block:: $ ls -la The following is an example of the files included in the new folder: - .. code-block:: console + .. code-block:: drwxrwxr-x. 10 sqream sqream 198 Jun 3 17:57 . drwx------. 25 sqream sqream 4096 Jun 7 18:11 .. @@ -958,7 +950,7 @@ Installing Your License ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Once you've configured your local environment, you must install your license by copying it into the SQream installation package folder located in the **./license** folder: -.. code-block:: console +.. code-block:: $ sudo ./sqream-install -k @@ -969,19 +961,19 @@ Validating Your License ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can copy your license package into the SQream console folder located in the **/license** folder by running the following command: -.. code-block:: console +.. code-block:: $ sudo ./sqream-install -K The following mandatory flags must be used in the first run: -.. code-block:: console +.. code-block:: $ sudo ./sqream-install -i -k -v The following is an example of the correct command syntax: -.. code-block:: console +.. code-block:: $ sudo ./sqream-install -i -k -c /etc/sqream -v /home/sqream/sqreamdb -l /var/log/sqream -d /home/sqream/data_ingest @@ -993,13 +985,13 @@ The information in this section is optional, and is only relevant for Hadoop use The following is the correct syntax when setting the Hadoop and Kubernetes connectivity parameters: -.. code-block:: console +.. code-block:: $ sudo ./sqream-install -p -e : The following is an example of setting the Hadoop and Kubernetes connectivity parameters: -.. code-block:: console +.. code-block:: $ sudo ./sqream-install -p -e kdc.sq.com:<192.168.1.111> @@ -1012,7 +1004,7 @@ Modifying Your Data Ingest Folder ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Once you've validated your license, you can modify your data ingest folder after the first run by running the following command: -.. code-block:: console +.. code-block:: $ sudo ./sqream-install -d /home/sqream/data_in @@ -1024,7 +1016,7 @@ Once you've modified your data ingest folder (if needed), you must validate that 1. To verify that your server network and Docker network do not overlap, run the following command: -.. code-block:: console +.. code-block:: $ ifconfig | grep 172. @@ -1033,7 +1025,7 @@ Once you've modified your data ingest folder (if needed), you must validate that * If running the above command output no results, continue the installation process. * If running the above command output results, run the following command: - .. code-block:: console + .. code-block:: $ ifconfig | grep 192.168. @@ -1044,13 +1036,13 @@ Once you've configured your network for Docker, you can check and verify your sy Running the following command shows you all the variables used by your SQream system: -.. code-block:: console +.. code-block:: $ ./sqream-install -s The following is an example of the correct output: -.. code-block:: console +.. code-block:: SQREAM_CONSOLE_TAG=1.5.4 SQREAM_TAG=2019.2.1 @@ -1100,7 +1092,7 @@ Starting Your SQream Console You can start your SQream console by running the following command: -.. code-block:: console +.. code-block:: $ ./sqream-console @@ -1113,13 +1105,13 @@ Starting the SQream Master 1. Start the metadata server (default port 3105) and picker (default port 3108) by running the following command: - .. code-block:: console + .. code-block:: $ sqream master --start The following is the correct output: - .. code-block:: console + .. code-block:: sqream-console> sqream master --start starting master server in single_host mode ... @@ -1128,7 +1120,7 @@ Starting the SQream Master 2. *Optional* - Change the metadata and server picker ports by adding ``-p `` and ``-m ``: - .. code-block:: console + .. code-block:: $ sqream-console>sqream master --start -p 4105 -m 43108 $ starting master server in single_host mode ... @@ -1145,13 +1137,13 @@ Starting SQream Workers When starting SQream workers, setting the ```` value sets how many workers to start. Leaving the ```` value unspecified runs all of the available resources. -.. code-block:: console +.. code-block:: $ sqream worker --start The following is an example of expected output when setting the ```` value to ``2``: - .. code-block:: console + .. code-block:: sqream-console>sqream worker --start 2 started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 @@ -1165,13 +1157,13 @@ Listing the Running Services You can list running SQream services to look for container names and ID's by running the following command: -.. code-block:: console +.. code-block:: $ sqream master --list The following is an example of the expected output: -.. code-block:: console +.. code-block:: sqream-console>sqream master --list container name: sqream_single_host_worker_0, container id: c919e8fb78c8 @@ -1187,13 +1179,13 @@ You can stop running services either for a single SQream worker, or all SQream s The following is the command for stopping a running service for a single SQream worker: -.. code-block:: console +.. code-block:: $ sqream worker --stop The following is an example of expected output when stopping a running service for a single SQream worker: -.. code-block:: console +.. code-block:: sqream worker stop stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 @@ -1201,13 +1193,13 @@ The following is an example of expected output when stopping a running service f You can stop all running SQream services (both master and worker) by running the following command: -.. code-block:: console +.. code-block:: $ sqream-console>sqream master --stop --all The following is an example of expected output when stopping all running services: -.. code-block:: console +.. code-block:: sqream-console>sqream master --stop --all stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 @@ -1224,13 +1216,13 @@ SQream Studio is an SQL statement editor. 1. Run the following command: - .. code-block:: console + .. code-block:: $ sqream studio --start The following is an example of the expected output: - .. code-block:: console + .. code-block:: SQream Acceleration Studio is available at http://192.168.1.62:8080 @@ -1241,13 +1233,13 @@ The following is an example of the expected output: You can stop your SQream Studio by running the following command: -.. code-block:: console +.. code-block:: $ sqream studio --stop The following is an example of the expected output: -.. code-block:: console +.. code-block:: sqream_admin stopped @@ -1256,8 +1248,6 @@ The following is an example of the expected output: Using the SQream Client ~~~~~~~~~~~~~~~~~ - - You can use the embedded SQream Client on the following nodes: * Master node @@ -1271,7 +1261,7 @@ When using the SQream Client on the Master node, the following default settings The following is an example: -.. code-block:: console +.. code-block:: $ sqream client --master -u sqream -w sqream @@ -1280,7 +1270,7 @@ When using the SQream Client on a Worker node (or nodes), you should use the ``- The following is an example: -.. code-block:: console +.. code-block:: $ sqream client --worker -p 5000 -u sqream -w sqream @@ -1314,7 +1304,7 @@ From the console you can define a spool size value. The following example shows the spool size being set to ``50``: -.. code-block:: console +.. code-block:: $ sqream-console>sqream worker --start 2 -m 50 @@ -1331,7 +1321,7 @@ You can start more than one sqreamd on a single GPU by splitting it. The following example shows the GPU being split into **two** sqreamd's on the GPU in **slot 0**: -.. code-block:: console +.. code-block:: $ sqream-console>sqream worker --start 2 -g 0 @@ -1342,7 +1332,7 @@ Splitting GPU and Setting the Spool Size You can simultaneously split a GPU and set the spool size by appending the ``-m`` flag: -.. code-block:: console +.. code-block:: $ sqream-console>sqream worker --start 2 -g 0 -m 50 @@ -1359,19 +1349,19 @@ The SQream console does not validate the integrity of your external configuratio When using your custom configuration file, you can use the ``-j`` flag to define the full path to the Configuration file, as in the example below: -.. code-block:: console +.. code-block:: $ sqream-console>sqream worker --start 1 -j /etc/sqream/configfile.json .. note:: To start more than one sqream daemon, you must provide files for each daemon, as in the example below: -.. code-block:: console +.. code-block:: $ sqream worker --start 2 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json .. note:: To split a specific GPU, you must also list the GPU flag, as in the example below: -.. code-block:: console +.. code-block:: $ sqream worker --start 2 -g 0 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json @@ -1382,7 +1372,7 @@ Clustering Your Docker Environment SQream lets you connect to a remote Master node to start Docker in Distributed mode. If you have already connected to a Slave node server in Distributed mode, the **sqream Master** and **Client** commands are only available on the Master node. -.. code-block:: console +.. code-block:: $ --master-host $ sqream-console>sqream worker --start 1 --master-host 192.168.0.1020 @@ -1401,13 +1391,13 @@ Checking the Status of SQream Services from the SQream Console From the SQream console, you can check the status of SQream services by running the following command: -.. code-block:: console +.. code-block:: $ sqream-console>sqream master --list The following is an example of the expected output: -.. code-block:: console +.. code-block:: $ sqream-console>sqream master --list $ checking 3 sqream services: @@ -1422,7 +1412,7 @@ Checking the Status of SQream Services from Outside the SQream Console From outside the Sqream Console, you can check the status of SQream services by running the following commands: -.. code-block:: console +.. code-block:: $ sqream-status $ NAMES STATUS PORTS @@ -1448,19 +1438,19 @@ This section describes how to upgrade your SQream system. 3. Extract the following tarball file received from the SQream Support team, under it with the same user and in the same folder that you used while :ref:`Downloading the SQream Software <_download_sqream_software>`. - .. code-block:: console + .. code-block:: $ tar -xvf sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ 4. Navigate to the new folder created as a result of extracting the tarball file: - .. code-block:: console + .. code-block:: $ cd sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ 5. Initiate the upgrade process: - .. code-block:: console + .. code-block:: $ ./sqream-install -i From 775b08676b6cfb870c56a8b91a93b6bae5a0cdfd Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 29 Mar 2022 16:55:16 +0300 Subject: [PATCH 221/300] Update sqream_studio_installation.rst --- installation_guides/sqream_studio_installation.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/installation_guides/sqream_studio_installation.rst b/installation_guides/sqream_studio_installation.rst index 8d6c16546..8646a35ad 100644 --- a/installation_guides/sqream_studio_installation.rst +++ b/installation_guides/sqream_studio_installation.rst @@ -9,11 +9,7 @@ The **Installing SQream Studio** page incudes the following installation guides: :maxdepth: 1 :glob: - installing_studio_on_stand_alone_server installing_prometheus_exporters installing_prometheus_using_binary_packages installing_dashboard_data_collector - - - - + installing_studio_on_stand_alone_server \ No newline at end of file From b6c63eaff5c993f0fec44e44fd7f503bfa6177aa Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 10 Apr 2022 13:28:22 +0300 Subject: [PATCH 222/300] Updated according to TPD-120 Updated according to https://sqream.atlassian.net/browse/TPD-120 (confirmed with Efrat). --- .../sql_syntax/keywords_and_identifiers.rst | 222 ++++++------------ 1 file changed, 68 insertions(+), 154 deletions(-) diff --git a/reference/sql/sql_syntax/keywords_and_identifiers.rst b/reference/sql/sql_syntax/keywords_and_identifiers.rst index 231b22e10..bc2cb1de6 100644 --- a/reference/sql/sql_syntax/keywords_and_identifiers.rst +++ b/reference/sql/sql_syntax/keywords_and_identifiers.rst @@ -1,158 +1,72 @@ .. _keywords_and_identifiers: *************************** -Keywords and Identifiers -*************************** - -SQL statements are made up of three components: - -* Keywords: Keywords have specific meaning in SQL, like ``SELECT``, ``CREATE``, ``WHERE``, etc. -* Identifiers: Names for things like tables, columns, databases, etc. - -.. _keywords: - -Keywords -=========== - -Keywords are special words that make up SQream DB's SQL syntax, and have a meaning in a statement. - -Keywords are not allowed as identifiers. :ref:`A full list of reserved keywords ` can be found at the end of this document. - -.. _identifiers: - Identifiers -============= - -Identifiers are typically used as database objects names, such as databases, tables, views or columns. Because of their use, these are also often also called "names". - -Identifiers can also be used to change a column name in the result (column alias) in a ``SELECT`` statement. - -Identifier rules ------------------- - -An identifier can be either quoted or unquoted, and are maximum 128 characters long. - -Regular identifiers follow these rules: - -#. Does not contain any special characters, apart for an underscore (``_``) -#. Case insensitive. SQream DB converts all identifiers to lowercase unless quoted. -#. Does not equal any :ref:`keyword `, like ``SELECT``, ``OR``, ``AND``, etc. - - -To bypass these limitations, use a quoted identifier by surrounding the identifier with double quotes (``"``). - -Quoted identifiers follow these rules: - -* Surrounded with double quotes ("). -* May contain any ASCII character, except ``@``, ``$`` or ``"``. -* Quoted identifiers are stored case-sensitive and must be referenced with double quotes. - -.. _reserved_keywords: - -Reserved keywords -================== - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Keyword - * - ``ALL`` - * - ``ANALYSE`` - * - ``ANALYZE`` - * - ``AND`` - * - ``ANY`` - * - ``ARRAY`` - * - ``AS`` - * - ``ASC`` - * - ``AUTHORIZATION`` - * - ``BINARY`` - * - ``BOTH`` - * - ``CASE`` - * - ``CAST`` - * - ``CHECK`` - * - ``COLLATE`` - * - ``COLUMN`` - * - ``CONCURRENTLY`` - * - ``CONSTRAINT`` - * - ``CREATE`` - * - ``CROSS`` - * - ``CURRENT_CATALOG`` - * - ``CURRENT_ROLE`` - * - ``CURRENT_TIME`` - * - ``CURRENT_USER`` - * - ``DEFAULT`` - * - ``DEFERRABLE`` - * - ``DESC`` - * - ``DISTINCT`` - * - ``DO`` - * - ``ELSE`` - * - ``END`` - * - ``EXCEPT`` - * - ``FALSE`` - * - ``FETCH`` - * - ``FOR`` - * - ``FREEZE`` - * - ``FROM`` - * - ``FULL`` - * - ``GRANT`` - * - ``GROUP`` - * - ``HASH`` - * - ``HAVING`` - * - ``ILIKE`` - * - ``IN`` - * - ``INITIALLY`` - * - ``INNER`` - * - ``INTERSECT`` - * - ``INTO`` - * - ``IS`` - * - ``ISNULL`` - * - ``JOIN`` - * - ``LEADING`` - * - ``LEFT`` - * - ``LIKE`` - * - ``LIMIT`` - * - ``LOCALTIME`` - * - ``LOCALTIMESTAMP`` - * - ``LOOP`` - * - ``MERGE`` - * - ``NATURAL`` - * - ``NOT`` - * - ``NOTNULL`` - * - ``NULL`` - * - ``OFFSET`` - * - ``ON`` - * - ``ONLY`` - * - ``OPTION`` - * - ``OR`` - * - ``ORDER`` - * - ``OUTER`` - * - ``OVER`` - * - ``OVERLAPS`` - * - ``PLACING`` - * - ``PRIMARY`` - * - ``REFERENCES`` - * - ``RETURNING`` - * - ``RIGHT`` - * - ``RLIKE`` - * - ``SELECT`` - * - ``SESSION_USER`` - * - ``SIMILAR`` - * - ``SOME`` - * - ``SYMMETRIC`` - * - ``SYMMETRIC`` - * - ``TABLE`` - * - ``THEN`` - * - ``TO`` - * - ``TRAILING`` - * - ``TRUE`` - * - ``UNION`` - * - ``UNIQUE`` - * - ``USER`` - * - ``USING`` - * - ``VARIADIC`` - * - ``VERBOSE`` - * - ``WHEN`` - * - ``WHERE`` - * - ``WINDOW`` - * - ``WITH`` \ No newline at end of file +*************************** +**Identifiers** are names given to SQL entities, such as tables, columns, databases, and variables. Identifiers must be unique so that entities can be correctly identified during the execution of a program. Identifiers can also be used to change a column name in the result (column alias) in a ``SELECT`` statement. Identifiers can be either quoted or unquoted and a maximum 128 characters long. + +Identifiers are sometimes referred to as "names". + +Regular identifiers must follow these rules: + +* Must not contain any special characters except for underscores (``_``). +* Must be case-insensitive. SQream converts all identifiers to lowercase unless quoted. +* Does not equal any keywords, such as ``SELECT``, ``OR``, or ``AND``, etc. + +To bypass the rules above you can surround an identifier with double quotes (``"``) or square brackets (``[]``). + +Quoted identifiers must follow these rules: + +* Must be surrounded with double quotes (``"``) or square brackets (``[]``). +* May contain any ASCII character except ``@``, ``$`` or ``"``. +* Must be case-sensitive and referenced with double quotes or square brackets (``[]``). + +Identifiers are different than **keywords**, which are predefined words reserved with specific meanings in a statement. Some examples of keywords are ``SELECT``, ``CREATE``, and ``WHERE``. Note that keywords **cannot** be used as identifiers. + +The following table shows a full list of the reserved keywords: + ++-------------------------------------------------------------------------------------------------+ +| **Keywords** | ++-------------------+---------------------+--------------------+------------------+---------------+ +| **A - C** | **C - G** | **H - N** | **N - S** | **S - W** | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``ALL`` | ``CURRENT_CATALOG`` | ``HASH`` | ``NOT`` | ``SIMILAR`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``ANALYSE`` | ``CURRENT_ROLE`` | ``HAVING`` | ``NOTNULL`` | ``SOME`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``ANALYZE`` | ``CURRENT_TIME`` | ``ILIKE`` | ``NULL`` | ``SYMMETRIC`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``AND`` | ``CURRENT_USER`` | ``IN`` | ``OFFSET`` | ``TABLE`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``ANY`` | ``DEFAULT`` | ``INITIALLY`` | ``ON`` | ``THEN`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``ARRAY`` | ``DEFERRABLE`` | ``INNER`` | ``ONLY`` | ``TO`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``AS`` | ``DESC`` | ``INTERSECT`` | ``OPTION`` | ``TRAILING`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``ASC`` | ``DISTINCT`` | ``INTO`` | ``OR`` | ``TRUE`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``AUTHORIZATION`` | ``DO`` | ``IS`` | ``ORDER`` | ``UNION`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``BINARY`` | ``ELSE`` | ``ISNULL`` | ``OUTER`` | ``UNIQUE`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``BOTH`` | ``END`` | ``JOIN`` | ``OVER`` | ``USER`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``CASE`` | ``EXCEPT`` | ``LEADING`` | ``OVERLAPS`` | ``USING`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``CAST`` | ``FALSE`` | ``LEFT`` | ``PLACING`` | ``VARIADIC`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``CHECK`` | ``FETCH`` | ``LIKE`` | ``PRIMARY`` | ``VERBOSE`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``COLLATE`` | ``FOR`` | ``LIMIT`` | ``REFERENCES`` | ``WHEN`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``COLUMN`` | ``FREEZE`` | ``LOCALTIME`` | ``RETURNING`` | ``WHERE`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``CONCURRENTLY`` | ``FROM`` | ``LOCALTIMESTAMP`` | ``RIGHT`` | ``WINDOW`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``CONSTRAINT`` | ``FULL`` | ``LOOP`` | ``RLIKE`` | ``WITH`` | ++-------------------+---------------------+--------------------+------------------+ | +| ``CREATE`` | ``GRANT`` | ``MERGE`` | ``SELECT`` | | ++-------------------+---------------------+--------------------+------------------+ | +| ``CROSS`` | ``GROUP`` | ``NATURAL`` | ``SESSION_USER`` | | ++-------------------+---------------------+--------------------+------------------+---------------+ From a7cf6bab44ba1e01e7a1c87531434021c98a4b11 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 12 Apr 2022 11:06:22 +0300 Subject: [PATCH 223/300] Updated Taco File Link --- third_party_tools/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party_tools/client_drivers/index.rst b/third_party_tools/client_drivers/index.rst index d9ad66a26..e8c53f151 100644 --- a/third_party_tools/client_drivers/index.rst +++ b/third_party_tools/client_drivers/index.rst @@ -41,7 +41,7 @@ The following are applicable to all operating systems: * **Tableau**: - * `Tableau connector `_ - SQream (.taco) + * `Tableau connector `_ - SQream (.taco) * `Tableau manual installation `_ From 451119798e4cdde2e5a2337ac741a465c5ede122 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 12 Apr 2022 11:44:32 +0300 Subject: [PATCH 224/300] Corrected DELIMITER Syntax --- operational_guides/logging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/logging.rst b/operational_guides/logging.rst index a40e08601..64ac5c8d8 100644 --- a/operational_guides/logging.rst +++ b/operational_guides/logging.rst @@ -374,7 +374,7 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas OPTIONS ( LOCATION = '/home/rhendricks/sqream_storage/logs/**/sqream*.log', - DELIMITER = '|' + DELIMITER = '|', CONTINUE_ON_ERROR = true ) ; From c18f91a0f3fe710cf0cc2b558421421b3c5df1be Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 13 Apr 2022 17:48:55 +0300 Subject: [PATCH 225/300] Added and Published Installing an NGINX Proxy Over a Secure Connection --- ...ing_nginx_proxy_over_secure_connection.rst | 403 ++++++++++++++++++ .../sqream_studio_installation.rst | 3 +- 2 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 installation_guides/installing_nginx_proxy_over_secure_connection.rst diff --git a/installation_guides/installing_nginx_proxy_over_secure_connection.rst b/installation_guides/installing_nginx_proxy_over_secure_connection.rst new file mode 100644 index 000000000..5aef5eaff --- /dev/null +++ b/installation_guides/installing_nginx_proxy_over_secure_connection.rst @@ -0,0 +1,403 @@ +.. _installing_nginx_proxy_over_secure_connection: + +************************* +Installing an NGINX Proxy Over a Secure Connection +************************* +Configuring your NGINX server to use a strong encryption for client connections provides you with secure servers requests, preventing outside parties from gaining access to your traffic. + +The **Installing an NGINX Proxy Over a Secure Connection** page describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +============== +The Node.js platform that SQream uses with our Studio user interface is susceptible to web exposure. This page describes how to implement HTTPS access on your proxy server to establish a secure connection. + +**TLS (Transport Layer Security)**, and its predecessor **SSL (Secure Sockets Layer)**, are standard web protocols used for wrapping normal traffic in a protected, encrypted wrapper. This technology prevents the interception of server-client traffic. It also uses a certificate system for helping users verify the identity of sites they visit. The **Installing an NGINX Proxy Over a Secure Connection** guide describes how to set up a self-signed SSL certificate for use with an NGINX web server on a CentOS 7 server. + +.. note:: A self-signed certificate encrypts communication between your server and any clients. However, because it is not signed by trusted certificate authorities included with web browsers, you cannot use the certificate to automatically validate the identity of your server. + +A self-signed certificate may be appropriate if your domain name is not associated with your server, and in cases where your encrypted web interface is not user-facing. If you do have a domain name, using a CA-signed certificate is generally preferrable. + +For more information on setting up a free trusted certificate, see `How To Secure Nginx with Let's Encrypt on CentOS 7 `_. + +Prerequisites +============== +The following prerequisites are required for installing an NGINX proxy over a secure connection: + +* Super user privileges + + :: + +* A domain name to create a certificate for + +Installing NGINX and Adjusting the Firewall +============== +After verifying that you have the above preriquisites, you must verify that the NGINX web server has been installed on your machine. + +Though NGINX is not available in the default CentOS repositories, it is available from the **EPEL (Extra Packages for Enterprise Linux)** repository. + +**To install NGINX and adjust the firewall:** + +1. Enable the EPEL repository to enable server access to the NGINX package: + + .. code-block:: console + + $ sudo yum install epel-release + +2. Install NGINX: + + .. code-block:: console + + $ sudo yum install nginx + +3. Start the NGINX service: + + .. code-block:: console + + $ sudo systemctl start nginx + +4. Verify that the service is running: + + .. code-block:: console + + $ systemctl status nginx + + The following is an example of the correct output: + + .. code-block:: console + + Output● nginx.service - The nginx HTTP and reverse proxy server + Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled) + Active: active (running) since Fri 2017-01-06 17:27:50 UTC; 28s ago + + . . . + + Jan 06 17:27:50 centos-512mb-nyc3-01 systemd[1]: Started The nginx HTTP and reverse proxy server. + +5. Enable NGINX to start when your server boots up: + + .. code-block:: console + + $ sudo systemctl enable nginx + +6. Verify that access to **ports 80 and 443** are not blocked by a firewall. + + :: + +7. Do one of the following: + + * If you are not using a firewall, skip to :ref:`Creating Your SSL Certificate`. + + :: + + * If you have a running firewall, open ports 80 and 443: + + .. code-block:: console + + $ sudo firewall-cmd --add-service=http + $ sudo firewall-cmd --add-service=https + $ sudo firewall-cmd --runtime-to-permanent + +8. If you have a running **iptables firewall**, for a basic rule set, add HTTP and HTTPS access: + + .. code-block:: console + + $ sudo iptables -I INPUT -p tcp -m tcp --dport 80 -j ACCEPT + $ sudo iptables -I INPUT -p tcp -m tcp --dport 443 -j ACCEPT + + .. note:: The commands in Step 8 above are highly dependent on your current rule set. + +9. Verify that you can access the default NGINX page from a web browser. + +.. _creating_your_ssl_certificate: + +Creating Your SSL Certificate +============== +After installing NGINX and adjusting your firewall, you must create your SSL certificate. + +TLS/SSL combines public certificates with private keys. The SSL key, kept private on your server, is used to encrypt content sent to clients, while the SSL certificate is publicly shared with anyone requesting content. In addition, the SSL certificate can be used to decrypt the content signed by the associated SSL key. Your public certificate is located in the **/etc/ssl/certs** directory on your server. + +This section describes how to create your **/etc/ssl/private directory**, used for storing your private key file. Because the privacy of this key is essential for security, the permissions must be locked down to prevent unauthorized access: + +**To create your SSL certificate:** + +1. Set the following permissions to **private**: + + .. code-block:: console + + $ sudo mkdir /etc/ssl/private + $ sudo chmod 700 /etc/ssl/private + +2. Create a self-signed key and certificate pair with OpenSSL with the following command: + + .. code-block:: console + + $ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt + + The following list describes the elements in the command above: + + * **openssl** - The basic command line tool used for creating and managing OpenSSL certificates, keys, and other files. + + :: + + * **req** - A subcommand for using the X.509 **Certificate Signing Request (CSR)** management. A public key infrastructure standard, SSL and TLS adhere X.509 key and certificate management regulations. + + :: + + * **-x509** - Used for modifying the previous subcommand by overriding the default functionality of generating a certificate signing request with making a self-signed certificate. + + :: + + * **-nodes** - Sets **OpenSSL** to skip the option of securing our certificate with a passphrase, letting NGINX read the file without user intervention when the server is activated. If you don't use **-nodes** you must enter your passphrase after every restart. + + :: + + * **-days 365** - Sets the certificate's validation duration to one year. + + :: + + * **-newkey rsa:2048** - Simultaneously generates a new certificate and new key. Because the key required to sign the certificate was not created in the previous step, it must be created along with the certificate. The **rsa:2048** generates an RSA 2048 bits long. + + :: + + * **-keyout** - Determines the location of the generated private key file. + + :: + + * **-out** - Determines the location of the certificate. + + After creating a self-signed key and certificate pair with OpenSSL, a series of prompts about your server is presented to correctly embed the information you provided in the certificate. + +3. Provide the information requested by the prompts. + + The most important piece of information is the **Common Name**, which is either the server **FQDN** or **your** name. You must enter the domain name associated with your server or your server’s public IP address. + + The following is an example of a filled out set of prompts: + + .. code-block:: console + + OutputCountry Name (2 letter code) [AU]:US + State or Province Name (full name) [Some-State]:New York + Locality Name (eg, city) []:New York City + Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bouncy Castles, Inc. + Organizational Unit Name (eg, section) []:Ministry of Water Slides + Common Name (e.g. server FQDN or YOUR name) []:server_IP_address + Email Address []:admin@your_domain.com + + Both files you create are stored in their own subdirectories of the **/etc/ssl** directory. + + Although SQream uses OpenSSL, in addition we recommend creating a strong **Diffie-Hellman** group, used for negotiating **Perfect Forward Secrecy** with clients. + +4. Create a strong Diffie-Hellman group: + + .. code-block:: console + + $ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 + + Creating a Diffie-Hellman group takes a few minutes, which is stored as the **dhparam.pem** file in the **/etc/ssl/certs** directory. This file can use in the configuration. + +Configuring NGINX to use SSL +============== +After creating your SSL certificate, you must configure NGINX to use SSL. + +The default CentOS NGINX configuration is fairly unstructured, with the default HTTP server block located in the main configuration file. NGINX checks for files ending in **.conf** in the **/etc/nginx/conf.d** directory for additional configuration. + +SQream creates a new file in the **/etc/nginx/conf.d** directory to configure a server block. This block serves content using the certificate files we generated. In addition, the default server block can be optionally configured to redirect HTTP requests to HTTPS. + +.. note:: The example on this page uses the IP address **127.0.0.1**, which you should replace with your machine's IP address. + +**To configure NGINX to use SSL:** + +1. Create and open a file called **ssl.conf** in the **/etc/nginx/conf.d** directory: + + .. code-block:: console + + $ sudo vi /etc/nginx/conf.d/ssl.conf + +2. In the file you created in Step 1 above, open a server block: + + 1. Listen to **port 443**, which is the TLS/SSL default port. + + :: + + 2. Set the ``server_name`` to the server’s domain name or IP address you used as the Common Name when generating your certificate. + + :: + + 3. Use the ``ssl_certificate``, ``ssl_certificate_key``, and ``ssl_dhparam`` directives to set the location of the SSL files you generated, as shown in the **/etc/nginx/conf.d/ssl.conf** file below: + + .. code-block:: console + + upstream ui { + server 127.0.0.1:8080; + } + server { + listen 443 http2 ssl; + listen [::]:443 http2 ssl; + + server_name nginx.sq.l; + + ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt; + ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key; + ssl_dhparam /etc/ssl/certs/dhparam.pem; + + root /usr/share/nginx/html; + + # location / { + # } + + location / { + proxy_pass http://ui; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $host; + add_header Front-End-Https on; + add_header X-Cache-Status $upstream_cache_status; + proxy_cache off; + proxy_cache_revalidate off; + proxy_cache_min_uses 1; + proxy_cache_valid 200 302 1h; + proxy_cache_valid 404 3s; + proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; + proxy_no_cache $cookie_nocache $arg_nocache $arg_comment $http_pragma $http_authorization; + proxy_redirect default; + proxy_max_temp_file_size 0; + proxy_connect_timeout 90; + proxy_send_timeout 90; + proxy_read_timeout 90; + proxy_buffer_size 4k; + proxy_buffering on; + proxy_buffers 4 32k; + proxy_busy_buffers_size 64k; + proxy_temp_file_write_size 64k; + proxy_intercept_errors on; + + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } + + error_page 404 /404.html; + location = /404.html { + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + } + } + +4. Open and modify the **nginx.conf** file located in the **/etc/nginx/conf.d** directory as follows: + + .. code-block:: console + + $ sudo vi /etc/nginx/conf.d/nginx.conf + + .. code-block:: console + + server { + listen 80; + listen [::]:80; + server_name _; + root /usr/share/nginx/html; + + # Load configuration files for the default server block. + include /etc/nginx/default.d/*.conf; + + error_page 404 /404.html; + location = /404.html { + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + } + } + +Redirecting Studio Access from HTTP to HTTPS +================== +After configuring NGINX to use SSL, you must redirect Studio access from HTTP to HTTPS. + +According to your current configuration, NGINX responds with encrypted content for requests on port 443, but with **unencrypted** content for requests on **port 80**. This means that our site offers encryption, but does not enforce its usage. This may be fine for some use cases, but it is usually better to require encryption. This is especially important when confidential data like passwords may be transferred between the browser and the server. + +The default NGINX configuration file allows us to easily add directives to the default port 80 server block by adding files in the /etc/nginx/default.d directory. + +**To create a redirect from HTTP to HTTPS:** + +1. Create a new file called **ssl-redirect.conf** and open it for editing: + + .. code-block:: console + + $ sudo vi /etc/nginx/default.d/ssl-redirect.conf + +2. Copy and paste this line: + + .. code-block:: console + + $ return 301 https://$host$request_uri:8080/; + +Activating Your NGINX Configuration +============== +After redirecting from HTTP to HTTPs, you must restart NGINX to activate your new configuration. + +**To activate your NGINX configuration:** + +1. Verify that your files contain no syntax errors: + + .. code-block:: console + + $ sudo nginx -t + + The following output is generated if your files contain no syntax errors: + + .. code-block:: console + + nginx: the configuration file /etc/nginx/nginx.conf syntax is ok + nginx: configuration file /etc/nginx/nginx.conf test is successful + +2. Restart NGINX to activate your configuration: + + .. code-block:: console + + $ sudo systemctl restart nginx + +Verifying that NGINX is Running +============== +After activating your NGINX configuration, you must verify that NGINX is running correctly. + +**To verify that NGINX is running correctly:** + +1. Check that the service is up and running: + + .. code-block:: console + + $ systemctl status nginx + + The following is an example of the correct output: + + .. code-block:: console + + Output● nginx.service - The nginx HTTP and reverse proxy server + Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled) + Active: active (running) since Fri 2017-01-06 17:27:50 UTC; 28s ago + + . . . + + Jan 06 17:27:50 centos-512mb-nyc3-01 systemd[1]: Started The nginx HTTP and reverse proxy server. + +2. Run the following command: + + .. code-block:: console + + $ sudo netstat -nltp |grep nginx + + The following is an example of the correct output: + + .. code-block:: console + + [sqream@dorb-pc etc]$ sudo netstat -nltp |grep nginx + tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 15486/nginx: master + tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 15486/nginx: master + tcp6 0 0 :::80 :::* LISTEN 15486/nginx: master + tcp6 0 0 :::443 :::* LISTEN 15486/nginx: master \ No newline at end of file diff --git a/installation_guides/sqream_studio_installation.rst b/installation_guides/sqream_studio_installation.rst index 8646a35ad..53c89772d 100644 --- a/installation_guides/sqream_studio_installation.rst +++ b/installation_guides/sqream_studio_installation.rst @@ -12,4 +12,5 @@ The **Installing SQream Studio** page incudes the following installation guides: installing_prometheus_exporters installing_prometheus_using_binary_packages installing_dashboard_data_collector - installing_studio_on_stand_alone_server \ No newline at end of file + installing_studio_on_stand_alone_server + installing_nginx_proxy_over_secure_connection \ No newline at end of file From c9243cffad329ee745ee448332a7cb8d3f08ad78 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 17 Apr 2022 10:33:01 +0300 Subject: [PATCH 226/300] Update installing_studio_on_stand_alone_server.rst Added lines 159-192 based on discussion with Slavi and Dor. --- ...nstalling_studio_on_stand_alone_server.rst | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/installation_guides/installing_studio_on_stand_alone_server.rst b/installation_guides/installing_studio_on_stand_alone_server.rst index 874adba8d..ecec67c7f 100644 --- a/installation_guides/installing_studio_on_stand_alone_server.rst +++ b/installation_guides/installing_studio_on_stand_alone_server.rst @@ -5,8 +5,6 @@ *********************** Installing Studio on a Stand-Alone Server *********************** - - The **Installing Studio on a Stand-Alone Server** guide describes how to install SQream Studio on a stand-alone server. A stand-alone server is a server that does not run SQream based on binary files, Docker, or Kubernetes. The Installing Studio on a Stand-Alone Server guide includes the following sections: @@ -147,7 +145,7 @@ After installing the Dashboard Data Collector, you can install Studio. .. code-block:: console - $ npm run setup -- -y --host= --port=3108 + $ npm run setup -- -y --host= --port=3108 --data-collector-url=http://:8100/api/dashboard/data The above command creates the **sqream-admin-config.json** configuration file in the **sqream-admin** folder and shows the following output: @@ -158,6 +156,40 @@ After installing the Dashboard Data Collector, you can install Studio. For more information about the available set-up arguments, see :ref:`Set-Up Arguments`. :: + +5. To access Studio over a secure connection, in your configuration file do the following: + + #. Change your ``port`` value to **3109**. + + :: + + #. Change your ``ssl`` flag value to **true**. + + The following is an example of the correctly modified configuration file: + + .. code-block:: console + + { + "debugSqream": false, + "webHost": "localhost", + "webPort": 8080, + "webSslPort": 8443, + "logsDirectory": "", + "clusterType": "standalone", + "dataCollectorUrl": "", + "connections": [ + { + "host": "127.0.0.1", + "port":3109, + "isCluster": true, + "name": "default", + "service": "sqream", + "ssl":true, + "networkTimeout": 60000, + "connectionTimeout": 3000 + } + ] + } 5. If you have installed Studio on a server where SQream is already installed, move the **sqream-admin-config.json** file to **/etc/sqream/**: @@ -575,4 +607,4 @@ Back to :ref:`Installing Studio in a Docker Container` +Back to :ref:`Installing Studio on a Stand-Alone Server` \ No newline at end of file From 1261144a33659a1b2fe407c856cdcc87a631fea0 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Apr 2022 17:40:42 +0300 Subject: [PATCH 227/300] Removed System Functions Moved System Functions to SQL Statements > Utilities, and removed System Functions --- reference/sql/sql_functions/index.rst | 110 +++++++-------- .../sql_functions/system_functions/index.rst | 19 --- reference/sql/sql_statements/index.rst | 128 ++++++++---------- .../utility_commands}/explain.rst | 0 .../utility_commands/get_license_info.rst | 72 ++++++++++ .../utility_commands}/show_connections.rst | 0 .../utility_commands}/show_locks.rst | 0 .../utility_commands}/show_node_info.rst | 2 +- .../utility_commands}/show_server_status.rst | 0 .../utility_commands}/show_version.rst | 0 .../utility_commands}/stop_statement.rst | 0 11 files changed, 189 insertions(+), 142 deletions(-) delete mode 100644 reference/sql/sql_functions/system_functions/index.rst rename reference/sql/{sql_functions/system_functions => sql_statements/utility_commands}/explain.rst (100%) create mode 100644 reference/sql/sql_statements/utility_commands/get_license_info.rst rename reference/sql/{sql_functions/system_functions => sql_statements/utility_commands}/show_connections.rst (100%) rename reference/sql/{sql_functions/system_functions => sql_statements/utility_commands}/show_locks.rst (100%) rename reference/sql/{sql_functions/system_functions => sql_statements/utility_commands}/show_node_info.rst (99%) rename reference/sql/{sql_functions/system_functions => sql_statements/utility_commands}/show_server_status.rst (100%) rename reference/sql/{sql_functions/system_functions => sql_statements/utility_commands}/show_version.rst (100%) rename reference/sql/{sql_functions/system_functions => sql_statements/utility_commands}/stop_statement.rst (100%) diff --git a/reference/sql/sql_functions/index.rst b/reference/sql/sql_functions/index.rst index bb2e581f6..a66760b7f 100644 --- a/reference/sql/sql_functions/index.rst +++ b/reference/sql/sql_functions/index.rst @@ -1,25 +1,26 @@ .. _sql_functions: **************** -SQL functions +SQL Functions **************** -SQream DB supports functions from ANSI SQL, as well as others for compatibility. +SQream supports functions from ANSI SQL, as well as others for compatibility. -Summary of functions +Summary of Functions ======================= .. contents:: :local: -Scalar functions +Built-In Scalar Functions ------------------- +For more information about built-in scalar functions, see :ref:`scalar_functions`. -See more about :ref:`scalar_functions` - -Bitwise operations +Bitwise Operations ^^^^^^^^^^^^^^^^^^^^^^^ +The following table shows the **bitwise operations** functions: + .. list-table:: :widths: auto :header-rows: 1 @@ -41,6 +42,7 @@ Bitwise operations Conditionals ^^^^^^^^^^^^^^ +The following table shows the **conditionals** functions: .. list-table:: :widths: auto @@ -65,6 +67,7 @@ Conditionals Conversion ^^^^^^^^^^^^ +The following table shows the **conversion** functions: .. list-table:: :widths: auto @@ -79,8 +82,9 @@ Conversion * - :ref:`to_unixts` - Converts a ``DATE`` or ``DATETIME`` to a UNIX Timestamp -Date and time +Date and Time ^^^^^^^^^^^^^^^^ +The following table shows the **date and time** functions: .. list-table:: :widths: auto @@ -113,10 +117,9 @@ Date and time Numeric ^^^^^^^^^^^ +The following table shows the **arithmetic operators**: -See more about :ref:`arithmetic_operators` - -.. list-table:: Arithmetic operators +.. list-table:: Arithmetic Operators :widths: auto :header-rows: 1 @@ -145,7 +148,11 @@ See more about :ref:`arithmetic_operators` - ``a % b`` - Modulu of ``a`` by ``b``. See also :ref:`mod` -.. list-table:: Functions +For more information about arithmetic operators, see :ref:`arithmetic_operators`. + +The following table shows the **arithmetic operator** functions: + +.. list-table:: Arithemtic Operator Functions :widths: auto :header-rows: 1 @@ -202,6 +209,7 @@ See more about :ref:`arithmetic_operators` Strings ^^^^^^^^^^^ +The following table shows the **string** functions: .. list-table:: :widths: auto @@ -215,6 +223,8 @@ Strings - Calculates the position where a string starts inside another string * - :ref:`concat` - Concatenates two strings + * - :ref:`decode` + - Decodes or extracts binary data from a textual input string * - :ref:`isprefixof` - Matches if a string is the prefix of another string * - :ref:`left` @@ -235,6 +245,8 @@ Strings - Calculates the number of matches of a regular expression match in an argument * - :ref:`regexp_instr` - Returns the start position of a regular expression match in an argument + * - :ref:`regexp_replace` + - Replaces and returns the text column substrings of a regular expression match in an argument * - :ref:`regexp_substr` - Returns a substring of an argument that matches a regular expression * - :ref:`repeat` @@ -256,11 +268,14 @@ Strings * - :ref:`upper` - Converts an argument to an upper-case equivalent - -Aggregate functions +User-Defined Scalar Functions --------------------- +For more information about user-defined scalar functions, see :ref:`scalar_sql_udf`. -See more about :ref:`aggregate_functions` + +Aggregate Functions +--------------------- +The following table shows the **aggregate** functions: .. list-table:: :widths: auto @@ -306,10 +321,11 @@ See more about :ref:`aggregate_functions` - ``varp`` - Calculates population variance of values -Window functions -------------------- +For more information about aggregate functions, see :ref:`aggregate_functions`. -See more about :ref:`window_functions` +Window Functions +------------------- +The following table shows the **window** functions: .. list-table:: :widths: auto @@ -325,41 +341,30 @@ See more about :ref:`window_functions` - Calculates the maximum value * - :ref:`min` - Calculates the minimum value - * - :ref:`rank` - - Calculates the rank of a row - * - :ref:`row_number` - - Calculates the row number * - :ref:`sum` - - Calculates the sum of all of the values - -System functions ------------------- - -System functions allow you to execute actions in the system, such as aborting a query or get information about system processes. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Function - - Description - * - :ref:`explain` - - Returns a static query plan for a statement - * - :ref:`show_connections` - - Returns a list of jobs and statements on the current worker - * - :ref:`show_locks` - - Returns any existing locks in the database - * - :ref:`show_node_info` - - Returns a query plan for an actively running statement with timing information - * - :ref:`show_server_status` - - Shows running statements across the cluster - * - :ref:`show_version` - - Returns the version of SQream DB - * - :ref:`stop_statement` - - Stops a query (or statement) if it is currently running - -Workload management functions + - Calculates the sum of all of the values + * - :ref:`rank` + - Calculates the rank of a row + * - :ref:`first_value` + - Returns the value in the first row of a window + * - :ref:`last_value` + - Returns the value in the last row of a window + * - :ref:`nth_value` + - Returns the value in a specified ``(n)`` row of a window + * - :ref:`dense_rank` + - Returns the rank of the current row with no gaps + * - :ref:`percent_rank` + - Returns the relative rank of the current row + * - :ref:`cume_dist` + - Returns the cumulative distribution of rows + * - :ref:`ntile` + - Returns an integer ranging between ``1`` and the argument value, dividing the partitions as equally as possible + +For more information about window functions, see :ref:`window_functions`. + +Workload Management Functions --------------------------------- +The following table shows the **workload management** functions: .. list-table:: :widths: auto @@ -384,5 +389,4 @@ Workload management functions scalar_functions/index user_defined_functions/index aggregate_functions/index - window_functions/index - system_functions/index + window_functions/index \ No newline at end of file diff --git a/reference/sql/sql_functions/system_functions/index.rst b/reference/sql/sql_functions/system_functions/index.rst deleted file mode 100644 index ba99610ba..000000000 --- a/reference/sql/sql_functions/system_functions/index.rst +++ /dev/null @@ -1,19 +0,0 @@ -.. _system_functions_functions: - -******************** -System Functions -******************** -**System functions** are used for returning system information, such as version and node information, and for maintenance operations that are not regularly accessed from any interface. - -The System Functions page describes the following: - -.. hlist:: - :columns: 1 - - * :ref:`explain` - * :ref:`show_version` - * :ref:`show_connections` - * :ref:`show_locks` - * :ref:`show_node_info` - * :ref:`show_server_status` - * :ref:`stop_statement` \ No newline at end of file diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 3218d5f92..6845ae7cd 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -1,66 +1,75 @@ .. _sql_statements: *************** -SQL statements +SQL Statements *************** +The **SQL Statements** page describes the following commands: + +.. contents:: + :local: + :depth: 1 SQream DB supports commands from ANSI SQL. .. _ddl_commands_list: -Data Definition commands (DDL) +Data Definition Commands (DDL) ================================ -.. list-table:: DDL commands +.. list-table:: DDL Commands :widths: auto :header-rows: 1 :name: ddl_commands * - Command - Usage - * - :ref:`ADD COLUMN` + * - :ref:`add_column` - Add a new column to a table - * - :ref:`ALTER DEFAULT SCHEMA` + * - :ref:`alter_default_schema` - Change the default schema for a role - * - :ref:`ALTER TABLE` + * - :ref:`alter_table` - Change the schema of a table - * - :ref:`CREATE DATABASE` + * - :ref:`cluster_by` + - Change clustering keys in a table + * - :ref:`create_database` - Create a new database - * - :ref:`CREATE EXTERNAL TABLE` + * - :ref:`create_external_table` - Create a new external table in the database (deprecated) - * - :ref:`CREATE FOREIGN TABLE` + * - :ref:`create_foreign_table` - Create a new foreign table in the database - * - :ref:`CREATE FUNCTION ` + * - :ref:`create_function` - Create a new user defined function in the database - * - :ref:`CREATE SCHEMA` + * - :ref:`create_schema` - Create a new schema in the database - * - :ref:`CREATE TABLE` + * - :ref:`create_table` - Create a new table in the database - * - :ref:`CREATE TABLE AS` + * - :ref:`create_table_as` - Create a new table in the database using results from a select query - * - :ref:`CREATE VIEW` + * - :ref:`create_view` - Create a new view in the database - * - :ref:`DROP COLUMN` + * - :ref:`drop_clustering_key` + - Drops all clustering keys in a table + * - :ref:`drop_column` - Drop a column from a table - * - :ref:`DROP DATABASE` + * - :ref:`drop_database` - Drop a database and all of its objects - * - :ref:`DROP FUNCTION` + * - :ref:`drop_function` - Drop a function - * - :ref:`DROP SCHEMA` + * - :ref:`drop_schema` - Drop a schema - * - :ref:`DROP TABLE` + * - :ref:`drop_table` - Drop a table and its contents from a database - * - :ref:`DROP VIEW` + * - :ref:`drop_view` - Drop a view - * - :ref:`RENAME COLUMN` + * - :ref:`rename_column` - Rename a column - * - :ref:`RENAME TABLE` + * - :ref:`rename_table` - Rename a table -Data manipulation commands (DML) +Data Manipulation Commands (DML) ================================ -.. list-table:: DML commands +.. list-table:: DML Commands :widths: auto :header-rows: 1 :name: dml_commands @@ -82,18 +91,24 @@ Data manipulation commands (DML) - Select rows and column from a table * - :ref:`TRUNCATE` - Delete all rows from a table + * - :ref:`UPDATE` + - Modify the value of certain columns in existing rows without creating a table * - :ref:`VALUES` - Return rows containing literal values -Utility commands +Utility Commands ================== -.. list-table:: Utility commands +.. list-table:: Utility Commands :widths: auto :header-rows: 1 * - Command - Usage + * - :ref:`EXPLAIN` + - Returns a static query plan, which can be used to debug query plans + * - :ref:`SELECT GET_LICENSE_INFO` + - View a user's license information * - :ref:`SELECT GET_DDL` - View the ``CREATE TABLE`` statement for a table * - :ref:`SELECT GET_FUNCTION_DDL` @@ -104,37 +119,26 @@ Utility commands - Recreate a view after schema changes * - :ref:`SELECT DUMP_DATABASE_DDL` - View the ``CREATE TABLE`` statement for an current database + * - :ref:`SHOW CONNECTIONS` + - Returns a list of active sessions on the current worker + * - :ref:`SHOW LOCKS` + - Returns a list of locks from across the cluster + * - :ref:`SHOW NODE INFO` + - Returns a snapshot of the current query plan, similar to ``EXPLAIN ANALYZE`` from other databases + * - :ref:`SHOW SERVER STATUS` + - Returns a list of active sessions across the cluster + * - :ref:`SHOW VERSION` + - Returns the system version for SQream DB + * - :ref:`STOP STATEMENT` + - Stops or aborts an active statement -Saved queries -=================== - -See more about :ref:`saved_queries` - -.. list-table:: Saved queries - :widths: auto - :header-rows: 1 - - * - Command - - Usage - * - :ref:`SELECT DROP_SAVED_QUERY` - - Drop a saved query - * - :ref:`SELECT EXECUTE_SAVED_QUERY` - - Executes a saved query - * - :ref:`SELECT LIST_SAVED_QUERIES` - - Returns a list of saved queries - * - :ref:`SELECT RECOMPILE_SAVED_QUERY` - - Recompiles a query that has been invalidated by a schema change - * - :ref:`SELECT SAVE_QUERY` - - Compiles and saves a query for re-use and sharing - * - :ref:`SELECT SHOW_SAVED_QUERY` - - Shows query text for a saved query Monitoring =============== Monitoring statements allow a database administrator to execute actions in the system, such as aborting a query or get information about system processes. -.. list-table:: +.. list-table:: Monitoring :widths: auto :header-rows: 1 @@ -155,10 +159,10 @@ Monitoring statements allow a database administrator to execute actions in the s * - :ref:`stop_statement` - Stops a query (or statement) if it is currently running -Workload management +Workload Management ====================== -.. list-table:: +.. list-table:: Workload Management :widths: auto :header-rows: 1 @@ -171,10 +175,10 @@ Workload management * - :ref:`show_subscribed_instances` - Return a list of service queues and workers -Access control commands +Access Control Commands ================================ -.. list-table:: Access control commands +.. list-table:: Access Control Commands :widths: auto :header-rows: 1 @@ -195,18 +199,4 @@ Access control commands * - :ref:`revoke` - Revoke permissions from a role * - :ref:`rename_role` - - Rename a role - - -.. toctree:: - :maxdepth: 1 - :titlesonly: - :hidden: - :glob: - - ddl_commands/* - dml_commands/* - utility_commands/* - monitoring_commands/* - wlm_commands/* - access_control_commands/* \ No newline at end of file + - Rename a role \ No newline at end of file diff --git a/reference/sql/sql_functions/system_functions/explain.rst b/reference/sql/sql_statements/utility_commands/explain.rst similarity index 100% rename from reference/sql/sql_functions/system_functions/explain.rst rename to reference/sql/sql_statements/utility_commands/explain.rst diff --git a/reference/sql/sql_statements/utility_commands/get_license_info.rst b/reference/sql/sql_statements/utility_commands/get_license_info.rst new file mode 100644 index 000000000..8c28c0ea4 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get_license_info.rst @@ -0,0 +1,72 @@ +.. _get_license_info: + +******************** +GET_LICENSE_INFO +******************** +``GET_LICENSE_INFO`` displays information related to data size limitations, expiration date, and type of license currently used by the SQream cluster. + +Permissions +============= +No special permissions are required. + +Syntax +========== +The following is the correct syntax for running the ``GET LICENSE INFO`` statement: + +.. code-block:: postgres + + get_license_info_statement ::= + SELECT GET_LICENSE_INFO() + ; + +Returns +========== +The following table shows the ``GET_LICENSE_INFO`` license information in the order that it is returned: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + - Example + * - ``compressed_cluster_size`` + - Shows the compressed size (GB) of the cluster. + - 10 + * - ``uncompressed_cluster_size`` + - Shows the uncompressed size (GB) of the cluster. + - 10 + * - ``compress_type`` + - Shows the compression type (``compressed``, ``uncompressed``). + - compressed + * - ``cluster_size_limit`` + - Shows the cluster size limit (GB) of the current license. + - 20 + * - ``expiration_date`` + - Shows the expiration date of the current license. + - 2024-03-18 + * - ``is_date_expired`` + - Shows whether the date has expired or not (``0`` - **No**, ``1`` - **Yes**). + - 0 + * - ``is_size_exceeded`` + - Shows whether the cluster size has exceeded the license size limit or not (``0`` - **No**, ``1`` - **Yes**). + - 0 + * - ``cluster_size_left`` + - Shows the remaining available cluster size (GB) in the license. + - 10 + +Example +=========== +The following is an example of the returned license information described in the **Returns** section above: + +.. code-block:: psql + + 10,100,compressed,20,2045-03-18,0,0,10 + +Parameters +============ +The ``GET_LICENSE_INFO`` command has no parameters. + +Notes +========= +If the license expires or exceeds quotas, contact a SQream representative to extend the license. diff --git a/reference/sql/sql_functions/system_functions/show_connections.rst b/reference/sql/sql_statements/utility_commands/show_connections.rst similarity index 100% rename from reference/sql/sql_functions/system_functions/show_connections.rst rename to reference/sql/sql_statements/utility_commands/show_connections.rst diff --git a/reference/sql/sql_functions/system_functions/show_locks.rst b/reference/sql/sql_statements/utility_commands/show_locks.rst similarity index 100% rename from reference/sql/sql_functions/system_functions/show_locks.rst rename to reference/sql/sql_statements/utility_commands/show_locks.rst diff --git a/reference/sql/sql_functions/system_functions/show_node_info.rst b/reference/sql/sql_statements/utility_commands/show_node_info.rst similarity index 99% rename from reference/sql/sql_functions/system_functions/show_node_info.rst rename to reference/sql/sql_statements/utility_commands/show_node_info.rst index 345d16440..9c1e1ec11 100644 --- a/reference/sql/sql_functions/system_functions/show_node_info.rst +++ b/reference/sql/sql_statements/utility_commands/show_node_info.rst @@ -108,7 +108,7 @@ This is a full list of node types: - Compress data with both CPU and GPU schemes * - ``CpuDecompress`` - CPU - - Decompression operation, common for longer ``VARCHAR`` types + - Decompression operation, common for longer ``TEXT`` types * - ``CpuLoopJoin`` - CPU - A non-indexed nested loop join, performed on the CPU diff --git a/reference/sql/sql_functions/system_functions/show_server_status.rst b/reference/sql/sql_statements/utility_commands/show_server_status.rst similarity index 100% rename from reference/sql/sql_functions/system_functions/show_server_status.rst rename to reference/sql/sql_statements/utility_commands/show_server_status.rst diff --git a/reference/sql/sql_functions/system_functions/show_version.rst b/reference/sql/sql_statements/utility_commands/show_version.rst similarity index 100% rename from reference/sql/sql_functions/system_functions/show_version.rst rename to reference/sql/sql_statements/utility_commands/show_version.rst diff --git a/reference/sql/sql_functions/system_functions/stop_statement.rst b/reference/sql/sql_statements/utility_commands/stop_statement.rst similarity index 100% rename from reference/sql/sql_functions/system_functions/stop_statement.rst rename to reference/sql/sql_statements/utility_commands/stop_statement.rst From e1a37ac87bc2c72ad88cece008bf2407479c87b2 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Apr 2022 17:53:02 +0300 Subject: [PATCH 228/300] Added Update, Remove Truncate If Exists --- .../dml_commands/truncate_if_exists.rst | 84 ------ .../sql_statements/dml_commands/update.rst | 245 ++++++++++++++++++ 2 files changed, 245 insertions(+), 84 deletions(-) delete mode 100644 reference/sql/sql_statements/dml_commands/truncate_if_exists.rst create mode 100644 reference/sql/sql_statements/dml_commands/update.rst diff --git a/reference/sql/sql_statements/dml_commands/truncate_if_exists.rst b/reference/sql/sql_statements/dml_commands/truncate_if_exists.rst deleted file mode 100644 index fc1f4b85e..000000000 --- a/reference/sql/sql_statements/dml_commands/truncate_if_exists.rst +++ /dev/null @@ -1,84 +0,0 @@ -.. _truncate: - -********************** -TRUNCATE_IF_EXISTS -********************** - -``TRUNCATE_IF_EXISTS`` removes all rows from a table. It does not generate an error if the table does not exist. - -It is functionally identical to running a ``DELETE`` statement without a ``WHERE`` clause. - -Permissions -============= - -The role must have the ``DELETE`` permission at the table level. - -Syntax -========== - -.. code-block:: postgres - - truncate_table_statement ::= - TRUNCATE [ TABLE ] [schema_name.]table_name - [ RESTART IDENTITY | CONTINUE IDENTITY ] - ; - - table_name ::= identifier - - schema_name ::= identifier - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``schema_name`` - - The name of the schema for the table. - * - ``table_name`` - - The name of the table to truncate. - * - ``RESTART IDENTITY`` - - Automatically restart sequences owned by columns of the truncated table. - * - ``CONTINUE IDENTITY`` - - Do not change the values of sequences. This is the default. - -Examples -=========== - -Truncating an existing table ---------------------------------------------- - -.. code-block:: psql - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N - - 6 rows - - farm=> SELECT TRUNCATE_IF_EXISTS('public', 'cool_animals'); - Status: 0 result rows - - farm=> SELECT * FROM cool_animals; - - 0 rows - - -Truncating a non-existing table ---------------------------------------------- -.. code-block:: psql - - farm=> SELECT * FROM cool_animals2; - - Status: Ended with errorError preparing statement: At row 1, col 15: table not found public.cool_animals2 - - farm=> SELECT TRUNCATE_IF_EXISTS('public', 'cool_animals2'); - - Status: 0 result rows \ No newline at end of file diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst new file mode 100644 index 000000000..143363b3b --- /dev/null +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -0,0 +1,245 @@ +.. _update: + +********************** +UPDATE +********************** + +The **UPDATE** statement page describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +========== +The ``UPDATE`` command is used to modify the value of certain columns in existing rows without creating a table. + +It can be used to do the following: + +* Perform localized changes in existing data, such as correcting mistakes discovered after ingesting data. + +* Setting columns based on the values of others. + +Syntax +========== +The following is the correct syntax for the ``UPDATE`` command: + +.. code-block:: postgres + + UPDATE target_table_name [[AS] alias1] + SET column_name = expression [,...] + [FROM additional_table_name [[AS] alias2][,...]] + [WHERE condition] + +The following is the correct syntax for triggering a clean-up: + +.. code-block:: postgres + + SELECT cleanup_chunks('schema_name','table_name'); + SELECT cleanup_extents('schema_name','table_name'); + +**Comment** - *The cleanup example above is different than the one used on the DELETED page. Is this correct?* + +Parameters +============ +The following table describes the ``UPDATE`` parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``target_table_name`` + - Specifies the table containing the data to be updated. + * - ``column_name`` + - Specifies the column containing the data to be updated. + * - ``additional_table_name`` + - Additional tables used in the WHERE condition for performing complex joins. + * - ``condition`` + - Specifies the condition for updating the data. + +.. note:: Similar to a DELETE statement, an UPDATE statement may leave some uncleaned data behind, which requires a cleanup operation. + +Examples +=========== +The **Examples** section includes the following examples: + +.. contents:: + :local: + :depth: 1 + +Updating an Entire Table +----------------- +The Examples section shows how to modify the value of certain columns in existing rows without creating a table. The examples are based on the following tables: + +.. image:: /_static/images/delete_optimization.png + +The following methods for updating an entire table generate the same output, and result with the ``bands`` record set to ``NULL``: + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0; + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0 WHERE true; + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0 USING countries; + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0 USING countries WHERE 1=1; + +Performing Simple Updates +----------------- +The following is an example of performing a simple update: + +.. code-block:: postgres + + UPDATE bands SET records_sold = records_sold + 1 WHERE name LIKE 'The %'; + +Updating Tables that Contain Multi-Table Conditions +----------------- +The following shows an example of updating tables that contain multi-table conditions: + +.. code-block:: postgres + + UPDATE bands + SET records_sold = records_sold + 1 + WHERE EXISTS ( + SELECT 1 FROM countries + WHERE countries.id=bands.country_id + AND country.name = 'Sweden' + ); + +You can also write the statement above using the FROM clause: + +.. code-block:: psql + + UPDATE bands + SET records_sold = records_sold + 1 + FROM countries + WHERE countries.id=bands.country_id AND country.name = 'Sweden'; + +Updating Tables that Contain Multi-Table Expressions +----------------- +The following shows an example of updating tables that contain multi-table expressions: + +.. code-block:: postgres + + UPDATE bands + SET records_sold = records_sold + + CASE + WHEN c.name = 'Israel' THEN 2 + ELSE 1 + END + FROM countries c + +Configuring Update Behavior +----------------- +The ``failOnNondeterministicUpdate`` flag is used to configure ``UPDATE`` behavior when updating tables containing multi-table expressions. This flag is needed when you use the ``FROM`` clause along with a set expression containing columns from additional tables. Doing this can cause a match to occur between a row from the target table with multiple rows from the additional tables. + +**Note to self** - *Check if the Studio documentation must be updated for this flag.* + +For instance, the example in the previous section sets the records sold to ``2`` when the country name is Israel. If you were to insert a new entry into this table with Israel spelled in Hebrew (using the same country ID), you would have two rows with identical country ID's. + +When this happens, both rows 5 and 6 in the ``bands`` table match both Israel entries. Because no algorithm exists for determining which entry to use, updating this table may either increase ``records_sold`` by 2 (for Israel in English) or 1 (for Israel in Hebrew). + +You must set the ``failOnNondeterministicUpdate`` flag to ``FALSE`` to prevent an error from occuring. + +**Comment** - *Does the system actually choose one, or does it generate an error?* + +Note that a similar ambiguity can occur when the Hebrew spelling is used in the following example: + +.. code-block:: postgres + + UPDATE bands + SET record_count = record_count + 1 + FROM countries c + WHERE c.name = 'Israel' + +However, the ``WHERE`` clause above prevents a match with any entry other than the defined one. Because the target table row must match with the ``WHERE`` condition at least once to be included in the UPDATE statment, this scenario does not require configuring the ``failOnNondeterministicUpdate`` flag. + +**Comment** - *Please review the paragraph above. I'm pretty sure I described this correctly.* + +For more information, see `SQream Acceleration Studio `_. + +Identifying and Cleaning Up Tables +--------------------------------------- +**Comment** - *I copied and pasted this entire section from "DELETE". Does anything have to adjusted here for "UPDATE"?* + +The following section shows examples of each phase required for cleaning up tables: + +* :ref:`Listing tables that require clean-up` +* :ref:`Identifying clean-up predicates` +* :ref:`Triggering a clean-up` + +.. _listing_tables_that_require_cleanup: + +Listing Tables that Require Clean-Up +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following shows an example of listing tables that require clean-up: + +.. code-block:: psql + + farm=> SELECT t.table_name FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + GROUP BY 1; + cool_animals + + 1 row + +.. _identifying_cleanup_predicates: + +Identifying Clean-Up Predicates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following shows an example of listing the clean-up predicates: + +.. code-block:: psql + + farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + WHERE t.table_name = 'cool_animals'; + weight > 1000 + + 1 row + +.. _triggering_a_cleanup: + +Triggering a Clean-Up +^^^^^^^^^^^^^^^^^^^^^^ +The following shows an example of triggering a clean-up: + +.. code-block:: psql + + -- Chunk reorganization (SWEEP) + farm=> SELECT CLEANUP_CHUNKS('public','cool_animals'); + executed + + -- Delete leftover files (VACUUM) + farm=> SELECT CLEANUP_EXTENTS('public','cool_animals'); + executed + + + farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + WHERE t.table_name = 'cool_animals'; + + 0 rows + +Permissions +============= +Executing an ``UPDATE`` statement requires the following permissions: + +* Both ``UPDATE`` and ``SELECT`` permissions on the target table. +* The ``SELECT`` permission for each additional table you reference in the statement (in ither the ``FROM`` clause or ``WHERE`` subquery section). + +Locking and Concurrency +============= +Executing the ``UPDATE`` statement obtains an exclusive UPDATE lock on the target table, but does not lock the destination tables. \ No newline at end of file From dc164a57bb6fde580a372d1cad896486e853e5a2 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 1 May 2022 09:44:44 +0300 Subject: [PATCH 229/300] Removed Global Locks: SQ-10436 https://sqream.atlassian.net/browse/SQ-10436 Capitalized headers --- feature_guides/concurrency_and_locks.rst | 26 ++++++------------------ 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/feature_guides/concurrency_and_locks.rst b/feature_guides/concurrency_and_locks.rst index bdff2235a..2a85d2642 100644 --- a/feature_guides/concurrency_and_locks.rst +++ b/feature_guides/concurrency_and_locks.rst @@ -10,7 +10,7 @@ Read only transactions are never blocked, and never block anything. Even if you .. _locking_modes: -Locking modes +Locking Modes ================ SQream DB has two kinds of locks: @@ -27,7 +27,7 @@ SQream DB has two kinds of locks: This lock allows other statements to insert or delete data from a table, but they'll have to wait in order to run DDL. -When are locks obtained? +When are Locks Obtained? ============================ .. list-table:: @@ -64,23 +64,7 @@ When are locks obtained? Statements that wait will exit with an error if they hit the lock timeout. The default timeout is 3 seconds, see ``statementLockTimeout``. -Global locks ----------------- - -Some operations require exclusive global locks at the cluster level. These usually short-lived locks will be obtained for the following operations: - - * :ref:`create_database` - * :ref:`create_role` - * :ref:`create_table` - * :ref:`alter_role` - * :ref:`alter_table` - * :ref:`drop_database` - * :ref:`drop_role` - * :ref:`drop_table` - * :ref:`grant` - * :ref:`revoke` - -Monitoring locks +Monitoring Locks =================== Monitoring locks across the cluster can be useful when transaction contention takes place, and statements appear "stuck" while waiting for a previous statement to release locks. @@ -99,4 +83,6 @@ In this example, we create a table based on results (:ref:`create_table_as`), bu 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | globalpermission$ | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | schema$t$public | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 \ No newline at end of file + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + +For more information on troubleshooting lock related issues, see :ref:`lock_related_issues`. \ No newline at end of file From 789ff8e15cda204d0d4fe51d5d082f2bd13c89e3 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 2 May 2022 11:25:50 +0300 Subject: [PATCH 230/300] TPD-123 --- .../ddl_commands/cluster_by.rst | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/cluster_by.rst b/reference/sql/sql_statements/ddl_commands/cluster_by.rst index 1a6972b1e..3f6023533 100644 --- a/reference/sql/sql_statements/ddl_commands/cluster_by.rst +++ b/reference/sql/sql_statements/ddl_commands/cluster_by.rst @@ -3,28 +3,38 @@ ********************** CLUSTER BY ********************** +The ``CLUSTER BY`` command is used for changing clustering keys in a table. -``CLUSTER BY`` can be used to change clustering keys in a table. +For more information, see the following: +* :ref:`flexible_data_clustering` -Read our :ref:`data_clustering` guide for more information. + :: -See also: :ref:`drop_clustering_key`, :ref:`create_table`. +* :ref:`drop_clustering_key` - -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. + :: + +* :ref:`create_table` Syntax ========== +The following is the correct syntax for the CLUSTER BY command: .. code-block:: postgres alter_table_rename_table_statement ::= ALTER TABLE [schema_name.]table_name CLUSTER BY column_name [, ...] ; + + create_table_statement ::= + CREATE [ OR REPLACE ] TABLE [schema_name.]table_name ( + { column_def [, ...] } + ) + [ CLUSTER BY { column_name [, ...] } ] + ; + + column_def :: = { column_name type_name [ default ] [ column_constraint ] } table_name ::= identifier @@ -33,6 +43,7 @@ Syntax Parameters ============ +The following table shows the CLUSTER BY parameters: .. list-table:: :widths: auto @@ -42,28 +53,32 @@ Parameters - Description * - ``schema_name`` - The schema name for the table. Defaults to ``public`` if not specified. + * - ``OR REPLACE`` + - Creates a new tables and overwrites any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. + * - ``column_def`` + - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. * - ``table_name`` - The table name to apply the change to. * - ``column_name [, ... ]`` - - Comma separated list of columns to create clustering keys for + - Comma separated list of columns to create clustering keys for. - -Usage notes +Usage Notes ================= - Removing clustering keys does not affect existing data. -To force data to re-cluster, the table has to be recreated (i.e. with :ref:`create_table_as`). +To force data to re-cluster, the table has to be recreated (i.e. with :ref:`create_table`). -Examples +Example =========== - -Reclustering a table +Reclustering a Table ----------------------------------------- +The following example shows how to recluster a table: .. code-block:: postgres ALTER TABLE public.users CLUSTER BY start_date; - +Permissions +============= +The role must have the ``DDL`` permission at the database or table level. \ No newline at end of file From df5c8d2c45869eb2e2374f2183b96e78f0b2653a Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 2 May 2022 14:30:08 +0300 Subject: [PATCH 231/300] Update executing_statements_and_running_queries_from_the_editor.rst --- ...ts_and_running_queries_from_the_editor.rst | 180 +++++++++--------- 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst index 8dc5e8072..85592f84d 100644 --- a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst @@ -102,7 +102,83 @@ The database object functions are used to perform the following: * The **additional operations** |icon-dots| - displays the following additional options: +.. |icon-user| image:: /_static/images/studio_icon_user.png + :align: middle + +.. |icon-dots| image:: /_static/images/studio_icon_dots.png + :align: middle + +.. |icon-editor| image:: /_static/images/studio_icon_editor.png + :align: middle + +.. |icon-copy| image:: /_static/images/studio_icon_copy.png + :align: middle + +.. |icon-select| image:: /_static/images/studio_icon_select.png + :align: middle + +.. |icon-dots| image:: /_static/images/studio_icon_dots.png + :align: middle + +.. |icon-filter| image:: /_static/images/studio_icon_filter.png + :align: middle + +.. |icon-ddl-edit| image:: /_static/images/studio_icon_ddl_edit.png + :align: middle + +.. |icon-run-optimizer| image:: /_static/images/studio_icon_run_optimizer.png + :align: middle + +.. |icon-generate-create-statement| image:: /_static/images/studio_icon_generate_create_statement.png + :align: middle + +.. |icon-plus| image:: /_static/images/studio_icon_plus.png + :align: middle + +.. |icon-close| image:: /_static/images/studio_icon_close.png + :align: middle + +.. |icon-left| image:: /_static/images/studio_icon_left.png + :align: middle + +.. |icon-right| image:: /_static/images/studio_icon_right.png + :align: middle + +.. |icon-format-sql| image:: /_static/images/studio_icon_format.png + :align: middle + +.. |icon-download-query| image:: /_static/images/studio_icon_download_query.png + :align: middle + +.. |icon-open-query| image:: /_static/images/studio_icon_open_query.png + :align: middle +.. |icon-execute| image:: /_static/images/studio_icon_execute.png + :align: middle + +.. |icon-stop| image:: /_static/images/studio_icon_stop.png + :align: middle + +.. |icon-dashboard| image:: /_static/images/studio_icon_dashboard.png + :align: middle + +.. |icon-expand| image:: /_static/images/studio_icon_expand.png + :align: middle + +.. |icon-scale| image:: /_static/images/studio_icon_scale.png + :align: middle + +.. |icon-expand-down| image:: /_static/images/studio_icon_expand_down.png + :align: middle + +.. |icon-add| image:: /_static/images/studio_icon_add.png + :align: middle + +.. |icon-add-worker| image:: /_static/images/studio_icon_add_worker.png + :align: middle + +.. |keep-tabs| image:: /_static/images/studio_keep_tabs.png + :align: middle .. list-table:: @@ -112,23 +188,23 @@ The database object functions are used to perform the following: * - Function - Description * - Insert statement - - Generates an `INSERT `_ statement for the selected table in the editing area. + - Generates an `INSERT `_ statement for the selected table in the editing area. * - Delete statement - - Generates a `DELETE `_ statement for the selected table in the editing area. + - Generates a `DELETE `_ statement for the selected table in the editing area. * - Create Table As statement - - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. + - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. * - Rename statement - - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. + - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. * - Adding column statement - - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. + - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. * - Truncate table statement - - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. + - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. * - Drop table statement - Generates a ``DROP`` statement for the selected object in the editing area. * - Table DDL - - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL `_. + - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL `_. * - DDL Optimizer - - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. + - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. Optimizing Database Tables Using the DDL Optimizer ----------------------- @@ -153,17 +229,17 @@ The following table describes the DDL Optimizer screen: Clicking **Run Optimizer** adds a tab to the Statement panel showing the optimized results of the selected object. -For more information, see `Optimization and Best Practices `_. +For more information, see `Optimization and Best Practices `_. Executing Pre-Defined Queries from the System Queries Panel --------------- The **System Queries** panel lets you execute predefined queries and includes the following system query types: -* **Catalog queries** - used for analyzing table compression rates, users and permissions, etc. +* **Catalog queries** - Used for analyzing table compression rates, users and permissions, etc. :: -* **Admin queries** - queries related to available (describe the functionality in a general way). Queries useful for SQream database management. +* **Admin queries** - Queries useful for SQream database management. Clicking an item pastes the query into the Statement pane, and you can undo a previous operation by pressing **Ctrl + Z**. @@ -198,7 +274,7 @@ You can add and name new tabs for each statement that you need to execute, and S You can also rename the default tab name by double-clicking it and typing a new name and write multiple statements in tandem in the same tab by separating them with semicolons (``;``).If too many tabs to fit into the Statement Pane are open at the same time, the tab arrows are displayed. You can scroll through the tabs by clicking |icon-left| or |icon-right|, and close tabs by clicking |icon-close|. You can also close all tabs at once by clicking **Close all** located to the right of the tabs. -.. tip:: If this is your first time using SQream, see `Getting Started `_. +.. tip:: If this is your first time using SQream, see `Getting Started `_. .. Keyboard shortcuts @@ -336,6 +412,8 @@ The Execution Tree tracks each phase of your query in real time as a vertical tr Each node displays a number displaying its **node ID**, its **type**, **table name** (if relevant), **status**, and **runtime**. The nodes are color-coded for easy identification. Green nodes indicate **completed nodes**, yellow indicates **nodes in progress**, and red indicates **slowest nodes**, typically joins, as shown below: +.. image:: /_static/images/nodes.png + Viewing Query Statistics ^^^^^^^^^^^^ The following statistical information is displayed in the top left corner, as shown in the figure above: @@ -412,81 +490,3 @@ The SQL View panel allows you to more easily view certain queries, such as a lon :ref:`Back to Viewing Statement and Query Results from the Results Panel` :ref:`Back to Executing Statements and Running Queries from the Editor` - -.. |icon-user| image:: /_static/images/studio_icon_user.png - :align: middle - -.. |icon-dots| image:: /_static/images/studio_icon_dots.png - :align: middle - -.. |icon-editor| image:: /_static/images/studio_icon_editor.png - :align: middle - -.. |icon-copy| image:: /_static/images/studio_icon_copy.png - :align: middle - -.. |icon-select| image:: /_static/images/studio_icon_select.png - :align: middle - -.. |icon-dots| image:: /_static/images/studio_icon_dots.png - :align: middle - -.. |icon-filter| image:: /_static/images/studio_icon_filter.png - :align: middle - -.. |icon-ddl-edit| image:: /_static/images/studio_icon_ddl_edit.png - :align: middle - -.. |icon-run-optimizer| image:: /_static/images/studio_icon_run_optimizer.png - :align: middle - -.. |icon-generate-create-statement| image:: /_static/images/studio_icon_generate_create_statement.png - :align: middle - -.. |icon-plus| image:: /_static/images/studio_icon_plus.png - :align: middle - -.. |icon-close| image:: /_static/images/studio_icon_close.png - :align: middle - -.. |icon-left| image:: /_static/images/studio_icon_left.png - :align: middle - -.. |icon-right| image:: /_static/images/studio_icon_right.png - :align: middle - -.. |icon-format-sql| image:: /_static/images/studio_icon_format.png - :align: middle - -.. |icon-download-query| image:: /_static/images/studio_icon_download_query.png - :align: middle - -.. |icon-open-query| image:: /_static/images/studio_icon_open_query.png - :align: middle - -.. |icon-execute| image:: /_static/images/studio_icon_execute.png - :align: middle - -.. |icon-stop| image:: /_static/images/studio_icon_stop.png - :align: middle - -.. |icon-dashboard| image:: /_static/images/studio_icon_dashboard.png - :align: middle - -.. |icon-expand| image:: /_static/images/studio_icon_expand.png - :align: middle - -.. |icon-scale| image:: /_static/images/studio_icon_scale.png - :align: middle - -.. |icon-expand-down| image:: /_static/images/studio_icon_expand_down.png - :align: middle - -.. |icon-add| image:: /_static/images/studio_icon_add.png - :align: middle - -.. |icon-add-worker| image:: /_static/images/studio_icon_add_worker.png - :align: middle - -.. |keep-tabs| image:: /_static/images/studio_keep_tabs.png - :align: middle From a6a2af0aa7106a07ed4d3ae8be8e7f82168b3683 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 2 May 2022 14:36:32 +0300 Subject: [PATCH 232/300] Update executing_statements_and_running_queries_from_the_editor.rst --- ...ts_and_running_queries_from_the_editor.rst | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst index 85592f84d..25d2be354 100644 --- a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst @@ -188,23 +188,23 @@ The database object functions are used to perform the following: * - Function - Description * - Insert statement - - Generates an `INSERT `_ statement for the selected table in the editing area. + - Generates an `INSERT `_ statement for the selected table in the editing area. * - Delete statement - - Generates a `DELETE `_ statement for the selected table in the editing area. + - Generates a `DELETE `_ statement for the selected table in the editing area. * - Create Table As statement - - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. + - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. * - Rename statement - - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. + - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. * - Adding column statement - - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. + - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. * - Truncate table statement - - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. + - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. * - Drop table statement - Generates a ``DROP`` statement for the selected object in the editing area. * - Table DDL - - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL `_. + - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL `_. * - DDL Optimizer - - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. + - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. Optimizing Database Tables Using the DDL Optimizer ----------------------- @@ -229,7 +229,7 @@ The following table describes the DDL Optimizer screen: Clicking **Run Optimizer** adds a tab to the Statement panel showing the optimized results of the selected object. -For more information, see `Optimization and Best Practices `_. +For more information, see `Optimization and Best Practices `_. Executing Pre-Defined Queries from the System Queries Panel --------------- @@ -274,7 +274,7 @@ You can add and name new tabs for each statement that you need to execute, and S You can also rename the default tab name by double-clicking it and typing a new name and write multiple statements in tandem in the same tab by separating them with semicolons (``;``).If too many tabs to fit into the Statement Pane are open at the same time, the tab arrows are displayed. You can scroll through the tabs by clicking |icon-left| or |icon-right|, and close tabs by clicking |icon-close|. You can also close all tabs at once by clicking **Close all** located to the right of the tabs. -.. tip:: If this is your first time using SQream, see `Getting Started `_. +.. tip:: If this is your first time using SQream, see `Getting Started `_. .. Keyboard shortcuts From 7daf5a1aab9a30310113f0721da3183b31a4d57f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 10 May 2022 13:50:24 +0300 Subject: [PATCH 233/300] TPD-106 --- .../ddl_commands/rename_column.rst | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/rename_column.rst b/reference/sql/sql_statements/ddl_commands/rename_column.rst index f91933f71..1022ce0f2 100644 --- a/reference/sql/sql_statements/ddl_commands/rename_column.rst +++ b/reference/sql/sql_statements/ddl_commands/rename_column.rst @@ -3,16 +3,11 @@ ********************** RENAME COLUMN ********************** - -``RENAME COLUMN`` can be used to rename columns in a table. - -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. +The ``RENAME COLUMN`` command can be used to rename columns in a table. Syntax ========== +The following is the correct syntax for the ``RENAME_COLUMN`` command: .. code-block:: postgres @@ -30,6 +25,7 @@ Syntax Parameters ============ +The following table describes the `RENAME_COLUMN`` parameters: .. list-table:: :widths: auto @@ -48,18 +44,29 @@ Parameters Examples =========== +The **Examples** section includes the following examples: -Renaming a column +.. contents:: + :local: + :depth: 1 + +Renaming a Column ----------------------------------------- +The following is an example of renaming a column: .. code-block:: postgres -- Remove the 'weight' column ALTER TABLE users RENAME COLUMN weight TO mass; -Renaming a quoted name +Renaming a Quoted Name -------------------------- +The following is an example of renaming a quoted name: .. code-block:: postgres - ALTER TABLE users RENAME COLUMN "mass" TO "Mass (Kilograms); \ No newline at end of file + ALTER TABLE users RENAME COLUMN "mass" TO "Mass (Kilograms); + +Permissions +============= +The role must have the ``DDL`` permission at the database or table level. \ No newline at end of file From 67876eca019874b4bb080e641c99f26827a80eed Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 10 May 2022 14:44:56 +0300 Subject: [PATCH 234/300] TPd-155 --- .../ddl_commands/add_column.rst | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/add_column.rst b/reference/sql/sql_statements/ddl_commands/add_column.rst index d532c956f..bac71bd2c 100644 --- a/reference/sql/sql_statements/ddl_commands/add_column.rst +++ b/reference/sql/sql_statements/ddl_commands/add_column.rst @@ -3,14 +3,11 @@ ********************** ADD COLUMN ********************** - The ``ADD COLUMN`` command is used to add columns to an existing table. - - Syntax ========== -The following is the correct syntax for adding a table: +The following is the correct syntax for adding a column to an existing table: .. code-block:: postgres @@ -32,8 +29,6 @@ The following is the correct syntax for adding a table: default ::= DEFAULT default_value - - Parameters ============ The following parameters can be used for adding a table: @@ -52,19 +47,20 @@ The following parameters can be used for adding a table: - A comma separated list of ADD COLUMN commands * - ``column_def`` - A column definition. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. + +Usage Notes +=========== +The following usage notes apply when adding a column to an existing table: -.. note:: * When adding a new column to an existing table, a default (or null constraint) has to be specified, even if the table is empty. - * A new column added to the table can not contain an IDENTITY or be of the TEXT type. - -Permissions -============= -The role must have the ``DDL`` permission at the database or table level. + :: + + * New columns you add to the table cannot be TEXT or contain an IDENTITY. Examples =========== -This section includes the following examples: +The **Examples** section includes the following examples: .. contents:: :local: @@ -77,8 +73,7 @@ This example shows how to add a simple column with a default value: .. code-block:: postgres ALTER TABLE cool_animals - ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL; - + ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL; Adding Several Columns in One Command ------------------------------------------- @@ -88,4 +83,8 @@ This example shows how to add several columns in one command: ALTER TABLE cool_animals ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL, - ADD COLUMN date_seen DATE DEFAULT '2019-08-01'; + ADD COLUMN date_seen DATE DEFAULT '2019-08-01'; + +Permissions +============= +The role must have the ``DDL`` permission at the database or table level. \ No newline at end of file From 7f303f7dd8fe26136d15eadce679eb58f680ac6b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 10 May 2022 17:25:12 +0300 Subject: [PATCH 235/300] TPD-88 --- reference/sql/sql_statements/ddl_commands/cluster_by.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/reference/sql/sql_statements/ddl_commands/cluster_by.rst b/reference/sql/sql_statements/ddl_commands/cluster_by.rst index 3f6023533..e4cf42ad4 100644 --- a/reference/sql/sql_statements/ddl_commands/cluster_by.rst +++ b/reference/sql/sql_statements/ddl_commands/cluster_by.rst @@ -40,6 +40,7 @@ The following is the correct syntax for the CLUSTER BY command: column_name ::= identifier +.. note:: SQream does not support clustering by TEXT columns. Parameters ============ From 9f69b50ab76c4edf4f891f61455d79c20e23de7e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 12 May 2022 13:04:04 +0300 Subject: [PATCH 236/300] Fixed Drivers Link and Capitalized Headings --- .../client_drivers/cpp/index.rst | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/third_party_tools/client_drivers/cpp/index.rst b/third_party_tools/client_drivers/cpp/index.rst index 703643b0f..7cbabd1ef 100644 --- a/third_party_tools/client_drivers/cpp/index.rst +++ b/third_party_tools/client_drivers/cpp/index.rst @@ -13,7 +13,7 @@ This tutorial shows how to write a C++ program that uses this driver. :local: -Installing the C++ driver +Installing the C++ Driver ================================== Prerequisites @@ -21,13 +21,13 @@ Prerequisites The SQream DB C++ driver was built on 64-bit Linux, and is designed to work with RHEL 7 and Ubuntu 16.04 and newer. -Getting the library +Getting the Library --------------------- -The C++ driver is provided as a tarball containing the compiled ``libsqream.so`` file and a header ``sqream.h``. Get the driver from the `SQream Drivers page `_. The library can be integrated into your C++-based applications or projects. +The C++ driver is provided as a tarball containing the compiled ``libsqream.so`` file and a header ``sqream.h``. Get the driver from the `SQream Drivers page `_. The library can be integrated into your C++-based applications or projects. -Extract the tarball archive +Extract the Tarball Archive ----------------------------- Extract the library files from the tarball @@ -41,7 +41,7 @@ Examples Assuming there is a SQream DB worker to connect to, we'll connect to it using the application and run some statements. -Testing the connection to SQream DB +Testing the Connection to SQream -------------------------------------------- Download this file by right clicking and saving to your computer :download:`connect_test.cpp `. @@ -52,7 +52,7 @@ Download this file by right clicking and saving to your computer :download:`conn :linenos: -Compiling and running the application +Compiling and Running the Application ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ To build this code, place the library and header file in ./libsqream-3.0/ and run @@ -64,7 +64,7 @@ To build this code, place the library and header file in ./libsqream-3.0/ and ru Modify the ``-I`` and ``-L`` arguments to match the ``.so`` library and ``.h`` file if they are in another directory. -Creating a table and inserting values +Creating a Table and Inserting Values -------------------------------------------- Download this file by right clicking and saving to your computer :download:`insert_test.cpp `. @@ -75,7 +75,7 @@ Download this file by right clicking and saving to your computer :download:`inse :linenos: -Compiling and running the application +Compiling and Running the Application ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ To build this code, use @@ -83,5 +83,4 @@ To build this code, use .. code-block:: console $ g++ -Wall -Ilibsqream-3.0 -Llibsqream-3.0 -lsqream insert_test.cpp -o insert_test - $ ./insert_test - + $ ./insert_test \ No newline at end of file From 011ba6ec45a777332aa6254ba83533dc41e12944 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 12 May 2022 13:36:13 +0300 Subject: [PATCH 237/300] Update index.rst --- third_party_tools/client_drivers/cpp/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party_tools/client_drivers/cpp/index.rst b/third_party_tools/client_drivers/cpp/index.rst index 7cbabd1ef..dcb76cfbc 100644 --- a/third_party_tools/client_drivers/cpp/index.rst +++ b/third_party_tools/client_drivers/cpp/index.rst @@ -24,7 +24,7 @@ The SQream DB C++ driver was built on 64-bit Linux, and is designed to work with Getting the Library --------------------- -The C++ driver is provided as a tarball containing the compiled ``libsqream.so`` file and a header ``sqream.h``. Get the driver from the `SQream Drivers page `_. The library can be integrated into your C++-based applications or projects. +The C++ driver is provided as a tarball containing the compiled ``libsqream.so`` file and a header ``sqream.h``. Get the driver from the `SQream Drivers page `_. The library can be integrated into your C++-based applications or projects. Extract the Tarball Archive From 2669a379a367cd087fa10ec58415b36e04f9e412 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 12 May 2022 16:29:34 +0300 Subject: [PATCH 238/300] TPD-154: Partial implementation Implemented some of Natalia's comments. Questions remain about others. --- feature_guides/workload_manager.rst | 4 ++-- reference/sql/sql_statements/index.rst | 2 +- sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/feature_guides/workload_manager.rst b/feature_guides/workload_manager.rst index bc00d0c20..ca545a2ca 100644 --- a/feature_guides/workload_manager.rst +++ b/feature_guides/workload_manager.rst @@ -9,7 +9,7 @@ The **Workload Manager** allows SQream DB workers to identify their availability Overview =============================== -The Workload Manager allows a system engineer or database administrator to allocate specific workers and compute resoucres for various tasks. +The Workload Manager allows a system engineer or database administrator to allocate specific workers and compute resources for various tasks. For example: @@ -60,7 +60,7 @@ The configuration in this example allocates resources as shown below: - ✓ - ✓ -This configuration gives the ETL queue dedicated access to two workers, one of which cannot be used by regular queries. +This configuration gives the ETL queue dedicated access to one worker, which cannot be used. Queries from management uses any available worker. diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 6845ae7cd..04b24a58f 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -171,7 +171,7 @@ Workload Management * - :ref:`subscribe_service` - Add a SQream DB worker to a service queue * - :ref:`unsubscribe_service` - - Remove a SQream DB worker to a service queue + - Remove a SQream DB worker from a service queue * - :ref:`show_subscribed_instances` - Return a list of service queues and workers diff --git a/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst b/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst index 889a4ea64..2b5a80e8a 100644 --- a/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst +++ b/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst @@ -20,4 +20,4 @@ Exporting and Importing Configuration Files ------------------------- You can also export and import your configuration settings into a .json file. This allows you to easily edit your parameters and to share this file with other users if required. -For more information about configuring your instance of SQream, see :ref:`Configuration`. \ No newline at end of file +For more information about configuring your instance of SQream, see `Configuration `_. \ No newline at end of file From 4d7bd11697e302c2a1ff684e4f6bf1850b26fb9e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 15 May 2022 11:24:32 +0300 Subject: [PATCH 239/300] SQ-10052 --- data_type_guides/converting_and_casting_types.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index ee5e273da..bb6475646 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -23,4 +23,6 @@ SQream supports the following three data conversion types: :: -* See the :ref:`SQL functions reference ` for additional functions that convert from a specific value which is not an SQL type, such as :ref:`from_unixts`, etc. \ No newline at end of file +* See the :ref:`SQL functions reference ` for additional functions that convert from a specific value which is not an SQL type, such as :ref:`from_unixts`, etc. + +.. note:: SQream interprets integer constants exceeding the maximum bigint value as float constants, which may cause precision loss. \ No newline at end of file From f29839784d878f3331914457a8ff1c7d2533fe9a Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 15 May 2022 11:54:51 +0300 Subject: [PATCH 240/300] Moved show_server_status to Utility Commands --- .../show_server_status.rst | 109 ------------------ 1 file changed, 109 deletions(-) delete mode 100644 reference/sql/sql_statements/monitoring_commands/show_server_status.rst diff --git a/reference/sql/sql_statements/monitoring_commands/show_server_status.rst b/reference/sql/sql_statements/monitoring_commands/show_server_status.rst deleted file mode 100644 index 5ef1886af..000000000 --- a/reference/sql/sql_statements/monitoring_commands/show_server_status.rst +++ /dev/null @@ -1,109 +0,0 @@ -.. _show_server_status: - -******************** -SHOW_SERVER_STATUS -******************** - -``SHOW_SERVER_STATUS`` returns a list of active sessions across the cluster. - -To list active statements on the current worker only, see :ref:`show_connections`. - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - show_server_status_statement ::= - SELECT SHOW_SERVER_STATUS() - ; - -Parameters -============ - -None - -Returns -========= - -This function returns a list of active sessions. If no sessions are active across the cluster, the result set will be empty. - -.. list-table:: Result columns - :widths: auto - :header-rows: 1 - - * - ``service`` - - The service name for the statement - * - ``instance`` - - The worker ID - * - ``connection_id`` - - Connection ID - * - ``serverip`` - - Worker end-point IP - * - ``serverport`` - - Worker end-point port - * - ``database_name`` - - Database name for the statement - * - ``user_name`` - - Username running the statement - * - ``clientip`` - - Client IP - * - ``statementid`` - - Statement ID - * - ``statement`` - - Statement text - * - ``statementstarttime`` - - Statement start timestamp - * - ``statementstatus`` - - Statement status (see table below) - * - ``statementstatusstart`` - - Last updated timestamp - -.. include from here: 66 - - -.. list-table:: Statement status values - :widths: auto - :header-rows: 1 - - * - Status - - Description - * - ``Preparing`` - - Statement is being prepared - * - ``In queue`` - - Statement is waiting for execution - * - ``Initializing`` - - Statement has entered execution checks - * - ``Executing`` - - Statement is executing - * - ``Stopping`` - - Statement is in the process of stopping - - - -.. include until here 86 - -Notes -=========== - -* This utility shows the active sessions. Some sessions may be actively connected, but not running any statements. - -Examples -=========== - -Using ``SHOW_SERVER_STATUS`` to get statement IDs ----------------------------------------------------- - - -.. code-block:: psql - - t=> SELECT SHOW_SERVER_STATUS(); - service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart - --------+------------+---------------+--------------+------------+---------------+------------+-------------+-------------+-----------------------------+---------------------+-----------------+--------------------- - sqream | | 102 | 192.168.1.91 | 5000 | t | rhendricks | 192.168.0.1 | 128 | SELECT SHOW_SERVER_STATUS() | 24-12-2019 00:14:53 | Executing | 24-12-2019 00:14:53 - -The statement ID is ``128``, running on worker ``192.168.1.91``. From 37646bffa73b588f91f6591950969e6701fee086 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 15 May 2022 12:14:01 +0300 Subject: [PATCH 241/300] Moved Monitoring commands to Utility commands --- reference/sql/sql_statements/index.rst | 25 -- .../monitoring_commands/explain.rst | 59 ---- .../monitoring_commands/show_connections.rst | 78 ----- .../monitoring_commands/show_locks.rst | 79 ----- .../monitoring_commands/show_node_info.rst | 310 ------------------ .../monitoring_commands/stop_statement.rst | 77 ----- 6 files changed, 628 deletions(-) delete mode 100644 reference/sql/sql_statements/monitoring_commands/explain.rst delete mode 100644 reference/sql/sql_statements/monitoring_commands/show_connections.rst delete mode 100644 reference/sql/sql_statements/monitoring_commands/show_locks.rst delete mode 100644 reference/sql/sql_statements/monitoring_commands/show_node_info.rst delete mode 100644 reference/sql/sql_statements/monitoring_commands/stop_statement.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 04b24a58f..98c4b0bc5 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -133,31 +133,6 @@ Utility Commands - Stops or aborts an active statement -Monitoring -=============== - -Monitoring statements allow a database administrator to execute actions in the system, such as aborting a query or get information about system processes. - -.. list-table:: Monitoring - :widths: auto - :header-rows: 1 - - * - Command - - Usage - * - :ref:`explain` - - Returns a static query plan for a statement - * - :ref:`show_connections` - - Returns a list of jobs and statements on the current worker - * - :ref:`show_locks` - - Returns any existing locks in the database - * - :ref:`show_node_info` - - Returns a query plan for an actively running statement with timing information - * - :ref:`show_server_status` - - Shows running statements across the cluster - * - :ref:`show_version` - - Returns the version of SQream DB - * - :ref:`stop_statement` - - Stops a query (or statement) if it is currently running Workload Management ====================== diff --git a/reference/sql/sql_statements/monitoring_commands/explain.rst b/reference/sql/sql_statements/monitoring_commands/explain.rst deleted file mode 100644 index e9b7e7ee9..000000000 --- a/reference/sql/sql_statements/monitoring_commands/explain.rst +++ /dev/null @@ -1,59 +0,0 @@ -.. _explain: - -***************** -EXPLAIN -***************** - -``EXPLAIN`` returns a static query plan, which can be used to debug query plans. - -To see an actively running query or statement, use :ref:`show_node_info` instead. - -See also :ref:`show_node_info`, :ref:`show_server_status`. - - -Permissions -============= - -The role must have the ``SELECT`` permissions for any tables referenced by the query. - -Syntax -========== - -.. code-block:: postgres - - explain_statement ::= - SELECT EXPLAIN(query_stmt) - ; - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``query_stmt`` - - The select query to generate the plan for. - -Notes -=========== - -Use dollar-quoting to escape the query text - -Examples -=========== - -Generating a static query plan ----------------------------------- - -.. code-block:: psql - - t=> SELECT EXPLAIN($$SELECT DATEADD(hour,1,dt) FROM cool_dates$$); - Select - Specific (TTNative Gpu) (dateadd@null := dt@null, - dateadd@val := (pure_if dt@null "0" (addHoursdt2dt dt@val "1"))) - Table Scan - public.cool_dates ("dt@null", "dt@val") [] - diff --git a/reference/sql/sql_statements/monitoring_commands/show_connections.rst b/reference/sql/sql_statements/monitoring_commands/show_connections.rst deleted file mode 100644 index 1bd320a4c..000000000 --- a/reference/sql/sql_statements/monitoring_commands/show_connections.rst +++ /dev/null @@ -1,78 +0,0 @@ -.. _show_connections: - -******************** -SHOW_CONNECTIONS -******************** - -``SHOW_CONNECTIONS`` returns a list of active sessions on the current worker. - -To see sessions across the cluster, see :ref:`show_server_status`. - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - show_connections_statement ::= - SELECT SHOW_CONNECTIONS() - ; - -Parameters -============ - -None - -Returns -========= - -This function returns a list of active sessions. If no sessions are active on the worker, the result set will be empty. - -.. list-table:: Result columns - :widths: auto - :header-rows: 1 - - * - ``ip`` - - The worker hostname or IP - * - ``conn_id`` - - Connection ID - * - ``conn_start_time`` - - Connection start timestamp - * - ``stmt_id`` - - Statement ID. Connections with no active statement display ``-1``. - * - ``stmt_start_time`` - - Statement start timestamp - * - ``stmt`` - - Statement text - - -Notes -=========== - -* This utility shows the active connections. Some sessions may be actively connected, but not currently running a statement. - -* A connection is typically reused. There could be many statements under a single connection ID. - -Examples -=========== - -Using ``SHOW_CONNECTIONS`` to get statement IDs ----------------------------------------------------- - - -.. code-block:: psql - - t=> SELECT SHOW_CONNECTIONS(); - ip | conn_id | conn_start_time | stmt_id | stmt_start_time | stmt - -------------+---------+---------------------+---------+---------------------+-------------------------- - 192.168.1.91 | 103 | 2019-12-24 00:01:27 | 129 | 2019-12-24 00:38:18 | SELECT GET_DATE(), * F... - 192.168.1.91 | 23 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | - 192.168.1.91 | 22 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | - 192.168.1.91 | 26 | 2019-12-24 00:01:28 | -1 | 2019-12-24 00:01:28 | - - -The statement ID we're interested in is ``129``. We can see the connection started at 00:01:27, while the statement started at 00:38:18. \ No newline at end of file diff --git a/reference/sql/sql_statements/monitoring_commands/show_locks.rst b/reference/sql/sql_statements/monitoring_commands/show_locks.rst deleted file mode 100644 index d5e7c02ec..000000000 --- a/reference/sql/sql_statements/monitoring_commands/show_locks.rst +++ /dev/null @@ -1,79 +0,0 @@ -.. _show_locks: - -******************** -SHOW_LOCKS -******************** - -``SHOW_LOCKS`` returns a list of locks from across the cluster. - -Read more about locks in :ref:`concurrency_and_locks`. - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - show_locks_statement ::= - SELECT SHOW_LOCKS() - ; - -Parameters -============ - -None - -Returns -========= - -This function returns a list of active locks. If no locks are active in the cluster, the result set will be empty. - -.. list-table:: Result columns - :widths: auto - :header-rows: 1 - - * - ``stmt_id`` - - Statement ID that caused the lock. - * - ``stmt_string`` - - Statement text - * - ``username`` - - The role that executed the statement - * - ``server`` - - The worker node's IP - * - ``port`` - - The worker node's port - * - ``locked_object`` - - The full qualified name of the object being locked, separated with ``$`` (e.g. ``table$t$public$nba2`` for table ``nba2`` in schema ``public``, in database ``t`` - * - ``lockmode`` - - The locking mode (:ref:`inclusive` or :ref:`exclusive`). - * - ``statement_start_time`` - - Timestamp the statement started - * - ``lock_start_time`` - - Timestamp the lock was obtained - - -Examples -=========== - -Using ``SHOW_LOCKS`` to see active locks ---------------------------------------------------- - -In this example, we create a table based on results (:ref:`create_table_as`), but we are also effectively dropping the previous table (by using ``OR REPLACE``). Thus, SQream DB applies locks during the table creation process to prevent the table from being altered during it's creation. - - -.. code-block:: psql - - t=> SELECT SHOW_LOCKS(); - statement_id | statement_string | username | server | port | locked_object | lockmode | statement_start_time | lock_start_time - -------------+-------------------------------------------------------------------------------------------------+----------+--------------+------+---------------------------------+-----------+----------------------+-------------------- - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | database$t | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | globalpermission$ | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | schema$t$public | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - - diff --git a/reference/sql/sql_statements/monitoring_commands/show_node_info.rst b/reference/sql/sql_statements/monitoring_commands/show_node_info.rst deleted file mode 100644 index 345d16440..000000000 --- a/reference/sql/sql_statements/monitoring_commands/show_node_info.rst +++ /dev/null @@ -1,310 +0,0 @@ -.. _show_node_info: - -******************** -SHOW_NODE_INFO -******************** - -``SHOW_NODE_INFO`` returns a snapshot of the current query plan, similar to ``EXPLAIN ANALYZE`` from other databases. - -The snapshot provides information about execution which can be used for monitoring and troubleshooting slow running statements by helping identify long-running execution nodes (components that process data), etc. - -See also :ref:`explain`, :ref:`show_server_status`. - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - show_node_info_statement ::= - SELECT SHOW_NODE_INFO(stmt_id) - ; - - stmt_id ::= bigint - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``stmt_id`` - - The statement ID to explore - -Returns -========= - -This utility returns details of the execution nodes, if the statement is still running. - -If the statement has finished, or the statment ID does not exist, the utility returns an empty result set. - -.. list-table:: Result columns - :widths: auto - :header-rows: 1 - - * - Column name - - Description - * - ``stmt_id`` - - The ID for the statement - * - ``node_id`` - - This node's ID in this execution plan - * - ``node_type`` - - The node type - * - ``rows`` - - Total number of rows this node has processed - * - ``chunks`` - - Number of chunks this node has processed - * - ``avg_rows_in_chunk`` - - Average amount of rows that this node processes in each chunk (``rows / chunks``) - * - ``time`` - - Timestamp for this node's creation - * - ``parent_node_id`` - - The ``node_id`` of this node's parent - * - ``read`` - - Total data read from disk - * - ``write`` - - Total data written to disk - * - ``comment`` - - Additional information (e.g. table name for ``ReadTable``) - * - ``timesum`` - - Total elapsed time for this execution node's processing - - -.. _node_types: - -Node types -============= - -This is a full list of node types: - -.. list-table:: Node types - :widths: auto - :header-rows: 1 - - * - Column name - - Execution location - - Description - * - ``AddChunkId`` - - - - Used during insert operations - * - ``AddSequences`` - - - - Used during insert operations, with :ref:`identity columns` - * - ``AddMinMaxMetadata`` - - - - Used to calculate ranges for the :ref:`chunk metadata system` - * - ``AddTopSortFilters`` - - - - An operation to optimize ``LIMIT`` when used alongside ``ORDER BY`` - * - ``Compress`` - - CPU and GPU - - Compress data with both CPU and GPU schemes - * - ``CpuDecompress`` - - CPU - - Decompression operation, common for longer ``VARCHAR`` types - * - ``CpuLoopJoin`` - - CPU - - A non-indexed nested loop join, performed on the CPU - * - ``CpuReduce`` - - CPU - - A reduce process performed on the CPU, primarily with ``DISTINCT`` aggregates (e.g. ``COUNT(DISTINCT ...)``) - * - ``CpuToGpu``, ``GpuToCpu`` - - - - An operation that moves data to or from the GPU for processing - * - ``CpuTransform`` - - CPU - - A transform operation performed on the CPU, usually a :ref:`scalar function` - * - ``CrossJoin`` - - - - A join without a join condition - * - ``DeferredGather`` - - CPU - - Merges the results of GPU operations with a result set [#f0]_ - * - ``Distinct`` - - GPU - - Removes duplicate rows (usually as part of the ``DISTINCT`` operation) - * - ``Distinct_Merge`` - - CPU - - The merge operation of the ``Distinct`` operation - * - ``Filter`` - - GPU - - A filtering operation, such as a ``WHERE`` or ``JOIN`` clause - * - ``GpuCopy`` - - GPU - - Copies data between GPUs or within a single GPU - * - ``GpuDecompress`` - - GPU - - Decompression operation - * - ``GpuReduceMerge`` - - GPU - - An operation to optimize part of the merger phases in the GPU - * - ``GpuTransform`` - - GPU - - A transformation operation such as a type cast or :ref:`scalar function` - * - ``Hash`` - - CPU - - Hashes the output result. Used internally. - * - ``JoinSideMarker`` - - - - Used internally. - * - ``LiteralValues`` - - CPU - - Creates a virtual relation (table), when :ref:`values` is used - * - ``LocateFiles`` - - CPU - - Validates external file paths for foreign data wrappers, expanding directories and GLOB patterns - * - ``LoopJoin`` - - GPU - - A non-indexed nested loop join, performed on the GPU - * - ``MarkMatchedJoinRows`` - - - - Used in outer joins, matches rows for larger join operations - * - ``NullifyDuplicates`` - - - - Replaces duplicate values with ``NULL`` to calculate distinct aggregates - * - ``NullSink`` - - CPU - - Used internally - * - ``ParseCsv`` - - CPU - - A CSV parser, used after ``ReadFiles`` to convert the CSV into columnar data - * - ``PopNetworkQueue`` - - CPU - - Fetches data from the network queue (e.g. when used with :ref:`insert`) - * - ``PushToNetworkQueue`` - - CPU - - Sends result sets to a client connected over the network - * - ``ReadCatalog`` - - CPU - - Converts the :ref:`catalog` into a relation (table) - * - ``ReadFiles`` - - CPU - - Reads external flat-files - * - ``ReadOrc`` - - CPU - - Reads data from an ORC file - * - ``ReadParquet`` - - CPU - - Reads data from a Parquet file - * - ``ReadTable`` - - CPU - - Reads data from a standard table stored on disk - * - ``ReadTableMetadata`` - - CPU - - Reads only table metadata as an optimization - * - ``Rechunk`` - - - - Reorganize multiple small :ref:`chunks` into a full chunk. Commonly found after joins and when :ref:`HIGH_SELECTIVITY` is used - * - ``Reduce`` - - GPU - - A reduction operation, such as a ``GROUP BY`` - * - ``ReduceMerge`` - - GPU - - A merge operation of a reduction operation, helps operate on larger-than-RAM data - * - ``ReorderInput`` - - - - Change the order of arguments in preparation for the next operation - * - ``SeparatedGather`` - - GPU - - Gathers additional columns for the result - * - ``Sort`` - - GPU - - Sort operation [#f1]_ - * - ``SortMerge`` - - CPU - - A merge operation of a sort operation, helps operate on larger-than-RAM data - * - ``SortMergeJoin`` - - GPU - - A sort-merge join, performed on the GPU - * - ``TakeRowsFromChunk`` - - - - Take the first N rows from each chunk, to optimize ``LIMIT`` when used alongside ``ORDER BY`` - * - ``Top`` - - - - Limits the input size, when used with ``LIMIT`` (or its alias ``TOP``) - * - ``UdfTransform`` - - CPU - - Executes a :ref:`user defined function` - * - ``UnionAll`` - - - - Combines two sources of data when ``UNION ALL`` is used - * - ``VarCharJoiner`` - - - - Used internally - * - ``VarCharSplitter`` - - - - Used intenrally - * - ``Window`` - - GPU - - Executes a non-ranking :ref:`window function` - * - ``WindowRanking`` - - GPU - - Executes a ranking :ref:`window function` - * - ``WriteTable`` - - CPU - - Writes the result set to a standard table stored on disk - -.. rubric:: Footnotes - -.. [#f0] Gathers columns which should be returned. This node typically spends most of the time on decompressing additional columns. - -.. [#f1] A GPU sort operation can be added by the statement compiler before ``GROUP BY`` or ``JOIN`` operations. - -Statement statuses -======================= - -.. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst - :start-line: 67 - :end-line: 84 - -Notes -=========== - -* This utility shows the execution information for active statements. Once a query has finished execution, the information is no longer available using this utility. See :ref:`logging` for more information about extracting the information from the logs. - -* This utility is primarily intended for troubleshooting with SQream support. - -Examples -=========== - -Getting execution details for a statement ------------------------------------------------- - - -.. code-block:: psql - - t=> SELECT SHOW_SERVER_STATUS(); - service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart - --------+------------+---------------+--------------+------------+---------------+-----------+--------------+-------------+-----------------------------------------------------------------+---------------------+-----------------+--------------------- - sqream | | 152 | 192.168.1.91 | 5000 | t | sqream | 192.168.1.91 | 176 | SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | 25-12-2019 23:53:13 | Executing | 25-12-2019 23:53:13 - sqream | | 151 | 192.168.1.91 | 5000 | t | sqream | 192.168.0.1 | 177 | SELECT show_server_status() | 25-12-2019 23:51:31 | Executing | 25-12-2019 23:53:13 - - -The statement ID we want to reserach is ``176``, running on worker ``192.168.1.91``. - -The query text is ``SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1;`` - -.. code-block:: psql - - t=> SELECT SHOW_NODE_INFO(176); - stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum - --------+---------+--------------------+------+--------+-------------------+---------------------+----------------+------+-------+------------+-------- - 176 | 1 | PushToNetworkQueue | 1 | 1 | 1 | 2019-12-25 23:53:13 | -1 | | | | 0.0025 - 176 | 2 | Rechunk | 1 | 1 | 1 | 2019-12-25 23:53:13 | 1 | | | | 0 - 176 | 3 | GpuToCpu | 1 | 1 | 1 | 2019-12-25 23:53:13 | 2 | | | | 0 - 176 | 4 | ReorderInput | 1 | 1 | 1 | 2019-12-25 23:53:13 | 3 | | | | 0 - 176 | 5 | Filter | 1 | 1 | 1 | 2019-12-25 23:53:13 | 4 | | | | 0.0002 - 176 | 6 | GpuTransform | 457 | 1 | 457 | 2019-12-25 23:53:13 | 5 | | | | 0.0002 - 176 | 7 | GpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 6 | | | | 0 - 176 | 8 | CpuToGpu | 457 | 1 | 457 | 2019-12-25 23:53:13 | 7 | | | | 0.0003 - 176 | 9 | Rechunk | 457 | 1 | 457 | 2019-12-25 23:53:13 | 8 | | | | 0 - 176 | 10 | CpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 9 | | | | 0 - 176 | 11 | ReadTable | 457 | 1 | 457 | 2019-12-25 23:53:13 | 10 | 4MB | | public.nba | 0.0004 - diff --git a/reference/sql/sql_statements/monitoring_commands/stop_statement.rst b/reference/sql/sql_statements/monitoring_commands/stop_statement.rst deleted file mode 100644 index 30efc25b5..000000000 --- a/reference/sql/sql_statements/monitoring_commands/stop_statement.rst +++ /dev/null @@ -1,77 +0,0 @@ -.. _stop_statement: - -******************** -STOP_STATEMENT -******************** - -``STOP_STATEMENT`` stops or aborts an active statement. - -To find a statement by ID, see :ref:`show_server_status` and :ref:`show_connections`. - -.. tip:: Some DBMSs call this process killing a session, terminating a job, or kill query - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - stop_statement_statement ::= - SELECT STOP_STATEMENT(stmt_id) - ; - - stmt_id ::= bigint - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``stmt_id`` - - The statement ID to stop - -Returns -========= - -This utility does not return any value, and always succeeds even if the statement does not exist, or has already stopped. - - -Notes -=========== - -* This utility always succeeds even if the statement does not exist, or has already stopped. - -Examples -=========== - -Using :ref:`show_connections` to get statement IDs ----------------------------------------------------- - -.. tip:: Use :ref:`show_server_status` to find statments from across the entire cluster, or :ref:`show_connections` to show statements from the current worker the client is connected to. - -.. code-block:: psql - - t=> SELECT SHOW_CONNECTIONS(); - ip | conn_id | conn_start_time | stmt_id | stmt_start_time | stmt - -------------+---------+---------------------+---------+---------------------+-------------------------- - 192.168.1.91 | 103 | 2019-12-24 00:01:27 | 129 | 2019-12-24 00:38:18 | SELECT GET_DATE(), * F... - 192.168.1.91 | 23 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | - 192.168.1.91 | 22 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | - 192.168.1.91 | 26 | 2019-12-24 00:01:28 | -1 | 2019-12-24 00:01:28 | - - -The statement ID we're interested in is ``129``. We can now stop this statement: - -.. code-block:: psql - - t=> SELECT STOP_STATEMENT(129) - executed - From f565758c8f1ca38c856ebc45ef55175216666e1c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 17 May 2022 14:42:45 +0300 Subject: [PATCH 242/300] Removed UPDATE UPDATE is part of the 2022.1 RN and was accidentally documented on this branch. Checking and removing from ALL BRANCHES. --- .../sql_statements/dml_commands/update.rst | 245 ------------------ reference/sql/sql_statements/index.rst | 2 - 2 files changed, 247 deletions(-) delete mode 100644 reference/sql/sql_statements/dml_commands/update.rst diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst deleted file mode 100644 index 143363b3b..000000000 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ /dev/null @@ -1,245 +0,0 @@ -.. _update: - -********************** -UPDATE -********************** - -The **UPDATE** statement page describes the following: - -.. contents:: - :local: - :depth: 1 - -Overview -========== -The ``UPDATE`` command is used to modify the value of certain columns in existing rows without creating a table. - -It can be used to do the following: - -* Perform localized changes in existing data, such as correcting mistakes discovered after ingesting data. - -* Setting columns based on the values of others. - -Syntax -========== -The following is the correct syntax for the ``UPDATE`` command: - -.. code-block:: postgres - - UPDATE target_table_name [[AS] alias1] - SET column_name = expression [,...] - [FROM additional_table_name [[AS] alias2][,...]] - [WHERE condition] - -The following is the correct syntax for triggering a clean-up: - -.. code-block:: postgres - - SELECT cleanup_chunks('schema_name','table_name'); - SELECT cleanup_extents('schema_name','table_name'); - -**Comment** - *The cleanup example above is different than the one used on the DELETED page. Is this correct?* - -Parameters -============ -The following table describes the ``UPDATE`` parameters: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``target_table_name`` - - Specifies the table containing the data to be updated. - * - ``column_name`` - - Specifies the column containing the data to be updated. - * - ``additional_table_name`` - - Additional tables used in the WHERE condition for performing complex joins. - * - ``condition`` - - Specifies the condition for updating the data. - -.. note:: Similar to a DELETE statement, an UPDATE statement may leave some uncleaned data behind, which requires a cleanup operation. - -Examples -=========== -The **Examples** section includes the following examples: - -.. contents:: - :local: - :depth: 1 - -Updating an Entire Table ------------------ -The Examples section shows how to modify the value of certain columns in existing rows without creating a table. The examples are based on the following tables: - -.. image:: /_static/images/delete_optimization.png - -The following methods for updating an entire table generate the same output, and result with the ``bands`` record set to ``NULL``: - -.. code-block:: postgres - - UPDATE bands SET records_sold = 0; - -.. code-block:: postgres - - UPDATE bands SET records_sold = 0 WHERE true; - -.. code-block:: postgres - - UPDATE bands SET records_sold = 0 USING countries; - -.. code-block:: postgres - - UPDATE bands SET records_sold = 0 USING countries WHERE 1=1; - -Performing Simple Updates ------------------ -The following is an example of performing a simple update: - -.. code-block:: postgres - - UPDATE bands SET records_sold = records_sold + 1 WHERE name LIKE 'The %'; - -Updating Tables that Contain Multi-Table Conditions ------------------ -The following shows an example of updating tables that contain multi-table conditions: - -.. code-block:: postgres - - UPDATE bands - SET records_sold = records_sold + 1 - WHERE EXISTS ( - SELECT 1 FROM countries - WHERE countries.id=bands.country_id - AND country.name = 'Sweden' - ); - -You can also write the statement above using the FROM clause: - -.. code-block:: psql - - UPDATE bands - SET records_sold = records_sold + 1 - FROM countries - WHERE countries.id=bands.country_id AND country.name = 'Sweden'; - -Updating Tables that Contain Multi-Table Expressions ------------------ -The following shows an example of updating tables that contain multi-table expressions: - -.. code-block:: postgres - - UPDATE bands - SET records_sold = records_sold + - CASE - WHEN c.name = 'Israel' THEN 2 - ELSE 1 - END - FROM countries c - -Configuring Update Behavior ------------------ -The ``failOnNondeterministicUpdate`` flag is used to configure ``UPDATE`` behavior when updating tables containing multi-table expressions. This flag is needed when you use the ``FROM`` clause along with a set expression containing columns from additional tables. Doing this can cause a match to occur between a row from the target table with multiple rows from the additional tables. - -**Note to self** - *Check if the Studio documentation must be updated for this flag.* - -For instance, the example in the previous section sets the records sold to ``2`` when the country name is Israel. If you were to insert a new entry into this table with Israel spelled in Hebrew (using the same country ID), you would have two rows with identical country ID's. - -When this happens, both rows 5 and 6 in the ``bands`` table match both Israel entries. Because no algorithm exists for determining which entry to use, updating this table may either increase ``records_sold`` by 2 (for Israel in English) or 1 (for Israel in Hebrew). - -You must set the ``failOnNondeterministicUpdate`` flag to ``FALSE`` to prevent an error from occuring. - -**Comment** - *Does the system actually choose one, or does it generate an error?* - -Note that a similar ambiguity can occur when the Hebrew spelling is used in the following example: - -.. code-block:: postgres - - UPDATE bands - SET record_count = record_count + 1 - FROM countries c - WHERE c.name = 'Israel' - -However, the ``WHERE`` clause above prevents a match with any entry other than the defined one. Because the target table row must match with the ``WHERE`` condition at least once to be included in the UPDATE statment, this scenario does not require configuring the ``failOnNondeterministicUpdate`` flag. - -**Comment** - *Please review the paragraph above. I'm pretty sure I described this correctly.* - -For more information, see `SQream Acceleration Studio `_. - -Identifying and Cleaning Up Tables ---------------------------------------- -**Comment** - *I copied and pasted this entire section from "DELETE". Does anything have to adjusted here for "UPDATE"?* - -The following section shows examples of each phase required for cleaning up tables: - -* :ref:`Listing tables that require clean-up` -* :ref:`Identifying clean-up predicates` -* :ref:`Triggering a clean-up` - -.. _listing_tables_that_require_cleanup: - -Listing Tables that Require Clean-Up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The following shows an example of listing tables that require clean-up: - -.. code-block:: psql - - farm=> SELECT t.table_name FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - GROUP BY 1; - cool_animals - - 1 row - -.. _identifying_cleanup_predicates: - -Identifying Clean-Up Predicates -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The following shows an example of listing the clean-up predicates: - -.. code-block:: psql - - farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; - weight > 1000 - - 1 row - -.. _triggering_a_cleanup: - -Triggering a Clean-Up -^^^^^^^^^^^^^^^^^^^^^^ -The following shows an example of triggering a clean-up: - -.. code-block:: psql - - -- Chunk reorganization (SWEEP) - farm=> SELECT CLEANUP_CHUNKS('public','cool_animals'); - executed - - -- Delete leftover files (VACUUM) - farm=> SELECT CLEANUP_EXTENTS('public','cool_animals'); - executed - - - farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; - - 0 rows - -Permissions -============= -Executing an ``UPDATE`` statement requires the following permissions: - -* Both ``UPDATE`` and ``SELECT`` permissions on the target table. -* The ``SELECT`` permission for each additional table you reference in the statement (in ither the ``FROM`` clause or ``WHERE`` subquery section). - -Locking and Concurrency -============= -Executing the ``UPDATE`` statement obtains an exclusive UPDATE lock on the target table, but does not lock the destination tables. \ No newline at end of file diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 98c4b0bc5..1431f82e1 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -91,8 +91,6 @@ Data Manipulation Commands (DML) - Select rows and column from a table * - :ref:`TRUNCATE` - Delete all rows from a table - * - :ref:`UPDATE` - - Modify the value of certain columns in existing rows without creating a table * - :ref:`VALUES` - Return rows containing literal values From d9baa017e527b6f0d356ff7d393939b818b1c63f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 22 May 2022 15:13:59 +0300 Subject: [PATCH 243/300] Reinstated EXECUTE SAVED QUERY Removed by accident --- reference/sql/sql_statements/index.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 1431f82e1..ca4ec0f72 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -103,6 +103,8 @@ Utility Commands * - Command - Usage + * - :ref:`EXECUTE SAVED QUERY` + - Executes a previously saved query * - :ref:`EXPLAIN` - Returns a static query plan, which can be used to debug query plans * - :ref:`SELECT GET_LICENSE_INFO` From 544a360c7fcb5c3a9219983efce954856ab7c55c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 22 May 2022 15:28:47 +0300 Subject: [PATCH 244/300] Fixed links. --- .../sql/sql_statements/utility_commands/execute_saved_query.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst index 6fe41fa08..1d972e61f 100644 --- a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst @@ -8,7 +8,7 @@ EXECUTE_SAVED_QUERY Read more in the :ref:`saved_queries` guide. -See also: ref:`save_query`, :ref:`drop_saved_query`, ref:`show_saved_query`, ref:`list_saved_queries`. +See also: :ref:`save_query`, :ref:`drop_saved_query`, :ref:`show_saved_query`, :ref:`list_saved_queries`. Permissions ============= From a77241492efb5df441f3cb32ef11a904d885581e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 22 May 2022 15:59:26 +0300 Subject: [PATCH 245/300] Fixed broken links. --- configuration_guides/current_configuration_method.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configuration_guides/current_configuration_method.rst b/configuration_guides/current_configuration_method.rst index f86500972..7ea2bba72 100644 --- a/configuration_guides/current_configuration_method.rst +++ b/configuration_guides/current_configuration_method.rst @@ -705,8 +705,8 @@ Configuration Roles =========== SQream divides flags into the following roles, each with their own set of permissions: -* **`Administration flags `_**: can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command. -* **`Generic flags `_**: can be modified by standard users on a session basis. +* `Administration flags `_: can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command. +* `Generic flags `_: can be modified by standard users on a session basis. Showing All Flags in the Catalog Table ======= From 382714cbe4ce9477491d0f3b7e5bd84bc1a6192b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 22 May 2022 17:15:11 +0300 Subject: [PATCH 246/300] Updated .Net Driver Link --- third_party_tools/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party_tools/client_drivers/index.rst b/third_party_tools/client_drivers/index.rst index e8c53f151..d348cc85d 100644 --- a/third_party_tools/client_drivers/index.rst +++ b/third_party_tools/client_drivers/index.rst @@ -62,7 +62,7 @@ The following are applicable to Windows: For more information on installing and configuring ODBC on Windows, see :ref:`Install and configure ODBC on Windows `. -* **Net driver** - `SQream .Net driver v3.0.2 `_ +* **Net driver** - `SQream .Net driver v3.0.2 `_ From 94660ed9d4d4877359cc47ac298a2b316fc03901 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 23 May 2022 14:03:11 +0300 Subject: [PATCH 247/300] Removed and deleted Flexible Data Clustering --- feature_guides/flexible_data_clustering.rst | 16 -- .../flexible_data_clustering_chunks.rst | 18 -- ...ata_clustering_data_clustering_methods.rst | 180 ------------------ ...flexible_data_clustering_data_examples.rst | 22 --- ...e_data_clustering_data_rechunking_data.rst | 11 -- .../flexible_data_clustering_overview.rst | 16 -- feature_guides/index.rst | 1 - 7 files changed, 264 deletions(-) delete mode 100644 feature_guides/flexible_data_clustering.rst delete mode 100644 feature_guides/flexible_data_clustering_chunks.rst delete mode 100644 feature_guides/flexible_data_clustering_data_clustering_methods.rst delete mode 100644 feature_guides/flexible_data_clustering_data_examples.rst delete mode 100644 feature_guides/flexible_data_clustering_data_rechunking_data.rst delete mode 100644 feature_guides/flexible_data_clustering_overview.rst diff --git a/feature_guides/flexible_data_clustering.rst b/feature_guides/flexible_data_clustering.rst deleted file mode 100644 index ce0f3d321..000000000 --- a/feature_guides/flexible_data_clustering.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. _flexible_data_clustering: - -*********************** -Flexible Data Clustering -*********************** -The **Flexible Data Clustering** section describes the following: - -.. toctree:: - :maxdepth: 4 - :titlesonly: - - flexible_data_clustering_overview - flexible_data_clustering_chunks - flexible_data_clustering_data_clustering_methods - flexible_data_clustering_data_rechunking_data - flexible_data_clustering_data_examples \ No newline at end of file diff --git a/feature_guides/flexible_data_clustering_chunks.rst b/feature_guides/flexible_data_clustering_chunks.rst deleted file mode 100644 index b8146d0fc..000000000 --- a/feature_guides/flexible_data_clustering_chunks.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _flexible_data_clustering_chunks: - -*********************** -What are Chunks? -*********************** -Chunks, sometimes referred to as **partitions**, are a contiguous number of rows in a specific column. SQream relies on an advanced partitioning method called **chunking**, which provides all static partitioning capabilities without the known limitations. - -The following figure shows a table rows grouped as chunks: - -.. figure:: /_static/images/chunking2.png - :scale: 75 % - :align: center - -The following figure shows the rows from the table above converted into chunks: - -.. figure:: /_static/images/chunking_metadata2.png - :scale: 75 % - :align: center \ No newline at end of file diff --git a/feature_guides/flexible_data_clustering_data_clustering_methods.rst b/feature_guides/flexible_data_clustering_data_clustering_methods.rst deleted file mode 100644 index a9667b920..000000000 --- a/feature_guides/flexible_data_clustering_data_clustering_methods.rst +++ /dev/null @@ -1,180 +0,0 @@ -.. _flexible_data_clustering_data_clustering_methods: - -*********************** -Data Clustering Methods -*********************** -The following data clustering methods can be used in tandem or separately to enhance query performance: - -.. contents:: - :local: - :depth: 1 - -Using Time-Based Data Management -============ -Overview -~~~~~~~~~~ -**Time-based data management** refers to sorting table data along naturally occuring dimensions. The most common and naturally occuring sorting mechanism is a **timestamp**, which indicates the point in time at which data was inserted into SQream. Because SQream is a columnar storage system, timestamped metadata facilitates quick and easy query processing. - -The following is the correct syntax for timestamping a chunk: - -.. code-block:: postgres - - SELECT DATEPART(HOUR, timestamp), - MIN(transaction_amount), - MAX(transaction_amount), - avg(transaction_amount) - FROM transactions - WHERE timestamp BETWEEN (CURRENT_TIMESTAMP AND DATEADD(MONTH,-3,CURRENT_TIMESTAMP)) - GROUP BY 1; - -Timestamping data includes the following properties: - -* Data is loaded in a natural order while being inserted. - - :: - -* Updates are infrequent or non-existent. Updates occur by inserting new rows, which have their own timestamps. - - :: - -* Queries on timestamped data is typically on continuous time range. - - :: - -* Inserting and reading data are performed independently, not in the operation or transaction. - - :: - -* Timestamped data has a high data volume and accumulates faster than typical online transactional processing workloads. - -The following are some scenarios ideal for timestamping: - -* Running analytical queries spanning specific date ranges (such as the sum of transactions during August-July 2020 versus August-July 2019). - - :: - -* Deleting data older than a specific number of months old. - - :: - -* Regulations require you to maintain several years of data that you do not need to query on a regular basis. - -Best Practices for Time-Based Management -~~~~~~~~~~ -Data inserted in bulks is automatically timestamped with the insertion date and time. Therefore, inserting data through small and frequent bulks has the effect of naturally ordering data according to timestamp. Frequent bulks generally refers to short time frames, such as at 15-minute, hourly, or daily intervals. As you insert new data, SQream chunks and appends it into your existing tables according to its timestamp. - -The ``DATE`` and ``DATETIME`` types were created to improve performance, minimze storage size, and maintain data integrity. SQream recommends using them instead of ``VARCHAR``. - -Using Clustering Keys -============ -Overview -~~~~~~~~~~ -While data clustering occurs relatively naturally within a table, certain practices can be used to actively enhance query performance and runtime. Defining **clustering keys** increases performance by explicitly co-locating your data, enabling SQream to avoid processing irrelevant chunks. - -A clustering key is a subset of table columns or expressions and is defined using the ``CLUSTER BY`` statement, as shown below: - -.. code-block:: postgres - - CREATE TABLE users ( - name VARCHAR(30) NOT NULL, - start_date datetime not null, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL - ) CLUSTER BY country; - - - -The ``CLUSTER BY`` statement splits ingested data based on the range of data corresponding to the clustering key. This helps create chunks based on specific or related data, avoiding mixed chunks as much as possible. For example, instead of creating chunks based on a fixed number of rows, the ``CLUSTER_BY`` statement creates them based on common values. This optimizes the ``DELETE`` command as well, which deletes rows based on their location in a table. - -For more information, see the following: - -* `The CLUSTER_BY statement `_ -* `The DELETE statement `_ -* `The Deleting Data guide `_ - -Inspecting Clustered Table Health -~~~~~~~~~~ -You can use the ``clustering_health`` utility function to check how well a table is clustered, as shown below: - -.. code-block:: postgres - - SELECT CLUSTERING_HEALTH('table_name','clustering_keys'); - -The ``CLUSTERING_HEALTH`` function returns the average clustering depth of your table relative to the clustering keys. A lower value indicates a well-clustered table. - -Clustering keys are useful for restructuring large tables not optimally ordered when inserted or as a result of extensive DML. A table that uses clustering keys is referred to as a **clustered table**. Tables that are not clustered require SQream's query optimizer to scan entire tables while running queries, dramatically increasing runtime. Some queries significantly benefit from clustering, such as filtering or joining extensively on clustered columns. - -SQream partially sorts data that you load into a clustered table. Note that while clustering tables increases query performance, clustering during the insertion stage can decrease performance by 75%. Nevertheless, once a table is clustered subsequent queries run more quickly. - -.. note:: - - To determine whether clustering will enhance performance, SQream recommends end-to-end testing your clustering keys on a small subset of your data before committing them to permanent use. This is relevant for testing insert and query performance. - -For more information, see the following: - -* **Data Manipulation commands (DML)** - see `Data Manipulation Commands (DML) `_. - -* **Creating tables** - see :ref:`create_table`. When you create a table, all new data is clustered upon insert. - -* **Modifying tables** - see :ref:`cluster_by`. - -* **Modifying a table schema** - see :ref:`alter_table`. - -Using Metadata -============ -SQream uses an automated and transparent system for collecting metadata describing each chunk. This metadata enables skipping unnecessary chunks and extents during query runtime. The system collects chunk metadata when data is inserted into SQream. This is done by splitting data into chunks and collecting and storing specific parameters to be used later. - -Because collecting metadata is not process-heavy and does not contribute significantly to query processing, it occurs continuously as a background process. Most metadata collection is typically performed by the GPU. For example, for a 10TB dataset, the metadata storage overhead is approximately 0.5GB. - -When a query includes a filter (such as a ``WHERE`` or ``JOIN`` condition) on a range of values spanning a fraction of the table values, SQream scans only the filtered segment of the table. - -Once collected, several metadata parameters are stored for later use, including: - -* The range of values on each column chunk (minimum, maximum). - - :: - -* The number of values. - - :: - -* Additional information for query optimization. - -Data is collected automatically and transparently on every column type. - -Queries filtering highly granular date and time ranges are the most effective, particularly when data is timestamped, and when tables contain a large amount of historical data. - -Using Chunks and Extents -============ -SQream stores data in logical tables made up of rows spanning one or more columns. Internally, data is stored in vertical partitions by column, and horizontally by chunks. The **Using Chunks and Extents** section describes how to leverge chunking to optimize query performance. - -A **chunk** is a contiguous number of rows in a specific column. Depending on data type, a chunk's uncompressed size typically ranges between 1MB and a few hundred megabytes. This size range is suitable for filtering and deleting data from large tables, which may contain between hundreds, millions, or billions of chunks. - -An **extent** is a specific number of contiguous chunks. Extents optimize disk access patterns, at around 20MB uncompressed, on-disk. Extents typically include between one and 25 chunks based on the compressed size of each chunk. - -.. note:: - - SQream compresses all data. In addition, all tables are automatically and transparently chunked. - -Unlike node-partitioning (or sharding), chunks are: - -* Small enough to be read concurrently by multiple workers. - - :: - -* Optimized for inserting data quickly. - - :: - -* Capable of carrying metadata, which narrows down their contents for the query optimizer. - - :: - -* Ideal for data retension because they can be deleted in bulk. - - :: - -* Optimized for reading into RAM and the GPU. - - :: - -* Compressed individually to improve compression and data locality. \ No newline at end of file diff --git a/feature_guides/flexible_data_clustering_data_examples.rst b/feature_guides/flexible_data_clustering_data_examples.rst deleted file mode 100644 index 0c720ff04..000000000 --- a/feature_guides/flexible_data_clustering_data_examples.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. _flexible_data_clustering_data_examples: - -*********************** -Examples -*********************** -The **Examples** includes the following examples: - -.. contents:: - :local: - :depth: 1 - -Creating a Clustered Table ------------------------------ -The following is an example of syntax for creating a clustered table on a table naturally ordered by ``start_date``. An alternative cluster key can be defined on such a table to improve performance on queries already ordered by ``country``: - -.. code-block:: postgres - - CREATE TABLE users ( - name VARCHAR(30) NOT NULL, - start_date datetime not null, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL - ) CLUSTER BY country; \ No newline at end of file diff --git a/feature_guides/flexible_data_clustering_data_rechunking_data.rst b/feature_guides/flexible_data_clustering_data_rechunking_data.rst deleted file mode 100644 index 30a74bbaa..000000000 --- a/feature_guides/flexible_data_clustering_data_rechunking_data.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. _flexible_data_clustering_data_rechunking_data: - -*********************** -Rechunking Data -*********************** -SQream performs background storage reorganization operations to optimize I/O and read patterns. - -For example, when small batches of data are inserted, SQream runs two background processes called **rechunk** and **reextent** to reorganize the data into larger contiguous chunks and extents. This is also what happens when data is deleted. - - -Instead of overwriting data, SQream writes new optimized chunks and extents to replace old ones. After rewriting all old data, SQream switches to the new optimized chunks and extents and deletes the old data. \ No newline at end of file diff --git a/feature_guides/flexible_data_clustering_overview.rst b/feature_guides/flexible_data_clustering_overview.rst deleted file mode 100644 index 3ba59a603..000000000 --- a/feature_guides/flexible_data_clustering_overview.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. _flexible_data_clustering_overview: - -*********************** -Overeview -*********************** -**Flexible data clustering** refers to sorting table data along naturally occuring dimensions, such as name, date, or location. Data clustering optimizes table structure to significantly improve query performance, especially on very large tables. A well-clustered table increases the effectivity of the metadata collected by focusing on a specific and limited range of rows, called **chunks**. - -The following are some scenarios ideal for data clustering: - -* Queries containg a ``WHERE`` predicate written as ``column COMPARISON value``, such as ``date_column > '2019-01-01'`` or ``id = 107`` when the columns referenced are clustering keys. - - In such a case SQream reads the portion of data that contain values matching these predicates only. - -* Two clustered tables joined by their respective clustering keys. - - In such a case SQream uses metadata to more easily identify matching chunks. \ No newline at end of file diff --git a/feature_guides/index.rst b/feature_guides/index.rst index 948915df4..ce5cc2a17 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -15,7 +15,6 @@ This section describes the following features: access_control delete_guide compression - flexible_data_clustering python_functions saved_queries viewing_system_objects_as_ddl From 0ff51b57283069b09093b3f65f32a0e72852bd56 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 29 May 2022 13:53:08 +0300 Subject: [PATCH 248/300] Modified delete_guide Moved delete_guide from feature_guides to operational_guides. Delete delete.rst (replaced with delete_guides). --- feature_guides/delete.rst | 214 ------------------ feature_guides/index.rst | 1 - .../delete_guide.rst | 0 operational_guides/index.rst | 1 + 4 files changed, 1 insertion(+), 215 deletions(-) delete mode 100644 feature_guides/delete.rst rename {feature_guides => operational_guides}/delete_guide.rst (100%) diff --git a/feature_guides/delete.rst b/feature_guides/delete.rst deleted file mode 100644 index 24ab5a218..000000000 --- a/feature_guides/delete.rst +++ /dev/null @@ -1,214 +0,0 @@ -.. _delete_guide: - -*********************** -Deleting Data -*********************** - -SQream DB supports deleting data, but it's important to understand how this works and how to maintain deleted data. - -How does deleting in SQream DB work? -======================================== - -In SQream DB, when you run a delete statement, any rows that match the delete predicate will no longer be returned when running subsequent queries. -Deleted rows are tracked in a separate location, in *delete predicates*. - -After the delete statement, a separate process can be used to reclaim the space occupied by these rows, and to remove the small overhead that queries will have until this is done. - -Some benefits to this design are: - -#. Delete transactions complete quickly - -#. The total disk footprint overhead at any time for a delete transaction or cleanup process is small and bounded (while the system still supports low overhead commit, rollback and recovery for delete transactions). - - -Phase 1: Delete ---------------------------- - -.. TODO: isn't the delete cleanup able to complete a certain amount of work transactionally, so that you can do a massive cleanup in stages? - -.. TODO: our current best practices is to use a cron job with sqream sql to run the delete cleanup. we should document how to do this, we have customers with very different delete schedules so we can give a few extreme examples and when/why you'd use them - -When a :ref:`delete` statement is run, SQream DB records the delete predicates used. These predicates will be used to filter future statements on this table until all this delete predicate's matching rows have been physically cleaned up. - -This filtering process takes full advantage of SQream's zone map feature. - -Phase 2: Clean-up --------------------- - -The cleanup process is not automatic. This gives control to the user or DBA, and gives flexibility on when to run the clean up. - -Files marked for deletion during the logical deletion stage are removed from disk. This is achieved by calling both utility function commands: ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` sequentially. - -.. note:: - * :ref:`alter_table` and other DDL operations are blocked on tables that require clean-up. See more in the :ref:`concurrency_and_locks` guide. - * If the estimated time for a cleanup processs is beyond a threshold, you will get an error message about it. The message will explain how to override this limitation and run the process anywhere. - -Notes on data deletion -========================================= - -.. note:: - * If the number of deleted records crosses the threshold defined by the ``mixedColumnChunksThreshold`` parameter, the delete operation will be aborted. - * This is intended to alert the user that the large number of deleted records may result in a large number of mixed chuncks. - * To circumvent this alert, replace XXX with the desired number of records before running the delete operation: - -.. code-block:: postgres - - set mixedColumnChunksThreshold=XXX; - - -Deleting data does not free up space ------------------------------------------ - -With the exception of a full table delete (:ref:`TRUNCATE`), deleting data does not free up disk space. To free up disk space, trigger the cleanup process. - -``SELECT`` performance on deleted rows ----------------------------------------- - -Queries on tables that have deleted rows may have to scan data that hasn't been cleaned up. -In some cases, this can cause queries to take longer than expected. To solve this issue, trigger the cleanup process. - -Use ``TRUNCATE`` instead of ``DELETE`` ---------------------------------------- -For tables that are frequently emptied entirely, consider using :ref:`truncate` rather than :ref:`delete`. TRUNCATE removes the entire content of the table immediately, without requiring a subsequent cleanup to free up disk space. - -Cleanup is I/O intensive -------------------------------- - -The cleanup process actively compacts tables by writing a complete new version of column chunks with no dead space. This minimizes the size of the table, but can take a long time. It also requires extra disk space for the new copy of the table, until the operation completes. - -Cleanup operations can create significant I/O load on the database. Consider this when planning the best time for the cleanup process. - -If this is an issue with your environment, consider using ``CREATE TABLE AS`` to create a new table and then rename and drop the old table. - - -Example -============= - -Deleting values from a table ------------------------------- - -.. code-block:: psql - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N - - 6 rows - - farm=> DELETE FROM cool_animals WHERE weight > 1000; - executed - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 6,\N,\N - - 4 rows - -Deleting values based on more complex predicates ---------------------------------------------------- - -.. code-block:: psql - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N - - 6 rows - - farm=> DELETE FROM cool_animals WHERE weight > 1000; - executed - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 6,\N,\N - - 4 rows - -Identifying and cleaning up tables ---------------------------------------- - -List tables that haven't been cleaned up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - farm=> SELECT t.table_name FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - GROUP BY 1; - cool_animals - - 1 row - -Identify predicates for clean-up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; - weight > 1000 - - 1 row - -Triggering a cleanup -^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - -- Chunk reorganization (aka SWEEP) - farm=> SELECT CLEANUP_CHUNKS('public','cool_animals'); - executed - - -- Delete leftover files (aka VACUUM) - farm=> SELECT CLEANUP_EXTENTS('public','cool_animals'); - executed - - - farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; - - 0 rows - - - -Best practices for data deletion -===================================== - -* Run ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` after large ``DELETE`` operations. - -* When deleting large proportions of data from very large tables, consider running a ``CREATE TABLE AS`` operation instead, then rename and drop the original table. - -* Avoid killing ``CLEANUP_EXTENTS`` operations after they've started. - -* SQream DB is optimised for time-based data. When data is naturally ordered by a date or timestamp, deleting based on those columns will perform best. For more information, see our :ref:`time based data management guide`. - - - -.. soft update concept - -.. delete cleanup and it's properties. automatic/manual, in transaction or background - -.. automatic background gives fast delete, minimal transaction overhead, -.. small cost to queries until background reorganised - -.. when does delete use the metadata effectively - -.. more examples - diff --git a/feature_guides/index.rst b/feature_guides/index.rst index ce5cc2a17..89383a049 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -13,7 +13,6 @@ This section describes the following features: access_control - delete_guide compression python_functions saved_queries diff --git a/feature_guides/delete_guide.rst b/operational_guides/delete_guide.rst similarity index 100% rename from feature_guides/delete_guide.rst rename to operational_guides/delete_guide.rst diff --git a/operational_guides/index.rst b/operational_guides/index.rst index b7ea1502d..7a019a433 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -16,6 +16,7 @@ This section summarizes the following operational guides: creating_or_cloning_a_storage_cluster external_data external_tables + delete_guide exporting_data logging monitoring_query_performance From 7ee68d8f27763ffe9128d9bb371dcea8f9bfc74e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 30 May 2022 14:53:26 +0300 Subject: [PATCH 249/300] Update cluster_by.rst --- reference/sql/sql_statements/ddl_commands/cluster_by.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/cluster_by.rst b/reference/sql/sql_statements/ddl_commands/cluster_by.rst index e4cf42ad4..7dcedaaf1 100644 --- a/reference/sql/sql_statements/ddl_commands/cluster_by.rst +++ b/reference/sql/sql_statements/ddl_commands/cluster_by.rst @@ -7,10 +7,6 @@ The ``CLUSTER BY`` command is used for changing clustering keys in a table. For more information, see the following: -* :ref:`flexible_data_clustering` - - :: - * :ref:`drop_clustering_key` :: From 946c4f831fe0cb8d6d29a507a5138474f9306929 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 7 Jun 2022 14:41:25 +0300 Subject: [PATCH 250/300] Update show_server_status.rst TPD-128 --- .../utility_commands/show_server_status.rst | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/show_server_status.rst b/reference/sql/sql_statements/utility_commands/show_server_status.rst index f59f79ccc..73902a046 100644 --- a/reference/sql/sql_statements/utility_commands/show_server_status.rst +++ b/reference/sql/sql_statements/utility_commands/show_server_status.rst @@ -3,18 +3,13 @@ ******************** SHOW_SERVER_STATUS ******************** - ``SHOW_SERVER_STATUS`` returns a list of active sessions across the cluster. To list active statements on the current worker only, see :ref:`show_connections`. -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - Syntax ========== +The following is the correct syntax when showing your server status: .. code-block:: postgres @@ -24,85 +19,90 @@ Syntax Parameters ============ - -None +The Parameters section is not relevant for the ``SHOW_SERVER_STATUS`` statement. Returns ========= +The ``SHOW_SERVER_STATUS`` function returns a list of active sessions. If no sessions are active across the cluster, the result set will be empty. -This function returns a list of active sessions. If no sessions are active across the cluster, the result set will be empty. +The following table shows the ``SHOW_SERVER_STATUS`` result columns; -.. list-table:: Result columns +.. list-table:: Result Columns :widths: auto :header-rows: 1 - * - ``service`` - - The service name for the statement + * - service + - Statement Service Name * - ``instance`` - - The worker ID + - Shows the worker ID. * - ``connection_id`` - - Connection ID + - Shows the connection ID. * - ``serverip`` - - Worker end-point IP + - Shows the worker end-point IP. * - ``serverport`` - - Worker end-point port + - Shows the worker end-point port. * - ``database_name`` - - Database name for the statement + - Shows the statement's database name. * - ``user_name`` - - Username running the statement + - Shows the username running the statement. * - ``clientip`` - - Client IP + - Shows the client IP. * - ``statementid`` - - Statement ID + - Shows the statement ID. * - ``statement`` - - Statement text + - Shows the statement text. * - ``statementstarttime`` - - Statement start timestamp + - Shows the statement start timestamp. * - ``statementstatus`` - - Statement status (see table below) + - Shows the statement status (see table below). * - ``statementstatusstart`` - - Last updated timestamp + - Shows the most recently updated timestamp. .. include from here: 66 +The following table shows the statement status values: -.. list-table:: Statement status values +.. list-table:: Statement Status Values :widths: auto :header-rows: 1 * - Status - Description * - ``Preparing`` - - Statement is being prepared + - The statement is being prepared. * - ``In queue`` - - Statement is waiting for execution + - The statement is waiting for execution. * - ``Initializing`` - - Statement has entered execution checks + - The statement has entered execution checks. * - ``Executing`` - - Statement is executing + - The statement is executing. * - ``Stopping`` - - Statement is in the process of stopping - + - The statement is in the process of stopping. .. include until here 86 Notes =========== +This utility shows the active sessions. Some sessions may be actively connected, but not running any statements. -* This utility shows the active sessions. Some sessions may be actively connected, but not running any statements. - -Examples +Example =========== -Using ``SHOW_SERVER_STATUS`` to get statement IDs +Using SHOW_SERVER_STATUS to Get Statement IDs ---------------------------------------------------- - +The following example shows how to use the ``SHOW_SERVER_STATUS`` statement to get statement IDs: .. code-block:: psql t=> SELECT SHOW_SERVER_STATUS(); - service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart - --------+------------+---------------+--------------+------------+---------------+------------+-------------+-------------+-----------------------------+---------------------+-----------------+--------------------- - sqream | | 102 | 192.168.1.91 | 5000 | t | rhendricks | 192.168.0.1 | 128 | SELECT SHOW_SERVER_STATUS() | 24-12-2019 00:14:53 | Executing | 24-12-2019 00:14:53 + service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart + --------+------------+---------------+---------------+------------+---------------+------------------+---------------+-------------+-------------------------------------------------------------------------------------------------------+---------------------+-----------------+--------------------- + sqream | sqream_2 | 19 | 192.168.0.111 | 5000 | master | etl | 192.168.0.011 |2484923 | SELECT t1.account, t1.msisd from table a t1 join table b t2 on t1.id = t2.id where t1.msid='123123'; | 17-01-2022 16:19:31 | Executing | 17-01-2022 16:19:32 + sqream | sqream_1 | 2 | 192.168.1.112 | 5000 | master | etl | 192.168.1.112 |2484924 | select show_server_status(); | 17-01-2022 16:19:39 | Executing | 17-01-2022 16:19:39 + sqream | None | 248 | 192.168.1.112 | 5007 | master | maintenance_user | 192.168.1.112 |2484665 | select * from sqream_catalog.tables; | 17-01-2022 15:55:01 | In Queue | 17-01-2022 15:55:02 The statement ID is ``128``, running on worker ``192.168.1.91``. + +Permissions +============= +The role must have the ``SUPERUSER`` permissions. From 0174e3e71ae67fb7ed38c61080f0585b464416dd Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 12 Jun 2022 10:34:11 +0300 Subject: [PATCH 251/300] TPD-67 --- .../client_drivers/jdbc/index.rst | 127 ++++++++++-------- 1 file changed, 68 insertions(+), 59 deletions(-) diff --git a/third_party_tools/client_drivers/jdbc/index.rst b/third_party_tools/client_drivers/jdbc/index.rst index 07e384e89..832987efa 100644 --- a/third_party_tools/client_drivers/jdbc/index.rst +++ b/third_party_tools/client_drivers/jdbc/index.rst @@ -3,160 +3,169 @@ ************************* JDBC ************************* +The SQream JDBC driver lets you connect to SQream using many Java applications and tools. This page describes how to write a Java application using the JDBC interface. The JDBC driver requires Java 1.8 or newer. -The SQream DB JDBC driver allows many Java applications and tools connect to SQream DB. -This tutorial shows how to write a Java application using the JDBC interface. +The JDBC page includes the following sections: -The JDBC driver requires Java 1.8 or newer. - -.. contents:: In this topic: +.. contents:: :local: + :depth: 1 -Installing the JDBC driver +Installing the JDBC Driver ================================== +The **Installing the JDBC Driver** section describes the following: + +.. contents:: + :local: + :depth: 1 Prerequisites ---------------- +The SQream JDBC driver requires Java 1.8 or newer, and SQream recommends using Oracle Java or OpenJDK.: -The SQream DB JDBC driver requires Java 1.8 or newer. We recommend either Oracle Java or OpenJDK. - -**Oracle Java** - -Download and install Java 8 from Oracle for your platform +* **Oracle Java** - Download and install `Java 8 `_ from Oracle for your platform. -https://www.java.com/en/download/manual.jsp - -**OpenJDK** - -For Linux and BSD, see https://openjdk.java.net/install/ - -For Windows, SQream recommends Zulu 8 https://www.azul.com/downloads/zulu-community/?&version=java-8-lts&architecture=x86-64-bit&package=jdk + :: + +* **OpenJDK** - Install `OpenJDK `_ -.. _get_jdbc_jar: + :: + +* **Windows** - SQream recommends installing `Zulu 8 `_ Getting the JAR file --------------------- +SQream provides the JDBC driver as a zipped JAR file, available for download from the :ref:`client drivers download page`. This JAR file can be integrated into your Java-based applications or projects. -The JDBC driver is provided as a zipped JAR file, available for download from the :ref:`client drivers download page`. This JAR file can integrate into your Java-based applications or projects. - - -Extract the zip archive +Extracting the ZIP Archive ------------------------- - -Extract the JAR file from the zip archive +Run the following command to extract the JAR file from the ZIP archive: .. code-block:: console $ unzip sqream-jdbc-4.3.0.zip -Setting up the Class Path +Setting Up the Class Path ---------------------------- +To use the driver, you must include the JAR named ``sqream-jdbc-.jar`` in the class path, either by inserting it in the ``CLASSPATH`` environment variable, or by using flags on the relevant Java command line. -To use the driver, the JAR named ``sqream-jdbc-.jar`` (for example, ``sqream-jdbc-4.3.0.jar``) needs to be included in the class path, either by putting it in the ``CLASSPATH`` environment variable, or by using flags on the relevant Java command line. - -For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-4.3.0.jar``, the application should be run as follows: +For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-4.3.0.jar``, the following command is used to run application: .. code-block:: console $ export CLASSPATH=/home/sqream/sqream-jdbc-4.3.0.jar:$CLASSPATH $ java my_java_app -An alternative method is to pass ``-classpath`` to the Java executable: +Alternatively, you can pass ``-classpath`` to the Java executable file: .. code-block:: console $ java -classpath .:/home/sqream/sqream-jdbc-4.3.0.jar my_java_app - -Connect to SQream DB with a JDBC application +Connecting to SQream Using a JDBC Application ============================================== +You can connect to SQream using one of the following JDBC applications: -Driver class +.. contents:: + :local: + :depth: 1 + +Driver Class -------------- - Use ``com.sqream.jdbc.SQDriver`` as the driver class in the JDBC application. - -.. _connection_string: - -Connection string +Connection String -------------------- +JDBC drivers rely on a connection string. -JDBC drivers rely on a connection string. Use the following syntax for SQream DB +The following is the syntax for SQream: .. code-block:: text jdbc:Sqream:///;user=;password=sqream;[; ...] -Connection parameters +Connection Parameters ^^^^^^^^^^^^^^^^^^^^^^^^ +The following table shows the connection string parameters: .. list-table:: :widths: auto :header-rows: 1 * - Item - - Optional + - State - Default - Description * - ```` - - ✗ + - Mandatory - None - Hostname and port of the SQream DB worker. For example, ``127.0.0.1:5000``, ``sqream.mynetwork.co:3108`` * - ```` - - ✗ + - Mandatory - None - Database name to connect to. For example, ``master`` * - ``username=`` - - ✗ + - Mandatory - None - Username of a role to use for connection. For example, ``username=rhendricks`` * - ``password=`` - - ✗ + - Mandatory - None - Specifies the password of the selected role. For example, ``password=Tr0ub4dor&3`` * - ``service=`` - - ✓ + - Optional - ``sqream`` - Specifices service queue to use. For example, ``service=etl`` * - ```` - - ✓ + - Optional - ``false`` - Specifies SSL for this connection. For example, ``ssl=true`` * - ```` - - ✓ + - Optional - ``true`` - Connect via load balancer (use only if exists, and check port). + * - ```` + - Optional + - ``true`` + - Enables on-demand loading, and defines double buffer size for result. The ``fetchSize`` parameter is rounded according to chunk size. For example, ``fetchSize=1`` loads one row and is rounded to one chunk. If the fetchSize is 100,600, a chunk size of 100,000 loads, and is rounded to, two chunks. + * - ```` + - Optional + - ``true`` + - Defines the bytes size for inserting a buffer before flushing data to the server. Clients running a parameterized insert (network insert) can define the amount of data to collect before flushing the buffer. + * - ```` + - Optional + - ``true`` + - Defines the logger level as either ``debug`` or ``trace``. + * - ```` + - Optional + - ``true`` + - Enables the file appender and defines the file name. The file name can be set as either the file name or the file path. -Connection string examples +Connection String Examples ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -For a SQream DB cluster with load balancer and no service queues, with SSL +The following is an example of a SQream cluster with load balancer and no service queues (with SSL): .. code-block:: text jdbc:Sqream://sqream.mynetwork.co:3108/master;user=rhendricks;password=Tr0ub4dor&3;ssl=true;cluster=true -Minimal example for a local, standalone SQream DB +The following is a minimal example for a local standalone SQream database: .. code-block:: text jdbc:Sqream://127.0.0.1:5000/master;user=rhendricks;password=Tr0ub4dor&3 -For a SQream DB cluster with load balancer and a specific service queue named ``etl``, to the database named ``raviga`` +The following is an example of a SQream cluster with load balancer and a specific service queue named ``etl``, to the database named ``raviga`` .. code-block:: text jdbc:Sqream://sqream.mynetwork.co:3108/raviga;user=rhendricks;password=Tr0ub4dor&3;cluster=true;service=etl - -Sample Java program +Sample Java Program -------------------- - -Download this file by right clicking and saving to your computer :download:`sample.java `. +You can download the :download:`JDBC Application Sample File ` below by right-clicking and saving it to your computer. .. literalinclude:: sample.java :language: java - :caption: JDBC application sample + :caption: JDBC Application Sample :linenos: - From 28a49e5566ab0077773f471d3f47594471de57e2 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 19 Jun 2022 18:27:38 +0300 Subject: [PATCH 252/300] Replace VARCHAR with TEXT --- .../current_configuration_method.rst | 249 +++++++++--------- configuration_guides/varchar_identifiers.rst | 12 - data_ingestion/csv.rst | 10 +- data_ingestion/oracle.rst | 28 +- data_ingestion/orc.rst | 70 ++--- data_ingestion/parquet.rst | 16 +- data_type_guides/sql_data_types_string.rst | 16 +- feature_guides/compression.rst | 10 +- getting_started/querying_data.rst | 10 +- ...external_tables.rst => foreign_tables.rst} | 76 +++--- operational_guides/index.rst | 2 +- operational_guides/logging.rst | 4 +- .../monitoring_query_performance.rst | 241 +---------------- .../optimization_best_practices.rst | 25 +- operational_guides/s3.rst | 10 +- .../sql_functions/aggregate_functions/avg.rst | 10 +- .../aggregate_functions/corr.rst | 10 +- .../aggregate_functions/count.rst | 10 +- .../aggregate_functions/covar_pop.rst | 10 +- .../aggregate_functions/covar_samp.rst | 10 +- .../sql_functions/aggregate_functions/max.rst | 10 +- .../sql_functions/aggregate_functions/min.rst | 10 +- .../aggregate_functions/stddev_pop.rst | 10 +- .../aggregate_functions/stddev_samp.rst | 10 +- .../sql_functions/aggregate_functions/sum.rst | 10 +- .../aggregate_functions/var_pop.rst | 10 +- .../aggregate_functions/var_samp.rst | 10 +- .../scalar_functions/conversion/to_hex.rst | 4 +- .../scalar_functions/string/concat.rst | 14 +- .../scalar_functions/string/like.rst | 10 +- .../scalar_functions/string/regexp_count.rst | 10 +- .../scalar_functions/string/regexp_instr.rst | 10 +- .../scalar_functions/string/regexp_substr.rst | 10 +- .../scalar_functions/string/rlike.rst | 10 +- .../scalar_functions/string/rtrim.rst | 2 +- .../scalar_functions/string/substring.rst | 10 +- .../window_functions/first_value.rst | 2 +- .../sql_functions/window_functions/lag.rst | 10 +- .../window_functions/last_value.rst | 2 +- .../sql_functions/window_functions/lead.rst | 10 +- .../window_functions/nba-t10.csv | 19 +- .../window_functions/nth_value.rst | 4 +- .../sql_functions/window_functions/rank.rst | 10 +- .../window_functions/row_number.rst | 10 +- .../ddl_commands/create_external_table.rst | 156 ----------- .../ddl_commands/create_foreign_table.rst | 6 +- .../sql_statements/dml_commands/select.rst | 10 +- .../utility_commands/execute_saved_query.rst | 12 +- .../utility_commands/get_ddl.rst | 4 +- .../utility_commands/save_query.rst | 12 +- reference/sql/sql_syntax/subqueries.rst | 10 +- reference/sql/sql_syntax/window_functions.rst | 10 +- troubleshooting/log_related_issues.rst | 4 +- 53 files changed, 428 insertions(+), 842 deletions(-) delete mode 100644 configuration_guides/varchar_identifiers.rst rename operational_guides/{external_tables.rst => foreign_tables.rst} (72%) delete mode 100644 reference/sql/sql_statements/ddl_commands/create_external_table.rst diff --git a/configuration_guides/current_configuration_method.rst b/configuration_guides/current_configuration_method.rst index 7ea2bba72..d0d87e0b5 100644 --- a/configuration_guides/current_configuration_method.rst +++ b/configuration_guides/current_configuration_method.rst @@ -72,8 +72,8 @@ SQream uses cluster-based configuration, enabling you to centralize configuratio For more information, see the following: -* `Using SQream SQL `_ - modifying flag attributes from the CLI. -* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. +* `Using SQream SQL `_ - modifying flag attributes from the CLI. +* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. For more information on flag-based access to cluster-based configuration, see **Configuration Flag Types** below. @@ -92,8 +92,8 @@ For example, when the query below has completed executing, the values configured For more information, see the following: -* `Using SQream SQL `_ - modifying flag attributes from the CLI. -* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. +* `Using SQream SQL `_ - modifying flag attributes from the CLI. +* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. Configuration Flag Types ========== @@ -309,6 +309,59 @@ The following table describes the **Generic** and **Administration** configurati ``33554432,67108864,134217728,268435456,536870912,786432000,107374,`` ``1824,1342177280,1610612736,1879048192,2147483648,2415919104,`` ``2684354560,2952790016,3221225472`` + + * - ``cacheDiskDir`` + - Generic + - Regular + - Sets the ondisk directory location for the spool to save files on. + - size_t + - Any legal string + + + * - ``cacheDiskGB`` + - Generic + - Regular + - Sets the amount of memory (GB) to be used by Spool on the disk. + - size_t + - ``128`` + + * - ``cacheEvictionMilliseconds`` + - Generic + - Regular + - Sets how long the cache stores contents before being flushed. + - size_t + - ``2000`` + + * - ``cachePartitions`` + - Generic + - Regular + - Sets the number of partitions that the cache is split into. + - size_t + - ``4`` + + + * - ``cachePersistentDir`` + - Generic + - Regular + - Sets the persistent directory location for the spool to save files on. + - string + - Any legal string + + + * - ``cachePersistentGB`` + - Generic + - Regular + - Sets the amount of data (GB) for the cache to store persistently. + - size_t + - ``128`` + + + * - ``cacheRamGB`` + - Generic + - Regular + - Sets the amount of memory (GB) to be used by Spool InMemory. + - size_t + - ``16`` * - ``checkCudaMemory`` - Administration @@ -403,12 +456,8 @@ The following table describes the **Generic** and **Administration** configurati - * - ``varcharIdentifiers`` - - Administration - - Regular - - Activates using varchar as an identifier. - - boolean - - ``true`` + + @@ -417,7 +466,16 @@ The following table describes the **Generic** and **Administration** configurati - Cluster - Sets the minimum size in mebibytes of extents for table bulk data. - uint - - ``20`` + - ``20`` + + * - ``flipJoinOrder`` + - Generic + - Regular + - Reorders join to force equijoins and/or equijoins sorted by table size. + - boolean + - ``FALSE`` + + * - ``gatherMemStat`` - Administration @@ -445,7 +503,29 @@ The following table describes the **Generic** and **Administration** configurati - Regular - Sets the buffer size. - uint - - ``524288`` + - ``524288`` + + * - ``limitQueryMemoryGB`` + - Generic + - Worker + - Prevents a query from processing more memory than the flag’s value. + - uint + - ``100000`` + + * - ``logSysLevel`` + - Generic + - Regular + - + Determines the client log level: + 0 - L_SYSTEM, + 1 - L_FATAL, + 2 - L_ERROR, + 3 - L_WARN, + 4 - L_INFO, + 5 - L_DEBUG, + 6 - L_TRACE + - uint + - ``100000`` * - ``machineIP`` - Administration @@ -455,7 +535,14 @@ The following table describes the **Generic** and **Administration** configurati - ``127.0.0.1`` - + + * - ``maxAvgBlobSizeToCompressOnGpu`` + - Generic + - Regular + - Sets the CPU to compress columns with size above (flag’s value) * (row count). + - uint + - ``120`` + * - ``memoryResetTriggerMB`` - Administration @@ -492,12 +579,30 @@ The following table describes the **Generic** and **Administration** configurati - boolean - ``TRUE`` + + * - ``sessionTag`` + - Generic + - Regular + - Sets the name of the session tag. + - string + - Any legal string + + + + * - ``spoolMemoryGB`` + - Generic + - Regular + - Sets the amount of memory (GB) to be used by the server for spooling. + - uint + - ``8`` + * - ``statementLockTimeout`` - Administration - Regular - Sets the timeout (seconds) for acquiring object locks before executing statements. - uint - - ``3`` + - ``3`` + * - ``useConfigIP`` - Administration @@ -519,121 +624,9 @@ The following table describes the **Generic** and **Administration** configurati - Interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. Used to preserve legacy behavior in existing customers. - boolean - ``FALSE`` - - * - ``flipJoinOrder`` - - Generic - - Regular - - Reorders join to force equijoins and/or equijoins sorted by table size. - - boolean - - ``FALSE`` - - * - ``limitQueryMemoryGB`` - - Generic - - Worker - - Prevents a query from processing more memory than the flag’s value. - - uint - - ``100000`` - - * - ``cacheEvictionMilliseconds`` - - Generic - - Regular - - Sets how long the cache stores contents before being flushed. - - size_t - - ``2000`` - - - * - ``cacheDiskDir`` - - Generic - - Regular - - Sets the ondisk directory location for the spool to save files on. - - size_t - - Any legal string - - - * - ``cacheDiskGB`` - - Generic - - Regular - - Sets the amount of memory (GB) to be used by Spool on the disk. - - size_t - - ``128`` - - * - ``cachePartitions`` - - Generic - - Regular - - Sets the number of partitions that the cache is split into. - - size_t - - ``4`` - - - * - ``cachePersistentDir`` - - Generic - - Regular - - Sets the persistent directory location for the spool to save files on. - - string - - Any legal string - - - * - ``cachePersistentGB`` - - Generic - - Regular - - Sets the amount of data (GB) for the cache to store persistently. - - size_t - - ``128`` - - - * - ``cacheRamGB`` - - Generic - - Regular - - Sets the amount of memory (GB) to be used by Spool InMemory. - - size_t - - ``16`` - - - - - - - - * - ``logSysLevel`` - - Generic - - Regular - - - Determines the client log level: - 0 - L_SYSTEM, - 1 - L_FATAL, - 2 - L_ERROR, - 3 - L_WARN, - 4 - L_INFO, - 5 - L_DEBUG, - 6 - L_TRACE - - uint - - ``100000`` - - * - ``maxAvgBlobSizeToCompressOnGpu`` - - Generic - - Regular - - Sets the CPU to compress columns with size above (flag’s value) * (row count). - - uint - - ``120`` - - - * - ``sessionTag`` - - Generic - - Regular - - Sets the name of the session tag. - - string - - Any legal string - * - ``spoolMemoryGB`` - - Generic - - Regular - - Sets the amount of memory (GB) to be used by the server for spooling. - - uint - - ``8`` - - Configuration Commands ========== The configuration commands are associated with particular flag types based on permissions. @@ -705,8 +698,8 @@ Configuration Roles =========== SQream divides flags into the following roles, each with their own set of permissions: -* `Administration flags `_: can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command. -* `Generic flags `_: can be modified by standard users on a session basis. +* `Administration flags `_: can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command. +* `Generic flags `_: can be modified by standard users on a session basis. Showing All Flags in the Catalog Table ======= diff --git a/configuration_guides/varchar_identifiers.rst b/configuration_guides/varchar_identifiers.rst deleted file mode 100644 index 889e5c16e..000000000 --- a/configuration_guides/varchar_identifiers.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. _varchar_identifiers: - -************************* -Interpreting VARCHAR as TEXT -************************* -The ``varcharIdentifiers`` flag activates using **varchar** as an identifier. - -The following describes the ``varcharIdentifiers`` flag: - -* **Data type** - boolean -* **Default value** - ``true`` -* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index f44c3c9e9..789c89a19 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -83,14 +83,14 @@ We will make note of the file structure to create a matching ``CREATE TABLE`` st CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text, + Team text, Number tinyint, - Position varchar(2), + Position text, Age tinyint, - Height varchar(4), + Height text, Weight real, - College varchar(40), + College text, Salary float ); diff --git a/data_ingestion/oracle.rst b/data_ingestion/oracle.rst index 0b0e6d5c8..4646d5622 100644 --- a/data_ingestion/oracle.rst +++ b/data_ingestion/oracle.rst @@ -94,7 +94,7 @@ Refer to the table below to match the Oracle source data type to a new SQream DB - SQream DB data type * - ``CHAR(n)``, ``CHARACTER(n)`` - Any ``n`` - - ``VARCHAR(n)`` + - ``TEXT`` * - ``BLOB``, ``CLOB``, ``NCLOB``, ``LONG`` - - ``TEXT`` @@ -108,7 +108,7 @@ Refer to the table below to match the Oracle source data type to a new SQream DB - p > 63 - ``FLOAT``, ``DOUBLE`` - * - ``NCHAR(n)``, ``NVARCHAR2(n)`` + * - ``NCHAR(n)`` - Any ``n`` - ``TEXT`` (alias of ``NVARCHAR``) @@ -132,9 +132,9 @@ Refer to the table below to match the Oracle source data type to a new SQream DB - f > 0 - ``FLOAT`` / ``DOUBLE`` - * - ``VARCHAR(n)``, ``VARCHAR2(n)`` + * - ``TEXT`` - Any ``n`` - - ``VARCHAR(n)`` or ``TEXT`` + - ``TEXT`` * - ``TIMESTAMP`` - - ``DATETIME`` @@ -165,15 +165,15 @@ Consider Oracle's ``HR.EMPLOYEES`` sample table: CREATE TABLE employees ( employee_id NUMBER(6) - , first_name VARCHAR2(20) - , last_name VARCHAR2(25) + , first_name TEXT + , last_name TEXT CONSTRAINT emp_last_name_nn NOT NULL - , email VARCHAR2(25) + , email TEXT CONSTRAINT emp_email_nn NOT NULL - , phone_number VARCHAR2(20) + , phone_number TEXT , hire_date DATE CONSTRAINT emp_hire_date_nn NOT NULL - , job_id VARCHAR2(10) + , job_id TEXT CONSTRAINT emp_job_nn NOT NULL , salary NUMBER(8,2) , commission_pct NUMBER(2,2) @@ -208,12 +208,12 @@ This table rewritten for SQream DB would be created like this: CREATE TABLE employees ( employee_id SMALLINT NOT NULL, - first_name VARCHAR(20), - last_name VARCHAR(25) NOT NULL, - email VARCHAR(20) NOT NULL, - phone_number VARCHAR(20), + first_name TEXT, + last_name TEXT NOT NULL, + email TEXT NOT NULL, + phone_number TEXT, hire_date DATE NOT NULL, - job_id VARCHAR(10) NOT NULL, + job_id TEXT NOT NULL, salary FLOAT, commission_pct REAL, manager_id SMALLINT, diff --git a/data_ingestion/orc.rst b/data_ingestion/orc.rst index d199e958e..9a756dea1 100644 --- a/data_ingestion/orc.rst +++ b/data_ingestion/orc.rst @@ -31,11 +31,11 @@ Prepare the source ORC files, with the following requirements: - ``DATE`` - ``DATETIME`` * - ``boolean`` - - ✓ - - ✓ [#f5]_ - - ✓ [#f5]_ - - ✓ [#f5]_ - - ✓ [#f5]_ + - Supported + - Supported [#f5]_ + - Supported [#f5]_ + - Supported [#f5]_ + - Supported [#f5]_ - - - @@ -43,10 +43,10 @@ Prepare the source ORC files, with the following requirements: - * - ``tinyint`` - ○ [#f6]_ - - ✓ - - ✓ - - ✓ - - ✓ + - Supported + - Supported + - Supported + - Supported - - - @@ -55,9 +55,9 @@ Prepare the source ORC files, with the following requirements: * - ``smallint`` - ○ [#f6]_ - ○ [#f7]_ - - ✓ - - ✓ - - ✓ + - Supported + - Supported + - Supported - - - @@ -67,8 +67,8 @@ Prepare the source ORC files, with the following requirements: - ○ [#f6]_ - ○ [#f7]_ - ○ [#f7]_ - - ✓ - - ✓ + - Supported + - Supported - - - @@ -79,7 +79,7 @@ Prepare the source ORC files, with the following requirements: - ○ [#f7]_ - ○ [#f7]_ - ○ [#f7]_ - - ✓ + - Supported - - - @@ -91,8 +91,8 @@ Prepare the source ORC files, with the following requirements: - - - - - ✓ - - ✓ + - Supported + - Supported - - - @@ -102,12 +102,12 @@ Prepare the source ORC files, with the following requirements: - - - - - ✓ - - ✓ + - Supported + - Supported - - - - * - ``string`` / ``char`` / ``varchar`` + * - ``string`` / ``char`` / ``text`` - - - @@ -115,7 +115,7 @@ Prepare the source ORC files, with the following requirements: - - - - - ✓ + - Supported - - * - ``date`` @@ -127,8 +127,8 @@ Prepare the source ORC files, with the following requirements: - - - - - ✓ - - ✓ + - Supported + - Supported * - ``timestamp``, ``timestamp`` with timezone - - @@ -139,19 +139,19 @@ Prepare the source ORC files, with the following requirements: - - - - - ✓ + - Supported * If an ORC file has an unsupported type like ``binary``, ``list``, ``map``, and ``union``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query), the statement will succeed. If the column is referenced, an error will be thrown to the user, explaining that the type is not supported, but the column may be ommited. This can be worked around. See more information in the examples. .. rubric:: Footnotes -.. [#f0] Text values include ``TEXT``, ``VARCHAR``, and ``NVARCHAR`` +.. [#f0] Text values include ``TEXT``. -.. [#f5] Boolean values are cast to 0, 1 +.. [#f5] Boolean values are cast to 0, 1. -.. [#f6] Will succeed if all values are 0, 1 +.. [#f6] Will succeed if all values are 0, 1. -.. [#f7] Will succeed if all values fit the destination type +.. [#f7] Will succeed if all values fit the destination type. 2. Place ORC files where SQream DB workers can access them ================================================================ @@ -186,14 +186,14 @@ We will make note of the file structure to create a matching ``CREATE FOREIGN TA CREATE FOREIGN TABLE ext_nba ( - Name VARCHAR(40), - Team VARCHAR(40), + Name TEXT, + Team TEXT, Number BIGINT, - Position VARCHAR(2), + Position TEXT, Age BIGINT, - Height VARCHAR(4), + Height TEXT, Weight BIGINT, - College VARCHAR(40), + College TEXT, Salary FLOAT ) WRAPPER orc_fdw @@ -288,7 +288,7 @@ Loading a table from a directory of ORC files on HDFS .. code-block:: postgres CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name TEXT NOT NULL, email TEXT NOT NULL) WRAPPER orc_fdw OPTIONS ( @@ -303,7 +303,7 @@ Loading a table from a bucket of files on S3 .. code-block:: postgres CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name TEXT NOT NULL, email TEXT NOT NULL) WRAPPER orc_fdw OPTIONS ( LOCATION = 's3://pp-secret-bucket/users/*.ORC', diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index 800c3122a..67d255c2f 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -125,11 +125,11 @@ Prepare the source Parquet files, with the following requirements: .. rubric:: Footnotes -.. [#f0] Text values include ``TEXT``, ``VARCHAR``, and ``NVARCHAR`` +.. [#f0] Text values include ``TEXT``. -.. [#f2] With UTF8 annotation +.. [#f2] With UTF8 annotation. -.. [#f3] With ``TIMESTAMP_NANOS`` or ``TIMESTAMP_MILLIS`` annotation +.. [#f3] With ``TIMESTAMP_NANOS`` or ``TIMESTAMP_MILLIS`` annotation. .. [#f4] Any microseconds will be rounded down to milliseconds. @@ -167,14 +167,14 @@ We will make note of the file structure to create a matching ``CREATE EXTERNAL T CREATE FOREIGN TABLE ext_nba ( - Name VARCHAR(40), - Team VARCHAR(40), + Name TEXT, + Team TEXT, Number BIGINT, - Position VARCHAR(2), + Position TEXT, Age BIGINT, - Height VARCHAR(4), + Height TEXT, Weight BIGINT, - College VARCHAR(40), + College TEXT, Salary FLOAT ) WRAPPER parquet_fdw diff --git a/data_type_guides/sql_data_types_string.rst b/data_type_guides/sql_data_types_string.rst index beb970b8d..a4321f387 100644 --- a/data_type_guides/sql_data_types_string.rst +++ b/data_type_guides/sql_data_types_string.rst @@ -3,9 +3,7 @@ ************************* String ************************* -``TEXT`` and ``VARCHAR`` are types designed for storing text or strings of characters. - -SQream separates ASCII (``VARCHAR``) and UTF-8 representations (``TEXT``). +The ``TEXT`` type is designed for storing text or strings of characters. .. note:: The data type ``NVARCHAR`` has been deprecated by ``TEXT`` as of version 2020.1. @@ -21,24 +19,20 @@ The following table describes the String types: - Details - Data Size (Not Null, Uncompressed) - Example - * - ``TEXT [(n)]``, ``NVARCHAR (n)`` + * - ``TEXT [(n)]`` - Varaiable length string - UTF-8 unicode. ``NVARCHAR`` is synonymous with ``TEXT``. - Up to ``4*n`` bytes - ``'キウイは楽しい鳥です'`` - * - ``VARCHAR (n)`` - - Variable length string - ASCII only - - ``n`` bytes - - ``'Kiwis have tiny wings, but cannot fly.'`` Length ^^^^^^^^^ -When using ``TEXT``, specifying a size is optional. If not specified, the text field carries no constraints. To limit the size of the input, use ``VARCHAR(n)`` or ``TEXT(n)``, where ``n`` is the permitted number of characters. +When using ``TEXT``, specifying a size is optional. If not specified, the text field carries no constraints. To limit the size of the input, use ``TEXT(n)``, where ``n`` is the permitted number of characters. The following apply to setting the String type length: * If the data exceeds the column length limit on ``INSERT`` or ``COPY`` operations, SQream DB will return an error. -* When casting or converting, the string has to fit in the target. For example, ``'Kiwis are weird birds' :: VARCHAR(5)`` will return an error. Use ``SUBSTRING`` to truncate the length of the string. -* ``VARCHAR`` strings are padded with spaces. +* When casting or converting, the string has to fit in the target. For example, ``'Kiwis are weird birds' :: TEXT`` will return an error. Use ``SUBSTRING`` to truncate the length of the string. +* ``TEXT`` strings are padded with spaces. Syntax ^^^^^^^^ diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index 710641036..96d2c69ec 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -108,7 +108,7 @@ The following two are equivalent: CREATE TABLE t ( x INT, - y VARCHAR(50) + y TEXT ); In this version, the default compression is specified explicitly: @@ -117,7 +117,7 @@ In this version, the default compression is specified explicitly: CREATE TABLE t ( x INT CHECK('CS "default"'), - y VARCHAR(50) CHECK('CS "default"') + y TEXT CHECK('CS "default"') ); Forcing no compression (flat) @@ -130,7 +130,7 @@ in order to reduce CPU or GPU resource utilization at the expense of increased I CREATE TABLE t ( x INT NOT NULL CHECK('CS "flat"'), -- This column won't be compressed - y VARCHAR(50) -- This column will still be compressed automatically + y TEXT -- This column will still be compressed automatically ); @@ -146,8 +146,8 @@ For example: CREATE TABLE t ( id BIGINT NOT NULL CHECK('CS "sequence"'), - y VARCHAR(110) CHECK('CS "lz4"'), -- General purpose text compression - z VARCHAR(80) CHECK('CS "dict"'), -- Low cardinality column + y TEXT CHECK('CS "lz4"'), -- General purpose text compression + z TEXT CHECK('CS "dict"'), -- Low cardinality column ); diff --git a/getting_started/querying_data.rst b/getting_started/querying_data.rst index 36bf9e78b..58047c334 100644 --- a/getting_started/querying_data.rst +++ b/getting_started/querying_data.rst @@ -11,14 +11,14 @@ To begin familiarizing yourself with querying data, you can create the following CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text, + Team text, Number tinyint, - Position varchar(2), + Position text, Age tinyint, - Height varchar(4), + Height text, Weight real, - College varchar(40), + College text, Salary float ); diff --git a/operational_guides/external_tables.rst b/operational_guides/foreign_tables.rst similarity index 72% rename from operational_guides/external_tables.rst rename to operational_guides/foreign_tables.rst index 005dc961f..c743c72dc 100644 --- a/operational_guides/external_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -1,25 +1,27 @@ -.. _external_tables: +.. _foreign_tables: *********************** -External Tables +Foreign Tables *********************** -External tables can be used to run queries directly on data without inserting it into SQream DB first. -SQream DB supports read only external tables, so you can query from external tables, but you cannot insert to them, or run deletes or updates on them. -Running queries directly on external data is most effectively used for things like one off querying. If you will be repeatedly querying data, the performance will usually be better if you insert the data into SQream DB first. -Although external tables can be used without inserting data into SQream DB, one of their main use cases is to help with the insertion process. An insert select statement on an external table can be used to insert data into SQream using the full power of the query engine to perform ETL. +Foreign tables can be used to run queries directly on data without inserting it into SQream DB first. + +SQream DB supports read only foreign tables, so you can query from foreign tables, but you cannot insert to them, or run deletes or updates on them. +Running queries directly on foreign data is most effectively used for things like one off querying. If you will be repeatedly querying data, the performance will usually be better if you insert the data into SQream DB first. + +Although foreign tables can be used without inserting data into SQream DB, one of their main use cases is to help with the insertion process. An insert select statement on a foreign table can be used to insert data into SQream using the full power of the query engine to perform ETL. .. contents:: In this topic: :local: -What kind of data is supported? +What Kind of Data is Supported? ===================================== -SQream DB supports external tables over: +SQream DB supports foreign tables over: * text files (e.g. CSV, PSV, TSV) * ORC * Parquet -What kind of data staging is supported? +What Kind of Data Staging is Supported? ============================================ SQream DB can stage data from: @@ -27,39 +29,40 @@ SQream DB can stage data from: * :ref:`s3` buckets (e.g. ``s3://pp-secret-bucket/users/*.parquet``) * :ref:`hdfs` (e.g. ``hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv``) -Using external tables - a practical example + +Using foreign tables - a practical example ============================================== -Use an external table to stage data before loading from CSV, Parquet or ORC files. +Use a foreign table to stage data before loading from CSV, Parquet or ORC files. -Planning for data staging +Planning for Data Staging -------------------------------- For the following examples, we will want to interact with a CSV file. Here's a peek at the table contents: -.. csv-table:: nba.csv - - :file: nba-t10.csv +.. csv-table:: nba-t10 + :file: ../_static/samples/nba-t10.csv :widths: auto - :header-rows: 1 + :header-rows: 1 The file is stored on :ref:`s3`, at ``s3://sqream-demo-data/nba_players.csv``. -We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_TABLE`` statement. +We will make note of the file structure, to create a matching ``CREATE_FOREIGN_TABLE`` statement. + -Creating the external table +Creating the foreign table ----------------------------- -Based on the source file structure, we we :ref:`create an external table` with the appropriate structure, and point it to the file. +Based on the source file structure, we we :ref:`create a foreign table` with the appropriate structure, and point it to the file. .. code-block:: postgres - CREATE EXTERNAL TABLE nba + CREATE FOREIGN TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text, + Team text, Number tinyint, - Position varchar(2), + Position text, Age tinyint, - Height varchar(4), + Height text, Weight real, - College varchar(40), + College text, Salary float ) USING FORMAT CSV -- Text file @@ -68,10 +71,11 @@ Based on the source file structure, we we :ref:`create an external table SELECT * FROM nba; master=> select * from nba; Record delimiter mismatch during CSV parsing. User defined line delimiter \n does not match the first delimiter \r\n found in s3://sqream-demo-data/nba.csv -* Since the data for an external table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against an external table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. +* Since the data for a foreign table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against a foreign table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. \ No newline at end of file diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 7a019a433..048efb06f 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -15,7 +15,7 @@ This section summarizes the following operational guides: access_control creating_or_cloning_a_storage_cluster external_data - external_tables + foreign_tables delete_guide exporting_data logging diff --git a/operational_guides/logging.rst b/operational_guides/logging.rst index 64ac5c8d8..9eefe3283 100644 --- a/operational_guides/logging.rst +++ b/operational_guides/logging.rst @@ -354,7 +354,7 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas CREATE FOREIGN TABLE logs ( - start_marker VARCHAR(4), + start_marker TEXT, row_id BIGINT, timestamp DATETIME, message_level TEXT, @@ -368,7 +368,7 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas service_name TEXT, message_type_id INT, message TEXT, - end_message VARCHAR(5) + end_message TEXT ) WRAPPER csv_fdw OPTIONS diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index d6d60dbe4..703a0e39f 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -17,6 +17,7 @@ Setting Up the System for Monitoring ================================================= By default, SQream DB logs execution details for every statement that runs for more than 60 seconds. If you want to see the execution details for a currently running statement, see :ref:`using_show_node_info` below. + Adjusting the Logging Frequency --------------------------------------- To adjust the frequency of logging for statements, you may want to reduce the interval from 60 seconds down to, @@ -46,7 +47,7 @@ First, create a foreign table for the logs .. code-block:: postgres CREATE FOREIGN TABLE logs ( - start_marker VARCHAR(4), + start_marker TEXT, row_id BIGINT, timestamp DATETIME, message_level TEXT, @@ -60,7 +61,7 @@ First, create a foreign table for the logs service_name TEXT, message_type_id INT, message TEXT, - end_message VARCHAR(5) + end_message TEXT ) WRAPPER cdv_fdw OPTIONS @@ -132,15 +133,14 @@ Understanding the Query Execution Plan Output Both :ref:`show_node_info` and the logged execution plans represents the query plan as a graph hierarchy, with data separated into different columns. Each row represents a single logical database operation, which is also called a **node** or **chunk producer**. A node reports several metrics during query execution, such as how much data it has read and written, how many chunks and rows, and how much time has elapsed. -Consider the example show_node_info presented above. The source node with ID #11 (``ReadTable``), has a parent node ID #10 -(``CpuDecompress``). If we were to draw this out in a graph, it'd look like this: +Consider the example show_node_info presented above. The source node with ID #11 (``ReadTable``), has a parent node ID #10 (``CpuDecompress``). + +If we were to draw this out in a graph, it would look like this: + .. figure:: /_static/images/show_node_info_graph.png :height: 70em :align: center - - This graph explains how the query execution details are arranged in a logical order, from the bottom up. - - + The last node, also called the sink, has a parent node ID of -1, meaning it has no parent. This is typically a node that sends data over the network or into a table. @@ -199,7 +199,7 @@ Commonly Seen Nodes - Description * - ``CpuDecompress`` - CPU - - Decompression operation, common for longer ``VARCHAR`` types + - Decompression operation, common for longer ``TEXT`` types * - ``CpuLoopJoin`` - CPU - A non-indexed nested loop join, performed on the CPU @@ -459,6 +459,7 @@ Identifying the Offending Nodes 494 | 194 | DeferredGather | 133241 | 20 | 6662 | 2020-09-04 19:07:03 | 193 | | | | 0.41 [...] 494 | 221 | ReadTable | 20000000 | 20 | 1000000 | 2020-09-04 19:07:01 | 220 | 20MB | | public.part | 0.1 + When you see ``DeferredGather`` operations taking more than a few seconds, that's a sign that you're selecting too much data. In this case, the DeferredGather with node ID 166 took over 21 seconds. @@ -619,224 +620,8 @@ Common Solutions for Improving Filtering * Use :ref:`clustering keys and naturally ordered data` in your filters. * Avoid full table scans when possible -4. Joins with ``varchar`` Keys ------------------------------------ -Joins on long text keys, such as ``varchar(100)`` do not perform as well as numeric data types or very short text keys. - -Identifying the Situation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -When a join is inefficient, you may note that a query spends a lot of time on the ``Join`` node. -For example, consider these two table structures: - -.. code-block:: postgres - CREATE TABLE t_a - ( - amt FLOAT NOT NULL, - i INT NOT NULL, - ts DATETIME NOT NULL, - country_code VARCHAR(3) NOT NULL, - flag VARCHAR(10) NOT NULL, - fk VARCHAR(50) NOT NULL - ); - CREATE TABLE t_b - ( - id VARCHAR(50) NOT NULL - prob FLOAT NOT NULL, - j INT NOT NULL, - ); -#. - Run a query. - - In this example, we will join ``t_a.fk`` with ``t_b.id``, both of which are ``VARCHAR(50)``. - - .. code-block:: postgres - - SELECT AVG(t_b.j :: BIGINT), - t_a.country_code - FROM t_a - JOIN t_b ON (t_a.fk = t_b.id) - GROUP BY t_a.country_code -#. - - Observe the execution information by using the foreign table, or use ``show_node_info`` - - The execution below has been shortened, but note the highlighted rows for ``Join``. - The ``Join`` node is by far the most time-consuming part of this statement - clocking in at 69.7 seconds - joining 1.5 billion records. - - .. code-block:: psql - :linenos: - :emphasize-lines: 8 - - t=> SELECT show_node_info(5); - stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum - --------+---------+----------------------+------------+--------+-------------------+---------------------+----------------+-------+-------+------------+-------- - [...] - 5 | 19 | GpuTransform | 1497366528 | 204 | 7340032 | 2020-09-08 18:29:03 | 18 | | | | 1.46 - 5 | 20 | ReorderInput | 1497366528 | 204 | 7340032 | 2020-09-08 18:29:03 | 19 | | | | 0 - 5 | 21 | ReorderInput | 1497366528 | 204 | 7340032 | 2020-09-08 18:29:03 | 20 | | | | 0 - 5 | 22 | Join | 1497366528 | 204 | 7340032 | 2020-09-08 18:29:03 | 21 | | | inner | 69.7 - 5 | 24 | AddSortedMinMaxMet.. | 6291456 | 1 | 6291456 | 2020-09-08 18:26:05 | 22 | | | | 0 - 5 | 25 | Sort | 6291456 | 1 | 6291456 | 2020-09-08 18:26:05 | 24 | | | | 2.06 - [...] - 5 | 31 | ReadTable | 6291456 | 1 | 6291456 | 2020-09-08 18:26:03 | 30 | 235MB | | public.t_b | 0.02 - [...] - 5 | 41 | CpuDecompress | 10000000 | 2 | 5000000 | 2020-09-08 18:26:09 | 40 | | | | 0 - 5 | 42 | ReadTable | 10000000 | 2 | 5000000 | 2020-09-08 18:26:09 | 41 | 14MB | | public.t_a | 0 - -Improving Query Performance -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -* In general, try to avoid ``VARCHAR`` as a join key. As a rule of thumb, ``BIGINT`` works best as a join key. -* - Convert text values on-the-fly before running the query. For example, the :ref:`crc64` function takes a text - input and returns a ``BIGINT`` hash. - - For example: - - .. code-block:: postgres - - SELECT AVG(t_b.j :: BIGINT), - t_a.country_code - FROM t_a - JOIN t_b ON (crc64_join(t_a.fk) = crc64_join(t_b.id)) - GROUP BY t_a.country_code - The execution below has been shortened, but note the highlighted rows for ``Join``. - The ``Join`` node went from taking nearly 70 seconds, to just 6.67 seconds for joining 1.5 billion records. - - .. code-block:: psql - :linenos: - :emphasize-lines: 8 - - t=> SELECT show_node_info(6); - stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum - --------+---------+----------------------+------------+--------+-------------------+---------------------+----------------+-------+-------+------------+-------- - [...] - 6 | 19 | GpuTransform | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 18 | | | | 1.48 - 6 | 20 | ReorderInput | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 19 | | | | 0 - 6 | 21 | ReorderInput | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 20 | | | | 0 - 6 | 22 | Join | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 21 | | | inner | 6.67 - 6 | 24 | AddSortedMinMaxMet.. | 6291456 | 1 | 6291456 | 2020-09-08 18:55:12 | 22 | | | | 0 - [...] - 6 | 32 | ReadTable | 6291456 | 1 | 6291456 | 2020-09-08 18:55:12 | 31 | 235MB | | public.t_b | 0.02 - [...] - 6 | 43 | CpuDecompress | 10000000 | 2 | 5000000 | 2020-09-08 18:55:13 | 42 | | | | 0 - 6 | 44 | ReadTable | 10000000 | 2 | 5000000 | 2020-09-08 18:55:13 | 43 | 14MB | | public.t_a | 0 - -* You can map some text values to numeric types by using a dimension table. Then, reconcile the values when you need them by joining the dimension table. - -5. Sorting on big ``VARCHAR`` fields ---------------------------------------- -In general, SQream DB automatically inserts a ``Sort`` node which arranges the data prior to reductions and aggregations. -When running a ``GROUP BY`` on large ``VARCHAR`` fields, you may see nodes for ``Sort`` and ``Reduce`` taking a long time. - -Identifying the Situation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -When running a statement, inspect it with :ref:`show_node_info`. If you see ``Sort`` and ``Reduce`` among -your top five longest running nodes, there is a potential issue. -For example: -#. - Run a query to test it out. - - - Our ``t_inefficient`` table contains 60,000,000 rows, and the structure is simple, but with an oversized ``country_code`` column: - - .. code-block:: postgres - :emphasize-lines: 5 - - CREATE TABLE t_inefficient ( - i INT NOT NULL, - amt DOUBLE NOT NULL, - ts DATETIME NOT NULL, - country_code VARCHAR(100) NOT NULL, - flag VARCHAR(10) NOT NULL, - string_fk VARCHAR(50) NOT NULL - ); - - We will run a query, and inspect it's execution details: - - .. code-block:: psql - - t=> SELECT country_code, - . SUM(amt) - . FROM t_inefficient - . GROUP BY country_code; - executed - time: 47.55s - - country_code | sum - -------------+----------- - VUT | 1195416012 - GIB | 1195710372 - TUR | 1195946178 - [...] - - - .. code-block:: psql - :emphasize-lines: 8,9 - - t=> select show_node_info(30); - stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum - --------+---------+--------------------+----------+--------+-------------------+---------------------+----------------+-------+-------+----------------------+-------- - 30 | 1 | PushToNetworkQueue | 249 | 1 | 249 | 2020-09-10 16:17:10 | -1 | | | | 0.25 - 30 | 2 | Rechunk | 249 | 1 | 249 | 2020-09-10 16:17:10 | 1 | | | | 0 - 30 | 3 | ReduceMerge | 249 | 1 | 249 | 2020-09-10 16:17:10 | 2 | | | | 0.01 - 30 | 4 | GpuToCpu | 1508 | 15 | 100 | 2020-09-10 16:17:10 | 3 | | | | 0 - 30 | 5 | Reduce | 1508 | 15 | 100 | 2020-09-10 16:17:10 | 4 | | | | 7.23 - 30 | 6 | Sort | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 5 | | | | 36.8 - 30 | 7 | GpuTransform | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 6 | | | | 0.08 - 30 | 8 | GpuDecompress | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 7 | | | | 2.01 - 30 | 9 | CpuToGpu | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 8 | | | | 0.16 - 30 | 10 | Rechunk | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 9 | | | | 0 - 30 | 11 | CpuDecompress | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 10 | | | | 0 - 30 | 12 | ReadTable | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 11 | 520MB | | public.t_inefficient | 0.05 -#. We can look to see if there's any shrinking we can do on the ``GROUP BY`` key - - .. code-block:: psql - - t=> SELECT MAX(LEN(country_code)) FROM t_inefficient; - max - --- - 3 - With a maximum string length of just 3 characters, our ``VARCHAR(100)`` is way oversized. -#. - We can recreate the table with a more restrictive ``VARCHAR(3)``, and can examine the difference in performance: - - .. code-block:: psql - t=> CREATE TABLE t_efficient - . AS SELECT i, - . amt, - . ts, - . country_code::VARCHAR(3) AS country_code, - . flag - . FROM t_inefficient; - executed - time: 16.03s - - t=> SELECT country_code, - . SUM(amt::bigint) - . FROM t_efficient - . GROUP BY country_code; - executed - time: 4.75s - country_code | sum - -------------+----------- - VUT | 1195416012 - GIB | 1195710372 - TUR | 1195946178 - [...] - - This time, the entire query took just 4.75 seconds, or just about 91% faster. - -Improving Sort Performance on Text Keys -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -When using VARCHAR, ensure that the maximum length defined in the table structure is as small as necessary. -For example, if you're storing phone numbers, don't define the field as ``VARCHAR(255)``, as that affects sort performance. - -You can run a query to get the maximum column length (e.g. ``MAX(LEN(a_column))``), and potentially modify the table structure. - -.. _high_selectivity_data_opt: -6. High Selectivity Data +4. High Selectivity Data -------------------------- Selectivity is the ratio of cardinality to the number of records of a chunk. We define selectivity as :math:`\frac{\text{Distinct values}}{\text{Total number of records in a chunk}}` SQream DB has a hint called ``HIGH_SELECTIVITY``, which is a function you can wrap a condition in. @@ -871,7 +656,7 @@ Improving Performance with High Selectivity Hints to cut out more than 60% of the result set. * Use when the data is uniformly distributed or random -7. Performance of unsorted data in joins +5. Performance of unsorted data in joins ------------------------------------------ When data is not well-clustered or naturally ordered, a join operation can take a long time. @@ -934,7 +719,7 @@ To tell SQream DB to rechunk the data, wrap a condition (or several) in the ``HI AND EnterpriseID=1150 AND MSISDN='9724871140341'; -8. Manual Join Reordering +6. Manual Join Reordering -------------------------------- When joining multiple tables, you may wish to change the join order to join the smallest tables first. diff --git a/operational_guides/optimization_best_practices.rst b/operational_guides/optimization_best_practices.rst index 1cc0ca01e..64ebaabd9 100644 --- a/operational_guides/optimization_best_practices.rst +++ b/operational_guides/optimization_best_practices.rst @@ -20,20 +20,7 @@ This section describes best practices and guidelines for designing tables. Use date and datetime types for columns ----------------------------------------- -When creating tables with dates or timestamps, using the purpose-built ``DATE`` and ``DATETIME`` types over integer types or ``VARCHAR`` will bring performance and storage footprint improvements, and in many cases huge performance improvements (as well as data integrity benefits). SQream DB stores dates and datetimes very efficiently and can strongly optimize queries using these specific types. - -Reduce varchar length to a minimum --------------------------------------- - -With the ``VARCHAR`` type, the length has a direct effect on query performance. - -If the size of your column is predictable, by defining an appropriate column length (no longer than the maximum actual value) you will get the following benefits: - -* Data loading issues can be identified more quickly - -* SQream DB can reserve less memory for decompression operations - -* Third-party tools that expect a data size are less likely to over-allocate memory +When creating tables with dates or timestamps, using the purpose-built ``DATE`` and ``DATETIME`` types over integer types or ``TEXT`` will bring performance and storage footprint improvements, and in many cases huge performance improvements (as well as data integrity benefits). SQream DB stores dates and datetimes very efficiently and can strongly optimize queries using these specific types. Don't flatten or denormalize data ----------------------------------- @@ -71,14 +58,6 @@ For example, if a value can't be missing (or ``NULL``), specify a ``NOT NULL`` c Not only does specifying ``NOT NULL`` save on data storage, it lets the query compiler know that a column cannot have a ``NULL`` value, which can improve query performance. -Keep VARCHAR lengths to a minimum -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -While it won't make a big difference in storage, large strings allocate a lot of memory at query time. - -If a column's string length never exceeds 50 characters, specify ``VARCHAR(50)`` rather than an arbitrarily large number. - - Sorting ============== @@ -86,7 +65,7 @@ Data sorting is an important factor in minimizing storage size and improving que * Minimizing storage saves on physical resources and increases performance by reducing overall disk I/O. Prioritize the sorting of low-cardinality columns. This reduces the number of chunks and extents that SQream DB reads during query execution. -* Where possible, sort columns with the lowest cardinality first. Avoid sorting ``VARCHAR`` and ``TEXT/NVARCHAR`` columns with lengths exceeding 50 characters. +* Where possible, sort columns with the lowest cardinality first. Avoid sorting ``TEXT`` columns with lengths exceeding 50 characters. * For longer-running queries that run on a regular basis, performance can be improved by sorting data based on the ``WHERE`` and ``GROUP BY`` parameters. Data can be sorted during insert by using :ref:`external_tables` or by using :ref:`create_table_as`. diff --git a/operational_guides/s3.rst b/operational_guides/s3.rst index bba878830..89c4d2343 100644 --- a/operational_guides/s3.rst +++ b/operational_guides/s3.rst @@ -66,14 +66,14 @@ Based on the source file's structure, you can create a foreign table with the ap CREATE FOREIGN TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text, + Team text, Number tinyint, - Position varchar(2), + Position text, Age tinyint, - Height varchar(4), + Height text, Weight real, - College varchar(40), + College text, Salary float ) WRAPPER csv_fdw diff --git a/reference/sql/sql_functions/aggregate_functions/avg.rst b/reference/sql/sql_functions/aggregate_functions/avg.rst index be0294d46..40eafbdc0 100644 --- a/reference/sql/sql_functions/aggregate_functions/avg.rst +++ b/reference/sql/sql_functions/aggregate_functions/avg.rst @@ -62,14 +62,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/corr.rst b/reference/sql/sql_functions/aggregate_functions/corr.rst index 212ab89d2..c9d26235a 100644 --- a/reference/sql/sql_functions/aggregate_functions/corr.rst +++ b/reference/sql/sql_functions/aggregate_functions/corr.rst @@ -51,14 +51,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/count.rst b/reference/sql/sql_functions/aggregate_functions/count.rst index 803e529c0..f0b0b5613 100644 --- a/reference/sql/sql_functions/aggregate_functions/count.rst +++ b/reference/sql/sql_functions/aggregate_functions/count.rst @@ -67,14 +67,14 @@ The examples in this section are based on a table named ``nba``, structured as f CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/covar_pop.rst b/reference/sql/sql_functions/aggregate_functions/covar_pop.rst index c0d7cd35d..53e83f691 100644 --- a/reference/sql/sql_functions/aggregate_functions/covar_pop.rst +++ b/reference/sql/sql_functions/aggregate_functions/covar_pop.rst @@ -55,14 +55,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/covar_samp.rst b/reference/sql/sql_functions/aggregate_functions/covar_samp.rst index 29d7b7493..6f385e9e0 100644 --- a/reference/sql/sql_functions/aggregate_functions/covar_samp.rst +++ b/reference/sql/sql_functions/aggregate_functions/covar_samp.rst @@ -56,14 +56,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/max.rst b/reference/sql/sql_functions/aggregate_functions/max.rst index 529e2230d..d2a7afc66 100644 --- a/reference/sql/sql_functions/aggregate_functions/max.rst +++ b/reference/sql/sql_functions/aggregate_functions/max.rst @@ -53,14 +53,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/min.rst b/reference/sql/sql_functions/aggregate_functions/min.rst index d488d87fc..3f5a2d402 100644 --- a/reference/sql/sql_functions/aggregate_functions/min.rst +++ b/reference/sql/sql_functions/aggregate_functions/min.rst @@ -53,14 +53,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/stddev_pop.rst b/reference/sql/sql_functions/aggregate_functions/stddev_pop.rst index 5a8a7e677..fbbdc9bab 100644 --- a/reference/sql/sql_functions/aggregate_functions/stddev_pop.rst +++ b/reference/sql/sql_functions/aggregate_functions/stddev_pop.rst @@ -58,14 +58,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/stddev_samp.rst b/reference/sql/sql_functions/aggregate_functions/stddev_samp.rst index 0328e2241..b7d9bd468 100644 --- a/reference/sql/sql_functions/aggregate_functions/stddev_samp.rst +++ b/reference/sql/sql_functions/aggregate_functions/stddev_samp.rst @@ -62,14 +62,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/sum.rst b/reference/sql/sql_functions/aggregate_functions/sum.rst index e8f648894..132c24d68 100644 --- a/reference/sql/sql_functions/aggregate_functions/sum.rst +++ b/reference/sql/sql_functions/aggregate_functions/sum.rst @@ -65,14 +65,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/var_pop.rst b/reference/sql/sql_functions/aggregate_functions/var_pop.rst index 4ddf45a1e..94404f2f6 100644 --- a/reference/sql/sql_functions/aggregate_functions/var_pop.rst +++ b/reference/sql/sql_functions/aggregate_functions/var_pop.rst @@ -58,14 +58,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/var_samp.rst b/reference/sql/sql_functions/aggregate_functions/var_samp.rst index 6f0c91e63..e1e79ad68 100644 --- a/reference/sql/sql_functions/aggregate_functions/var_samp.rst +++ b/reference/sql/sql_functions/aggregate_functions/var_samp.rst @@ -63,14 +63,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst b/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst index f3cf6fb82..d33643f22 100644 --- a/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst +++ b/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst @@ -11,7 +11,7 @@ Syntax .. code-block:: postgres - TO_HEX( expr ) --> VARCHAR + TO_HEX( expr ) --> TEXT Arguments ============ @@ -28,7 +28,7 @@ Arguments Returns ============ -* Representation of the hexadecimal number of type ``VARCHAR``. +* Representation of the hexadecimal number of type ``TEXT``. Examples diff --git a/reference/sql/sql_functions/scalar_functions/string/concat.rst b/reference/sql/sql_functions/scalar_functions/string/concat.rst index 0409216cd..286af690a 100644 --- a/reference/sql/sql_functions/scalar_functions/string/concat.rst +++ b/reference/sql/sql_functions/scalar_functions/string/concat.rst @@ -48,14 +48,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text, + Team text, Number tinyint, - Position varchar(2), + Position text, Age tinyint, - Height varchar(4), + Height text, Weight real, - College varchar(40), + College text, Salary float ); @@ -76,7 +76,7 @@ Convert values to string types before concatenation .. code-block:: psql - nba=> SELECT ("Age" :: VARCHAR(2)) || "Name" FROM nba ORDER BY 1 DESC LIMIT 5; + nba=> SELECT ("Age" :: TEXT) || "Name" FROM nba ORDER BY 1 DESC LIMIT 5; ?column? ---------------- 40Tim Duncan @@ -116,7 +116,7 @@ Add a space and concatenate it first to bypass the space trimming issue .. code-block:: psql - nba=> SELECT ("Age" :: VARCHAR(2) || (' ' || "Name")) FROM nba ORDER BY 1 DESC LIMIT 5; + nba=> SELECT ("Age" :: TEXT || (' ' || "Name")) FROM nba ORDER BY 1 DESC LIMIT 5; ?column? ----------------- 40 Tim Duncan diff --git a/reference/sql/sql_functions/scalar_functions/string/like.rst b/reference/sql/sql_functions/scalar_functions/string/like.rst index 4640ba9be..ce5ca4942 100644 --- a/reference/sql/sql_functions/scalar_functions/string/like.rst +++ b/reference/sql/sql_functions/scalar_functions/string/like.rst @@ -83,14 +83,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text(40), + Team text(40), Number tinyint, - Position varchar(2), + Position text(2), Age tinyint, - Height varchar(4), + Height text(4), Weight real, - College varchar(40), + College text(40), Salary float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst index 5f3bd75a0..dc16413af 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst @@ -99,14 +99,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst index bade0bb01..da2922798 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst @@ -105,14 +105,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst index 1730d6ebf..9d623bf7f 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst @@ -104,14 +104,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/rlike.rst b/reference/sql/sql_functions/scalar_functions/string/rlike.rst index 324a6e525..b379568df 100644 --- a/reference/sql/sql_functions/scalar_functions/string/rlike.rst +++ b/reference/sql/sql_functions/scalar_functions/string/rlike.rst @@ -99,14 +99,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text, + Team text, Number tinyint, - Position varchar(2), + Position text, Age tinyint, - Height varchar(4), + Height text, Weight real, - College varchar(40), + College text, Salary float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/rtrim.rst b/reference/sql/sql_functions/scalar_functions/string/rtrim.rst index 2bd5bbc38..61fdc877d 100644 --- a/reference/sql/sql_functions/scalar_functions/string/rtrim.rst +++ b/reference/sql/sql_functions/scalar_functions/string/rtrim.rst @@ -35,7 +35,7 @@ Returns the same type as the argument supplied. Notes ======= -* When using ``VARCHAR`` values, SQream DB automatically trims the trailing whitespace. Using ``RTRIM`` on ``VARCHAR`` does not affect the result. +* When using ``TEXT`` values, SQream DB automatically trims the trailing whitespace. Using ``RTRIM`` on ``TEXT`` does not affect the result. * This function is equivalent to the ANSI form ``TRIM( TRAILING FROM expr )`` diff --git a/reference/sql/sql_functions/scalar_functions/string/substring.rst b/reference/sql/sql_functions/scalar_functions/string/substring.rst index b07d951fb..bf2f6a0df 100644 --- a/reference/sql/sql_functions/scalar_functions/string/substring.rst +++ b/reference/sql/sql_functions/scalar_functions/string/substring.rst @@ -54,14 +54,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text, + Team text, Number tinyint, - Position varchar(2), + Position text, Age tinyint, - Height varchar(4), + Height text, Weight real, - College varchar(40), + College text Salary float ); diff --git a/reference/sql/sql_functions/window_functions/first_value.rst b/reference/sql/sql_functions/window_functions/first_value.rst index 07708872d..65d904a04 100644 --- a/reference/sql/sql_functions/window_functions/first_value.rst +++ b/reference/sql/sql_functions/window_functions/first_value.rst @@ -5,7 +5,7 @@ FIRST_VALUE ************************** The **FIRST_VALUE** function returns the value located in the selected column of the first row of a segment. If the table is not segmented, the FIRST_VALUE function returns the value from the first row of the whole table. -This function returns the same type of variable that you input for your requested value. For example, requesting the value for the first employee in a list using an ``int`` type output returns an ``int`` type ID column. If you use a ``varchar`` type, the function returns a ``varchar`` type name column. +This function returns the same type of variable that you input for your requested value. For example, requesting the value for the first employee in a list using an ``int`` type output returns an ``int`` type ID column. If you use a ``text`` type, the function returns a ``text`` type name column. Syntax ------- diff --git a/reference/sql/sql_functions/window_functions/lag.rst b/reference/sql/sql_functions/window_functions/lag.rst index e93be2821..9c7333107 100644 --- a/reference/sql/sql_functions/window_functions/lag.rst +++ b/reference/sql/sql_functions/window_functions/lag.rst @@ -59,14 +59,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/window_functions/last_value.rst b/reference/sql/sql_functions/window_functions/last_value.rst index 3cadaa9d1..967ed6baf 100644 --- a/reference/sql/sql_functions/window_functions/last_value.rst +++ b/reference/sql/sql_functions/window_functions/last_value.rst @@ -5,7 +5,7 @@ LAST_VALUE ************************** The **LAST_VALUE** function returns the value located in the selected column of the last row of a segment. If the table is not segmented, the LAST_VALUE function returns the value from the last row of the whole table. -This function returns the same type of variable that you input for your requested value. For example, requesting the value for the last employee in a list using an ``int`` type output returns an ``int`` type ID column. If you use a ``varchar`` type, the function returns a ``varchar`` type name column. +This function returns the same type of variable that you input for your requested value. For example, requesting the value for the last employee in a list using an ``int`` type output returns an ``int`` type ID column. If you use a ``text`` type, the function returns a ``text`` type name column. Syntax ------- diff --git a/reference/sql/sql_functions/window_functions/lead.rst b/reference/sql/sql_functions/window_functions/lead.rst index bc311689f..ef3f30ff8 100644 --- a/reference/sql/sql_functions/window_functions/lead.rst +++ b/reference/sql/sql_functions/window_functions/lead.rst @@ -59,14 +59,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/window_functions/nba-t10.csv b/reference/sql/sql_functions/window_functions/nba-t10.csv index 024530355..c3d41e729 100644 --- a/reference/sql/sql_functions/window_functions/nba-t10.csv +++ b/reference/sql/sql_functions/window_functions/nba-t10.csv @@ -1,10 +1,9 @@ -Name,Team,Number,Position,Age,Height,Weight,College,Salary -Avery Bradley,Boston Celtics,0.0,PG,25.0,6-2,180.0,Texas,7730337.0 -Jae Crowder,Boston Celtics,99.0,SF,25.0,6-6,235.0,Marquette,6796117.0 -John Holland,Boston Celtics,30.0,SG,27.0,6-5,205.0,Boston University, -R.J. Hunter,Boston Celtics,28.0,SG,22.0,6-5,185.0,Georgia State,1148640.0 -Jonas Jerebko,Boston Celtics,8.0,PF,29.0,6-10,231.0,,5000000.0 -Amir Johnson,Boston Celtics,90.0,PF,29.0,6-9,240.0,,12000000.0 -Jordan Mickey,Boston Celtics,55.0,PF,21.0,6-8,235.0,LSU,1170960.0 -Kelly Olynyk,Boston Celtics,41.0,C,25.0,7-0,238.0,Gonzaga,2165160.0 -Terry Rozier,Boston Celtics,12.0,PG,22.0,6-2,190.0,Louisville,1824360.0 +Avery Bradley,Boston Celtics,0,PG,25,2-Jun,180,Texas,7730337 +Jae Crowder,Boston Celtics,99,SF,25,6-Jun,235,Marquette,6796117 +John Holland,Boston Celtics,30,SG,27,5-Jun,205,Boston University, +R.J. Hunter,Boston Celtics,28,SG,22,5-Jun,185,Georgia State,1148640 +Jonas Jerebko,Boston Celtics,8,PF,29,10-Jun,231,,5000000 +Amir Johnson,Boston Celtics,90,PF,29,9-Jun,240,,12000000 +Jordan Mickey,Boston Celtics,55,PF,21,8-Jun,235,LSU,1170960 +Kelly Olynyk,Boston Celtics,41,C,25,Jul-00,238,Gonzaga,2165160 +Terry Rozier,Boston Celtics,12,PG,22,2-Jun,190,Louisville,1824360 diff --git a/reference/sql/sql_functions/window_functions/nth_value.rst b/reference/sql/sql_functions/window_functions/nth_value.rst index a2c1dd9a6..05617e484 100644 --- a/reference/sql/sql_functions/window_functions/nth_value.rst +++ b/reference/sql/sql_functions/window_functions/nth_value.rst @@ -22,8 +22,8 @@ The following example shows the syntax for a table named ``superstore`` used for CREATE TABLE superstore ( - "Section" varchar(40), - "Product_Name" varchar(40), + "Section" text, + "Product_Name" text, "Sales_In_K" int, ); diff --git a/reference/sql/sql_functions/window_functions/rank.rst b/reference/sql/sql_functions/window_functions/rank.rst index 28856bd04..5586a7328 100644 --- a/reference/sql/sql_functions/window_functions/rank.rst +++ b/reference/sql/sql_functions/window_functions/rank.rst @@ -48,14 +48,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_functions/window_functions/row_number.rst b/reference/sql/sql_functions/window_functions/row_number.rst index ea5786aef..6b798d0c1 100644 --- a/reference/sql/sql_functions/window_functions/row_number.rst +++ b/reference/sql/sql_functions/window_functions/row_number.rst @@ -48,14 +48,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_statements/ddl_commands/create_external_table.rst b/reference/sql/sql_statements/ddl_commands/create_external_table.rst deleted file mode 100644 index fc05ca71e..000000000 --- a/reference/sql/sql_statements/ddl_commands/create_external_table.rst +++ /dev/null @@ -1,156 +0,0 @@ -.. _create_external_table: - -*********************** -CREATE EXTERNAL TABLE -*********************** - -.. warning:: - - The ``CREATE EXTERNAL TABLE`` syntax is deprecated, and will be removed in future versions. - - Starting with SQream DB v2020.2, external tables have been renamed to :ref:`foreign tables`, and use a more flexible foreign data wrapper concept. See :ref:`create_foreign_table` instead. - - Upgrading to a new version of SQream DB converts existing tables automatically. When creating a new external tables, use the new foreign table syntax. - - -``CREATE TABLE`` creates a new external table in an existing database. - -See more in the :ref:`External tables guide`. - -.. tip:: - - * Data in an external table can change if the sources change, and frequent access to remote files may harm performance. - - * To create a regular table, see :ref:`CREATE TABLE ` - -Permissions -============= - -The role must have the ``CREATE`` permission at the database level. - -Syntax -========== - -.. code-block:: postgres - - create_table_statement ::= - CREATE [ OR REPLACE ] EXTERNAL TABLE [schema_name].table_name ( - { column_def [, ...] } - ) - USING FORMAT format_def - WITH { external_table_option [ ...] } - ; - - schema_name ::= identifier - - table_name ::= identifier - - format_def ::= { PARQUET | ORC | CSV } - - external_table_option ::= { - PATH '{ path_spec }' - | FIELD DELIMITER '{ field_delimiter }' - | RECORD DELIMITER '{ record_delimiter }' - | AWS_ID '{ AWS ID }' - | AWS_SECRET '{ AWS SECRET }' - } - - path_spec ::= { local filepath | S3 URI | HDFS URI } - - field_delimiter ::= delimiter_character - - record_delimiter ::= delimiter_character - - column_def ::= { column_name type_name [ default ] [ column_constraint ] } - - column_name ::= identifier - - column_constraint ::= - { NOT NULL | NULL } - - default ::= - - DEFAULT default_value - | IDENTITY [ ( start_with [ , increment_by ] ) ] - -.. _cet_parameters: - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``OR REPLACE`` - - Create a new table, and overwrite any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. - * - ``schema_name`` - - The name of the schema in which to create the table. - * - ``table_name`` - - The name of the table to create, which must be unique inside the schema. - * - ``column_def`` - - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. - * - ``USING FORMAT ...`` - - Specifies the format of the source files, such as ``PARQUET``, ``ORC``, or ``CSV``. - * - ``WITH PATH ...`` - - Specifies a path or URI of the source files, such as ``/path/to/*.parquet``. - * - ``FIELD DELIMITER`` - - Specifies the field delimiter for CSV files. Defaults to ``,``. - * - ``RECORD DELIMITER`` - - Specifies the record delimiter for CSV files. Defaults to a newline, ``\n`` - * - ``AWS_ID``, ``AWS_SECRET`` - - Credentials for authenticated S3 access - - -Examples -=========== - -A simple table from Tab-delimited file (TSV) ----------------------------------------------- - -.. code-block:: postgres - - CREATE OR REPLACE EXTERNAL TABLE cool_animals - (id INT NOT NULL, name VARCHAR(30) NOT NULL, weight FLOAT NOT NULL) - USING FORMAT csv - WITH PATH '/home/rhendricks/cool_animals.csv' - FIELD DELIMITER '\t'; - - -A table from a directory of Parquet files on HDFS ------------------------------------------------------ - -.. code-block:: postgres - - CREATE EXTERNAL TABLE users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) - USING FORMAT Parquet - WITH PATH 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet'; - -A table from a bucket of files on S3 --------------------------------------- - -.. code-block:: postgres - - CREATE EXTERNAL TABLE users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) - USING FORMAT Parquet - WITH PATH 's3://pp-secret-bucket/users/*.parquet' - AWS_ID 'our_aws_id' - AWS_SECRET 'our_aws_secret'; - - -Changing an external table to a regular table ------------------------------------------------- - -Materializes an external table into a regular table. - -.. tip: Using an external table allows you to perform ETL-like operations in SQream DB by applying SQL functions and operations to raw files - -.. code-block:: postgres - - CREATE TABLE real_table - AS SELECT * FROM external_table; - diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index d50e13380..09ebbe820 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -113,7 +113,7 @@ A simple table from Tab-delimited file (TSV) .. code-block:: postgres CREATE OR REPLACE FOREIGN TABLE cool_animals - (id INT NOT NULL, name VARCHAR(30) NOT NULL, weight FLOAT NOT NULL) + (id INT NOT NULL, name TEXT NOT NULL, weight FLOAT NOT NULL) WRAPPER csv_fdw OPTIONS ( LOCATION = '/home/rhendricks/cool_animals.csv', @@ -128,7 +128,7 @@ A table from a directory of Parquet files on HDFS .. code-block:: postgres CREATE FOREIGN TABLE users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name TEXT NOT NULL, email TEXT NOT NULL) WRAPPER parquet_fdw OPTIONS ( @@ -141,7 +141,7 @@ A table from a bucket of ORC files on S3 .. code-block:: postgres CREATE FOREIGN TABLE users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name TEXT NOT NULL, email TEXT NOT NULL) WRAPPER orc_fdw OPTIONS ( diff --git a/reference/sql/sql_statements/dml_commands/select.rst b/reference/sql/sql_statements/dml_commands/select.rst index f47ffaec1..c2d7bc786 100644 --- a/reference/sql/sql_statements/dml_commands/select.rst +++ b/reference/sql/sql_statements/dml_commands/select.rst @@ -163,14 +163,14 @@ Assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text, + Team text, Number tinyint, - Position varchar(2), + Position text, Age tinyint, - Height varchar(4), + Height text, Weight real, - College varchar(40), + College text, Salary float ); diff --git a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst index 1d972e61f..b5e0283d3 100644 --- a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst @@ -53,7 +53,7 @@ Notes * Query parameters can be used as substitutes for literal expressions. Parameters cannot be used to substitute identifiers, column names, table names, or other parts of the query. -* Query parameters of a string datatype (like ``VARCHAR``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc) +* Query parameters of a string datatype (like ``TEXT``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc) * Query parameters' types are inferred at compile time. @@ -66,14 +66,14 @@ Assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text, + Team text, Number tinyint, - Position varchar(2), + Position text, Age tinyint, - Height varchar(4), + Height text, Weight real, - College varchar(40), + College text, Salary float ); diff --git a/reference/sql/sql_statements/utility_commands/get_ddl.rst b/reference/sql/sql_statements/utility_commands/get_ddl.rst index f2566e99a..5afbab035 100644 --- a/reference/sql/sql_statements/utility_commands/get_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_ddl.rst @@ -55,7 +55,7 @@ The result of the ``GET_DDL`` function is a verbose version of the :ref:`create_ farm=> CREATE TABLE cool_animals ( id INT NOT NULL, - name varchar(30) NOT NULL, + name text NOT NULL, weight FLOAT, is_agressive BOOL DEFAULT false NOT NULL ); @@ -64,7 +64,7 @@ The result of the ``GET_DDL`` function is a verbose version of the :ref:`create_ farm=> SELECT GET_DDL('cool_animals'); create table "public"."cool_animals" ( "id" int not null, - "name" varchar(30) not null, + "name" text not null, "weight" double null, "is_agressive" bool default false not null ) ; diff --git a/reference/sql/sql_statements/utility_commands/save_query.rst b/reference/sql/sql_statements/utility_commands/save_query.rst index be34c33ed..079ce86b9 100644 --- a/reference/sql/sql_statements/utility_commands/save_query.rst +++ b/reference/sql/sql_statements/utility_commands/save_query.rst @@ -56,7 +56,7 @@ Notes * Query parameters can be used as substitutes for literal expressions. Parameters cannot be used to substitute identifiers, column names, table names, or other parts of the query. -* Query parameters of a string datatype (like ``VARCHAR``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc) +* Query parameters of a string datatype (like ``TEXT``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc) * Query parameters' types are inferred at compile time. @@ -70,14 +70,14 @@ Assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text, + Team text, Number tinyint, - Position varchar(2), + Position text, Age tinyint, - Height varchar(4), + Height text, Weight real, - College varchar(40), + College text, Salary float ); diff --git a/reference/sql/sql_syntax/subqueries.rst b/reference/sql/sql_syntax/subqueries.rst index 785b1f6df..921f69b50 100644 --- a/reference/sql/sql_syntax/subqueries.rst +++ b/reference/sql/sql_syntax/subqueries.rst @@ -24,14 +24,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/reference/sql/sql_syntax/window_functions.rst b/reference/sql/sql_syntax/window_functions.rst index cb87e085e..71fde1def 100644 --- a/reference/sql/sql_syntax/window_functions.rst +++ b/reference/sql/sql_syntax/window_functions.rst @@ -221,14 +221,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text, + "Team" text, "Number" tinyint, - "Position" varchar(2), + "Position" text, "Age" tinyint, - "Height" varchar(4), + "Height" text, "Weight" real, - "College" varchar(40), + "College" text, "Salary" float ); diff --git a/troubleshooting/log_related_issues.rst b/troubleshooting/log_related_issues.rst index a260f59d5..4b02957e4 100644 --- a/troubleshooting/log_related_issues.rst +++ b/troubleshooting/log_related_issues.rst @@ -18,7 +18,7 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas CREATE FOREIGN TABLE logs ( - start_marker VARCHAR(4), + start_marker TEXT, row_id BIGINT, timestamp DATETIME, message_level TEXT, @@ -32,7 +32,7 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas service_name TEXT, message_type_id INT, message TEXT, - end_message VARCHAR(5) + end_message TEXT ) WRAPPER csv_fdw OPTIONS From 623c36c353ba206d072a6f5ef99e80bd77b26592 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 19 Jun 2022 18:52:56 +0300 Subject: [PATCH 253/300] Replaced VARCHAR with TEXT --- configuration_guides/admin_regular_flags.rst | 3 +- .../current_configuration_method.rst | 16 +- data_ingestion/inserting_data.rst | 104 ++-- data_ingestion/nba-t10.csv | 19 +- .../converting_and_casting_types.rst | 2 +- data_type_guides/sql_data_types_date.rst | 2 +- .../sql_data_types_floating_point.rst | 2 +- data_type_guides/sql_data_types_integer.rst | 2 +- data_type_guides/supported_data_types.rst | 9 +- getting_started/creating_your_first_table.rst | 6 +- getting_started/getting_started.rst | 493 ------------------ operational_guides/saved_queries.rst | 2 +- .../seeing_system_objects_as_ddl.rst | 4 +- reference/cli/sqream_sql.rst | 4 +- .../conditionals/is_ascii.rst | 2 +- .../scalar_functions/conditionals/is_null.rst | 2 +- .../date_and_time/dateadd.rst | 2 +- .../date_and_time/datediff.rst | 2 +- .../date_and_time/datepart.rst | 2 +- .../date_and_time/eomonth.rst | 2 +- .../date_and_time/extract.rst | 2 +- .../scalar_functions/date_and_time/trunc.rst | 2 +- .../scalar_functions/string/char_length.rst | 2 +- .../scalar_functions/string/charindex.rst | 2 +- .../scalar_functions/string/isprefixof.rst | 2 +- .../scalar_functions/string/len.rst | 2 +- .../scalar_functions/string/lower.rst | 2 +- .../scalar_functions/string/nba-t10.csv | 19 +- .../scalar_functions/string/octet_length.rst | 2 +- .../scalar_functions/string/patindex.rst | 2 +- .../scalar_functions/string/replace.rst | 5 +- .../scalar_functions/string/trim.rst | 2 +- .../scalar_functions/string/upper.rst | 2 +- .../ddl_commands/create_function.rst | 2 +- .../ddl_commands/create_table.rst | 12 +- .../utility_commands/dump_database_ddl.rst | 2 +- reference/sql/sql_syntax/literals.rst | 3 +- reference/sql/sql_syntax/nba-t10.csv | 19 +- reference/sql_feature_support.rst | 136 ++--- ...ts_and_running_queries_from_the_editor.rst | 2 +- .../client_drivers/cpp/insert_test.cpp | 4 +- .../client_drivers/python/index.rst | 6 +- .../client_drivers/python/nba-t10.csv | 19 +- .../client_platforms/tibco_spotfire.rst | 2 +- 44 files changed, 212 insertions(+), 721 deletions(-) delete mode 100644 getting_started/getting_started.rst diff --git a/configuration_guides/admin_regular_flags.rst b/configuration_guides/admin_regular_flags.rst index 4818a7d6b..187d44df5 100644 --- a/configuration_guides/admin_regular_flags.rst +++ b/configuration_guides/admin_regular_flags.rst @@ -28,5 +28,4 @@ The **Regular Administration Flags** page describes **Regular** modification typ * `Setting Implicit Casts in ORC Files `_ * `Setting Timeout Limit for Locking Objects before Executing Statements `_ * `Interpreting Decimal Literals as Double Instead of Numeric `_ -* `Interpreting VARCHAR as TEXT `_ -* `VARCHAR Identifiers `_ \ No newline at end of file +* `Interpreting VARCHAR as TEXT ` \ No newline at end of file diff --git a/configuration_guides/current_configuration_method.rst b/configuration_guides/current_configuration_method.rst index d0d87e0b5..740dcd22e 100644 --- a/configuration_guides/current_configuration_method.rst +++ b/configuration_guides/current_configuration_method.rst @@ -72,8 +72,8 @@ SQream uses cluster-based configuration, enabling you to centralize configuratio For more information, see the following: -* `Using SQream SQL `_ - modifying flag attributes from the CLI. -* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. +* `Using SQream SQL `_ - modifying flag attributes from the CLI. +* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. For more information on flag-based access to cluster-based configuration, see **Configuration Flag Types** below. @@ -92,8 +92,8 @@ For example, when the query below has completed executing, the values configured For more information, see the following: -* `Using SQream SQL `_ - modifying flag attributes from the CLI. -* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. +* `Using SQream SQL `_ - modifying flag attributes from the CLI. +* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. Configuration Flag Types ========== @@ -624,8 +624,6 @@ The following table describes the **Generic** and **Administration** configurati - Interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. Used to preserve legacy behavior in existing customers. - boolean - ``FALSE`` - - Configuration Commands ========== @@ -698,8 +696,8 @@ Configuration Roles =========== SQream divides flags into the following roles, each with their own set of permissions: -* `Administration flags `_: can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command. -* `Generic flags `_: can be modified by standard users on a session basis. +* `Administration flags `_: can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command. +* `Generic flags `_: can be modified by standard users on a session basis. Showing All Flags in the Catalog Table ======= @@ -716,7 +714,7 @@ The following is an example of a catalog table query: .. code-block:: console externalTableBlobEstimate, 100, 100, default, - varcharEncoding, ascii, ascii, default, Changes the expected encoding for Varchar columns + textEncoding, ascii, ascii, default, Changes the expected encoding for Text columns useCrcForTextJoinKeys, true, true, default, hiveStyleImplicitStringCasts, false, false, default, diff --git a/data_ingestion/inserting_data.rst b/data_ingestion/inserting_data.rst index 660cd61bd..0f4c4afaa 100644 --- a/data_ingestion/inserting_data.rst +++ b/data_ingestion/inserting_data.rst @@ -53,7 +53,7 @@ SQream therefore recommends: * Applications such as :ref:`Tableau` and others have been tested, and work -* Data types were not over-provisioned (e.g. don't use VARCHAR(2000) to store a short string) +* Data types were not over-provisioned (e.g. don't use TEXT to store a short string) File Soure Location when Loading -------------------------------- @@ -78,27 +78,27 @@ SQream DB's :ref:`COPY FROM` syntax can be used to load CSV files, bu - ORC - Streaming data * - :ref:`copy_from` - - ✓ - - ✗ - - ✗ - - ✗ + - Supported + - Not supported + - Not supported + - Not supported * - :ref:`external_tables` - - ✓ - - ✓ - - ✓ - - ✗ + - Supported + - Supported + - Supported + - Not supported * - :ref:`insert` - - ✗ - - ✗ - - ✗ - - ✓ (Python, JDBC, Node.JS) + - Not supported + - Not supported + - Not supported + - Supported (Python, JDBC, Node.JS) Unsupported Data Types ----------------------------- SQream DB doesn't support the entire set of features that some other database systems may have, such as ``ARRAY``, ``BLOB``, ``ENUM``, ``SET``, etc. -These data types will have to be converted before load. For example, ``ENUM`` can often be stored as a ``VARCHAR``. +These data types will have to be converted before load. For example, ``ENUM`` can often be stored as a ``TEXT``. Handing Extended Errors ---------------------------- @@ -157,7 +157,7 @@ Type Support and Behavior Notes - ``DATE`` - ``DATETIME`` * - ``BOOLEAN`` - - ✓ + - Supported - - - @@ -170,7 +170,7 @@ Type Support and Behavior Notes * - ``INT16`` - - - - ✓ + - Supported - - - @@ -182,7 +182,7 @@ Type Support and Behavior Notes - - - - - ✓ + - Supported - - - @@ -194,7 +194,7 @@ Type Support and Behavior Notes - - - - - ✓ + - Supported - - - @@ -206,7 +206,7 @@ Type Support and Behavior Notes - - - - - ✓ + - Supported - - - @@ -218,7 +218,7 @@ Type Support and Behavior Notes - - - - - ✓ + - Supported - - - @@ -230,7 +230,7 @@ Type Support and Behavior Notes - - - - - ✓ + - Supported - - * - ``INT96`` [#f3]_ @@ -243,7 +243,7 @@ Type Support and Behavior Notes - - - - - ✓ [#f4]_ + - Supported [#f4]_ * If a Parquet file has an unsupported type like ``enum``, ``uuid``, ``time``, ``json``, ``bson``, ``lists``, ``maps``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query), the statement will succeed. If the column is referenced, an error will be thrown to the user, explaining that the type is not supported, but the column may be ommited. @@ -280,11 +280,11 @@ Type Support and Behavior Notes - ``DATE`` - ``DATETIME`` * - ``boolean`` - - ✓ - - ✓ [#f5]_ - - ✓ [#f5]_ - - ✓ [#f5]_ - - ✓ [#f5]_ + - Supported + - Supported [#f5]_ + - Supported [#f5]_ + - Supported [#f5]_ + - Supported [#f5]_ - - - @@ -292,10 +292,10 @@ Type Support and Behavior Notes - * - ``tinyint`` - ○ [#f6]_ - - ✓ - - ✓ - - ✓ - - ✓ + - Supported + - Supported + - Supported + - Supported - - - @@ -304,9 +304,9 @@ Type Support and Behavior Notes * - ``smallint`` - ○ [#f6]_ - ○ [#f7]_ - - ✓ - - ✓ - - ✓ + - Supported + - Supported + - Supported - - - @@ -316,8 +316,8 @@ Type Support and Behavior Notes - ○ [#f6]_ - ○ [#f7]_ - ○ [#f7]_ - - ✓ - - ✓ + - Supported + - Supported - - - @@ -328,7 +328,7 @@ Type Support and Behavior Notes - ○ [#f7]_ - ○ [#f7]_ - ○ [#f7]_ - - ✓ + - Supported - - - @@ -340,8 +340,8 @@ Type Support and Behavior Notes - - - - - ✓ - - ✓ + - Supported + - Supported - - - @@ -351,12 +351,12 @@ Type Support and Behavior Notes - - - - - ✓ - - ✓ + - Supported + - Supported - - - - * - ``string`` / ``char`` / ``varchar`` + * - ``string`` / ``char`` / ``text`` - - - @@ -364,7 +364,7 @@ Type Support and Behavior Notes - - - - - ✓ + - Supported - - * - ``date`` @@ -376,8 +376,8 @@ Type Support and Behavior Notes - - - - - ✓ - - ✓ + - Supported + - Supported * - ``timestamp``, ``timestamp`` with timezone - - @@ -388,7 +388,7 @@ Type Support and Behavior Notes - - - - - ✓ + - Supported * If an ORC file has an unsupported type like ``binary``, ``list``, ``map``, and ``union``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query), the statement will succeed. If the column is referenced, an error will be thrown to the user, explaining that the type is not supported, but the column may be ommited. @@ -459,16 +459,16 @@ Further Reading and Migration Guides .. rubric:: Footnotes -.. [#f0] Text values include ``TEXT``, ``VARCHAR``, and ``NVARCHAR`` +.. [#f0] Text values include ``TEXT``. -.. [#f2] With UTF8 annotation +.. [#f2] With UTF8 annotation. -.. [#f3] With ``TIMESTAMP_NANOS`` or ``TIMESTAMP_MILLIS`` annotation +.. [#f3] With ``TIMESTAMP_NANOS`` or ``TIMESTAMP_MILLIS`` annotation. .. [#f4] Any microseconds will be rounded down to milliseconds. -.. [#f5] Boolean values are cast to 0, 1 +.. [#f5] Boolean values are cast to 0, 1. -.. [#f6] Will succeed if all values are 0, 1 +.. [#f6] Will succeed if all values are 0, 1. -.. [#f7] Will succeed if all values fit the destination type +.. [#f7] Will succeed if all values fit the destination type. diff --git a/data_ingestion/nba-t10.csv b/data_ingestion/nba-t10.csv index 024530355..c3d41e729 100644 --- a/data_ingestion/nba-t10.csv +++ b/data_ingestion/nba-t10.csv @@ -1,10 +1,9 @@ -Name,Team,Number,Position,Age,Height,Weight,College,Salary -Avery Bradley,Boston Celtics,0.0,PG,25.0,6-2,180.0,Texas,7730337.0 -Jae Crowder,Boston Celtics,99.0,SF,25.0,6-6,235.0,Marquette,6796117.0 -John Holland,Boston Celtics,30.0,SG,27.0,6-5,205.0,Boston University, -R.J. Hunter,Boston Celtics,28.0,SG,22.0,6-5,185.0,Georgia State,1148640.0 -Jonas Jerebko,Boston Celtics,8.0,PF,29.0,6-10,231.0,,5000000.0 -Amir Johnson,Boston Celtics,90.0,PF,29.0,6-9,240.0,,12000000.0 -Jordan Mickey,Boston Celtics,55.0,PF,21.0,6-8,235.0,LSU,1170960.0 -Kelly Olynyk,Boston Celtics,41.0,C,25.0,7-0,238.0,Gonzaga,2165160.0 -Terry Rozier,Boston Celtics,12.0,PG,22.0,6-2,190.0,Louisville,1824360.0 +Avery Bradley,Boston Celtics,0,PG,25,2-Jun,180,Texas,7730337 +Jae Crowder,Boston Celtics,99,SF,25,6-Jun,235,Marquette,6796117 +John Holland,Boston Celtics,30,SG,27,5-Jun,205,Boston University, +R.J. Hunter,Boston Celtics,28,SG,22,5-Jun,185,Georgia State,1148640 +Jonas Jerebko,Boston Celtics,8,PF,29,10-Jun,231,,5000000 +Amir Johnson,Boston Celtics,90,PF,29,9-Jun,240,,12000000 +Jordan Mickey,Boston Celtics,55,PF,21,8-Jun,235,LSU,1170960 +Kelly Olynyk,Boston Celtics,41,C,25,Jul-00,238,Gonzaga,2165160 +Terry Rozier,Boston Celtics,12,PG,22,2-Jun,190,Louisville,1824360 diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index bb6475646..d6ae9cb4f 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -15,7 +15,7 @@ You can rectify this by casting the value to a larger data type, as shown below: SQream supports the following three data conversion types: -* ``CAST( TO )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO VARCHAR(30))``. +* ``CAST( TO )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO TEXT)``. :: diff --git a/data_type_guides/sql_data_types_date.rst b/data_type_guides/sql_data_types_date.rst index da83f80cc..88236c113 100644 --- a/data_type_guides/sql_data_types_date.rst +++ b/data_type_guides/sql_data_types_date.rst @@ -108,5 +108,5 @@ The following table shows the possible ``DATE`` and ``DATETIME`` value conversio * - Type - Details - * - ``VARCHAR(n)`` + * - ``TEXT`` - ``'1997-01-01'`` → ``'1997-01-01'``, ``'1955-11-05 01:24'`` → ``'1955-11-05 01:24:00.000'`` \ No newline at end of file diff --git a/data_type_guides/sql_data_types_floating_point.rst b/data_type_guides/sql_data_types_floating_point.rst index 18227140c..0c06df96f 100644 --- a/data_type_guides/sql_data_types_floating_point.rst +++ b/data_type_guides/sql_data_types_floating_point.rst @@ -74,7 +74,7 @@ The following table shows the possible Floating Point value conversions: - ``1.0`` → ``true``, ``0.0`` → ``false`` * - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT`` - ``2.0`` → ``2``, ``3.14159265358979`` → ``3``, ``2.718281828459`` → ``2``, ``0.5`` → ``0``, ``1.5`` → ``1`` - * - ``VARCHAR(n)`` (n > 6 recommended) + * - ``TEXT(n)`` (n > 6 recommended) - ``1`` → ``'1.0000'``, ``3.14159265358979`` → ``'3.1416'`` .. note:: As shown in the above examples, casting ``real`` to ``int`` rounds down. \ No newline at end of file diff --git a/data_type_guides/sql_data_types_integer.rst b/data_type_guides/sql_data_types_integer.rst index 9d4210731..213b50d42 100644 --- a/data_type_guides/sql_data_types_integer.rst +++ b/data_type_guides/sql_data_types_integer.rst @@ -79,5 +79,5 @@ The following table shows the possible Integer value conversions: - Details * - ``REAL``, ``DOUBLE`` - ``1`` → ``1.0``, ``-32`` → ``-32.0`` - * - ``VARCHAR(n)`` (All numberic values must fit in the string length) + * - ``TEXT`` (All numeric values must fit in the string length) - ``1`` → ``'1'``, ``2451`` → ``'2451'`` \ No newline at end of file diff --git a/data_type_guides/supported_data_types.rst b/data_type_guides/supported_data_types.rst index 2743b054b..3f88cdbfa 100644 --- a/data_type_guides/supported_data_types.rst +++ b/data_type_guides/supported_data_types.rst @@ -51,21 +51,16 @@ The following table shows the supported data types. - 8 bytes - ``0.000003`` - ``FLOAT``/``DOUBLE PRECISION`` - * - ``TEXT [(n)]``, ``NVARCHAR (n)`` + * - ``TEXT [(n)]`` - Variable length string - UTF-8 unicode - Up to ``4*n`` bytes - ``'キウイは楽しい鳥です'`` - - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR``, ``NVARCHAR`` + - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR``, ``TEXT`` * - ``NUMERIC`` - 38 digits - 16 bytes - ``0.123245678901234567890123456789012345678`` - ``DECIMAL`` - * - ``VARCHAR (n)`` - - Variable length string - ASCII only - - ``n`` bytes - - ``'Kiwis have tiny wings, but cannot fly.'`` - - ``SQL VARIANT`` * - ``DATE`` - Date - 4 bytes diff --git a/getting_started/creating_your_first_table.rst b/getting_started/creating_your_first_table.rst index c070b43ed..ee790444b 100644 --- a/getting_started/creating_your_first_table.rst +++ b/getting_started/creating_your_first_table.rst @@ -21,7 +21,7 @@ The ``CREATE TABLE`` syntax is used to create your first table. This table inclu CREATE TABLE cool_animals ( id INT NOT NULL, - name VARCHAR(20), + name TEXT, weight INT ); @@ -37,7 +37,7 @@ You can drop an existing table and create a new one by adding the ``OR REPLACE`` CREATE OR REPLACE TABLE cool_animals ( id INT NOT NULL, - name VARCHAR(20), + name TEXT, weight INT ); @@ -54,7 +54,7 @@ You can list the full, verbose ``CREATE TABLE`` statement for a table by using t test=> SELECT GET_DDL('cool_animals'); create table "public"."cool_animals" ( "id" int not null, - "name" varchar(20), + "name" text, "weight" int ); diff --git a/getting_started/getting_started.rst b/getting_started/getting_started.rst deleted file mode 100644 index b9cc2f894..000000000 --- a/getting_started/getting_started.rst +++ /dev/null @@ -1,493 +0,0 @@ -.. _first_steps: - -**************************** -Getting Started -**************************** - -The **Getting Started** page describes the following: - -.. contents:: - :local: - :depth: 1 - -Before Installing SQream -============================ -Before installing SQream, do the following: - - * Set up your local machine according to SQream's recommended pre-installation configurations. - - :: - - * Verify you have an NVIDIA-capable server, either on-premise or on supported cloud platforms: - - * Red Hat Enterprise Linux v7.x - - - * CentOS v7.x - - - * Ubuntu 18.04 - - - * Amazon Linux - - * Verify that you have the following: - - * An NVIDIA GPU - SQream recommends using a Tesla GPU. - - - * An SSH connection to your server. - - - * SUDO permissions for installation and configuration purposes. - - - * A SQream license - Contact support@sqream.com or your SQream account manager for your license key. -For more information, see the following: - -* :ref:`recommended_pre-installation_configurations` -* :ref:`Hardware Guide` - - - - - - - -Installing SQream -============================ -The **Installing SQream** section includes the following SQream installation methods: - -* `Installing SQream natively `_ - Describes installing SQream using binary packages provided by SQream. -* `Installing SQream with Kubernetes `_ - Describes installing SQream using the Kubernetes open source platform. -* `Installing and running SQream in a Docker container `_ - Describes how to run SQream in a Docker container. - -Using the SQream SQL Command Line Interface -============================================ -SQream includes a built-in client for executing SQL statements either interactively or using the Command Line Interface (CLI). The **SQream SQL CLI Reference** page provides a reference for the options and parameters. - -For more information, see `SQream SQL CLI Reference `_. - -Performing Basic SQream Operations -==================================== -After installing SQream you can perform the operations described in the **Performing Basic SQream Operations** section: - -.. contents:: - :local: - :depth: 1 - - -Running the SQream SQL Client ---------------------------------- -The following example shows how to run the SQream SQL client: - -.. code-block:: psql - - $ sqream sql --port=5000 --username=rhendricks -d master - Password: - - Interactive client mode - To quit, use ^D or \q. - - master=> _ - -Running the SQream SQL client prompts you to provide your password. Use the username and password that you have set up, or your DBA has provided. - -.. tip:: - * You can exit the shell by typing ``\q`` or :kbd:`Ctrl-d`. - * A new SQream cluster contains a database named `master,` which is the database used in the examples on this page. - -Creating a New Database --------------------------- -**To create a new database:** - -1. Write a :ref:`create_database` statement. - - The following is an example of creating a new database: - - .. code-block:: psql - - master=> CREATE DATABASE test; - executed - -2. Reconnect to the newly created database. - - 1. Exit the client by typing ``\q`` and pressing **Enter**. - 2. From the Linux shell, restart the client with the new database name: - - .. code-block:: psql - - $ sqream sql --port=5000 --username=rhendricks -d test - Password: - - Interactive client mode - To quit, use ^D or \q. - - test=> _ - - The name of the new database that you are connected to is displayed in the prompt. - -Creating Your First Table ------------------------------- -The **Creating Your First Table** section describes the following: - -* :ref:`Creating a table` -* :ref:`Replacing a table` -* :ref:`Listing a CREATE TABLE statement` -* :ref:`Dropping a table` - - -.. _creating_a_table: - -**Creating a Table** - -The ``CREATE TABLE`` syntax is used to create your first table. This table includes a table name and column specifications, as shown in the following example: - -.. code-block:: postgres - - CREATE TABLE cool_animals ( - id INT NOT NULL, - name VARCHAR(20), - weight INT - ); - -For more information on creating a table, see :ref:`create_table`. - -.. _replacing_a_table: - -**Replacing a Table** - -You can drop an existing table and create a new one by adding the ``OR REPLACE`` parameter after the ``CREATE`` keyword, as shown in the following example: - -.. code-block:: postgres - - CREATE OR REPLACE TABLE cool_animals ( - id INT NOT NULL, - name VARCHAR(20), - weight INT - ); - -.. TODO: cool_animals? I think we need to decide if the customer for this documenation is 12 years old, or an IT professional. - -.. _listing_a_create_table_statement: - -**Listing a CREATE TABLE Statement** - -You can list the full, verbose ``CREATE TABLE`` statement for a table by using the **GET DDL** function with the table name as shown in the following example: - -.. code-block:: psql - - test=> SELECT GET_DDL('cool_animals'); - create table "public"."cool_animals" ( - "id" int not null, - "name" varchar(20), - "weight" int - ); - -.. note:: - - * SQream DB identifier names such as table names and column names are not case sensitive. SQream DB lowercases all identifiers bu default. If you want to maintain case, enclose the identifiers with double-quotes. - * SQream DB places all tables in the `public` schema, unless another schema is created and specified as part of the table name. - -For information on listing a ``CREATE TABLE`` statement, see :ref:`get_ddl`. - -.. _dropping_a_table: - -**Dropping a Table** - -When you have finished working with your table, you can drop the table to remove it table and its content, as shown in the following example: - -.. code-block:: psql - - test=> DROP TABLE cool_animals; - - executed - -For more information on dropping tables, see :ref:`drop_table`. - -Listing Tables ------------------- -To see the tables in the current database you can query the catalog, as shown in the following example: - -.. code-block:: psql - - test=> SELECT table_name FROM sqream_catalog.tables; - cool_animals - - 1 rows - -Inserting Rows -------------------- -The **Inserting Rows** section describes the following: - -* :ref:`Inserting basic rows` -* :ref:`Changing value order` -* :ref:`Inserting multiple rows` -* :ref:`Omitting columns` - - -.. _inserting_basic_rows: - -**Inserting Basic Rows** - -You can insert basic rows into a table using the ``INSERT`` statement. The inserted statement includes the table name, an optional list of column names, and column values listed in the same order as the column names, as shown in the following example: - -.. code-block:: psql - - test=> INSERT INTO cool_animals VALUES (1, 'Dog', 7); - - executed - -.. _changing_value_order: - -**Changing Value Order** - -You can change the order of values by specifying the column order, as shown in the following example: - -.. code-block:: psql - - test=> INSERT INTO cool_animals(weight, id, name) VALUES (3, 2, 'Possum'); - - executed - -.. _inserting_multiple_rows: - -**Inserting Multiple Rows** - -You can insert multiple rows using the ``INSERT`` statement by using sets of parentheses separated by commas, as shown in the following example: - -.. code-block:: psql - - test=> INSERT INTO cool_animals VALUES - (3, 'Cat', 5) , - (4, 'Elephant', 6500) , - (5, 'Rhinoceros', 2100); - - executed - -.. note:: You can load large data sets using bulk loading methods instead. For more information, see :ref:`inserting_data`. - -.. _omitting_columns: - -**Omitting Columns** - -Omitting columns that have a default values (including default ``NULL`` values) uses the default value, as shown in the following example: - -.. code-block:: psql - - test=> INSERT INTO cool_animals (id) VALUES (6); - - executed - -.. code-block:: psql - - test=> INSERT INTO cool_animals (id) VALUES (6); - - executed - test=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N - - 6 rows - -.. note:: Null row values are represented as ``\N`` - -For more information on inserting rows, see :ref:`insert`. - -For more information on default values, see :ref:`default value`. - - -Running Queries ------------------- -The **Running Queries** section describes the following: - -* :ref:`Running basic queries` -* :ref:`Outputting all columns` -* :ref:`Outputting shorthand table values` -* :ref:`Filtering results` -* :ref:`Sorting results` -* :ref:`Filtering null rows` - - -.. _running_basic_queries: - -**Running Basic Queries** - -You can run a basic query using the ``SELECT`` keyword, followed by a list of columns and values to be returned, and the table to get the data from, as shown in the following example: - -.. code-block:: psql - - test=> SELECT id, name, weight FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N - - 6 rows - -For more information on the ``SELECT`` keyword, see :ref:`select`. - -.. _outputting_all_columns: - -**To Output All Columns** - -You can output all columns without specifying them using the star operator ``*``, as shown in the following example: - -.. code-block:: psql - - test=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N - - 6 rows - -.. _outputting_shorthand_table_values: - -**Outputting Shorthand Table Values** - -You can output the number of values in a table without getting the full result set by using the ``COUNT`` statement: - -.. code-block:: psql - - test=> SELECT COUNT(*) FROM cool_animals; - 6 - - 1 row - -.. _filtering_results: - -**Filtering Results** - -You can filter results by adding a ``WHERE`` clause and specifying the filter condition, as shown in the following example: - -.. code-block:: psql - - test=> SELECT id, name, weight FROM cool_animals WHERE weight > 1000; - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - - 2 rows - -.. _sorting_results: - -**Sorting Results** - -You can sort results by adding an ``ORDER BY`` clause and specifying ascending (``ASC``) or descending (``DESC``) order, as shown in the following example: - -.. code-block:: psql - - test=> SELECT * FROM cool_animals ORDER BY weight DESC; - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 1,Dog ,7 - 3,Cat ,5 - 2,Possum ,3 - 6,\N,\N - - 6 rows - -.. _filtering_null_rows: - -**Filtering Null Rows** - -You can filter null rows by adding an ``IS NOT NULL`` filter, as shown in the following example: - -.. code-block:: psql - - test=> SELECT * FROM cool_animals WHERE weight IS NOT NULL ORDER BY weight DESC; - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 1,Dog ,7 - 3,Cat ,5 - 2,Possum ,3 - - 5 rows - -For more information, see the following: - -* Outputting the number of values in a table without getting the full result set - :ref:`COUNT(*)`. -* Filtering results - :ref:`WHERE` -* Sorting results - :ref:`ORDER BY` -* Filtering rows - :ref:`IS NOT NULL` - - - -Deleting Rows ------------------ -The **Deleting Rows** section describes the following: - -* :ref:`Deleting selected rows` -* :ref:`Deleting all rows` - -.. _deleting_selected_rows: - -**Deleting Selected Rows** - -You can delete rows in a table selectively using the ``DELETE`` command. You must include a table name and `WHERE` clause to specify the rows to delete, as shown in the following example: - -.. code-block:: psql - - test=> DELETE FROM cool_animals WHERE weight is null; - - executed - master=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - - 5 rows - -.. _deleting_all_rows: - -**Deleting All Rows** - -You can delete all rows in a table using the ``TRUNCATE`` command followed by the table name, as shown in the following example: - -.. code-block:: psql - - test=> TRUNCATE TABLE cool_animals; - - executed - -.. note:: While :ref:`truncate` deletes data from disk immediately, :ref:`delete` does not physically remove the deleted rows. - -For more information, see the following: - -* Deleting selected rows - :ref:`DELETE` -* Deleting all rows - :ref:`TRUNCATE` - -Saving Query Results to a CSV or PSV File --------------------------------------------- - - -You can save query results to a CSV or PSV file using the ``sqream sql`` command from a CLI client. This saves your query results to the selected delimited file format, as shown in the following example: - -.. code-block:: console - - $ sqream sql --username=mjordan --database=nba --host=localhost --port=5000 -c "SELECT * FROM nba LIMIT 5" --results-only --delimiter='|' > nba.psv - $ cat nba.psv - Avery Bradley |Boston Celtics |0|PG|25|6-2 |180|Texas |7730337 - Jae Crowder |Boston Celtics |99|SF|25|6-6 |235|Marquette |6796117 - John Holland |Boston Celtics |30|SG|27|6-5 |205|Boston University |\N - R.J. Hunter |Boston Celtics |28|SG|22|6-5 |185|Georgia State |1148640 - Jonas Jerebko |Boston Celtics |8|PF|29|6-10|231|\N|5000000 - -For more output options, see :ref:`Controlling the Client Output`. - -.. rubric:: What's next? - -* Explore all of SQream DB's :ref:`SQL Syntax `. -* See the full :ref:`SQream SQL CLI reference `. -* Connect a :ref:`third party tool ` to start analyzing data. diff --git a/operational_guides/saved_queries.rst b/operational_guides/saved_queries.rst index d554b4dc8..fb36ac481 100644 --- a/operational_guides/saved_queries.rst +++ b/operational_guides/saved_queries.rst @@ -18,7 +18,7 @@ Query parameters can be used as substitutes for literal expressions in queries. * Parameters cannot be used to substitute things like column names and table names. -* Query parameters of a string datatype (like ``VARCHAR``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc.) +* Query parameters of a string datatype (like ``TEXT``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc.) Creating a saved query ====================== diff --git a/operational_guides/seeing_system_objects_as_ddl.rst b/operational_guides/seeing_system_objects_as_ddl.rst index fc8ff3b83..06caeca72 100644 --- a/operational_guides/seeing_system_objects_as_ddl.rst +++ b/operational_guides/seeing_system_objects_as_ddl.rst @@ -22,7 +22,7 @@ Getting the DDL for a table farm=> SELECT GET_DDL('cool_animals'); create table "public"."cool_animals" ( "id" int not null, - "name" varchar(30) not null, + "name" text not null, "weight" double null, "is_agressive" bool default false not null ) ; @@ -142,7 +142,7 @@ Exporting database DDL to a client farm=> SELECT DUMP_DATABASE_DDL(); create table "public"."cool_animals" ( "id" int not null, - "name" varchar(30) not null, + "name" text not null, "weight" double null, "is_agressive" bool default false not null ) diff --git a/reference/cli/sqream_sql.rst b/reference/cli/sqream_sql.rst index 9273b4252..f759b921d 100644 --- a/reference/cli/sqream_sql.rst +++ b/reference/cli/sqream_sql.rst @@ -222,7 +222,7 @@ Creating a new database and switching over to it without reconnecting: .. code-block:: psql - farm=> create table animals(id int not null, name varchar(30) not null, is_angry bool not null); + farm=> create table animals(id int not null, name text not null, is_angry bool not null); executed time: 0.011940s @@ -300,7 +300,7 @@ Assuming a file containing SQL statements (separated by semicolons): $ cat some_queries.sql CREATE TABLE calm_farm_animals - ( id INT IDENTITY(0, 1), name VARCHAR(30) + ( id INT IDENTITY(0, 1), name TEXT ); INSERT INTO calm_farm_animals (name) diff --git a/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst b/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst index bb9e3b2f9..79ff6d3bb 100644 --- a/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst +++ b/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst @@ -45,7 +45,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE dictionary (id INT NOT NULL, fw TEXT(30), en VARCHAR(30)); + CREATE TABLE dictionary (id INT NOT NULL, fw TEXT, en TEXT); INSERT INTO dictionary VALUES (1, '行こう', 'Let''s go'), (2, '乾杯', 'Cheers'), (3, 'L''chaim', 'Cheers'); diff --git a/reference/sql/sql_functions/scalar_functions/conditionals/is_null.rst b/reference/sql/sql_functions/scalar_functions/conditionals/is_null.rst index c99f4e7d1..ee17b6e7b 100644 --- a/reference/sql/sql_functions/scalar_functions/conditionals/is_null.rst +++ b/reference/sql/sql_functions/scalar_functions/conditionals/is_null.rst @@ -40,7 +40,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE t (id INT NOT NULL, name VARCHAR(30), weight INT); + CREATE TABLE t (id INT NOT NULL, name TEXT, weight INT); INSERT INTO t VALUES (1, 'Kangaroo', 120), (2, 'Koala', 20), (3, 'Wombat', 60) ,(4, 'Kappa', NULL),(5, 'Echidna', 8),(6, 'Chupacabra', NULL) diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst index cff5268e6..7d8623499 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst @@ -106,7 +106,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); + CREATE TABLE cool_dates(name TEXT, d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst index 5c91a88d9..6a1db9d9e 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst @@ -100,7 +100,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); + CREATE TABLE cool_dates(name TEXT, d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst index 8a43a1472..74296e159 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst @@ -109,7 +109,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); + CREATE TABLE cool_dates(name TEXT, d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst index 92e3f7940..56454da9c 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst @@ -48,7 +48,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); + CREATE TABLE cool_dates(name TEXT, d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst index 2fd79ca86..6a1c72a49 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst @@ -86,7 +86,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); + CREATE TABLE cool_dates(name TEXT, d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst index d9d791cc3..df4961919 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst @@ -104,7 +104,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); + CREATE TABLE cool_dates(name TEXT, d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/string/char_length.rst b/reference/sql/sql_functions/scalar_functions/string/char_length.rst index f89c397ab..556b88834 100644 --- a/reference/sql/sql_functions/scalar_functions/string/char_length.rst +++ b/reference/sql/sql_functions/scalar_functions/string/char_length.rst @@ -12,7 +12,7 @@ Calculates the number of characters in a string. * To get the length in bytes, see :ref:`octet_length`. - * For ``VARCHAR`` strings, the octet length is the number of characters. Use :ref:`len` instead. + * For ``TEXT`` strings, the octet length is the number of characters. Use :ref:`len` instead. Syntax ========== diff --git a/reference/sql/sql_functions/scalar_functions/string/charindex.rst b/reference/sql/sql_functions/scalar_functions/string/charindex.rst index fa9c89027..25edb1858 100644 --- a/reference/sql/sql_functions/scalar_functions/string/charindex.rst +++ b/reference/sql/sql_functions/scalar_functions/string/charindex.rst @@ -49,7 +49,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line VARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') diff --git a/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst b/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst index 4a978b1ff..989528fec 100644 --- a/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst +++ b/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst @@ -50,7 +50,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line VARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') diff --git a/reference/sql/sql_functions/scalar_functions/string/len.rst b/reference/sql/sql_functions/scalar_functions/string/len.rst index d3cba24b2..1e54f2465 100644 --- a/reference/sql/sql_functions/scalar_functions/string/len.rst +++ b/reference/sql/sql_functions/scalar_functions/string/len.rst @@ -49,7 +49,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line VARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT); INSERT INTO jabberwocky VALUES ($$'Twas brillig, and the slithy toves$$), (' Did gyre and gimble in the wabe:') diff --git a/reference/sql/sql_functions/scalar_functions/string/lower.rst b/reference/sql/sql_functions/scalar_functions/string/lower.rst index 69dfd4f1a..e6ff2e8a3 100644 --- a/reference/sql/sql_functions/scalar_functions/string/lower.rst +++ b/reference/sql/sql_functions/scalar_functions/string/lower.rst @@ -45,7 +45,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line VARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves'), (' Did gyre and gimble in the wabe:') diff --git a/reference/sql/sql_functions/scalar_functions/string/nba-t10.csv b/reference/sql/sql_functions/scalar_functions/string/nba-t10.csv index 024530355..c3d41e729 100644 --- a/reference/sql/sql_functions/scalar_functions/string/nba-t10.csv +++ b/reference/sql/sql_functions/scalar_functions/string/nba-t10.csv @@ -1,10 +1,9 @@ -Name,Team,Number,Position,Age,Height,Weight,College,Salary -Avery Bradley,Boston Celtics,0.0,PG,25.0,6-2,180.0,Texas,7730337.0 -Jae Crowder,Boston Celtics,99.0,SF,25.0,6-6,235.0,Marquette,6796117.0 -John Holland,Boston Celtics,30.0,SG,27.0,6-5,205.0,Boston University, -R.J. Hunter,Boston Celtics,28.0,SG,22.0,6-5,185.0,Georgia State,1148640.0 -Jonas Jerebko,Boston Celtics,8.0,PF,29.0,6-10,231.0,,5000000.0 -Amir Johnson,Boston Celtics,90.0,PF,29.0,6-9,240.0,,12000000.0 -Jordan Mickey,Boston Celtics,55.0,PF,21.0,6-8,235.0,LSU,1170960.0 -Kelly Olynyk,Boston Celtics,41.0,C,25.0,7-0,238.0,Gonzaga,2165160.0 -Terry Rozier,Boston Celtics,12.0,PG,22.0,6-2,190.0,Louisville,1824360.0 +Avery Bradley,Boston Celtics,0,PG,25,2-Jun,180,Texas,7730337 +Jae Crowder,Boston Celtics,99,SF,25,6-Jun,235,Marquette,6796117 +John Holland,Boston Celtics,30,SG,27,5-Jun,205,Boston University, +R.J. Hunter,Boston Celtics,28,SG,22,5-Jun,185,Georgia State,1148640 +Jonas Jerebko,Boston Celtics,8,PF,29,10-Jun,231,,5000000 +Amir Johnson,Boston Celtics,90,PF,29,9-Jun,240,,12000000 +Jordan Mickey,Boston Celtics,55,PF,21,8-Jun,235,LSU,1170960 +Kelly Olynyk,Boston Celtics,41,C,25,Jul-00,238,Gonzaga,2165160 +Terry Rozier,Boston Celtics,12,PG,22,2-Jun,190,Louisville,1824360 diff --git a/reference/sql/sql_functions/scalar_functions/string/octet_length.rst b/reference/sql/sql_functions/scalar_functions/string/octet_length.rst index 8bb1e3daf..22516ce39 100644 --- a/reference/sql/sql_functions/scalar_functions/string/octet_length.rst +++ b/reference/sql/sql_functions/scalar_functions/string/octet_length.rst @@ -12,7 +12,7 @@ Calculates the number of bytes in a string. * To get the length in characters, see :ref:`char_length`. - * For ``VARCHAR`` strings, the octet length is the number of characters. Use :ref:`len` instead. + * For ``TEXT`` strings, the octet length is the number of characters. Use :ref:`len` instead. Syntax ========== diff --git a/reference/sql/sql_functions/scalar_functions/string/patindex.rst b/reference/sql/sql_functions/scalar_functions/string/patindex.rst index 7e2ce8f79..4a4e7208e 100644 --- a/reference/sql/sql_functions/scalar_functions/string/patindex.rst +++ b/reference/sql/sql_functions/scalar_functions/string/patindex.rst @@ -69,7 +69,7 @@ Notes * If the value is NULL, the result is NULL. -* PATINDEX works on ``VARCHAR`` text types only. +* PATINDEX works on ``TEXT`` text types only. * PATINDEX does not work on all literal values - only on column values. diff --git a/reference/sql/sql_functions/scalar_functions/string/replace.rst b/reference/sql/sql_functions/scalar_functions/string/replace.rst index 5552be269..11b3fb643 100644 --- a/reference/sql/sql_functions/scalar_functions/string/replace.rst +++ b/reference/sql/sql_functions/scalar_functions/string/replace.rst @@ -6,9 +6,6 @@ REPLACE Replaces all occurrences of a specified string value with another string value. -.. warning:: With ``VARCHAR``, a substring can only be replaced with another substring of equal **byte length**. See :ref:`octet_length`. - - Syntax ========== @@ -40,7 +37,7 @@ Returns the same type as the argument supplied. Notes ======= -* In ``VARCHAR`` strings, the ``source_expr`` and ``replacement_expr`` must be the same **byte length**. See :ref:`octet_length`. +* In ``TEXT`` strings, the ``source_expr`` and ``replacement_expr`` must be the same **byte length**. See :ref:`octet_length`. * If the value is NULL, the result is NULL. diff --git a/reference/sql/sql_functions/scalar_functions/string/trim.rst b/reference/sql/sql_functions/scalar_functions/string/trim.rst index d6e90c2f8..d249c8952 100644 --- a/reference/sql/sql_functions/scalar_functions/string/trim.rst +++ b/reference/sql/sql_functions/scalar_functions/string/trim.rst @@ -35,7 +35,7 @@ Returns the same type as the argument supplied. Notes ======= -* When using ``VARCHAR`` values, SQream DB automatically trims the trailing whitespace. +* When using ``TEXT`` values, SQream DB automatically trims the trailing whitespace. * This function is equivalent to the ANSI form ``TRIM( BOTH FROM expr )`` diff --git a/reference/sql/sql_functions/scalar_functions/string/upper.rst b/reference/sql/sql_functions/scalar_functions/string/upper.rst index 219bc854e..d2b700144 100644 --- a/reference/sql/sql_functions/scalar_functions/string/upper.rst +++ b/reference/sql/sql_functions/scalar_functions/string/upper.rst @@ -45,7 +45,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line VARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves'), (' Did gyre and gimble in the wabe:') diff --git a/reference/sql/sql_statements/ddl_commands/create_function.rst b/reference/sql/sql_statements/ddl_commands/create_function.rst index 339543a0a..a693fc897 100644 --- a/reference/sql/sql_statements/ddl_commands/create_function.rst +++ b/reference/sql/sql_statements/ddl_commands/create_function.rst @@ -52,7 +52,7 @@ Parameters * - ``argument_list`` - A comma separated list of column definitions. A column definition includes a name identifier and a datatype. * - ``return_type`` - - The SQL datatype of the return value, such as ``INT``, ``VARCHAR``, etc. + - The SQL datatype of the return value, such as ``INT``, ``TEXT``, etc. * - ``function_body`` - Python code, dollar-quoted (``$$``). diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index 9000e8310..a96cffe5c 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -140,7 +140,7 @@ The following is an example of the syntax used to create a standard table: CREATE TABLE cool_animals ( id INT NOT NULL, - name varchar(30) NOT NULL, + name text NOT NULL, weight FLOAT, is_agressive BOOL ); @@ -154,7 +154,7 @@ The following is an example of the syntax used to create a table with default va CREATE TABLE cool_animals ( id INT NOT NULL, - name varchar(30) NOT NULL, + name text NOT NULL, weight FLOAT, is_agressive BOOL DEFAULT false NOT NULL ); @@ -170,8 +170,8 @@ The following is an example of the syntax used to create a table with an identit CREATE TABLE users ( id BIGINT IDENTITY(0,1) NOT NULL , -- Start with 0, increment by 1 - name VARCHAR(30) NOT NULL, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL + name TEXT NOT NULL, + country TEXT DEFAULT 'Unknown' NOT NULL ); .. note:: @@ -202,9 +202,9 @@ The following is an example of the syntax used to create a table with a clusteri .. code-block:: postgres CREATE TABLE users ( - name VARCHAR(30) NOT NULL, + name TEXT NOT NULL, start_date datetime not null, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL + country TEXT DEFAULT 'Unknown' NOT NULL ) CLUSTER BY start_date; For more information on data clustering, see :ref:`data_clustering`. diff --git a/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst b/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst index bf246b803..0fe995d36 100644 --- a/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst @@ -51,7 +51,7 @@ Getting the DDL for a database farm=> SELECT DUMP_DATABASE_DDL(); create table "public"."cool_animals" ( "id" int not null, - "name" varchar(30) not null, + "name" text not null, "weight" double null, "is_agressive" bool default false not null ) diff --git a/reference/sql/sql_syntax/literals.rst b/reference/sql/sql_syntax/literals.rst index 5ec0e6512..503bec57e 100644 --- a/reference/sql/sql_syntax/literals.rst +++ b/reference/sql/sql_syntax/literals.rst @@ -81,7 +81,7 @@ Examples '1997-01-01' -- This is a string -The actual data type of the value changes based on context, the format used, and the value itself. In the example below, the first value is interpreted as a ``DATE``, while the second is interpreted as a ``VARCHAR``. +The actual data type of the value changes based on context, the format used, and the value itself. In the example below, the first value is interpreted as a ``DATE``, while the second is interpreted as ``TEXT``. .. code-block:: postgres @@ -127,7 +127,6 @@ Syntax reference | REAL | DATE | DATETIME - | VARCHAR ( digits ) | TEXT ( digits ) Examples diff --git a/reference/sql/sql_syntax/nba-t10.csv b/reference/sql/sql_syntax/nba-t10.csv index 024530355..c3d41e729 100644 --- a/reference/sql/sql_syntax/nba-t10.csv +++ b/reference/sql/sql_syntax/nba-t10.csv @@ -1,10 +1,9 @@ -Name,Team,Number,Position,Age,Height,Weight,College,Salary -Avery Bradley,Boston Celtics,0.0,PG,25.0,6-2,180.0,Texas,7730337.0 -Jae Crowder,Boston Celtics,99.0,SF,25.0,6-6,235.0,Marquette,6796117.0 -John Holland,Boston Celtics,30.0,SG,27.0,6-5,205.0,Boston University, -R.J. Hunter,Boston Celtics,28.0,SG,22.0,6-5,185.0,Georgia State,1148640.0 -Jonas Jerebko,Boston Celtics,8.0,PF,29.0,6-10,231.0,,5000000.0 -Amir Johnson,Boston Celtics,90.0,PF,29.0,6-9,240.0,,12000000.0 -Jordan Mickey,Boston Celtics,55.0,PF,21.0,6-8,235.0,LSU,1170960.0 -Kelly Olynyk,Boston Celtics,41.0,C,25.0,7-0,238.0,Gonzaga,2165160.0 -Terry Rozier,Boston Celtics,12.0,PG,22.0,6-2,190.0,Louisville,1824360.0 +Avery Bradley,Boston Celtics,0,PG,25,2-Jun,180,Texas,7730337 +Jae Crowder,Boston Celtics,99,SF,25,6-Jun,235,Marquette,6796117 +John Holland,Boston Celtics,30,SG,27,5-Jun,205,Boston University, +R.J. Hunter,Boston Celtics,28,SG,22,5-Jun,185,Georgia State,1148640 +Jonas Jerebko,Boston Celtics,8,PF,29,10-Jun,231,,5000000 +Amir Johnson,Boston Celtics,90,PF,29,9-Jun,240,,12000000 +Jordan Mickey,Boston Celtics,55,PF,21,8-Jun,235,LSU,1170960 +Kelly Olynyk,Boston Celtics,41,C,25,Jul-00,238,Gonzaga,2165160 +Terry Rozier,Boston Celtics,12,PG,22,2-Jun,190,Louisville,1824360 diff --git a/reference/sql_feature_support.rst b/reference/sql_feature_support.rst index ba4ca39e4..5c0817e10 100644 --- a/reference/sql_feature_support.rst +++ b/reference/sql_feature_support.rst @@ -24,46 +24,46 @@ Read more about :ref:`supported data types`. - Supported - Further information * - ``BOOL`` - - ✓ + - Yes - Boolean values * - ``TINTINT`` - - ✓ + - Yes - Unsigned 1 byte integer (0 - 255) * - ``SMALLINT`` - - ✓ + - Yes - 2 byte integer (-32,768 - 32,767) * - ``INT`` - - ✓ + - Yes - 4 byte integer (-2,147,483,648 - 2,147,483,647) * - ``BIGINT`` - - ✓ + - Yes - 8 byte integer (-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807) * - ``REAL`` - - ✓ + - Yes - 4 byte floating point * - ``DOUBLE``, ``FLOAT`` - - ✓ + - Yes - 8 byte floating point * - ``DECIMAL``, ``NUMERIC`` - - ✓ + - Yes - Fixed-point numbers. - * - ``VARCHAR`` - - ✓ + * - ``TEXT`` + - Yes - Variable length string - ASCII only * - ``TEXT`` - - ✓ + - Yes - Variable length string - UTF-8 encoded * - ``DATE`` - - ✓ + - Yes - Date * - ``DATETIME``, ``TIMESTAMP`` - - ✓ + - Yes - Date and time * - ``NULL`` - - ✓ + - Yes - ``NULL`` values * - ``TIME`` - - ✗ + - No - Can be stored as a text string or as part of a ``DATETIME`` @@ -78,13 +78,13 @@ Contraints - Supported - Further information * - Not null - - ✓ + - Yes - ``NOT NULL`` * - Default values - - ✓ + - Yes - ``DEFAULT`` * - ``AUTO INCREMENT`` - - ✓ Different name + - Yes Different name - ``IDENTITY`` @@ -118,43 +118,43 @@ Schema Changes - Supported - Further information * - ``ALTER TABLE`` - - ✓ + - Yes - :ref:`alter_table` - Add column, alter column, drop column, rename column, rename table, modify clustering keys * - Rename database - - ✗ + - No - * - Rename table - - ✓ + - Yes - :ref:`rename_table` * - Rename column - - ✓ + - Yes - :ref:`rename_column` * - Add column - - ✓ + - Yes - :ref:`add_column` * - Remove column - - ✓ + - Yes - :ref:`drop_column` * - Alter column data type - - ✗ + - No - * - Add / modify clustering keys - - ✓ + - Yes - :ref:`cluster_by` * - Drop clustering keys - - ✓ + - Yes - :ref:`drop_clustering_key` * - Add / Remove constraints - - ✗ + - No - * - Rename schema - - ✗ + - No - * - Drop schema - - ✓ + - Yes - :ref:`drop_schema` * - Alter default schema per user - - ✓ + - Yes - :ref:`alter_default_schema` @@ -169,28 +169,28 @@ Statements - Supported - Further information * - SELECT - - ✓ + - Yes - :ref:`select` * - CREATE TABLE - - ✓ + - Yes - :ref:`create_table` * - CREATE FOREIGN / EXTERNAL TABLE - - ✓ + - Yes - :ref:`create_foreign_table` * - DELETE - - ✓ + - Yes - :ref:`delete_guide` * - INSERT - - ✓ + - Yes - :ref:`insert`, :ref:`copy_from` * - TRUNCATE - - ✓ + - Yes - :ref:`truncate` * - UPDATE - - ✗ + - No - * - VALUES - - ✓ + - Yes - :ref:`values` Clauses @@ -204,19 +204,19 @@ Clauses - Supported - Further information * - ``LIMIT`` / ``TOP`` - - ✓ + - Yes - * - ``LIMIT`` with ``OFFSET`` - - ✗ + - No - * - ``WHERE`` - - ✓ + - Yes - * - ``HAVING`` - - ✓ + - Yes - * - ``OVER`` - - ✓ + - Yes - Table Expressions @@ -230,19 +230,19 @@ Table Expressions - Supported - Further information * - Tables, Views - - ✓ + - Yes - * - Aliases, ``AS`` - - ✓ + - Yes - * - ``JOIN`` - ``INNER``, ``LEFT [ OUTER ]``, ``RIGHT [ OUTER ]``, ``CROSS`` - - ✓ + - Yes - * - Table expression subqueries - - ✓ + - Yes - * - Scalar subqueries - - ✗ + - No - @@ -259,34 +259,34 @@ Read more about :ref:`scalar_expressions`. - Supported - Further information * - Common functions - - ✓ + - Yes - ``CURRENT_TIMESTAMP``, ``SUBSTRING``, ``TRIM``, ``EXTRACT``, etc. * - Comparison operators - - ✓ + - Yes - ``<``, ``<=``, ``>``, ``>=``, ``=``, ``<>, !=``, ``IS``, ``IS NOT`` * - Boolean operators - - ✓ + - Yes - ``AND``, ``NOT``, ``OR`` * - Conditional expressions - - ✓ + - Yes - ``CASE .. WHEN`` * - Conditional functions - - ✓ + - Yes - ``COALESCE`` * - Pattern matching - - ✓ + - Yes - ``LIKE``, ``RLIKE``, ``ISPREFIXOF``, ``CHARINDEX``, ``PATINDEX`` * - REGEX POSIX pattern matching - - ✓ + - Yes - ``RLIKE``, ``REGEXP_COUNT``, ``REGEXP_INSTR``, ``REGEXP_SUBSTR``, * - ``EXISTS`` - - ✗ + - No - * - ``IN``, ``NOT IN`` - Partial - Literal values only * - Bitwise arithmetic - - ✓ + - Yes - ``&``, ``|``, ``XOR``, ``~``, ``>>``, ``<<`` @@ -304,16 +304,16 @@ Read more about :ref:`access_control` in SQream DB. - Supported - Further information * - Roles as users and groups - - ✓ + - Yes - * - Object default permissions - - ✓ + - Yes - * - Column / Row based permissions - - ✗ + - No - * - Object ownership - - ✗ + - No - @@ -329,20 +329,20 @@ Extra Functionality - Supported - Further information * - Information schema - - ✓ + - Yes - :ref:`catalog_reference` * - Views - - ✓ + - Yes - :ref:`create_view` * - Window functions - - ✓ + - Yes - :ref:`window_functions` * - CTEs - - ✓ + - Yes - :ref:`common_table_expressions` * - Saved queries, Saved queries with parameters - - ✓ + - Yes - :ref:`saved_queries` * - Sequences - - ✓ + - Yes - :ref:`identity` diff --git a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst index 25d2be354..6b8b3fc10 100644 --- a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst @@ -223,7 +223,7 @@ The following table describes the DDL Optimizer screen: * - Column area - Shows the column **names** and **column types** from the selected table. You can scroll down or to the right/left for long column lists. * - Optimization area - - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``VARCHAR`` fields), and the default percent buffer to add to ``VARCHAR`` lengths (10%). Attempts to determine field nullability. + - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``TEXT`` fields), and the default percent buffer to add to ``TEXT`` lengths (10%). Attempts to determine field nullability. * - Run Optimizer - Starts the optimization process. diff --git a/third_party_tools/client_drivers/cpp/insert_test.cpp b/third_party_tools/client_drivers/cpp/insert_test.cpp index d395be31a..560b04323 100644 --- a/third_party_tools/client_drivers/cpp/insert_test.cpp +++ b/third_party_tools/client_drivers/cpp/insert_test.cpp @@ -14,7 +14,7 @@ int main () { "raviga", "sqream"); run_direct_query(&sqc, - "CREATE TABLE animals (id INT NOT NULL, name VARCHAR(10) NOT NULL)"); + "CREATE TABLE animals (id INT NOT NULL, name TEXT NOT NULL)"); // prepare the statement sqc.new_query("INSERT INTO animals VALUES (?, ?)"); @@ -27,7 +27,7 @@ int main () { for (int i = 0; i < len; ++i) { sqc.set_int(0, row0[i]); - sqc.set_varchar(1, row1[i]); + sqc.set_text(1, row1[i]); sqc.next_query_row(); } diff --git a/third_party_tools/client_drivers/python/index.rst b/third_party_tools/client_drivers/python/index.rst index c2f5911b3..1e0d8435c 100644 --- a/third_party_tools/client_drivers/python/index.rst +++ b/third_party_tools/client_drivers/python/index.rst @@ -351,7 +351,7 @@ This example loads 10,000 rows of dummy data to a SQream DB instance , clustered=True) # Create a table for loading - create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s varchar(12), ss text, dt date, dtt datetime)' + create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s text, ss text, dt date, dtt datetime)' con.execute(create) # After creating the table, we can load data into it with the INSERT command @@ -471,8 +471,8 @@ For example: 'employees' , metadata , sa.Column('id', sa.Integer) - , sa.Column('name', sa.VARCHAR(32)) - , sa.Column('lastname', sa.VARCHAR(32)) + , sa.Column('name', sa.TEXT) + , sa.Column('lastname', sa.TEXT) , sa.Column('salary', sa.Float) ) diff --git a/third_party_tools/client_drivers/python/nba-t10.csv b/third_party_tools/client_drivers/python/nba-t10.csv index 024530355..c3d41e729 100644 --- a/third_party_tools/client_drivers/python/nba-t10.csv +++ b/third_party_tools/client_drivers/python/nba-t10.csv @@ -1,10 +1,9 @@ -Name,Team,Number,Position,Age,Height,Weight,College,Salary -Avery Bradley,Boston Celtics,0.0,PG,25.0,6-2,180.0,Texas,7730337.0 -Jae Crowder,Boston Celtics,99.0,SF,25.0,6-6,235.0,Marquette,6796117.0 -John Holland,Boston Celtics,30.0,SG,27.0,6-5,205.0,Boston University, -R.J. Hunter,Boston Celtics,28.0,SG,22.0,6-5,185.0,Georgia State,1148640.0 -Jonas Jerebko,Boston Celtics,8.0,PF,29.0,6-10,231.0,,5000000.0 -Amir Johnson,Boston Celtics,90.0,PF,29.0,6-9,240.0,,12000000.0 -Jordan Mickey,Boston Celtics,55.0,PF,21.0,6-8,235.0,LSU,1170960.0 -Kelly Olynyk,Boston Celtics,41.0,C,25.0,7-0,238.0,Gonzaga,2165160.0 -Terry Rozier,Boston Celtics,12.0,PG,22.0,6-2,190.0,Louisville,1824360.0 +Avery Bradley,Boston Celtics,0,PG,25,2-Jun,180,Texas,7730337 +Jae Crowder,Boston Celtics,99,SF,25,6-Jun,235,Marquette,6796117 +John Holland,Boston Celtics,30,SG,27,5-Jun,205,Boston University, +R.J. Hunter,Boston Celtics,28,SG,22,5-Jun,185,Georgia State,1148640 +Jonas Jerebko,Boston Celtics,8,PF,29,10-Jun,231,,5000000 +Amir Johnson,Boston Celtics,90,PF,29,9-Jun,240,,12000000 +Jordan Mickey,Boston Celtics,55,PF,21,8-Jun,235,LSU,1170960 +Kelly Olynyk,Boston Celtics,41,C,25,Jul-00,238,Gonzaga,2165160 +Terry Rozier,Boston Celtics,12,PG,22,2-Jun,190,Louisville,1824360 diff --git a/third_party_tools/client_platforms/tibco_spotfire.rst b/third_party_tools/client_platforms/tibco_spotfire.rst index b98ae0825..f68f71b25 100644 --- a/third_party_tools/client_platforms/tibco_spotfire.rst +++ b/third_party_tools/client_platforms/tibco_spotfire.rst @@ -141,7 +141,7 @@ After creating a connection, you can create your SQream data source template. Integer - VARCHAR(2048) + TEXT) String From d6a4285e1b60ec0f1d08f61a99c7600bd280bd91 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 19 Jun 2022 18:59:43 +0300 Subject: [PATCH 254/300] Replaced VARCHAR with TEXT --- configuration_guides/admin_regular_flags.rst | 3 +-- data_ingestion/parquet.rst | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/configuration_guides/admin_regular_flags.rst b/configuration_guides/admin_regular_flags.rst index 187d44df5..a863c20d4 100644 --- a/configuration_guides/admin_regular_flags.rst +++ b/configuration_guides/admin_regular_flags.rst @@ -27,5 +27,4 @@ The **Regular Administration Flags** page describes **Regular** modification typ * `Setting Worker Amount to Handle Concurrent Reads `_ * `Setting Implicit Casts in ORC Files `_ * `Setting Timeout Limit for Locking Objects before Executing Statements `_ -* `Interpreting Decimal Literals as Double Instead of Numeric `_ -* `Interpreting VARCHAR as TEXT ` \ No newline at end of file +* `Interpreting Decimal Literals as Double Instead of Numeric `_ \ No newline at end of file diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index 67d255c2f..225b53461 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -269,7 +269,7 @@ Loading a table from a directory of Parquet files on HDFS .. code-block:: postgres CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name TEXT NOT NULL, email TEXT NOT NULL) WRAPPER parquet_fdw OPTIONS ( @@ -284,7 +284,7 @@ Loading a table from a bucket of files on S3 .. code-block:: postgres CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name TEXT NOT NULL, email TEXT NOT NULL) WRAPPER parquet_fdw OPTIONS ( LOCATION = 's3://pp-secret-bucket/users/*.parquet', From 2f6c799369e73f4588e98a1d2d2cb8befcf57267 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 19 Jun 2022 19:05:00 +0300 Subject: [PATCH 255/300] Replaced VARCHAR with TEXT --- data_type_guides/sql_data_types_string.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_type_guides/sql_data_types_string.rst b/data_type_guides/sql_data_types_string.rst index a4321f387..35c0ffdf1 100644 --- a/data_type_guides/sql_data_types_string.rst +++ b/data_type_guides/sql_data_types_string.rst @@ -20,7 +20,7 @@ The following table describes the String types: - Data Size (Not Null, Uncompressed) - Example * - ``TEXT [(n)]`` - - Varaiable length string - UTF-8 unicode. ``NVARCHAR`` is synonymous with ``TEXT``. + - Variable length string - UTF-8 unicode. ``NVARCHAR`` is synonymous with ``TEXT``. - Up to ``4*n`` bytes - ``'キウイは楽しい鳥です'`` @@ -41,7 +41,7 @@ String types can be written with standard SQL string literals, which are enclose Size ^^^^^^ -``VARCHAR(n)`` can occupy up to *n* bytes, whereas ``TEXT(n)`` can occupy up to *4*n* bytes. However, the size of strings is variable and is compressed by SQream. +``TEXT(n)`` can occupy up to *4*n* bytes. However, the size of strings is variable and is compressed by SQream. String Examples ^^^^^^^^^^ From 7294bd3573821c1f0cf3b9b445d4ff302ee96e48 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 21 Jun 2022 18:51:45 +0300 Subject: [PATCH 256/300] Replaced TEXT with VARCHAR --- configuration_guides/admin_regular_flags.rst | 3 +- .../current_configuration_method.rst | 9 +++++- data_ingestion/csv.rst | 18 ++++++------ data_ingestion/inserting_data.rst | 20 ++++++------- data_ingestion/oracle.rst | 28 +++++++++---------- data_ingestion/orc.rst | 28 +++++++++---------- data_ingestion/parquet.rst | 20 ++++++------- .../converting_and_casting_types.rst | 2 +- data_type_guides/sql_data_types_date.rst | 2 +- .../sql_data_types_floating_point.rst | 2 +- data_type_guides/sql_data_types_integer.rst | 2 +- data_type_guides/sql_data_types_string.rst | 2 +- data_type_guides/supported_data_types.rst | 9 ++++-- feature_guides/compression.rst | 11 ++++---- getting_started/creating_your_first_table.rst | 13 ++++----- getting_started/querying_data.rst | 10 +++---- operational_guides/foreign_tables.rst | 20 ++++++------- operational_guides/logging.rst | 4 +-- .../optimization_best_practices.rst | 24 ++++++++++++++-- operational_guides/s3.rst | 18 ++++++------ operational_guides/saved_queries.rst | 2 +- .../seeing_system_objects_as_ddl.rst | 4 +-- reference/cli/sqream_sql.rst | 4 +-- .../sql_functions/aggregate_functions/avg.rst | 10 +++---- .../aggregate_functions/corr.rst | 10 +++---- .../aggregate_functions/count.rst | 10 +++---- .../aggregate_functions/covar_pop.rst | 10 +++---- .../aggregate_functions/covar_samp.rst | 10 +++---- .../sql_functions/aggregate_functions/max.rst | 10 +++---- .../sql_functions/aggregate_functions/min.rst | 10 +++---- .../aggregate_functions/stddev_pop.rst | 10 +++---- .../aggregate_functions/stddev_samp.rst | 10 +++---- .../sql_functions/aggregate_functions/sum.rst | 10 +++---- .../aggregate_functions/var_pop.rst | 10 +++---- .../aggregate_functions/var_samp.rst | 10 +++---- .../conditionals/is_ascii.rst | 2 +- .../scalar_functions/conditionals/is_null.rst | 2 +- .../scalar_functions/conversion/to_hex.rst | 4 +-- .../date_and_time/dateadd.rst | 2 +- .../date_and_time/datediff.rst | 2 +- .../date_and_time/datepart.rst | 2 +- .../date_and_time/eomonth.rst | 2 +- .../date_and_time/extract.rst | 2 +- .../scalar_functions/date_and_time/trunc.rst | 2 +- .../scalar_functions/string/char_length.rst | 2 +- .../scalar_functions/string/charindex.rst | 2 +- .../scalar_functions/string/concat.rst | 22 +++++++-------- .../scalar_functions/string/isprefixof.rst | 2 +- .../scalar_functions/string/len.rst | 2 +- .../scalar_functions/string/like.rst | 18 ++++++------ .../scalar_functions/string/lower.rst | 2 +- .../scalar_functions/string/octet_length.rst | 2 +- .../scalar_functions/string/patindex.rst | 2 +- .../scalar_functions/string/regexp_count.rst | 10 +++---- .../scalar_functions/string/regexp_instr.rst | 10 +++---- .../scalar_functions/string/regexp_substr.rst | 10 +++---- .../scalar_functions/string/replace.rst | 2 ++ .../scalar_functions/string/rlike.rst | 18 ++++++------ .../scalar_functions/string/rtrim.rst | 2 +- .../scalar_functions/string/substring.rst | 18 ++++++------ .../scalar_functions/string/trim.rst | 2 +- .../scalar_functions/string/upper.rst | 2 +- .../window_functions/first_value.rst | 2 +- .../sql_functions/window_functions/lag.rst | 10 +++---- .../window_functions/last_value.rst | 2 +- .../sql_functions/window_functions/lead.rst | 10 +++---- .../window_functions/nth_value.rst | 4 +-- .../sql_functions/window_functions/rank.rst | 10 +++---- .../window_functions/row_number.rst | 10 +++---- .../ddl_commands/create_foreign_table.rst | 6 ++-- .../ddl_commands/create_function.rst | 2 +- .../ddl_commands/create_table.rst | 12 ++++---- .../sql_statements/dml_commands/select.rst | 18 ++++++------ .../utility_commands/dump_database_ddl.rst | 2 +- .../utility_commands/get_ddl.rst | 4 +-- .../utility_commands/save_query.rst | 20 ++++++------- reference/sql/sql_syntax/literals.rst | 4 +-- reference/sql/sql_syntax/subqueries.rst | 10 +++---- reference/sql/sql_syntax/window_functions.rst | 10 +++---- reference/sql_feature_support.rst | 2 +- ...ts_and_running_queries_from_the_editor.rst | 2 +- .../client_drivers/cpp/insert_test.cpp | 4 +-- .../client_drivers/python/index.rst | 6 ++-- .../client_platforms/tibco_spotfire.rst | 2 +- troubleshooting/log_related_issues.rst | 4 +-- 85 files changed, 357 insertions(+), 322 deletions(-) diff --git a/configuration_guides/admin_regular_flags.rst b/configuration_guides/admin_regular_flags.rst index a863c20d4..d3296e1e4 100644 --- a/configuration_guides/admin_regular_flags.rst +++ b/configuration_guides/admin_regular_flags.rst @@ -27,4 +27,5 @@ The **Regular Administration Flags** page describes **Regular** modification typ * `Setting Worker Amount to Handle Concurrent Reads `_ * `Setting Implicit Casts in ORC Files `_ * `Setting Timeout Limit for Locking Objects before Executing Statements `_ -* `Interpreting Decimal Literals as Double Instead of Numeric `_ \ No newline at end of file +* `Interpreting Decimal Literals as Double Instead of Numeric `_ +* `VARCHAR Identifiers `_ \ No newline at end of file diff --git a/configuration_guides/current_configuration_method.rst b/configuration_guides/current_configuration_method.rst index 740dcd22e..238626279 100644 --- a/configuration_guides/current_configuration_method.rst +++ b/configuration_guides/current_configuration_method.rst @@ -625,6 +625,13 @@ The following table describes the **Generic** and **Administration** configurati - boolean - ``FALSE`` + * - ``varcharIdentifiers`` + - Administration + - Regular + - Activates using varchar as an identifier. + - boolean + - ``true` + Configuration Commands ========== The configuration commands are associated with particular flag types based on permissions. @@ -714,7 +721,7 @@ The following is an example of a catalog table query: .. code-block:: console externalTableBlobEstimate, 100, 100, default, - textEncoding, ascii, ascii, default, Changes the expected encoding for Text columns + varcharEncoding, ascii, ascii, default, Changes the expected encoding for Varchar columns useCrcForTextJoinKeys, true, true, default, hiveStyleImplicitStringCasts, false, false, default, diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index 789c89a19..ac4ba1741 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -83,15 +83,15 @@ We will make note of the file structure to create a matching ``CREATE TABLE`` st CREATE TABLE nba ( - Name text, - Team text, - Number tinyint, - Position text, - Age tinyint, - Height text, - Weight real, - College text, - Salary float + "Name" varchar(40), + "Team" varchar(40), + "Number" tinyint, + "Position" varchar(2), + "Age" tinyint, + "Height" varchar(4), + "Weight" real, + "College" varchar(40), + "Salary" float ); diff --git a/data_ingestion/inserting_data.rst b/data_ingestion/inserting_data.rst index 0f4c4afaa..0440ba84b 100644 --- a/data_ingestion/inserting_data.rst +++ b/data_ingestion/inserting_data.rst @@ -65,7 +65,7 @@ Supported load methods SQream DB's :ref:`COPY FROM` syntax can be used to load CSV files, but can't be used for Parquet and ORC. -:ref:`FOREIGN TABLE` can be used to load text files, Parquet, and ORC files, and can also transform the data prior to materialization as a full table. +:ref:`FOREIGN TABLE` can be used to load text files, Parquet, and ORC files, and can also transform the data prior to materialization as a full table. .. list-table:: :widths: auto @@ -82,7 +82,7 @@ SQream DB's :ref:`COPY FROM` syntax can be used to load CSV files, bu - Not supported - Not supported - Not supported - * - :ref:`external_tables` + * - :ref:`foreign_tables` - Supported - Supported - Supported @@ -98,12 +98,12 @@ Unsupported Data Types SQream DB doesn't support the entire set of features that some other database systems may have, such as ``ARRAY``, ``BLOB``, ``ENUM``, ``SET``, etc. -These data types will have to be converted before load. For example, ``ENUM`` can often be stored as a ``TEXT``. +These data types will have to be converted before load. For example, ``ENUM`` can often be stored as a ``VARCHAR``. Handing Extended Errors ---------------------------- -While :ref:`external tables` can be used to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options, as well as extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. +While :ref:`foreign tables` can be used to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options, as well as extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. Best Practices for CSV ------------------------------ @@ -129,7 +129,7 @@ Text files like CSV rarely conform to `RFC 4180 63 - ``FLOAT``, ``DOUBLE`` - * - ``NCHAR(n)`` + * - ``NCHAR(n)``, ``NVARCHAR2(n)`` - Any ``n`` - ``TEXT`` (alias of ``NVARCHAR``) @@ -132,9 +132,9 @@ Refer to the table below to match the Oracle source data type to a new SQream DB - f > 0 - ``FLOAT`` / ``DOUBLE`` - * - ``TEXT`` + * - ``VARCHAR(n)``, ``VARCHAR2(n)`` - Any ``n`` - - ``TEXT`` + - ``VARCHAR(n)`` or ``TEXT`` * - ``TIMESTAMP`` - - ``DATETIME`` @@ -165,15 +165,15 @@ Consider Oracle's ``HR.EMPLOYEES`` sample table: CREATE TABLE employees ( employee_id NUMBER(6) - , first_name TEXT - , last_name TEXT + , first_name VARCHAR2(20) + , last_name VARCHAR2(25) CONSTRAINT emp_last_name_nn NOT NULL - , email TEXT + , email VARCHAR2(25) CONSTRAINT emp_email_nn NOT NULL - , phone_number TEXT + , phone_number VARCHAR2(20) , hire_date DATE CONSTRAINT emp_hire_date_nn NOT NULL - , job_id TEXT + , job_id VARCHAR2(10) CONSTRAINT emp_job_nn NOT NULL , salary NUMBER(8,2) , commission_pct NUMBER(2,2) @@ -208,12 +208,12 @@ This table rewritten for SQream DB would be created like this: CREATE TABLE employees ( employee_id SMALLINT NOT NULL, - first_name TEXT, - last_name TEXT NOT NULL, - email TEXT NOT NULL, - phone_number TEXT, + first_name VARCHAR(20), + last_name VARCHAR(25) NOT NULL, + email VARCHAR(20) NOT NULL, + phone_number VARCHAR(20), hire_date DATE NOT NULL, - job_id TEXT NOT NULL, + job_id VARCHAR(10) NOT NULL, salary FLOAT, commission_pct REAL, manager_id SMALLINT, diff --git a/data_ingestion/orc.rst b/data_ingestion/orc.rst index 9a756dea1..effaa1e32 100644 --- a/data_ingestion/orc.rst +++ b/data_ingestion/orc.rst @@ -186,15 +186,15 @@ We will make note of the file structure to create a matching ``CREATE FOREIGN TA CREATE FOREIGN TABLE ext_nba ( - Name TEXT, - Team TEXT, - Number BIGINT, - Position TEXT, - Age BIGINT, - Height TEXT, - Weight BIGINT, - College TEXT, - Salary FLOAT + "Name" varchar(40), + "Team" varchar(40), + "Number" tinyint, + "Position" varchar(2), + "Age" tinyint, + "Height" varchar(4), + "Weight" real, + "College" varchar(40), + "Salary" float ) WRAPPER orc_fdw OPTIONS @@ -212,7 +212,7 @@ We will make note of the file structure to create a matching ``CREATE FOREIGN TA 4. Verify table contents ==================================== -External tables do not verify file integrity or structure, so verify that the table definition matches up and contains the correct data. +Foreign tables do not verify file integrity or structure, so verify that the table definition matches up and contains the correct data. .. code-block:: psql @@ -247,7 +247,7 @@ Working around unsupported column types Suppose you only want to load some of the columns - for example, if one of the columns isn't supported. -By ommitting unsupported columns from queries that access the ``EXTERNAL TABLE``, they will never be called, and will not cause a "type mismatch" error. +By ommitting unsupported columns from queries that access the ``FOREIGN TABLE``, they will never be called, and will not cause a "type mismatch" error. For this example, assume that the ``Position`` column isn't supported because of its type. @@ -288,7 +288,7 @@ Loading a table from a directory of ORC files on HDFS .. code-block:: postgres CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name TEXT NOT NULL, email TEXT NOT NULL) + (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) WRAPPER orc_fdw OPTIONS ( @@ -302,8 +302,8 @@ Loading a table from a bucket of files on S3 .. code-block:: postgres - CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name TEXT NOT NULL, email TEXT NOT NULL) + CREATE FOREIGN TABLE TEXT + (id INT NOT NULL, name TEXT NOT NULL, email TEXT(50) NOT NULL) WRAPPER orc_fdw OPTIONS ( LOCATION = 's3://pp-secret-bucket/users/*.ORC', diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index 225b53461..c7064a001 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -4,7 +4,7 @@ Inserting Data from a Parquet File ********************** -This guide covers inserting data from Parquet files into SQream DB using :ref:`FOREIGN TABLE`. +This guide covers inserting data from Parquet files into SQream DB using :ref:`FOREIGN TABLE`. .. contents:: In this topic: :local: @@ -33,7 +33,7 @@ Prepare the source Parquet files, with the following requirements: - ``DATE`` - ``DATETIME`` * - ``BOOLEAN`` - - ✓ + - Supported - - - @@ -46,7 +46,7 @@ Prepare the source Parquet files, with the following requirements: * - ``INT16`` - - - - ✓ + - Supported - - - @@ -58,7 +58,7 @@ Prepare the source Parquet files, with the following requirements: - - - - - ✓ + - Supported - - - @@ -70,7 +70,7 @@ Prepare the source Parquet files, with the following requirements: - - - - - ✓ + - Supported - - - @@ -82,7 +82,7 @@ Prepare the source Parquet files, with the following requirements: - - - - - ✓ + - Supported - - - @@ -94,7 +94,7 @@ Prepare the source Parquet files, with the following requirements: - - - - - ✓ + - Supported - - - @@ -106,7 +106,7 @@ Prepare the source Parquet files, with the following requirements: - - - - - ✓ + - Supported - - * - ``INT96`` [#f3]_ @@ -119,7 +119,7 @@ Prepare the source Parquet files, with the following requirements: - - - - - ✓ [#f4]_ + - Supported [#f4]_ * If a Parquet file has an unsupported type like ``enum``, ``uuid``, ``time``, ``json``, ``bson``, ``lists``, ``maps``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query), the statement will succeed. If the column is referenced, an error will be thrown to the user, explaining that the type is not supported, but the column may be ommited. This can be worked around. See more information in the examples. @@ -161,7 +161,7 @@ For example, to import the data from ``nba.parquet``, we will first look at the * The file is stored on S3, at ``s3://sqream-demo-data/nba.parquet``. -We will make note of the file structure to create a matching ``CREATE EXTERNAL TABLE`` statement. +We will make note of the file structure to create a matching ``CREATE FOREIGN TABLE`` statement. .. code-block:: postgres diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index d6ae9cb4f..bb6475646 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -15,7 +15,7 @@ You can rectify this by casting the value to a larger data type, as shown below: SQream supports the following three data conversion types: -* ``CAST( TO )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO TEXT)``. +* ``CAST( TO )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO VARCHAR(30))``. :: diff --git a/data_type_guides/sql_data_types_date.rst b/data_type_guides/sql_data_types_date.rst index 88236c113..da83f80cc 100644 --- a/data_type_guides/sql_data_types_date.rst +++ b/data_type_guides/sql_data_types_date.rst @@ -108,5 +108,5 @@ The following table shows the possible ``DATE`` and ``DATETIME`` value conversio * - Type - Details - * - ``TEXT`` + * - ``VARCHAR(n)`` - ``'1997-01-01'`` → ``'1997-01-01'``, ``'1955-11-05 01:24'`` → ``'1955-11-05 01:24:00.000'`` \ No newline at end of file diff --git a/data_type_guides/sql_data_types_floating_point.rst b/data_type_guides/sql_data_types_floating_point.rst index 0c06df96f..18227140c 100644 --- a/data_type_guides/sql_data_types_floating_point.rst +++ b/data_type_guides/sql_data_types_floating_point.rst @@ -74,7 +74,7 @@ The following table shows the possible Floating Point value conversions: - ``1.0`` → ``true``, ``0.0`` → ``false`` * - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT`` - ``2.0`` → ``2``, ``3.14159265358979`` → ``3``, ``2.718281828459`` → ``2``, ``0.5`` → ``0``, ``1.5`` → ``1`` - * - ``TEXT(n)`` (n > 6 recommended) + * - ``VARCHAR(n)`` (n > 6 recommended) - ``1`` → ``'1.0000'``, ``3.14159265358979`` → ``'3.1416'`` .. note:: As shown in the above examples, casting ``real`` to ``int`` rounds down. \ No newline at end of file diff --git a/data_type_guides/sql_data_types_integer.rst b/data_type_guides/sql_data_types_integer.rst index 213b50d42..9d4210731 100644 --- a/data_type_guides/sql_data_types_integer.rst +++ b/data_type_guides/sql_data_types_integer.rst @@ -79,5 +79,5 @@ The following table shows the possible Integer value conversions: - Details * - ``REAL``, ``DOUBLE`` - ``1`` → ``1.0``, ``-32`` → ``-32.0`` - * - ``TEXT`` (All numeric values must fit in the string length) + * - ``VARCHAR(n)`` (All numberic values must fit in the string length) - ``1`` → ``'1'``, ``2451`` → ``'2451'`` \ No newline at end of file diff --git a/data_type_guides/sql_data_types_string.rst b/data_type_guides/sql_data_types_string.rst index 35c0ffdf1..539198fe6 100644 --- a/data_type_guides/sql_data_types_string.rst +++ b/data_type_guides/sql_data_types_string.rst @@ -26,7 +26,7 @@ The following table describes the String types: Length ^^^^^^^^^ -When using ``TEXT``, specifying a size is optional. If not specified, the text field carries no constraints. To limit the size of the input, use ``TEXT(n)``, where ``n`` is the permitted number of characters. +When using ``TEXT``, specifying a size is optional. If not specified, the text field carries no constraints. To limit the size of the input, use ``VARCHAR(n)`` or ``TEXT(n)``, where ``n`` is the permitted number of characters. The following apply to setting the String type length: diff --git a/data_type_guides/supported_data_types.rst b/data_type_guides/supported_data_types.rst index 3f88cdbfa..2743b054b 100644 --- a/data_type_guides/supported_data_types.rst +++ b/data_type_guides/supported_data_types.rst @@ -51,16 +51,21 @@ The following table shows the supported data types. - 8 bytes - ``0.000003`` - ``FLOAT``/``DOUBLE PRECISION`` - * - ``TEXT [(n)]`` + * - ``TEXT [(n)]``, ``NVARCHAR (n)`` - Variable length string - UTF-8 unicode - Up to ``4*n`` bytes - ``'キウイは楽しい鳥です'`` - - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR``, ``TEXT`` + - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR``, ``NVARCHAR`` * - ``NUMERIC`` - 38 digits - 16 bytes - ``0.123245678901234567890123456789012345678`` - ``DECIMAL`` + * - ``VARCHAR (n)`` + - Variable length string - ASCII only + - ``n`` bytes + - ``'Kiwis have tiny wings, but cannot fly.'`` + - ``SQL VARIANT`` * - ``DATE`` - Date - 4 bytes diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index 96d2c69ec..8e15c5686 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -108,7 +108,7 @@ The following two are equivalent: CREATE TABLE t ( x INT, - y TEXT + y VARCHAR(50) ); In this version, the default compression is specified explicitly: @@ -117,7 +117,7 @@ In this version, the default compression is specified explicitly: CREATE TABLE t ( x INT CHECK('CS "default"'), - y TEXT CHECK('CS "default"') + y VARCHAR(50) CHECK('CS "default"') ); Forcing no compression (flat) @@ -130,7 +130,7 @@ in order to reduce CPU or GPU resource utilization at the expense of increased I CREATE TABLE t ( x INT NOT NULL CHECK('CS "flat"'), -- This column won't be compressed - y TEXT -- This column will still be compressed automatically + y VARCHAR(50) -- This column will still be compressed automatically ); @@ -146,8 +146,9 @@ For example: CREATE TABLE t ( id BIGINT NOT NULL CHECK('CS "sequence"'), - y TEXT CHECK('CS "lz4"'), -- General purpose text compression - z TEXT CHECK('CS "dict"'), -- Low cardinality column + y VARCHAR(110) CHECK('CS "lz4"'), -- General purpose text compression + z VARCHAR(80) CHECK('CS "dict"'), -- Low cardinality column + ); diff --git a/getting_started/creating_your_first_table.rst b/getting_started/creating_your_first_table.rst index ee790444b..db2e96964 100644 --- a/getting_started/creating_your_first_table.rst +++ b/getting_started/creating_your_first_table.rst @@ -21,7 +21,7 @@ The ``CREATE TABLE`` syntax is used to create your first table. This table inclu CREATE TABLE cool_animals ( id INT NOT NULL, - name TEXT, + name VARCHAR(20), weight INT ); @@ -37,16 +37,15 @@ You can drop an existing table and create a new one by adding the ``OR REPLACE`` CREATE OR REPLACE TABLE cool_animals ( id INT NOT NULL, - name TEXT, + name VARCHAR(20), weight INT ); .. TODO: cool_animals? I think we need to decide if the customer for this documenation is 12 years old, or an IT professional. - .. _listing_a_create_table_statement: **Listing a CREATE TABLE Statement** - + You can list the full, verbose ``CREATE TABLE`` statement for a table by using the **GET DDL** function with the table name as shown in the following example: .. code-block:: psql @@ -54,7 +53,7 @@ You can list the full, verbose ``CREATE TABLE`` statement for a table by using t test=> SELECT GET_DDL('cool_animals'); create table "public"."cool_animals" ( "id" int not null, - "name" text, + "name" varchar(20), "weight" int ); @@ -62,7 +61,7 @@ You can list the full, verbose ``CREATE TABLE`` statement for a table by using t * SQream DB identifier names such as table names and column names are not case sensitive. SQream DB lowercases all identifiers bu default. If you want to maintain case, enclose the identifiers with double-quotes. * SQream DB places all tables in the `public` schema, unless another schema is created and specified as part of the table name. - + For information on listing a ``CREATE TABLE`` statement, see :ref:`get_ddl`. .. _dropping_a_table: @@ -74,7 +73,7 @@ When you have finished working with your table, you can drop the table to remove .. code-block:: psql test=> DROP TABLE cool_animals; - + executed For more information on dropping tables, see :ref:`drop_table`. \ No newline at end of file diff --git a/getting_started/querying_data.rst b/getting_started/querying_data.rst index 58047c334..36bf9e78b 100644 --- a/getting_started/querying_data.rst +++ b/getting_started/querying_data.rst @@ -11,14 +11,14 @@ To begin familiarizing yourself with querying data, you can create the following CREATE TABLE nba ( - Name text, - Team text, + Name varchar(40), + Team varchar(40), Number tinyint, - Position text, + Position varchar(2), Age tinyint, - Height text, + Height varchar(4), Weight real, - College text, + College varchar(40), Salary float ); diff --git a/operational_guides/foreign_tables.rst b/operational_guides/foreign_tables.rst index c743c72dc..4399a0233 100644 --- a/operational_guides/foreign_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -55,15 +55,15 @@ Based on the source file structure, we we :ref:`create a foreign table SELECT * FROM nba; master=> select * from nba; Record delimiter mismatch during CSV parsing. User defined line delimiter \n does not match the first delimiter \r\n found in s3://sqream-demo-data/nba.csv -* Since the data for a foreign table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against a foreign table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. \ No newline at end of file +* Since the data for a foreign table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against a foreign table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. diff --git a/operational_guides/logging.rst b/operational_guides/logging.rst index 9eefe3283..64ac5c8d8 100644 --- a/operational_guides/logging.rst +++ b/operational_guides/logging.rst @@ -354,7 +354,7 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas CREATE FOREIGN TABLE logs ( - start_marker TEXT, + start_marker VARCHAR(4), row_id BIGINT, timestamp DATETIME, message_level TEXT, @@ -368,7 +368,7 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas service_name TEXT, message_type_id INT, message TEXT, - end_message TEXT + end_message VARCHAR(5) ) WRAPPER csv_fdw OPTIONS diff --git a/operational_guides/optimization_best_practices.rst b/operational_guides/optimization_best_practices.rst index 64ebaabd9..fe36269c6 100644 --- a/operational_guides/optimization_best_practices.rst +++ b/operational_guides/optimization_best_practices.rst @@ -20,7 +20,20 @@ This section describes best practices and guidelines for designing tables. Use date and datetime types for columns ----------------------------------------- -When creating tables with dates or timestamps, using the purpose-built ``DATE`` and ``DATETIME`` types over integer types or ``TEXT`` will bring performance and storage footprint improvements, and in many cases huge performance improvements (as well as data integrity benefits). SQream DB stores dates and datetimes very efficiently and can strongly optimize queries using these specific types. +When creating tables with dates or timestamps, using the purpose-built ``DATE`` and ``DATETIME`` types over integer types or ``VARCHAR`` will bring performance and storage footprint improvements, and in many cases huge performance improvements (as well as data integrity benefits). SQream DB stores dates and datetimes very efficiently and can strongly optimize queries using these specific types. + +Reduce varchar length to a minimum +-------------------------------------- + +With the ``VARCHAR`` type, the length has a direct effect on query performance. + +If the size of your column is predictable, by defining an appropriate column length (no longer than the maximum actual value) you will get the following benefits: + +* Data loading issues can be identified more quickly + +* SQream DB can reserve less memory for decompression operations + +* Third-party tools that expect a data size are less likely to over-allocate memory Don't flatten or denormalize data ----------------------------------- @@ -58,6 +71,13 @@ For example, if a value can't be missing (or ``NULL``), specify a ``NOT NULL`` c Not only does specifying ``NOT NULL`` save on data storage, it lets the query compiler know that a column cannot have a ``NULL`` value, which can improve query performance. +Keep VARCHAR lengths to a minimum +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +While it won't make a big difference in storage, large strings allocate a lot of memory at query time. + +If a column's string length never exceeds 50 characters, specify ``VARCHAR(50)`` rather than an arbitrarily large number. + Sorting ============== @@ -65,7 +85,7 @@ Data sorting is an important factor in minimizing storage size and improving que * Minimizing storage saves on physical resources and increases performance by reducing overall disk I/O. Prioritize the sorting of low-cardinality columns. This reduces the number of chunks and extents that SQream DB reads during query execution. -* Where possible, sort columns with the lowest cardinality first. Avoid sorting ``TEXT`` columns with lengths exceeding 50 characters. +* Where possible, sort columns with the lowest cardinality first. Avoid sorting ``VARCHAR`` and ``TEXT/NVARCHAR`` columns with lengths exceeding 50 characters. * For longer-running queries that run on a regular basis, performance can be improved by sorting data based on the ``WHERE`` and ``GROUP BY`` parameters. Data can be sorted during insert by using :ref:`external_tables` or by using :ref:`create_table_as`. diff --git a/operational_guides/s3.rst b/operational_guides/s3.rst index 89c4d2343..773a9e5fd 100644 --- a/operational_guides/s3.rst +++ b/operational_guides/s3.rst @@ -66,15 +66,15 @@ Based on the source file's structure, you can create a foreign table with the ap CREATE FOREIGN TABLE nba ( - Name text, - Team text, - Number tinyint, - Position text, - Age tinyint, - Height text, - Weight real, - College text, - Salary float + "Name" varchar(40), + "Team" varchar(40), + "Number" tinyint, + "Position" varchar(2), + "Age" tinyint, + "Height" varchar(4), + "Weight" real, + "College" varchar(40), + "Salary" float ) WRAPPER csv_fdw OPTIONS diff --git a/operational_guides/saved_queries.rst b/operational_guides/saved_queries.rst index fb36ac481..d554b4dc8 100644 --- a/operational_guides/saved_queries.rst +++ b/operational_guides/saved_queries.rst @@ -18,7 +18,7 @@ Query parameters can be used as substitutes for literal expressions in queries. * Parameters cannot be used to substitute things like column names and table names. -* Query parameters of a string datatype (like ``TEXT``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc.) +* Query parameters of a string datatype (like ``VARCHAR``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc.) Creating a saved query ====================== diff --git a/operational_guides/seeing_system_objects_as_ddl.rst b/operational_guides/seeing_system_objects_as_ddl.rst index 06caeca72..fc8ff3b83 100644 --- a/operational_guides/seeing_system_objects_as_ddl.rst +++ b/operational_guides/seeing_system_objects_as_ddl.rst @@ -22,7 +22,7 @@ Getting the DDL for a table farm=> SELECT GET_DDL('cool_animals'); create table "public"."cool_animals" ( "id" int not null, - "name" text not null, + "name" varchar(30) not null, "weight" double null, "is_agressive" bool default false not null ) ; @@ -142,7 +142,7 @@ Exporting database DDL to a client farm=> SELECT DUMP_DATABASE_DDL(); create table "public"."cool_animals" ( "id" int not null, - "name" text not null, + "name" varchar(30) not null, "weight" double null, "is_agressive" bool default false not null ) diff --git a/reference/cli/sqream_sql.rst b/reference/cli/sqream_sql.rst index f759b921d..87bb374c0 100644 --- a/reference/cli/sqream_sql.rst +++ b/reference/cli/sqream_sql.rst @@ -222,7 +222,7 @@ Creating a new database and switching over to it without reconnecting: .. code-block:: psql - farm=> create table animals(id int not null, name text not null, is_angry bool not null); + farm=> create table animals(id int not null, name varchar(30) not null, is_angry bool not null); executed time: 0.011940s @@ -300,7 +300,7 @@ Assuming a file containing SQL statements (separated by semicolons): $ cat some_queries.sql CREATE TABLE calm_farm_animals - ( id INT IDENTITY(0, 1), name TEXT + ( id INT IDENTITY(0, 1), name TEXT ); INSERT INTO calm_farm_animals (name) diff --git a/reference/sql/sql_functions/aggregate_functions/avg.rst b/reference/sql/sql_functions/aggregate_functions/avg.rst index 40eafbdc0..be0294d46 100644 --- a/reference/sql/sql_functions/aggregate_functions/avg.rst +++ b/reference/sql/sql_functions/aggregate_functions/avg.rst @@ -62,14 +62,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/corr.rst b/reference/sql/sql_functions/aggregate_functions/corr.rst index c9d26235a..212ab89d2 100644 --- a/reference/sql/sql_functions/aggregate_functions/corr.rst +++ b/reference/sql/sql_functions/aggregate_functions/corr.rst @@ -51,14 +51,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/count.rst b/reference/sql/sql_functions/aggregate_functions/count.rst index f0b0b5613..803e529c0 100644 --- a/reference/sql/sql_functions/aggregate_functions/count.rst +++ b/reference/sql/sql_functions/aggregate_functions/count.rst @@ -67,14 +67,14 @@ The examples in this section are based on a table named ``nba``, structured as f CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/covar_pop.rst b/reference/sql/sql_functions/aggregate_functions/covar_pop.rst index 53e83f691..c0d7cd35d 100644 --- a/reference/sql/sql_functions/aggregate_functions/covar_pop.rst +++ b/reference/sql/sql_functions/aggregate_functions/covar_pop.rst @@ -55,14 +55,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/covar_samp.rst b/reference/sql/sql_functions/aggregate_functions/covar_samp.rst index 6f385e9e0..29d7b7493 100644 --- a/reference/sql/sql_functions/aggregate_functions/covar_samp.rst +++ b/reference/sql/sql_functions/aggregate_functions/covar_samp.rst @@ -56,14 +56,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/max.rst b/reference/sql/sql_functions/aggregate_functions/max.rst index d2a7afc66..529e2230d 100644 --- a/reference/sql/sql_functions/aggregate_functions/max.rst +++ b/reference/sql/sql_functions/aggregate_functions/max.rst @@ -53,14 +53,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/min.rst b/reference/sql/sql_functions/aggregate_functions/min.rst index 3f5a2d402..d488d87fc 100644 --- a/reference/sql/sql_functions/aggregate_functions/min.rst +++ b/reference/sql/sql_functions/aggregate_functions/min.rst @@ -53,14 +53,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/stddev_pop.rst b/reference/sql/sql_functions/aggregate_functions/stddev_pop.rst index fbbdc9bab..5a8a7e677 100644 --- a/reference/sql/sql_functions/aggregate_functions/stddev_pop.rst +++ b/reference/sql/sql_functions/aggregate_functions/stddev_pop.rst @@ -58,14 +58,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/stddev_samp.rst b/reference/sql/sql_functions/aggregate_functions/stddev_samp.rst index b7d9bd468..0328e2241 100644 --- a/reference/sql/sql_functions/aggregate_functions/stddev_samp.rst +++ b/reference/sql/sql_functions/aggregate_functions/stddev_samp.rst @@ -62,14 +62,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/sum.rst b/reference/sql/sql_functions/aggregate_functions/sum.rst index 132c24d68..e8f648894 100644 --- a/reference/sql/sql_functions/aggregate_functions/sum.rst +++ b/reference/sql/sql_functions/aggregate_functions/sum.rst @@ -65,14 +65,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/var_pop.rst b/reference/sql/sql_functions/aggregate_functions/var_pop.rst index 94404f2f6..4ddf45a1e 100644 --- a/reference/sql/sql_functions/aggregate_functions/var_pop.rst +++ b/reference/sql/sql_functions/aggregate_functions/var_pop.rst @@ -58,14 +58,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/var_samp.rst b/reference/sql/sql_functions/aggregate_functions/var_samp.rst index e1e79ad68..6f0c91e63 100644 --- a/reference/sql/sql_functions/aggregate_functions/var_samp.rst +++ b/reference/sql/sql_functions/aggregate_functions/var_samp.rst @@ -63,14 +63,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst b/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst index 79ff6d3bb..bb9e3b2f9 100644 --- a/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst +++ b/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst @@ -45,7 +45,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE dictionary (id INT NOT NULL, fw TEXT, en TEXT); + CREATE TABLE dictionary (id INT NOT NULL, fw TEXT(30), en VARCHAR(30)); INSERT INTO dictionary VALUES (1, '行こう', 'Let''s go'), (2, '乾杯', 'Cheers'), (3, 'L''chaim', 'Cheers'); diff --git a/reference/sql/sql_functions/scalar_functions/conditionals/is_null.rst b/reference/sql/sql_functions/scalar_functions/conditionals/is_null.rst index ee17b6e7b..c99f4e7d1 100644 --- a/reference/sql/sql_functions/scalar_functions/conditionals/is_null.rst +++ b/reference/sql/sql_functions/scalar_functions/conditionals/is_null.rst @@ -40,7 +40,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE t (id INT NOT NULL, name TEXT, weight INT); + CREATE TABLE t (id INT NOT NULL, name VARCHAR(30), weight INT); INSERT INTO t VALUES (1, 'Kangaroo', 120), (2, 'Koala', 20), (3, 'Wombat', 60) ,(4, 'Kappa', NULL),(5, 'Echidna', 8),(6, 'Chupacabra', NULL) diff --git a/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst b/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst index d33643f22..f3cf6fb82 100644 --- a/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst +++ b/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst @@ -11,7 +11,7 @@ Syntax .. code-block:: postgres - TO_HEX( expr ) --> TEXT + TO_HEX( expr ) --> VARCHAR Arguments ============ @@ -28,7 +28,7 @@ Arguments Returns ============ -* Representation of the hexadecimal number of type ``TEXT``. +* Representation of the hexadecimal number of type ``VARCHAR``. Examples diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst index 7d8623499..cff5268e6 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst @@ -106,7 +106,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name TEXT, d DATE, dt DATETIME); + CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst index 6a1db9d9e..5c91a88d9 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst @@ -100,7 +100,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name TEXT, d DATE, dt DATETIME); + CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst index 74296e159..8a43a1472 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst @@ -109,7 +109,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name TEXT, d DATE, dt DATETIME); + CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst index 56454da9c..92e3f7940 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst @@ -48,7 +48,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name TEXT, d DATE, dt DATETIME); + CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst index 6a1c72a49..2fd79ca86 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst @@ -86,7 +86,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name TEXT, d DATE, dt DATETIME); + CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst index df4961919..d9d791cc3 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst @@ -104,7 +104,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name TEXT, d DATE, dt DATETIME); + CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/string/char_length.rst b/reference/sql/sql_functions/scalar_functions/string/char_length.rst index 556b88834..f89c397ab 100644 --- a/reference/sql/sql_functions/scalar_functions/string/char_length.rst +++ b/reference/sql/sql_functions/scalar_functions/string/char_length.rst @@ -12,7 +12,7 @@ Calculates the number of characters in a string. * To get the length in bytes, see :ref:`octet_length`. - * For ``TEXT`` strings, the octet length is the number of characters. Use :ref:`len` instead. + * For ``VARCHAR`` strings, the octet length is the number of characters. Use :ref:`len` instead. Syntax ========== diff --git a/reference/sql/sql_functions/scalar_functions/string/charindex.rst b/reference/sql/sql_functions/scalar_functions/string/charindex.rst index 25edb1858..fa9c89027 100644 --- a/reference/sql/sql_functions/scalar_functions/string/charindex.rst +++ b/reference/sql/sql_functions/scalar_functions/string/charindex.rst @@ -49,7 +49,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line TEXT); + CREATE TABLE jabberwocky(line VARCHAR(50)); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') diff --git a/reference/sql/sql_functions/scalar_functions/string/concat.rst b/reference/sql/sql_functions/scalar_functions/string/concat.rst index 286af690a..9c18902be 100644 --- a/reference/sql/sql_functions/scalar_functions/string/concat.rst +++ b/reference/sql/sql_functions/scalar_functions/string/concat.rst @@ -48,15 +48,15 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name text, - Team text, - Number tinyint, - Position text, - Age tinyint, - Height text, - Weight real, - College text, - Salary float + "Name" varchar(40), + "Team" varchar(40), + "Number" tinyint, + "Position" varchar(2), + "Age" tinyint, + "Height" varchar(4), + "Weight" real, + "College" varchar(40), + "Salary" float ); @@ -76,7 +76,7 @@ Convert values to string types before concatenation .. code-block:: psql - nba=> SELECT ("Age" :: TEXT) || "Name" FROM nba ORDER BY 1 DESC LIMIT 5; + nba=> SELECT ("Age" :: VARCHAR(2)) || "Name" FROM nba ORDER BY 1 DESC LIMIT 5; ?column? ---------------- 40Tim Duncan @@ -116,7 +116,7 @@ Add a space and concatenate it first to bypass the space trimming issue .. code-block:: psql - nba=> SELECT ("Age" :: TEXT || (' ' || "Name")) FROM nba ORDER BY 1 DESC LIMIT 5; + nba=> SELECT ("Age" :: VARCHAR(2) || (' ' || "Name")) FROM nba ORDER BY 1 DESC LIMIT 5; ?column? ----------------- 40 Tim Duncan diff --git a/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst b/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst index 989528fec..4a978b1ff 100644 --- a/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst +++ b/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst @@ -50,7 +50,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line TEXT); + CREATE TABLE jabberwocky(line VARCHAR(50)); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') diff --git a/reference/sql/sql_functions/scalar_functions/string/len.rst b/reference/sql/sql_functions/scalar_functions/string/len.rst index 1e54f2465..d3cba24b2 100644 --- a/reference/sql/sql_functions/scalar_functions/string/len.rst +++ b/reference/sql/sql_functions/scalar_functions/string/len.rst @@ -49,7 +49,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line TEXT); + CREATE TABLE jabberwocky(line VARCHAR(50)); INSERT INTO jabberwocky VALUES ($$'Twas brillig, and the slithy toves$$), (' Did gyre and gimble in the wabe:') diff --git a/reference/sql/sql_functions/scalar_functions/string/like.rst b/reference/sql/sql_functions/scalar_functions/string/like.rst index ce5ca4942..9a1b257be 100644 --- a/reference/sql/sql_functions/scalar_functions/string/like.rst +++ b/reference/sql/sql_functions/scalar_functions/string/like.rst @@ -83,15 +83,15 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name text(40), - Team text(40), - Number tinyint, - Position text(2), - Age tinyint, - Height text(4), - Weight real, - College text(40), - Salary float + "Name" varchar(40), + "Team" varchar(40), + "Number" tinyint, + "Position" varchar(2), + "Age" tinyint, + "Height" varchar(4), + "Weight" real, + "College" varchar(40), + "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/lower.rst b/reference/sql/sql_functions/scalar_functions/string/lower.rst index e6ff2e8a3..69dfd4f1a 100644 --- a/reference/sql/sql_functions/scalar_functions/string/lower.rst +++ b/reference/sql/sql_functions/scalar_functions/string/lower.rst @@ -45,7 +45,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line TEXT); + CREATE TABLE jabberwocky(line VARCHAR(50)); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves'), (' Did gyre and gimble in the wabe:') diff --git a/reference/sql/sql_functions/scalar_functions/string/octet_length.rst b/reference/sql/sql_functions/scalar_functions/string/octet_length.rst index 22516ce39..8bb1e3daf 100644 --- a/reference/sql/sql_functions/scalar_functions/string/octet_length.rst +++ b/reference/sql/sql_functions/scalar_functions/string/octet_length.rst @@ -12,7 +12,7 @@ Calculates the number of bytes in a string. * To get the length in characters, see :ref:`char_length`. - * For ``TEXT`` strings, the octet length is the number of characters. Use :ref:`len` instead. + * For ``VARCHAR`` strings, the octet length is the number of characters. Use :ref:`len` instead. Syntax ========== diff --git a/reference/sql/sql_functions/scalar_functions/string/patindex.rst b/reference/sql/sql_functions/scalar_functions/string/patindex.rst index 4a4e7208e..7e2ce8f79 100644 --- a/reference/sql/sql_functions/scalar_functions/string/patindex.rst +++ b/reference/sql/sql_functions/scalar_functions/string/patindex.rst @@ -69,7 +69,7 @@ Notes * If the value is NULL, the result is NULL. -* PATINDEX works on ``TEXT`` text types only. +* PATINDEX works on ``VARCHAR`` text types only. * PATINDEX does not work on all literal values - only on column values. diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst index dc16413af..5f3bd75a0 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst @@ -99,14 +99,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst index da2922798..bade0bb01 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst @@ -105,14 +105,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst index 9d623bf7f..1730d6ebf 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst @@ -104,14 +104,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/replace.rst b/reference/sql/sql_functions/scalar_functions/string/replace.rst index 11b3fb643..5d489e0d3 100644 --- a/reference/sql/sql_functions/scalar_functions/string/replace.rst +++ b/reference/sql/sql_functions/scalar_functions/string/replace.rst @@ -6,6 +6,8 @@ REPLACE Replaces all occurrences of a specified string value with another string value. +.. warning:: With ``VARCHAR``, a substring can only be replaced with another substring of equal **byte length**. See :ref:`octet_length`. + Syntax ========== diff --git a/reference/sql/sql_functions/scalar_functions/string/rlike.rst b/reference/sql/sql_functions/scalar_functions/string/rlike.rst index b379568df..15dab212a 100644 --- a/reference/sql/sql_functions/scalar_functions/string/rlike.rst +++ b/reference/sql/sql_functions/scalar_functions/string/rlike.rst @@ -99,15 +99,15 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name text, - Team text, - Number tinyint, - Position text, - Age tinyint, - Height text, - Weight real, - College text, - Salary float + "Name" varchar(40), + "Team" varchar(40), + "Number" tinyint, + "Position" varchar(2), + "Age" tinyint, + "Height" varchar(4), + "Weight" real, + "College" varchar(40), + "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/rtrim.rst b/reference/sql/sql_functions/scalar_functions/string/rtrim.rst index 61fdc877d..2bd5bbc38 100644 --- a/reference/sql/sql_functions/scalar_functions/string/rtrim.rst +++ b/reference/sql/sql_functions/scalar_functions/string/rtrim.rst @@ -35,7 +35,7 @@ Returns the same type as the argument supplied. Notes ======= -* When using ``TEXT`` values, SQream DB automatically trims the trailing whitespace. Using ``RTRIM`` on ``TEXT`` does not affect the result. +* When using ``VARCHAR`` values, SQream DB automatically trims the trailing whitespace. Using ``RTRIM`` on ``VARCHAR`` does not affect the result. * This function is equivalent to the ANSI form ``TRIM( TRAILING FROM expr )`` diff --git a/reference/sql/sql_functions/scalar_functions/string/substring.rst b/reference/sql/sql_functions/scalar_functions/string/substring.rst index bf2f6a0df..3bfd98b73 100644 --- a/reference/sql/sql_functions/scalar_functions/string/substring.rst +++ b/reference/sql/sql_functions/scalar_functions/string/substring.rst @@ -54,15 +54,15 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name text, - Team text, - Number tinyint, - Position text, - Age tinyint, - Height text, - Weight real, - College text - Salary float + "Name" varchar(40), + "Team" varchar(40), + "Number" tinyint, + "Position" varchar(2), + "Age" tinyint, + "Height" varchar(4), + "Weight" real, + "College" varchar(40), + "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/trim.rst b/reference/sql/sql_functions/scalar_functions/string/trim.rst index d249c8952..d6e90c2f8 100644 --- a/reference/sql/sql_functions/scalar_functions/string/trim.rst +++ b/reference/sql/sql_functions/scalar_functions/string/trim.rst @@ -35,7 +35,7 @@ Returns the same type as the argument supplied. Notes ======= -* When using ``TEXT`` values, SQream DB automatically trims the trailing whitespace. +* When using ``VARCHAR`` values, SQream DB automatically trims the trailing whitespace. * This function is equivalent to the ANSI form ``TRIM( BOTH FROM expr )`` diff --git a/reference/sql/sql_functions/scalar_functions/string/upper.rst b/reference/sql/sql_functions/scalar_functions/string/upper.rst index d2b700144..219bc854e 100644 --- a/reference/sql/sql_functions/scalar_functions/string/upper.rst +++ b/reference/sql/sql_functions/scalar_functions/string/upper.rst @@ -45,7 +45,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line TEXT); + CREATE TABLE jabberwocky(line VARCHAR(50)); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves'), (' Did gyre and gimble in the wabe:') diff --git a/reference/sql/sql_functions/window_functions/first_value.rst b/reference/sql/sql_functions/window_functions/first_value.rst index 65d904a04..07708872d 100644 --- a/reference/sql/sql_functions/window_functions/first_value.rst +++ b/reference/sql/sql_functions/window_functions/first_value.rst @@ -5,7 +5,7 @@ FIRST_VALUE ************************** The **FIRST_VALUE** function returns the value located in the selected column of the first row of a segment. If the table is not segmented, the FIRST_VALUE function returns the value from the first row of the whole table. -This function returns the same type of variable that you input for your requested value. For example, requesting the value for the first employee in a list using an ``int`` type output returns an ``int`` type ID column. If you use a ``text`` type, the function returns a ``text`` type name column. +This function returns the same type of variable that you input for your requested value. For example, requesting the value for the first employee in a list using an ``int`` type output returns an ``int`` type ID column. If you use a ``varchar`` type, the function returns a ``varchar`` type name column. Syntax ------- diff --git a/reference/sql/sql_functions/window_functions/lag.rst b/reference/sql/sql_functions/window_functions/lag.rst index 9c7333107..e93be2821 100644 --- a/reference/sql/sql_functions/window_functions/lag.rst +++ b/reference/sql/sql_functions/window_functions/lag.rst @@ -59,14 +59,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/window_functions/last_value.rst b/reference/sql/sql_functions/window_functions/last_value.rst index 967ed6baf..3cadaa9d1 100644 --- a/reference/sql/sql_functions/window_functions/last_value.rst +++ b/reference/sql/sql_functions/window_functions/last_value.rst @@ -5,7 +5,7 @@ LAST_VALUE ************************** The **LAST_VALUE** function returns the value located in the selected column of the last row of a segment. If the table is not segmented, the LAST_VALUE function returns the value from the last row of the whole table. -This function returns the same type of variable that you input for your requested value. For example, requesting the value for the last employee in a list using an ``int`` type output returns an ``int`` type ID column. If you use a ``text`` type, the function returns a ``text`` type name column. +This function returns the same type of variable that you input for your requested value. For example, requesting the value for the last employee in a list using an ``int`` type output returns an ``int`` type ID column. If you use a ``varchar`` type, the function returns a ``varchar`` type name column. Syntax ------- diff --git a/reference/sql/sql_functions/window_functions/lead.rst b/reference/sql/sql_functions/window_functions/lead.rst index ef3f30ff8..bc311689f 100644 --- a/reference/sql/sql_functions/window_functions/lead.rst +++ b/reference/sql/sql_functions/window_functions/lead.rst @@ -59,14 +59,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/window_functions/nth_value.rst b/reference/sql/sql_functions/window_functions/nth_value.rst index 05617e484..a2c1dd9a6 100644 --- a/reference/sql/sql_functions/window_functions/nth_value.rst +++ b/reference/sql/sql_functions/window_functions/nth_value.rst @@ -22,8 +22,8 @@ The following example shows the syntax for a table named ``superstore`` used for CREATE TABLE superstore ( - "Section" text, - "Product_Name" text, + "Section" varchar(40), + "Product_Name" varchar(40), "Sales_In_K" int, ); diff --git a/reference/sql/sql_functions/window_functions/rank.rst b/reference/sql/sql_functions/window_functions/rank.rst index 5586a7328..28856bd04 100644 --- a/reference/sql/sql_functions/window_functions/rank.rst +++ b/reference/sql/sql_functions/window_functions/rank.rst @@ -48,14 +48,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_functions/window_functions/row_number.rst b/reference/sql/sql_functions/window_functions/row_number.rst index 6b798d0c1..ea5786aef 100644 --- a/reference/sql/sql_functions/window_functions/row_number.rst +++ b/reference/sql/sql_functions/window_functions/row_number.rst @@ -48,14 +48,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index 09ebbe820..cc87c7b8f 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -113,7 +113,7 @@ A simple table from Tab-delimited file (TSV) .. code-block:: postgres CREATE OR REPLACE FOREIGN TABLE cool_animals - (id INT NOT NULL, name TEXT NOT NULL, weight FLOAT NOT NULL) + (id INT NOT NULL, name TEXT(30) NOT NULL, weight FLOAT NOT NULL) WRAPPER csv_fdw OPTIONS ( LOCATION = '/home/rhendricks/cool_animals.csv', @@ -128,7 +128,7 @@ A table from a directory of Parquet files on HDFS .. code-block:: postgres CREATE FOREIGN TABLE users - (id INT NOT NULL, name TEXT NOT NULL, email TEXT NOT NULL) + (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) WRAPPER parquet_fdw OPTIONS ( @@ -141,7 +141,7 @@ A table from a bucket of ORC files on S3 .. code-block:: postgres CREATE FOREIGN TABLE users - (id INT NOT NULL, name TEXT NOT NULL, email TEXT NOT NULL) + (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) WRAPPER orc_fdw OPTIONS ( diff --git a/reference/sql/sql_statements/ddl_commands/create_function.rst b/reference/sql/sql_statements/ddl_commands/create_function.rst index a693fc897..339543a0a 100644 --- a/reference/sql/sql_statements/ddl_commands/create_function.rst +++ b/reference/sql/sql_statements/ddl_commands/create_function.rst @@ -52,7 +52,7 @@ Parameters * - ``argument_list`` - A comma separated list of column definitions. A column definition includes a name identifier and a datatype. * - ``return_type`` - - The SQL datatype of the return value, such as ``INT``, ``TEXT``, etc. + - The SQL datatype of the return value, such as ``INT``, ``VARCHAR``, etc. * - ``function_body`` - Python code, dollar-quoted (``$$``). diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index a96cffe5c..9000e8310 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -140,7 +140,7 @@ The following is an example of the syntax used to create a standard table: CREATE TABLE cool_animals ( id INT NOT NULL, - name text NOT NULL, + name varchar(30) NOT NULL, weight FLOAT, is_agressive BOOL ); @@ -154,7 +154,7 @@ The following is an example of the syntax used to create a table with default va CREATE TABLE cool_animals ( id INT NOT NULL, - name text NOT NULL, + name varchar(30) NOT NULL, weight FLOAT, is_agressive BOOL DEFAULT false NOT NULL ); @@ -170,8 +170,8 @@ The following is an example of the syntax used to create a table with an identit CREATE TABLE users ( id BIGINT IDENTITY(0,1) NOT NULL , -- Start with 0, increment by 1 - name TEXT NOT NULL, - country TEXT DEFAULT 'Unknown' NOT NULL + name VARCHAR(30) NOT NULL, + country VARCHAR(30) DEFAULT 'Unknown' NOT NULL ); .. note:: @@ -202,9 +202,9 @@ The following is an example of the syntax used to create a table with a clusteri .. code-block:: postgres CREATE TABLE users ( - name TEXT NOT NULL, + name VARCHAR(30) NOT NULL, start_date datetime not null, - country TEXT DEFAULT 'Unknown' NOT NULL + country VARCHAR(30) DEFAULT 'Unknown' NOT NULL ) CLUSTER BY start_date; For more information on data clustering, see :ref:`data_clustering`. diff --git a/reference/sql/sql_statements/dml_commands/select.rst b/reference/sql/sql_statements/dml_commands/select.rst index c2d7bc786..299a83af1 100644 --- a/reference/sql/sql_statements/dml_commands/select.rst +++ b/reference/sql/sql_statements/dml_commands/select.rst @@ -163,15 +163,15 @@ Assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name text, - Team text, - Number tinyint, - Position text, - Age tinyint, - Height text, - Weight real, - College text, - Salary float + "Name" varchar(40), + "Team" varchar(40), + "Number" tinyint, + "Position" varchar(2), + "Age" tinyint, + "Height" varchar(4), + "Weight" real, + "College" varchar(40), + "Salary" float ); diff --git a/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst b/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst index 0fe995d36..bf246b803 100644 --- a/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst @@ -51,7 +51,7 @@ Getting the DDL for a database farm=> SELECT DUMP_DATABASE_DDL(); create table "public"."cool_animals" ( "id" int not null, - "name" text not null, + "name" varchar(30) not null, "weight" double null, "is_agressive" bool default false not null ) diff --git a/reference/sql/sql_statements/utility_commands/get_ddl.rst b/reference/sql/sql_statements/utility_commands/get_ddl.rst index 5afbab035..f2566e99a 100644 --- a/reference/sql/sql_statements/utility_commands/get_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_ddl.rst @@ -55,7 +55,7 @@ The result of the ``GET_DDL`` function is a verbose version of the :ref:`create_ farm=> CREATE TABLE cool_animals ( id INT NOT NULL, - name text NOT NULL, + name varchar(30) NOT NULL, weight FLOAT, is_agressive BOOL DEFAULT false NOT NULL ); @@ -64,7 +64,7 @@ The result of the ``GET_DDL`` function is a verbose version of the :ref:`create_ farm=> SELECT GET_DDL('cool_animals'); create table "public"."cool_animals" ( "id" int not null, - "name" text not null, + "name" varchar(30) not null, "weight" double null, "is_agressive" bool default false not null ) ; diff --git a/reference/sql/sql_statements/utility_commands/save_query.rst b/reference/sql/sql_statements/utility_commands/save_query.rst index 079ce86b9..d61d37fc3 100644 --- a/reference/sql/sql_statements/utility_commands/save_query.rst +++ b/reference/sql/sql_statements/utility_commands/save_query.rst @@ -56,7 +56,7 @@ Notes * Query parameters can be used as substitutes for literal expressions. Parameters cannot be used to substitute identifiers, column names, table names, or other parts of the query. -* Query parameters of a string datatype (like ``TEXT``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc) +* Query parameters of a string datatype (like ``VARCHAR``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc) * Query parameters' types are inferred at compile time. @@ -70,15 +70,15 @@ Assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name text, - Team text, - Number tinyint, - Position text, - Age tinyint, - Height text, - Weight real, - College text, - Salary float + "Name" varchar(40), + "Team" varchar(40), + "Number" tinyint, + "Position" varchar(2), + "Age" tinyint, + "Height" varchar(4), + "Weight" real, + "College" varchar(40), + "Salary" float ); diff --git a/reference/sql/sql_syntax/literals.rst b/reference/sql/sql_syntax/literals.rst index 503bec57e..1daf4f765 100644 --- a/reference/sql/sql_syntax/literals.rst +++ b/reference/sql/sql_syntax/literals.rst @@ -81,7 +81,7 @@ Examples '1997-01-01' -- This is a string -The actual data type of the value changes based on context, the format used, and the value itself. In the example below, the first value is interpreted as a ``DATE``, while the second is interpreted as ``TEXT``. +The actual data type of the value changes based on context, the format used, and the value itself. In the example below, the first value is interpreted as a ``DATE``, while the second is interpreted as a ``VARCHAR``. .. code-block:: postgres @@ -127,7 +127,7 @@ Syntax reference | REAL | DATE | DATETIME - | TEXT ( digits ) + | VARCHAR ( digits ) Examples ---------- diff --git a/reference/sql/sql_syntax/subqueries.rst b/reference/sql/sql_syntax/subqueries.rst index 921f69b50..785b1f6df 100644 --- a/reference/sql/sql_syntax/subqueries.rst +++ b/reference/sql/sql_syntax/subqueries.rst @@ -24,14 +24,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql/sql_syntax/window_functions.rst b/reference/sql/sql_syntax/window_functions.rst index 71fde1def..cb87e085e 100644 --- a/reference/sql/sql_syntax/window_functions.rst +++ b/reference/sql/sql_syntax/window_functions.rst @@ -221,14 +221,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" text, - "Team" text, + "Name" varchar(40), + "Team" varchar(40), "Number" tinyint, - "Position" text, + "Position" varchar(2), "Age" tinyint, - "Height" text, + "Height" varchar(4), "Weight" real, - "College" text, + "College" varchar(40), "Salary" float ); diff --git a/reference/sql_feature_support.rst b/reference/sql_feature_support.rst index 5c0817e10..8337724ca 100644 --- a/reference/sql_feature_support.rst +++ b/reference/sql_feature_support.rst @@ -47,7 +47,7 @@ Read more about :ref:`supported data types`. * - ``DECIMAL``, ``NUMERIC`` - Yes - Fixed-point numbers. - * - ``TEXT`` + * - ``VARCHAR`` - Yes - Variable length string - ASCII only * - ``TEXT`` diff --git a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst index 6b8b3fc10..25d2be354 100644 --- a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst @@ -223,7 +223,7 @@ The following table describes the DDL Optimizer screen: * - Column area - Shows the column **names** and **column types** from the selected table. You can scroll down or to the right/left for long column lists. * - Optimization area - - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``TEXT`` fields), and the default percent buffer to add to ``TEXT`` lengths (10%). Attempts to determine field nullability. + - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``VARCHAR`` fields), and the default percent buffer to add to ``VARCHAR`` lengths (10%). Attempts to determine field nullability. * - Run Optimizer - Starts the optimization process. diff --git a/third_party_tools/client_drivers/cpp/insert_test.cpp b/third_party_tools/client_drivers/cpp/insert_test.cpp index 560b04323..d395be31a 100644 --- a/third_party_tools/client_drivers/cpp/insert_test.cpp +++ b/third_party_tools/client_drivers/cpp/insert_test.cpp @@ -14,7 +14,7 @@ int main () { "raviga", "sqream"); run_direct_query(&sqc, - "CREATE TABLE animals (id INT NOT NULL, name TEXT NOT NULL)"); + "CREATE TABLE animals (id INT NOT NULL, name VARCHAR(10) NOT NULL)"); // prepare the statement sqc.new_query("INSERT INTO animals VALUES (?, ?)"); @@ -27,7 +27,7 @@ int main () { for (int i = 0; i < len; ++i) { sqc.set_int(0, row0[i]); - sqc.set_text(1, row1[i]); + sqc.set_varchar(1, row1[i]); sqc.next_query_row(); } diff --git a/third_party_tools/client_drivers/python/index.rst b/third_party_tools/client_drivers/python/index.rst index 1e0d8435c..c2f5911b3 100644 --- a/third_party_tools/client_drivers/python/index.rst +++ b/third_party_tools/client_drivers/python/index.rst @@ -351,7 +351,7 @@ This example loads 10,000 rows of dummy data to a SQream DB instance , clustered=True) # Create a table for loading - create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s text, ss text, dt date, dtt datetime)' + create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s varchar(12), ss text, dt date, dtt datetime)' con.execute(create) # After creating the table, we can load data into it with the INSERT command @@ -471,8 +471,8 @@ For example: 'employees' , metadata , sa.Column('id', sa.Integer) - , sa.Column('name', sa.TEXT) - , sa.Column('lastname', sa.TEXT) + , sa.Column('name', sa.VARCHAR(32)) + , sa.Column('lastname', sa.VARCHAR(32)) , sa.Column('salary', sa.Float) ) diff --git a/third_party_tools/client_platforms/tibco_spotfire.rst b/third_party_tools/client_platforms/tibco_spotfire.rst index f68f71b25..b98ae0825 100644 --- a/third_party_tools/client_platforms/tibco_spotfire.rst +++ b/third_party_tools/client_platforms/tibco_spotfire.rst @@ -141,7 +141,7 @@ After creating a connection, you can create your SQream data source template. Integer - TEXT) + VARCHAR(2048) String diff --git a/troubleshooting/log_related_issues.rst b/troubleshooting/log_related_issues.rst index 4b02957e4..a260f59d5 100644 --- a/troubleshooting/log_related_issues.rst +++ b/troubleshooting/log_related_issues.rst @@ -18,7 +18,7 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas CREATE FOREIGN TABLE logs ( - start_marker TEXT, + start_marker VARCHAR(4), row_id BIGINT, timestamp DATETIME, message_level TEXT, @@ -32,7 +32,7 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas service_name TEXT, message_type_id INT, message TEXT, - end_message TEXT + end_message VARCHAR(5) ) WRAPPER csv_fdw OPTIONS From 72ae126af297b5abbe6e32ee9c003d113a4cc01e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 21 Jun 2022 18:58:07 +0300 Subject: [PATCH 257/300] Update monitoring_query_performance.rst --- .../monitoring_query_performance.rst | 242 +++++++++++++++++- 1 file changed, 230 insertions(+), 12 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 703a0e39f..a542f61e6 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -47,7 +47,7 @@ First, create a foreign table for the logs .. code-block:: postgres CREATE FOREIGN TABLE logs ( - start_marker TEXT, + start_marker VARCHAR(4), row_id BIGINT, timestamp DATETIME, message_level TEXT, @@ -61,7 +61,7 @@ First, create a foreign table for the logs service_name TEXT, message_type_id INT, message TEXT, - end_message TEXT + end_message VARCHAR(5) ) WRAPPER cdv_fdw OPTIONS @@ -133,14 +133,15 @@ Understanding the Query Execution Plan Output Both :ref:`show_node_info` and the logged execution plans represents the query plan as a graph hierarchy, with data separated into different columns. Each row represents a single logical database operation, which is also called a **node** or **chunk producer**. A node reports several metrics during query execution, such as how much data it has read and written, how many chunks and rows, and how much time has elapsed. -Consider the example show_node_info presented above. The source node with ID #11 (``ReadTable``), has a parent node ID #10 (``CpuDecompress``). - -If we were to draw this out in a graph, it would look like this: - +Consider the example show_node_info presented above. The source node with ID #11 (``ReadTable``), has a parent node ID #10 +(``CpuDecompress``). If we were to draw this out in a graph, it'd look like this: .. figure:: /_static/images/show_node_info_graph.png :height: 70em :align: center - + + This graph explains how the query execution details are arranged in a logical order, from the bottom up. + + The last node, also called the sink, has a parent node ID of -1, meaning it has no parent. This is typically a node that sends data over the network or into a table. @@ -199,7 +200,7 @@ Commonly Seen Nodes - Description * - ``CpuDecompress`` - CPU - - Decompression operation, common for longer ``TEXT`` types + - Decompression operation, common for longer ``VARCHAR`` types * - ``CpuLoopJoin`` - CPU - A non-indexed nested loop join, performed on the CPU @@ -459,7 +460,7 @@ Identifying the Offending Nodes 494 | 194 | DeferredGather | 133241 | 20 | 6662 | 2020-09-04 19:07:03 | 193 | | | | 0.41 [...] 494 | 221 | ReadTable | 20000000 | 20 | 1000000 | 2020-09-04 19:07:01 | 220 | 20MB | | public.part | 0.1 - + When you see ``DeferredGather`` operations taking more than a few seconds, that's a sign that you're selecting too much data. In this case, the DeferredGather with node ID 166 took over 21 seconds. @@ -620,8 +621,225 @@ Common Solutions for Improving Filtering * Use :ref:`clustering keys and naturally ordered data` in your filters. * Avoid full table scans when possible +4. Joins with ``varchar`` Keys +----------------------------------- +Joins on long text keys, such as ``varchar(100)`` do not perform as well as numeric data types or very short text keys. + +Identifying the Situation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +When a join is inefficient, you may note that a query spends a lot of time on the ``Join`` node. +For example, consider these two table structures: + +.. code-block:: postgres + CREATE TABLE t_a + ( + amt FLOAT NOT NULL, + i INT NOT NULL, + ts DATETIME NOT NULL, + country_code VARCHAR(3) NOT NULL, + flag VARCHAR(10) NOT NULL, + fk VARCHAR(50) NOT NULL + ); + CREATE TABLE t_b + ( + id VARCHAR(50) NOT NULL + prob FLOAT NOT NULL, + j INT NOT NULL, + ); +#. + Run a query. + + In this example, we will join ``t_a.fk`` with ``t_b.id``, both of which are ``VARCHAR(50)``. + + .. code-block:: postgres + + SELECT AVG(t_b.j :: BIGINT), + t_a.country_code + FROM t_a + JOIN t_b ON (t_a.fk = t_b.id) + GROUP BY t_a.country_code +#. + + Observe the execution information by using the foreign table, or use ``show_node_info`` + + The execution below has been shortened, but note the highlighted rows for ``Join``. + The ``Join`` node is by far the most time-consuming part of this statement - clocking in at 69.7 seconds + joining 1.5 billion records. + + .. code-block:: psql + :linenos: + :emphasize-lines: 8 + + t=> SELECT show_node_info(5); + stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum + --------+---------+----------------------+------------+--------+-------------------+---------------------+----------------+-------+-------+------------+-------- + [...] + 5 | 19 | GpuTransform | 1497366528 | 204 | 7340032 | 2020-09-08 18:29:03 | 18 | | | | 1.46 + 5 | 20 | ReorderInput | 1497366528 | 204 | 7340032 | 2020-09-08 18:29:03 | 19 | | | | 0 + 5 | 21 | ReorderInput | 1497366528 | 204 | 7340032 | 2020-09-08 18:29:03 | 20 | | | | 0 + 5 | 22 | Join | 1497366528 | 204 | 7340032 | 2020-09-08 18:29:03 | 21 | | | inner | 69.7 + 5 | 24 | AddSortedMinMaxMet.. | 6291456 | 1 | 6291456 | 2020-09-08 18:26:05 | 22 | | | | 0 + 5 | 25 | Sort | 6291456 | 1 | 6291456 | 2020-09-08 18:26:05 | 24 | | | | 2.06 + [...] + 5 | 31 | ReadTable | 6291456 | 1 | 6291456 | 2020-09-08 18:26:03 | 30 | 235MB | | public.t_b | 0.02 + [...] + 5 | 41 | CpuDecompress | 10000000 | 2 | 5000000 | 2020-09-08 18:26:09 | 40 | | | | 0 + 5 | 42 | ReadTable | 10000000 | 2 | 5000000 | 2020-09-08 18:26:09 | 41 | 14MB | | public.t_a | 0 + +Improving Query Performance +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +* In general, try to avoid ``VARCHAR`` as a join key. As a rule of thumb, ``BIGINT`` works best as a join key. +* + Convert text values on-the-fly before running the query. For example, the :ref:`crc64` function takes a text + input and returns a ``BIGINT`` hash. + + For example: + + .. code-block:: postgres + + SELECT AVG(t_b.j :: BIGINT), + t_a.country_code + FROM t_a + JOIN t_b ON (crc64_join(t_a.fk) = crc64_join(t_b.id)) + GROUP BY t_a.country_code + The execution below has been shortened, but note the highlighted rows for ``Join``. + The ``Join`` node went from taking nearly 70 seconds, to just 6.67 seconds for joining 1.5 billion records. + + .. code-block:: psql + :linenos: + :emphasize-lines: 8 + + t=> SELECT show_node_info(6); + stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum + --------+---------+----------------------+------------+--------+-------------------+---------------------+----------------+-------+-------+------------+-------- + [...] + 6 | 19 | GpuTransform | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 18 | | | | 1.48 + 6 | 20 | ReorderInput | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 19 | | | | 0 + 6 | 21 | ReorderInput | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 20 | | | | 0 + 6 | 22 | Join | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 21 | | | inner | 6.67 + 6 | 24 | AddSortedMinMaxMet.. | 6291456 | 1 | 6291456 | 2020-09-08 18:55:12 | 22 | | | | 0 + [...] + 6 | 32 | ReadTable | 6291456 | 1 | 6291456 | 2020-09-08 18:55:12 | 31 | 235MB | | public.t_b | 0.02 + [...] + 6 | 43 | CpuDecompress | 10000000 | 2 | 5000000 | 2020-09-08 18:55:13 | 42 | | | | 0 + 6 | 44 | ReadTable | 10000000 | 2 | 5000000 | 2020-09-08 18:55:13 | 43 | 14MB | | public.t_a | 0 + +* You can map some text values to numeric types by using a dimension table. Then, reconcile the values when you need them by joining the dimension table. + +5. Sorting on big ``VARCHAR`` fields +--------------------------------------- +In general, SQream DB automatically inserts a ``Sort`` node which arranges the data prior to reductions and aggregations. +When running a ``GROUP BY`` on large ``VARCHAR`` fields, you may see nodes for ``Sort`` and ``Reduce`` taking a long time. + +Identifying the Situation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +When running a statement, inspect it with :ref:`show_node_info`. If you see ``Sort`` and ``Reduce`` among +your top five longest running nodes, there is a potential issue. +For example: +#. + Run a query to test it out. + + + Our ``t_inefficient`` table contains 60,000,000 rows, and the structure is simple, but with an oversized ``country_code`` column: + + .. code-block:: postgres + :emphasize-lines: 5 + + CREATE TABLE t_inefficient ( + i INT NOT NULL, + amt DOUBLE NOT NULL, + ts DATETIME NOT NULL, + country_code VARCHAR(100) NOT NULL, + flag VARCHAR(10) NOT NULL, + string_fk VARCHAR(50) NOT NULL + ); + + We will run a query, and inspect it's execution details: + + .. code-block:: psql + + t=> SELECT country_code, + . SUM(amt) + . FROM t_inefficient + . GROUP BY country_code; + executed + time: 47.55s + + country_code | sum + -------------+----------- + VUT | 1195416012 + GIB | 1195710372 + TUR | 1195946178 + [...] + + + .. code-block:: psql + :emphasize-lines: 8,9 + + t=> select show_node_info(30); + stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum + --------+---------+--------------------+----------+--------+-------------------+---------------------+----------------+-------+-------+----------------------+-------- + 30 | 1 | PushToNetworkQueue | 249 | 1 | 249 | 2020-09-10 16:17:10 | -1 | | | | 0.25 + 30 | 2 | Rechunk | 249 | 1 | 249 | 2020-09-10 16:17:10 | 1 | | | | 0 + 30 | 3 | ReduceMerge | 249 | 1 | 249 | 2020-09-10 16:17:10 | 2 | | | | 0.01 + 30 | 4 | GpuToCpu | 1508 | 15 | 100 | 2020-09-10 16:17:10 | 3 | | | | 0 + 30 | 5 | Reduce | 1508 | 15 | 100 | 2020-09-10 16:17:10 | 4 | | | | 7.23 + 30 | 6 | Sort | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 5 | | | | 36.8 + 30 | 7 | GpuTransform | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 6 | | | | 0.08 + 30 | 8 | GpuDecompress | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 7 | | | | 2.01 + 30 | 9 | CpuToGpu | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 8 | | | | 0.16 + 30 | 10 | Rechunk | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 9 | | | | 0 + 30 | 11 | CpuDecompress | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 10 | | | | 0 + 30 | 12 | ReadTable | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 11 | 520MB | | public.t_inefficient | 0.05 + +#. We can look to see if there's any shrinking we can do on the ``GROUP BY`` key + + .. code-block:: psql + + t=> SELECT MAX(LEN(country_code)) FROM t_inefficient; + max + --- + 3 + With a maximum string length of just 3 characters, our ``VARCHAR(100)`` is way oversized. +#. + We can recreate the table with a more restrictive ``VARCHAR(3)``, and can examine the difference in performance: + + .. code-block:: psql + t=> CREATE TABLE t_efficient + . AS SELECT i, + . amt, + . ts, + . country_code::VARCHAR(3) AS country_code, + . flag + . FROM t_inefficient; + executed + time: 16.03s + + t=> SELECT country_code, + . SUM(amt::bigint) + . FROM t_efficient + . GROUP BY country_code; + executed + time: 4.75s + country_code | sum + -------------+----------- + VUT | 1195416012 + GIB | 1195710372 + TUR | 1195946178 + [...] + + This time, the entire query took just 4.75 seconds, or just about 91% faster. + +Improving Sort Performance on Text Keys +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +When using VARCHAR, ensure that the maximum length defined in the table structure is as small as necessary. +For example, if you're storing phone numbers, don't define the field as ``VARCHAR(255)``, as that affects sort performance. + +You can run a query to get the maximum column length (e.g. ``MAX(LEN(a_column))``), and potentially modify the table structure. + +.. _high_selectivity_data_opt: -4. High Selectivity Data +6. High Selectivity Data -------------------------- Selectivity is the ratio of cardinality to the number of records of a chunk. We define selectivity as :math:`\frac{\text{Distinct values}}{\text{Total number of records in a chunk}}` SQream DB has a hint called ``HIGH_SELECTIVITY``, which is a function you can wrap a condition in. @@ -656,7 +874,7 @@ Improving Performance with High Selectivity Hints to cut out more than 60% of the result set. * Use when the data is uniformly distributed or random -5. Performance of unsorted data in joins +7. Performance of unsorted data in joins ------------------------------------------ When data is not well-clustered or naturally ordered, a join operation can take a long time. @@ -719,7 +937,7 @@ To tell SQream DB to rechunk the data, wrap a condition (or several) in the ``HI AND EnterpriseID=1150 AND MSISDN='9724871140341'; -6. Manual Join Reordering +8. Manual Join Reordering -------------------------------- When joining multiple tables, you may wish to change the join order to join the smallest tables first. From 87d17be9707b3563121304d529f9f25bae6a7a36 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 23 Jun 2022 11:02:24 +0300 Subject: [PATCH 258/300] Added missing table --- .../ddl_commands/create_table.rst | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index 9000e8310..51f46582b 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -62,7 +62,7 @@ The following parameters can be used when creating a table: - A commma separated list of clustering column keys. - See :ref:`data_clustering` for more information. + See :ref:`flexible_data_clustering` for more information. * - ``LIKE`` - Duplicates the column structure of an existing table. @@ -74,7 +74,7 @@ Default Value Constraints The ``DEFAULT`` value constraint specifies a value to use if one is not defined in an :ref:`insert` or :ref:`copy_from` statement. -The value may be either a literal, which is evaluated at the time the row is created. +The value may be a literal, which is evaluated at the time the row is created. .. note:: The ``DEFAULT`` constraint only applies if the column does not have a value specified in the :ref:`insert` or :ref:`copy_from` statement. You can still insert a ``NULL`` into an nullable column by explicitly inserting ``NULL``. For example, ``INSERT INTO cool_animals VALUES (1, 'Gnu', NULL)``. @@ -82,6 +82,7 @@ Syntax --------- The following is the correct syntax for using the **DEFAULT** value constraints: + .. code-block:: postgres column_def :: = { column_name type_name [ default ] [ column_constraint ] } @@ -260,9 +261,9 @@ Either of the following examples can be used to create a second table based on t The generated output of both of the statements above is identical. -Creating a Table based on External Tables and Views +Creating a Table based on Foreign Tables and Views ~~~~~~~~~~~~ -The following is example of creating a table based on external tables and views: +The following is example of creating a table based on foreign tables and views: .. code-block:: postgres @@ -272,6 +273,24 @@ The following is example of creating a table based on external tables and views: When duplicating the column structure of an existing table, the target table of the ``LIKE`` clause can be a regular or an external table, or a view. +The following table describes the properties that must be copied from the target table: + ++-----------------------------+------------------+---------------------------------+---------------------------------+ +| **Property** | **Native Table** | **External Table** | **View** | ++-----------------------------+------------------+---------------------------------+---------------------------------+ +| Column names | Must be copied | Must be copied | Must be copied | ++-----------------------------+------------------+---------------------------------+---------------------------------+ +| Column types | Must be copied | Must be copied | Must be copied | ++-----------------------------+------------------+---------------------------------+---------------------------------+ +| ``NULL``/``NOT NULL`` | Must be copied | Must be copied | Must be copied | ++-----------------------------+------------------+---------------------------------+---------------------------------+ +| ``text`` length constraints | Must be copied | Must be copied | Does not exist in source object | ++-----------------------------+------------------+---------------------------------+---------------------------------+ +| Compression specification | Must be copied | Does not exist in source object | Does not exist in source object | ++-----------------------------+------------------+---------------------------------+---------------------------------+ +| Default/identity | Must be copied | Does not exist in source object | Does not exist in source object | ++-----------------------------+------------------+---------------------------------+---------------------------------+ + Permissions ============= -The role must have the ``CREATE`` permission at the schema level. +The role must have the ``CREATE`` permission at the schema level. \ No newline at end of file From 560b0e8f8fb4c4b62f9b0b8c42ec739db0b3875f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 23 Jun 2022 11:24:08 +0300 Subject: [PATCH 259/300] Line 243 --- reference/sql/sql_syntax/literals.rst | 162 +++++++++++++++++++++++--- 1 file changed, 144 insertions(+), 18 deletions(-) diff --git a/reference/sql/sql_syntax/literals.rst b/reference/sql/sql_syntax/literals.rst index 1daf4f765..906684590 100644 --- a/reference/sql/sql_syntax/literals.rst +++ b/reference/sql/sql_syntax/literals.rst @@ -4,21 +4,23 @@ Literals *************************** + Literals represent constant values. -SQream DB contains several types of literals: +SQream DB contains the following types of literals: -* :ref:`Number literals` - define numbers such as ``1.3``, ``-5`` +* :ref:`Numeric literals` - define numbers such as ``1.3``, ``-5`` * :ref:`String literals` - define text values like ``'Foxes are cool'``, ``'1997-01-01'`` * :ref:`Typed literals` - define values with explicit types like ``(3.0 :: float)`` -* :ref:`Other constants` - predfined values like ``NULL`` or ``TRUE`` +* :ref:`Boolean literals` - define values that include ``true`` and ``false`` +* :ref:`Other constants` - predefined values like ``NULL`` or ``TRUE`` -.. _number_literals: +.. _numeric_literals: -Number literals +Numeric Literals =================== -A number literal can be expressed in the following way: +**Numeric literals** can be expressed as follows: .. code-block:: postgres @@ -55,16 +57,19 @@ Examples For example, any number containing the decimal point will be considered ``FLOAT`` by default. Any whole number will considered ``INT``, unless the value is larger than the :ref:`maximum value`, in which case the type will become a ``BIGINT``. +.. note:: + A numeric literal that contains neither a decimal point nor an exponent is considered ``INT`` by default if its value fits in type ``INT`` (32 bits). If not, it is considered ``BIGINT`` by default if its value fits in type ``BIGINT`` (64 bits). If neither are true, it is considered ``FLOAT``. Literals that contain decimal points and/or exponents are always considered ``FLOAT``. + .. _string_literals: -String literals +String Literals ================== -String literals are string (text) values, encoded either in ASCII or UTF-8. +**String literals** are string (text) values, encoded either in ASCII or UTF-8. -A string literal is quoted with single quotes (``'``) or dollars (``$$``) +String literals are surrounded by single quotes (``'``) or dollars (``$$``) -.. tip:: To use a single quote in a string, repeat the single quote twice. See examples below. +.. tip:: To use a single quote in a string, use a repeated single quote. Examples @@ -86,24 +91,131 @@ The actual data type of the value changes based on context, the format used, and .. code-block:: postgres INSERT INTO cool_dates(date_col, reason) VALUES ('1955-11-05', 'Doc Brown discovers flux capacitor'); + +This section describes the following types of literals: + +* :ref:`Regular string literals` +* :ref:`Dollar-quoted string literals` +* :ref:`Escaped string literals` + + +.. _regular_literals: + +Regular String Literals +----------------------- +In SQL, a **regular string literal** is a sequence of zero or more characters bound by single quotes (``'``): + +.. code-block:: postgres + + 'This is a string'. + +You can include a single-quote character in a string literal with two consecutive single quotes (``''``): + +.. code-block:: postgres + + 'Dianne''s horse'. + +Note that two adjacent single quotes is not the same as a double-quote character (``"``). + +Examples +------------ + +The following are some examples of regular string literals: + +.. code-block:: postgres + + '123' + + 'אבג' + + 'a''b' + + '' + +.. _dollar_quoted_string_literals: + +Dollar-Quoted String Literals +----------------------- +**Dollar-quoted string literals** consist of a dollar sign (``$``), an optional "tag" of zero or more characters, another dollar sign, an arbitrary sequence of characters that make up the string content, a dollar sign, the same tag at the beginning of the dollar quote, and another dollar sign. + + +Examples +------------ + +For example, below are two different ways to specify the string ``Dianne's horse`` using dollar-quoted string literals: + +.. code-block:: postgres + + $$Dianne's horse$$ + $$Dianne's horse$$ + +Note that you can use single quotes inside the dollar-quoted string without an escape. Because the string is always written literally, you do not need to escape any characters inside a dollar-quoted string. Backslashes and dollar signs indicate no specific functions unless they are part of a sequence matching the opening tag. + +Any used tags in a dollar-quoted string follow the same rules as for unquoted identifiers, except that they cannot contain a dollar sign. + +In addition, because tags are case sensitive, ``$$String content$$`` is correct, but ``$$String content$$`` is incorrect. + +A dollar-quoted string that follows a keyword or identifier must be separated from it by whitespace (such as spaces, tabs, or newlines). If you do not separate them with whitespace, the dollar-quoting delimiter is taken as part of the preceding identifier. + +.. _escaped_string_literals: + +Escaped String Literals +----------------------- +Because regular string literals do not support inserting special characters (such as new lines), the **escaped string literals** syntax was added to support inserting special characters with an escaping syntax. + +In addition to being enclosed by single quotes (e.g. 'abc'), escaped string literals are preceded by a capital ``E``. + +.. code-block:: postgres + + E'abc' + +The character sequence inside the single quotes can contain escaped characters in addition to regular characters, shown below: + +.. list-table:: + :widths: 25 85 + :header-rows: 1 + + * - Sequence + - Interpretation + * - ``\b`` + - Inserts a backspace. + * - ``\f`` + - Inserts a form feed. + * - ``\n`` + - Inserts a newline. + * - ``\r`` + - Inserts a carriage return. + * - ``\t`` + - Inserts a tab. + * - ``\o``, ``\oo``, ```\ooo``` (``o`` = ``0`` - ``7``) + - Inserts an octal byte value. This sequence is currently not supported. + * - ``\xh``, ``\xhh`` (``h`` = ``0`` - ``9``, ``A`` - ``F``) + - Inserts a hexadecimal byte value. This sequence is currently not supported. + * - ``\uxxxx``, ``\Uxxxxxxxx`` + - Inserts a 16 or 32-bit hexadecimal unicode character value (x = 0 - 9, A - F). + +Excluding the characters in the table above, escaped string literals take all other characters following a backslash literally. To include a backslash character, use two consecutive backslashes (``\\``). You can use a single quote in an escape string by writing ``\'``, in addition to the normal method (``''``). .. _typed_literals: -Typed literals +Typed Literals ================ -A typed literal allows the creation of any data type using either of the following syntaxes: +**Typed literals** allow you to create any data type using either of the following syntaxes: .. code-block:: postgres CAST(literal AS type_name) - -- or + +.. code-block:: postgres + literal :: type_name See also :ref:`cast` for more information about supported casts. -Syntax reference +Syntax Reference ------------------- +The following is a syntax reference for typed literals: .. code-block:: postgres @@ -128,6 +240,7 @@ Syntax reference | DATE | DATETIME | VARCHAR ( digits ) + | TEXT ( digits ) Examples ---------- @@ -142,12 +255,25 @@ Examples CAST(42 :: FLOAT) +.. _boolean_literals: + +Boolean Literals +=================== +**Boolean literals** include the keywords ``true`` or ``false``. + +Example +---------- + +.. code-block:: postgres + + INSERT INTO animals VALUES ('fox',true), ('cat',true), ('kiwi',false); + .. _constants: -Other constants +Other Constants ================ -* ``TRUE`` and ``FALSE`` are interpreted as values of type ``BOOL``. - -* ``NULL`` - which has no type by itself. The type is inferred from context during query compilation. +The following other constants can be used: +* ``TRUE`` and ``FALSE`` - interpreted as values of type ``BOOL``. +* ``NULL`` - which has no type of its own. The type is inferred from context during query compilation. From e28feba30c185f13ffb881dedb5928efca39ee0d Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 23 Jun 2022 13:20:59 +0300 Subject: [PATCH 260/300] Standardized with Master --- .../client_platforms/pentaho.rst | 165 +++++++----------- 1 file changed, 65 insertions(+), 100 deletions(-) diff --git a/third_party_tools/client_platforms/pentaho.rst b/third_party_tools/client_platforms/pentaho.rst index 998a7db22..fa8146c41 100644 --- a/third_party_tools/client_platforms/pentaho.rst +++ b/third_party_tools/client_platforms/pentaho.rst @@ -1,10 +1,8 @@ .. _pentaho_data_integration: - ************************* -Connect to SQream Using Pentaho Data Integration +Connecting to SQream Using Pentaho Data Integration ************************* - .. _pentaho_top: Overview @@ -19,7 +17,6 @@ The Connecting to SQream Using Pentaho page describes the following: * :ref:`Defining your output ` * :ref:`Importing your data ` - .. _install_pentaho: Installing Pentaho @@ -50,76 +47,67 @@ You can install the driver by copying and pasting the SQream JDBC .jar file into Creating a Transformation ~~~~~~~~~~~~~~~~~~ - After installing Pentaho you can create a transformation. **To create a transformation:** 1. Use the CLI to open the PDI client for your operating system (Windows): - .. code-block:: console + .. code-block:: console - $ spoon.bat + $ spoon.bat 2. Open the spoon.bat file from its folder location. - -.. image:: /_static/images/third_party_connectors/pentaho/spoon_bat_file.png +:: + 3. In the **View** tab, right-click **Transformations** and click **New**. -.. image:: /_static/images/third_party_connectors/pentaho/pentaho_1.png - -A new transformation tab is created. - -.. image:: /_static/images/third_party_connectors/pentaho/pentaho_2.png + A new transformation tab is created. 4. In the **Design** tab, click **Input** to show its file contents. -.. image:: /_static/images/third_party_connectors/pentaho/pentaho_3.png +:: 5. Drag and drop the **CSV file input** item to the new transformation tab that you created. -.. image:: /_static/images/third_party_connectors/pentaho/pentaho_4.png +:: 6. Double-click **CSV file input**. The **CSV file input** panel is displayed. -.. image:: /_static/images/third_party_connectors/pentaho/pentaho_5.png +:: 7. In the **Step name** field, type a name. -.. image:: /_static/images/third_party_connectors/pentaho/pentaho_6.png +:: 8. To the right of the **Filename** field, click **Browse**. -.. image:: /_static/images/third_party_connectors/pentaho/pentaho_select_file.png +:: 9. Select the file that you want to read from and click **OK**. -.. image:: /_static/images/third_party_connectors/pentaho/add_csv_file.png +:: 10. In the CSV file input window, click **Get Fields**. -.. image:: /_static/images/third_party_connectors/pentaho/get_fields.png +:: 11. In the **Sample data** window, enter the number of lines you want to sample and click **OK**. The default setting is **100**. -.. image:: /_static/images/third_party_connectors/pentaho/number_of_lines_to_sample.png - -The tool reads the file and suggests the field name and type. - -.. image:: /_static/images/third_party_connectors/pentaho/suggested_field_name_and_type.png + The tool reads the file and suggests the field name and type. 12. In the CSV file input window, click **Preview**. -.. image:: /_static/images/third_party_connectors/pentaho/preview.png +:: 13. In the **Preview size** window, enter the number of rows you want to preview and click **OK**. The default setting is **1000**. -.. image:: /_static/images/third_party_connectors/pentaho/number_of_rows_to_preview.png +:: 14. Verify that the preview data is correct and click **Close**. -.. image:: /_static/images/third_party_connectors/pentaho/examine.png +:: 15. Click **OK** in the **CSV file input** window. @@ -135,13 +123,11 @@ After creating your transformation you must define your output. 1. In the **Design** tab, click **Output**. -.. image:: /_static/images/third_party_connectors/pentaho/design_output.png - The Output folder is opened. 2. Drag and drop **Table output** item to the Transformation window. -.. image:: /_static/images/third_party_connectors/pentaho/table_output.png +:: 3. Double-click **Table output** to open the **Table output** dialog box. @@ -149,48 +135,42 @@ After creating your transformation you must define your output. 4. From the **Table output** dialog box, type a **Step name** and click **New** to create a new connection. Your **steps** are the building blocks of a transformation, such as file input or a table output. -.. image:: /_static/images/third_party_connectors/pentaho/rename_table_output.png - -The **Database Connection** window is displayed with the **General** tab selected by default. - -.. image:: /_static/images/third_party_connectors/pentaho/database_connection_window.png + The **Database Connection** window is displayed with the **General** tab selected by default. 5. Enter or select the following information in the Database Connection window and click **Test**. -.. image:: /_static/images/third_party_connectors/pentaho/pentaho_fillout_database_connection_window.png - -The following table shows and describes the information that you need to fill out in the Database Connection window: - -.. list-table:: - :widths: 6 31 73 - :header-rows: 1 - - * - No. - - Element Name - - Description - * - 1 - - Connection name - - Enter a name that uniquely describes your connection, such as **sampledata**. - * - 2 - - Connection type - - Select **Generic database**. - * - 3 - - Access - - Select **Native (JDBC)**. - * - 4 - - Custom connection URL - - Insert **jdbc:Sqream:///;user=;password=;[; ...];**. The IP is a node in your SQream cluster and is the name or schema of the database you want to connect to. Verify that you have not used any leading or trailing spaces. - * - 5 - - Custom driver class name - - Insert **com.sqream.jdbc.SQDriver**. Verify that you have not used any leading or trailing spaces. - * - 6 - - Username - - Your SQreamdb username. If you leave this blank, you will be prompted to provide it when you connect. - * - 7 - - Password - - Your password. If you leave this blank, you will be prompted to provide it when you connect. - -The following message is displayed: + The following table shows and describes the information that you need to fill out in the Database Connection window: + + .. list-table:: + :widths: 6 31 73 + :header-rows: 1 + + * - No. + - Element Name + - Description + * - 1 + - Connection name + - Enter a name that uniquely describes your connection, such as **sampledata**. + * - 2 + - Connection type + - Select **Generic database**. + * - 3 + - Access + - Select **Native (JDBC)**. + * - 4 + - Custom connection URL + - Insert **jdbc:Sqream:///;user=;password=;[; ...];**. The IP is a node in your SQream cluster and is the name or schema of the database you want to connect to. Verify that you have not used any leading or trailing spaces. + * - 5 + - Custom driver class name + - Insert **com.sqream.jdbc.SQDriver**. Verify that you have not used any leading or trailing spaces. + * - 6 + - Username + - Your SQreamdb username. If you leave this blank, you will be prompted to provide it when you connect. + * - 7 + - Password + - Your password. If you leave this blank, you will be prompted to provide it when you connect. + + The following message is displayed: .. image:: /_static/images/third_party_connectors/pentaho/connection_tested_successfully_2.png @@ -210,34 +190,33 @@ For more information about backing up users, permissions, or schedules, see `Bac 1. Double-click the **Table output** connection that you just created. -.. image:: /_static/images/third_party_connectors/pentaho/table_output.png +:: 2. To the right of the **Target schema** field, click **Browse** and select a schema name. -.. image:: /_static/images/third_party_connectors/pentaho/select_schema_name.png +:: 3. Click **OK**. The selected schema name is displayed in the **Target schema** field. -.. image:: /_static/images/third_party_connectors/pentaho/selected_target_schema.png +:: 4. Create a new hop connection between the **CSV file input** and **Table output** steps: 1. On the CSV file input step item, click the **new hop connection** icon. - .. image:: /_static/images/third_party_connectors/pentaho/csv_file_input_options.png - - + .. image:: /_static/images/third_party_connectors/pentaho/csv_file_input_options.png 2. Drag an arrow from the **CSV file input** step item to the **Table output** step item. - .. image:: /_static/images/third_party_connectors/pentaho/csv_file_input_options_2.png - + .. image:: /_static/images/third_party_connectors/pentaho/csv_file_input_options_2.png 3. Release the mouse button. The following options are displayed. + + :: 4. Select **Main output of step**. -.. image:: /_static/images/third_party_connectors/pentaho/main_output_of_step.png + .. image:: /_static/images/third_party_connectors/pentaho/main_output_of_step.png :: @@ -247,26 +226,16 @@ For more information about backing up users, permissions, or schedules, see `Bac 6. In the **Target table** field, define a target table name. - .. image:: /_static/images/third_party_connectors/pentaho/target_table_name.png - :: 7. Click **SQL** to open the **Simple SQL editor.** - - .. image:: /_static/images/third_party_connectors/pentaho/sql_editor.png :: 8. In the **Simple SQL editor**, click **Execute**. - .. image:: /_static/images/third_party_connectors/pentaho/execute_sql_statements.png - The system processes and displays the results of the SQL statements. - - .. image:: /_static/images/third_party_connectors/pentaho/sql_statement_results_2.png - -:: - + 9. Close all open dialog boxes. :: @@ -275,14 +244,10 @@ For more information about backing up users, permissions, or schedules, see `Bac .. image:: /_static/images/third_party_connectors/pentaho/execute_transformation.png -:: - -The **Run Options** dialog box is displayed. + The **Run Options** dialog box is displayed. - .. image:: /_static/images/third_party_connectors/pentaho/run_options_dialog_box.png - -11. Click **Run**. The **Execution Results** are displayed. +11. Click **Run**. - .. image:: /_static/images/third_party_connectors/pentaho/execution_results_2.png - -:ref:`Back to Overview ` + The **Execution Results** are displayed. + +:ref:`Back to Overview ` \ No newline at end of file From e90a044a9c2ef9e3a69f430ba8eaa2fb30ae1732 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 23 Jun 2022 13:33:45 +0300 Subject: [PATCH 261/300] Added missing images --- .../images/connection_tested_successfully_2.png | Bin 0 -> 26000 bytes _static/images/csv_file_input_options.png | Bin 0 -> 36158 bytes _static/images/csv_file_input_options_2.png | Bin 0 -> 25955 bytes _static/images/main_output_of_step.png | Bin 0 -> 18581 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 _static/images/connection_tested_successfully_2.png create mode 100644 _static/images/csv_file_input_options.png create mode 100644 _static/images/csv_file_input_options_2.png create mode 100644 _static/images/main_output_of_step.png diff --git a/_static/images/connection_tested_successfully_2.png b/_static/images/connection_tested_successfully_2.png new file mode 100644 index 0000000000000000000000000000000000000000..ea474c7cbd20b3f0a4c8d7a6a188da07b2c59dc5 GIT binary patch literal 26000 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 G$bSL?Yg!Kg literal 0 HcmV?d00001 diff --git a/_static/images/csv_file_input_options.png b/_static/images/csv_file_input_options.png new file mode 100644 index 0000000000000000000000000000000000000000..fbf64e0e5a2826058ab7170da16d7783fd86c1c0 GIT binary patch literal 36158 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

rtpa~Fee}I_ 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�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 literal 0 HcmV?d00001 From 5610724d5d8be316d1035e78f13430e0843595d1 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 23 Jun 2022 13:47:05 +0300 Subject: [PATCH 262/300] Moved images to correct folder --- .../pentaho}/connection_tested_successfully_2.png | Bin .../pentaho}/csv_file_input_options.png | Bin .../pentaho}/csv_file_input_options_2.png | Bin .../pentaho}/main_output_of_step.png | Bin 4 files changed, 0 insertions(+), 0 deletions(-) rename _static/images/{ => third_party_connectors/pentaho}/connection_tested_successfully_2.png (100%) rename _static/images/{ => third_party_connectors/pentaho}/csv_file_input_options.png (100%) rename _static/images/{ => third_party_connectors/pentaho}/csv_file_input_options_2.png (100%) rename _static/images/{ => third_party_connectors/pentaho}/main_output_of_step.png (100%) diff --git a/_static/images/connection_tested_successfully_2.png b/_static/images/third_party_connectors/pentaho/connection_tested_successfully_2.png similarity index 100% rename from _static/images/connection_tested_successfully_2.png rename to _static/images/third_party_connectors/pentaho/connection_tested_successfully_2.png diff --git a/_static/images/csv_file_input_options.png b/_static/images/third_party_connectors/pentaho/csv_file_input_options.png similarity index 100% rename from _static/images/csv_file_input_options.png rename to _static/images/third_party_connectors/pentaho/csv_file_input_options.png diff --git a/_static/images/csv_file_input_options_2.png b/_static/images/third_party_connectors/pentaho/csv_file_input_options_2.png similarity index 100% rename from _static/images/csv_file_input_options_2.png rename to _static/images/third_party_connectors/pentaho/csv_file_input_options_2.png diff --git a/_static/images/main_output_of_step.png b/_static/images/third_party_connectors/pentaho/main_output_of_step.png similarity index 100% rename from _static/images/main_output_of_step.png rename to _static/images/third_party_connectors/pentaho/main_output_of_step.png From dea4737e072940f17ab36b74f2e32ff79755c2a5 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 3 Jul 2022 11:04:30 +0300 Subject: [PATCH 263/300] Removed FULL OUTER JOIN https://sqream.atlassian.net/browse/SQ-10996 --- reference/sql/sql_syntax/joins.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/reference/sql/sql_syntax/joins.rst b/reference/sql/sql_syntax/joins.rst index 2563e7a5d..b12b08875 100644 --- a/reference/sql/sql_syntax/joins.rst +++ b/reference/sql/sql_syntax/joins.rst @@ -46,8 +46,8 @@ The following shows the correct syntax for creating an **inner join**: .. code-block:: postgres - left_side [ INNER ] JOIN right_side ON value_expr - left_side [ INNER ] JOIN right_side USING ( join_column [, ... ] ) + left_side [ INNER ] JOIN left_side ON value_expr + left_side [ INNER ] JOIN left_side USING ( join_column [, ... ] ) Inner joins are the default join type and return rows from the ``left_side`` and ``right_side`` based on a matching condition. @@ -60,7 +60,6 @@ An inner join can also be specified by listing several tables in the ``FROM`` cl [ { INNER JOIN | LEFT [OUTER] JOIN | RIGHT [OUTER] JOIN - | FULL [OUTER] JOIN } table2 ON table1.column1 = table2.column1 ] Omitting the ``ON`` or ``WHERE`` clause creates a ``CROSS JOIN``, where every ``left_side`` row is matched with every ``right_side`` row. @@ -117,7 +116,7 @@ The ``CROSS JOIN`` clause cannot have an ``ON`` clause, but the ``WHERE`` clause The following is an example of two tables that will be used as the basis for a cross join: -.. image:: /_static/images/joins/color_table.png +.. image:: /_static/images/color_table.png The following is the output result of the cross join: @@ -323,4 +322,4 @@ The following is an example of using a join hint: --+--- 2 | 2 4 | 4 - 5 | 5 + 5 | 5 \ No newline at end of file From 90a2cfbcad0c5c940658a6b2d905665bb63af970 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 3 Jul 2022 11:17:32 +0300 Subject: [PATCH 264/300] Create color_table.png --- _static/images/color_table.png | Bin 0 -> 5672 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 _static/images/color_table.png diff --git a/_static/images/color_table.png b/_static/images/color_table.png new file mode 100644 index 0000000000000000000000000000000000000000..b815f96167688d7c5b770dc427a358bc6169789a GIT binary patch literal 5672 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 literal 0 HcmV?d00001 From c242a6f93cdef5cfa7f929b1bed75a185902f48c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 3 Jul 2022 14:01:41 +0300 Subject: [PATCH 265/300] Updated Tableau Connector Link --- third_party_tools/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party_tools/client_drivers/index.rst b/third_party_tools/client_drivers/index.rst index d348cc85d..56ebea9a5 100644 --- a/third_party_tools/client_drivers/index.rst +++ b/third_party_tools/client_drivers/index.rst @@ -41,7 +41,7 @@ The following are applicable to all operating systems: * **Tableau**: - * `Tableau connector `_ - SQream (.taco) + * `Tableau connector `_ - SQream (.taco) * `Tableau manual installation `_ From 9903c64c030f47db548b6830b202a198b0061e6a Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 6 Jul 2022 11:50:03 +0300 Subject: [PATCH 266/300] Tables: https://sqream.atlassian.net/browse/TPD-208 --- .../sql_statements/dml_commands/copy_to.rst | 373 ++++++++++++++++-- 1 file changed, 343 insertions(+), 30 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index 3579dc154..bd32a325f 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -3,20 +3,23 @@ ********************** COPY TO ********************** +The **COPY TO** page includes the following sections: +.. contents:: + :local: + :depth: 1 + +Overview +========== ``COPY ... TO`` is a statement that can be used to export data from a SQream database table or query to a file on the filesystem. In general, ``COPY`` moves data between filesystem files and SQream DB tables. .. note:: To copy data from a file to a table, see :ref:`COPY FROM`. -Permissions -============= - -The role must have the ``SELECT`` permission on every table or schema that is referenced by the statement. - Syntax ========== +The following is the correct syntax for using the **COPY TO** statement: .. code-block:: postgres @@ -48,6 +51,11 @@ Syntax | AWS_ID = '{ AWS ID }' | AWS_SECRET = '{ AWS Secret }' + + | MAX_FILE_SIZE = '{ size_in_bytes }' + + | ENFORCE_SINGLE_FILE = { true | false } + delimiter ::= string @@ -57,8 +65,13 @@ Syntax AWS Secret ::= string +.. note:: The DELIMITER is applicable to the CSV format only. + +.. note:: In Studio, you must write the parameters using lower case letters. Using upper case letters generates an error. + Elements ============ +The following table shows the ``COPY_TO`` elements: .. list-table:: :widths: auto @@ -80,41 +93,332 @@ Elements - Specifies the character that separates fields (columns) within each row of the file. The default is a comma character (``,``). * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets + * - ``MAX_FILE_SIZE`` + - Sets the maximum file size (bytes). Default value: 16*2^20 (16MB). + * - ``ENFORCE_SINGLE_FILE`` + - Enforces the maximum file size (bytes). Permitted values: ``true`` - creates one file of unlimited size, ``false`` - permits creating several files together limited by the ``MAX_FILE_SIZE``. When set to ``true``, the single file size is not limited by the ``MAX_FILE_SIZE`` setting. When set to ``false``, the combined file sizes cannot exceed the ``MAX_FILE_SIZE``. Default value: ``FALSE``. -Usage notes +Usage Notes =============== +The **Usage Notes** describes the following: -Supported field delimiters +.. contents:: + :local: + :depth: 1 + +Supported Field Delimiters ------------------------------ +The **Supported Field Delimiters** section describes the following: -Printable characters -^^^^^^^^^^^^^^^^^^^^^ +.. contents:: + :local: + :depth: 1 +Printable ASCII Characters +^^^^^^^^^^^^^^^^^^^^^ Any printable ASCII character can be used as a delimiter without special syntax. The default CSV field delimiter is a comma (``,``). -A printable character is any ASCII character in the range 32 - 126. - -Non-printable characters +The following table shows the supported printable ASCII characters: + ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| **Character** | **Description** | **ASCII** | **Octal** | **Hex** | **Binary** | **HTML Code** | **HTML Name** | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| (Space) | Space | 32 | 40 | 20 | 100000 | | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ! | Exclamation Mark | 33 | 41 | 21 | 100001 | ! | ! | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| # | Hash or Number | 35 | 43 | 23 | 100011 | # | # | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| $ | Dollar Sign | 36 | 44 | 24 | 100100 | $ | $ | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| % | Percentage | 37 | 45 | 25 | 100101 | % | % | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| & | Ampersand | 38 | 46 | 26 | 100110 | & | & | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ( | Left Parenthesis | 40 | 50 | 28 | 101000 | ( | ( | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ) | Right Parenthesis | 41 | 51 | 29 | 101001 | ) | ) | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| * | Asterisk | 42 | 52 | 2A | 101010 | * | * | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| + | Plus Sign | 43 | 53 | 2B | 101011 | + | + | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| , | Comma | 44 | 54 | 2C | 101100 | , | , | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| / | Slash | 47 | 57 | 2F | 101111 | / | / | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ; | Semicolon | 59 | 73 | 3B | 111011 | ; | ; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| < | Less Than | 60 | 74 | 3C | 111100 | < | < | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| = | Equals Sign | 61 | 75 | 3D | 111101 | = | = | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| > | Greater Than | 62 | 76 | 3E | 111110 | > | > | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ? | Question Mark | 63 | 77 | 3F | 111111 | ? | ? | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| @ | At Sign | 64 | 100 | 40 | 1000000 | @ | @ | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| [ | Left Square Bracket | 91 | 133 | 5B | 1011011 | [ | [ | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| \ | Backslash | 92 | 134 | 5C | 1011100 | \ | \ | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ] | Right Square Bracket | 93 | 135 | 5D | 1011101 | ] | ] | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ^ | Caret or Circumflex | 94 | 136 | 5E | 1011110 | ^ | &hat; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| _ | Underscore | 95 | 137 | 5F | 1011111 | _ | _ | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ` | Grave Accent | 96 | 140 | 60 | 1100000 | ` | ` | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| { | Left Curly Bracket | 123 | 173 | 7B | 1111011 | { | { | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| | | Vertical Bar | 124 | 174 | 7C | 1111100 | | | | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| } | Right Curly Bracket | 125 | 175 | 7D | 1111101 | } | } | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ~ | Tilde | 126 | 176 | 7E | 1111110 | ~ | ˜ | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ + +Non-Printable ASCII Characters ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -A non-printable character (1 - 31, 127) can be used in its octal form. - +The following table shows the supported non-printable ASCII characters: + ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| **Character** | **Description** | **Octal** | **ASCII** | **Hex** | **Binary** | **HTML Code** | **HTML Name** | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| NUL | Null | 0 | 0 | 0 | 0 | � | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SOH | Start of Heading | 1 | 1 | 1 | 1 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| STX | Start of Text | 2 | 2 | 2 | 10 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ETX | End of Text | 3 | 3 | 3 | 11 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| EOT | End of Transmission | 4 | 4 | 4 | 100 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ENQ | Enquiry | 5 | 5 | 5 | 101 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ACK | Acknowledge | 6 | 6 | 6 | 110 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| BEL | Bell | 7 | 7 | 7 | 111 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| BS | Backspace | 10 | 8 | 8 | 1000 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| HT | Horizontal Tab | 11 | 9 | 9 | 1001 | | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| VT | Vertical Tab | 13 | 11 | 0B | 1011 | | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| FF | NP Form Feed, New Page | 14 | 12 | 0C | 1100 | | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SO | Shift Out | 16 | 14 | 0E | 1110 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SI | Shift In | 17 | 15 | 0F | 1111 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DLE | Data Link Escape | 20 | 16 | 10 | 10000 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DC1 | Device Control 1 | 21 | 17 | 11 | 10001 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DC2 | Device Control 2 | 22 | 18 | 12 | 10010 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DC3 | Device Control 3 | 23 | 19 | 13 | 10011 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DC4 | Device Control 4 | 24 | 20 | 14 | 10100 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| NAK | Negative Acknowledge | 25 | 21 | 15 | 10101 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SYN | Synchronous Idle | 26 | 22 | 16 | 10110 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ETB | End of Transmission Block | 27 | 23 | 17 | 10111 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| CAN | Cancel | 30 | 24 | 18 | 11000 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| EM | End of Medium | 31 | 25 | 19 | 11001 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SUB | Substitute | 32 | 26 | 1A | 11010 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ESC | Escape | 33 | 27 | 1B | 11011 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| FS | File Separator | 34 | 28 | 1C | 11100 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| GS | Group Separator | 35 | 29 | 1D | 11101 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| RS | Record Separator | 36 | 30 | 1E | 11110 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| US | Unit Separator | 37 | 31 | 1F | 11111 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DEL | Delete | 177 | 127 | 7F | 1111111 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ + A tab can be specified by escaping it, for example ``\t``. Other non-printable characters can be specified using their octal representations, by using the ``E'\000'`` format, where ``000`` is the octal value of the character. For example, ASCII character ``15``, known as "shift in", can be specified using ``E'\017'``. +.. note:: Delimiters are only applicable to the CSV file format. -Date format +Unsupported ASCII Field Delimiters +------------------------------ +The following table shows the unsupported ASCII field delimiters: + ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| **ASCII** | **Character** | **Description** | **Octal** | **Hex** | **Binary** | **HTML Code** | **HTML Name** | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 10 | LF | NL Line Feed, New Line | 12 | 0A | 1010 | | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 13 | CR | Carriage Return | 15 | 0D | 1101 | | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 34 | " | Double Quote | 42 | 22 | 100010 | " | " | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 39 | ' | Single Quote | 47 | 27 | 100111 | ' | ' | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 45 | - | Minus Sign | 55 | 2D | 101101 | - | − | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 46 | . | Period | 56 | 2E | 101110 | . | . | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 48 | 0 | Zero | 60 | 30 | 110000 | 0 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 49 | 1 | Number One | 61 | 31 | 110001 | 1 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 50 | 2 | Number Two | 62 | 32 | 110010 | 2 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 51 | 3 | Number Three | 63 | 33 | 110011 | 3 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 52 | 4 | Number Four | 64 | 34 | 110100 | 4 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 53 | 5 | Number Five | 65 | 35 | 110101 | 5 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 54 | 6 | Number Six | 66 | 36 | 110110 | 6 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 55 | 7 | Number Seven | 67 | 37 | 110111 | 7 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 56 | 8 | Number Eight | 70 | 38 | 111000 | 8 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 57 | 9 | Number Nine | 71 | 39 | 111001 | 9 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 58 | : | Colon | 72 | 3A | 111010 | : | : | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 65 | A | Upper Case Letter A | 101 | 41 | 1000001 | A | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 66 | B | Upper Case Letter B | 102 | 42 | 1000010 | B | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 67 | C | Upper Case Letter C | 103 | 43 | 1000011 | C | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 68 | D | Upper Case Letter D | 104 | 44 | 1000100 | D | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 69 | E | Upper Case Letter E | 105 | 45 | 1000101 | E | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 70 | F | Upper Case Letter F | 106 | 46 | 1000110 | F | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 71 | G | Upper Case Letter G | 107 | 47 | 1000111 | G | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 72 | H | Upper Case Letter H | 110 | 48 | 1001000 | H | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 73 | I | Upper Case Letter I | 111 | 49 | 1001001 | I | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 74 | J | Upper Case Letter J | 112 | 4A | 1001010 | J | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 75 | K | Upper Case Letter K | 113 | 4B | 1001011 | K | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 76 | L | Upper Case Letter L | 114 | 4C | 1001100 | L | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 77 | M | Upper Case Letter M | 115 | 4D | 1001101 | M | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 78 | N | Upper Case Letter N | 116 | 4E | 1001110 | N | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 79 | O | Upper Case Letter O | 117 | 4F | 1001111 | O | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 80 | P | Upper Case Letter P | 120 | 50 | 1010000 | P | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 81 | Q | Upper Case Letter Q | 121 | 51 | 1010001 | Q | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 82 | R | Upper Case Letter R | 122 | 52 | 1010010 | R | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 83 | S | Upper Case Letter S | 123 | 53 | 1010011 | S | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 84 | T | Upper Case Letter T | 124 | 54 | 1010100 | T | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 85 | U | Upper Case Letter U | 125 | 55 | 1010101 | U | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 86 | V | Upper Case Letter V | 126 | 56 | 1010110 | V | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 87 | W | Upper Case Letter W | 127 | 57 | 1010111 | W | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 88 | X | Upper Case Letter X | 130 | 58 | 1011000 | X | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 89 | Y | Upper Case Letter Y | 131 | 59 | 1011001 | Y | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 90 | Z | Upper Case Letter Z | 132 | 5A | 1011010 | Z | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 97 | a | Lower Case Letter a | 141 | 61 | 1100001 | a | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 98 | b | Lower Case Letter b | 142 | 62 | 1100010 | b | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 99 | c | Lower Case Letter c | 143 | 63 | 1100011 | c | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 100 | d | Lower Case Letter d | 144 | 64 | 1100100 | d | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 101 | e | Lower Case Letter e | 145 | 65 | 1100101 | e | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 102 | f | Lower Case Letter f | 146 | 66 | 1100110 | f | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 103 | g | Lower Case Letter g | 147 | 67 | 1100111 | g | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 104 | h | Lower Case Letter h | 150 | 68 | 1101000 | h | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 105 | i | Lower Case Letter i | 151 | 69 | 1101001 | i | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 106 | j | Lower Case Letter j | 152 | 6A | 1101010 | j | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 107 | k | Lower Case Letter k | 153 | 6B | 1101011 | k | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 108 | l | Lower Case Letter l | 154 | 6C | 1101100 | l | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 109 | m | Lower Case Letter m | 155 | 6D | 1101101 | m | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 110 | n | Lower Case Letter n | 156 | 6E | 1101110 | n | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 111 | o | Lower Case Letter o | 157 | 6F | 1101111 | o | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 112 | p | Lower Case Letter p | 160 | 70 | 1110000 | p | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 113 | q | Lower Case Letter q | 161 | 71 | 1110001 | q | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 114 | r | Lower Case Letter r | 162 | 72 | 1110010 | r | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 115 | s | Lower Case Letter s | 163 | 73 | 1110011 | s | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 116 | t | Lower Case Letter t | 164 | 74 | 1110100 | t | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 117 | u | Lower Case Letter u | 165 | 75 | 1110101 | u | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 118 | v | Lower Case Letter v | 166 | 76 | 1110110 | v | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 119 | w | Lower Case Letter w | 167 | 77 | 1110111 | w | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 120 | x | Lower Case Letter x | 170 | 78 | 1111000 | x | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 121 | y | Lower Case Letter y | 171 | 79 | 1111001 | y | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 122 | z | Lower Case Letter z | 172 | 7A | 1111010 | z | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ + +Date Format --------------- - The date format in the output CSV is formatted as ISO 8601 (``2019-12-31 20:30:55.123``), regardless of how it was parsed initially with :ref:`COPY FROM date parsers`. +For more information on the ``datetime`` format, see :ref:`sql_data_types_date`. Examples =========== +The **Examples** section shows the following examples: + +.. contents:: + :local: + :depth: 1 -Export table to a CSV without HEADER +Exporting a Table to a CSV File without a HEADER Row ------------------------------------ +The following is an example of exporting a table to a CSV file without a HEADER row: .. code-block:: psql @@ -130,8 +434,9 @@ Export table to a CSV without HEADER Jonas Jerebko,Boston Celtics,8,PF,29,6-10,231,\N,5000000 Amir Johnson,Boston Celtics,90,PF,29,6-9,240,\N,12000000 -Export table to a CSV with a HEADER row +Exporting a Table to a CSV with a HEADER Row ----------------------------------------- +The following is an example of exporting a table to a CSV file with a HEADER row: .. code-block:: psql @@ -147,8 +452,9 @@ Export table to a CSV with a HEADER row R.J. Hunter,Boston Celtics,28,SG,22,6-5,185,Georgia State,1148640 Jonas Jerebko,Boston Celtics,8,PF,29,6-10,231,\N,5000000 -Export table to a TSV with a header row +Exporting a Table to TSV with a HEADER Row ----------------------------------------- +The following is an example of exporting a table to a TSV file with a HEADER row: .. code-block:: psql @@ -164,8 +470,9 @@ Export table to a TSV with a header row R.J. Hunter Boston Celtics 28 SG 22 6-5 185 Georgia State 1148640 Jonas Jerebko Boston Celtics 8 PF 29 6-10 231 \N 5000000 -Use non-printable ASCII characters as delimiter +Using Non-Printable ASCII Characters as Delimiters ------------------------------------------------------- +The following is an example of using non-printable ASCII characters as delimiters: Non-printable characters can be specified using their octal representations, by using the ``E'\000'`` format, where ``000`` is the octal value of the character. @@ -179,8 +486,9 @@ For example, ASCII character ``15``, known as "shift in", can be specified using COPY nba TO WRAPPER csv_fdw OPTIONS (LOCATION = '/tmp/nba_export.csv', DELIMITER = E'\011'); -- 011 is a tab character -Exporting the result of a query to a CSV +Exporting the Result of a Query to CSV File -------------------------------------------- +The following is an example of exporting the result of a query to a CSV file: .. code-block:: psql @@ -195,41 +503,46 @@ Exporting the result of a query to a CSV Charlotte Hornets,5222728 Chicago Bulls,5785558 -Saving files to an authenticated S3 bucket +Saving Files to an Authenticated S3 Bucket -------------------------------------------- +The following is an example of saving files to an authenticated S3 bucket: .. code-block:: psql COPY (SELECT "Team", AVG("Salary") FROM nba GROUP BY 1) TO WRAPPER csv_fdw OPTIONS (LOCATION = 's3://my_bucket/salaries/nba_export.csv', AWS_ID = 'my_aws_id', AWS_SECRET = 'my_aws_secret'); -Saving files to an HDFS path +Saving Files to an HDFS Path -------------------------------------------- +The following is an example of saving files to an HDFS path: .. code-block:: psql COPY (SELECT "Team", AVG("Salary") FROM nba GROUP BY 1) TO WRAPPER csv_fdw OPTIONS (LOCATION = 'hdfs://pp_namenode:8020/nba_export.csv'); - -Export table to a parquet file +Exporting a Table to a Parquet File ------------------------------ +The following is an example of exporting a table to a Parquet file: .. code-block:: psql COPY nba TO WRAPPER parquet_fdw OPTIONS (LOCATION = '/tmp/nba_export.parquet'); - -Export a query to a parquet file +Exporting a Query to a Parquet File -------------------------------- +The following is an example of exporting a query to a Parquet file: .. code-block:: psql COPY (select x,y from t where z=0) TO WRAPPER parquet_fdw OPTIONS (LOCATION = '/tmp/file.parquet'); - -Export table to a ORC file +Exporting a Table to an ORC File ------------------------------ +The following is an example of exporting a table to an ORC file: .. code-block:: psql COPY nba TO WRAPPER orc_fdw OPTIONS (LOCATION = '/tmp/nba_export.orc'); +Permissions +============= +The role must have the ``SELECT`` permission on every table or schema that is referenced by the statement. From 0942a784577d277cfda79154c8a911d6c8e042b3 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 6 Jul 2022 16:08:16 +0300 Subject: [PATCH 267/300] Updated with Slavi --- operational_guides/hardware_guide.rst | 83 +++++++++++++++++++++------ 1 file changed, 65 insertions(+), 18 deletions(-) diff --git a/operational_guides/hardware_guide.rst b/operational_guides/hardware_guide.rst index d66797223..571d6a6a3 100644 --- a/operational_guides/hardware_guide.rst +++ b/operational_guides/hardware_guide.rst @@ -3,9 +3,7 @@ *********************** Hardware Guide *********************** - -This guide describes the SQream reference architecture, emphasizing the benefits to the technical audience, and provides guidance for end-users on selecting the right configuration for a SQream installation. - +The **Hardware Guide** describes the SQream reference architecture, emphasizing the benefits to the technical audience, and provides guidance for end-users on selecting the right configuration for a SQream installation. .. rubric:: Need help? @@ -15,20 +13,22 @@ Visit `SQream's support portal Date: Wed, 6 Jul 2022 16:28:19 +0300 Subject: [PATCH 268/300] Update hardware_guide.rst --- operational_guides/hardware_guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/hardware_guide.rst b/operational_guides/hardware_guide.rst index 571d6a6a3..252b71fc2 100644 --- a/operational_guides/hardware_guide.rst +++ b/operational_guides/hardware_guide.rst @@ -78,7 +78,7 @@ The following table shows SQream's recommended hardware specifications: .. list-table:: :widths: 15 65 - :header-rows: 2 + :header-rows: 1 * - Component - Type From 3773199472cc26d038cb64d6e8561093926237e7 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 6 Jul 2022 17:03:16 +0300 Subject: [PATCH 269/300] https://sqream.atlassian.net/browse/TPD-168 --- operational_guides/external_data.rst | 14 +++++++++-- operational_guides/hdfs.rst | 36 ++++++++++++++-------------- operational_guides/s3.rst | 34 +++++++++----------------- 3 files changed, 41 insertions(+), 43 deletions(-) diff --git a/operational_guides/external_data.rst b/operational_guides/external_data.rst index 98d157ab2..8bf51f108 100644 --- a/operational_guides/external_data.rst +++ b/operational_guides/external_data.rst @@ -3,8 +3,7 @@ ********************************** Working with External Data ********************************** - -SQream DB supports external data sources for use with :ref:`external_tables`, :ref:`copy_from`, and :ref:`copy_to`. +SQream supports the following external data sources: .. toctree:: :maxdepth: 1 @@ -13,3 +12,14 @@ SQream DB supports external data sources for use with :ref:`external_tables`, :r s3 hdfs +For more information, see the following: + +* :ref:`external_tables` + + :: + +* :ref:`copy_from` + + :: + +* :ref:`copy_to` \ No newline at end of file diff --git a/operational_guides/hdfs.rst b/operational_guides/hdfs.rst index 274926e36..a6ffe0ead 100644 --- a/operational_guides/hdfs.rst +++ b/operational_guides/hdfs.rst @@ -46,13 +46,13 @@ This section describes how to configure an HDFS environment for the user **sqrea $ PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin $ export PATH -3. Verify that the edits have been made: +2. Verify that the edits have been made: .. code-block:: console source /home/sqream/.bash_profile -4. Check if you can access Hadoop from your machine: +3. Check if you can access Hadoop from your machine: .. code-block:: console @@ -63,7 +63,7 @@ This section describes how to configure an HDFS environment for the user **sqrea **NOTICE:** If you cannot access Hadoop from your machine because it uses Kerberos, see `Connecting a SQream Server to Cloudera Hadoop with Kerberos `_ -5. Verify that an HDFS environment exists for SQream services: +4. Verify that an HDFS environment exists for SQream services: .. code-block:: console @@ -72,7 +72,7 @@ This section describes how to configure an HDFS environment for the user **sqrea .. _step_6: -6. If an HDFS environment does not exist for SQream services, create one (sqream_env.sh): +5. If an HDFS environment does not exist for SQream services, create one (sqream_env.sh): .. code-block:: console @@ -134,7 +134,7 @@ If your Hadoop server requires Kerberos authentication, do the following: $ ls -lrt -5. Look for a recently updated folder containing the text **hdfs**. +6. Look for a recently updated folder containing the text **hdfs**. The following is an example of the correct folder name: @@ -150,25 +150,25 @@ The following is an example of the correct folder name: Comment: - Does "something" need to be replaced with "file name" -6. Copy the .keytab file to user **sqream's** Home directory on the remote machines that you are planning to use Hadoop on. +7. Copy the .keytab file to user **sqream's** Home directory on the remote machines that you are planning to use Hadoop on. -7. Copy the following files to the **sqream sqream@server:/hdfs/hadoop/etc/hadoop:** directory: +8. Copy the following files to the **sqream sqream@server:/hdfs/hadoop/etc/hadoop:** directory: * core-site.xml * hdfs-site.xml -8. Connect to the sqream server and verify that the .keytab file's owner is a user sqream and is granted the correct permissions: +9. Connect to the sqream server and verify that the .keytab file's owner is a user sqream and is granted the correct permissions: .. code-block:: console $ sudo chown sqream:sqream /home/sqream/hdfs.keytab $ sudo chmod 600 /home/sqream/hdfs.keytab -9. Log into the sqream server. +10. Log into the sqream server. -10. Log in as the user **sqream**. +11. Log in as the user **sqream**. -11. Navigate to the Home directory and check the name of a Kerberos principal represented by the following .keytab file: +12. Navigate to the Home directory and check the name of a Kerberos principal represented by the following .keytab file: .. code-block:: console @@ -199,15 +199,15 @@ The following is an example of the correct folder name: $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM -12. Verify that the hdfs service named **hdfs/nn1@SQ.COM** is shown in the generated output above. +13. Verify that the hdfs service named **hdfs/nn1@SQ.COM** is shown in the generated output above. -13. Run the following: +14. Run the following: .. code-block:: console $ kinit -kt hdfs.keytab hdfs/nn1@SQ.COM - 13. Check the output: +15. Check the output: .. code-block:: console @@ -223,13 +223,13 @@ The following is an example of the correct folder name: $ Valid starting Expires Service principal $ 09/16/2020 13:44:18 09/17/2020 13:44:18 krbtgt/SQ.COM@SQ.COM -14. List the files located at the defined server name or IP address: +16. List the files located at the defined server name or IP address: .. code-block:: console $ hadoop fs -ls hdfs://:8020/ -15. Do one of the following: +17. Do one of the following: * If the list below is output, continue with Step 16. * If the list is not output, verify that your environment has been set up correctly. @@ -245,8 +245,8 @@ If any of the following are empty, verify that you followed :ref:`Step 6 ` \ No newline at end of file diff --git a/operational_guides/s3.rst b/operational_guides/s3.rst index 773a9e5fd..f8bb2dab6 100644 --- a/operational_guides/s3.rst +++ b/operational_guides/s3.rst @@ -1,9 +1,8 @@ .. _s3: *********************** -Amazon S3 +Inserting Data Using Amazon S3 *********************** - SQream uses a native S3 connector for inserting data. The ``s3://`` URI specifies an external file path on an S3 bucket. File names may contain wildcard characters, and the files can be in CSV or columnar format, such as Parquet and ORC. The **Amazon S3** describes the following topics: @@ -13,12 +12,10 @@ The **Amazon S3** describes the following topics: S3 Configuration ============================== - Any database host with access to S3 endpoints can access S3 without any configuration. To read files from an S3 bucket, the database must have listable files. S3 URI Format =============== - With S3, specify a location for a file (or files) when using :ref:`copy_from` or :ref:`external_tables`. The following is an example of the general S3 syntax: @@ -29,12 +26,10 @@ The following is an example of the general S3 syntax: Authentication ================= - SQream supports ``AWS ID`` and ``AWS SECRET`` authentication. These should be specified when executing a statement. Examples ========== - Use a foreign table to stage data from S3 before loading from CSV, Parquet, or ORC files. The **Examples** section includes the following examples: @@ -42,12 +37,8 @@ The **Examples** section includes the following examples: .. contents:: :local: :depth: 1 - - - Planning for Data Staging -------------------------------- - The examples in this section are based on a CSV file, as shown in the following table: .. csv-table:: nba.csv @@ -59,22 +50,21 @@ The file is stored on Amazon S3, and this bucket is public and listable. To crea Creating a Foreign Table ----------------------------- - Based on the source file's structure, you can create a foreign table with the appropriate structure, and point it to your file as shown in the following example: .. code-block:: postgres CREATE FOREIGN TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), - "Number" tinyint, - "Position" varchar(2), - "Age" tinyint, - "Height" varchar(4), - "Weight" real, - "College" varchar(40), - "Salary" float + Name varchar(40), + Team varchar(40), + Number tinyint, + Position varchar(2), + Age tinyint, + Height varchar(4), + Weight real, + College varchar(40), + Salary float ) WRAPPER csv_fdw OPTIONS @@ -93,7 +83,6 @@ For more information, see the following: Querying Foreign Tables ------------------------------ - The following shows the data in the foreign table: .. code-block:: psql @@ -114,7 +103,6 @@ The following shows the data in the foreign table: Bulk Loading a File from a Public S3 Bucket ---------------------------------------------- - The ``COPY FROM`` command can also be used to load data without staging it first. .. note:: The bucket must be publicly available and objects can be listed. @@ -135,4 +123,4 @@ The following is an example of loading fles from an authenticated S3 bucket: COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n' AWS_ID '12345678' - AWS_SECRET 'super_secretive_secret'; + AWS_SECRET 'super_secretive_secret'; \ No newline at end of file From 0ef6fcb61bd009c2a87441e9d435b238604aeb85 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 6 Jul 2022 17:14:07 +0300 Subject: [PATCH 270/300] Replaced foreign_tables with external_tables --- ...foreign_tables.rst => external_tables.rst} | 65 +++++++++---------- 1 file changed, 32 insertions(+), 33 deletions(-) rename operational_guides/{foreign_tables.rst => external_tables.rst} (73%) diff --git a/operational_guides/foreign_tables.rst b/operational_guides/external_tables.rst similarity index 73% rename from operational_guides/foreign_tables.rst rename to operational_guides/external_tables.rst index 4399a0233..5835cfc7e 100644 --- a/operational_guides/foreign_tables.rst +++ b/operational_guides/external_tables.rst @@ -1,21 +1,22 @@ -.. _foreign_tables: +.. _external_tables: *********************** -Foreign Tables +External Tables *********************** -Foreign tables can be used to run queries directly on data without inserting it into SQream DB first. +External tables can be used to run queries directly on data without inserting it into SQream DB first. -SQream DB supports read only foreign tables, so you can query from foreign tables, but you cannot insert to them, or run deletes or updates on them. -Running queries directly on foreign data is most effectively used for things like one off querying. If you will be repeatedly querying data, the performance will usually be better if you insert the data into SQream DB first. +SQream DB supports read only external tables, so you can query from external tables, but you cannot insert to them, or run deletes or updates on them. -Although foreign tables can be used without inserting data into SQream DB, one of their main use cases is to help with the insertion process. An insert select statement on a foreign table can be used to insert data into SQream using the full power of the query engine to perform ETL. +Running queries directly on external data is most effectively used for things like one off querying. If you will be repeatedly querying data, the performance will usually be better if you insert the data into SQream DB first. + +Although external tables can be used without inserting data into SQream DB, one of their main use cases is to help with the insertion process. An insert select statement on an external table can be used to insert data into SQream using the full power of the query engine to perform ETL. .. contents:: In this topic: :local: What Kind of Data is Supported? ===================================== -SQream DB supports foreign tables over: +SQream DB supports external tables over: * text files (e.g. CSV, PSV, TSV) * ORC @@ -29,10 +30,9 @@ SQream DB can stage data from: * :ref:`s3` buckets (e.g. ``s3://pp-secret-bucket/users/*.parquet``) * :ref:`hdfs` (e.g. ``hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv``) - -Using foreign tables - a practical example +Using External Tables - A Practical Example ============================================== -Use a foreign table to stage data before loading from CSV, Parquet or ORC files. +Use an external table to stage data before loading from CSV, Parquet or ORC files. Planning for Data Staging -------------------------------- @@ -44,26 +44,25 @@ For the following examples, we will want to interact with a CSV file. Here's a p :header-rows: 1 The file is stored on :ref:`s3`, at ``s3://sqream-demo-data/nba_players.csv``. -We will make note of the file structure, to create a matching ``CREATE_FOREIGN_TABLE`` statement. - +We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_TABLE`` statement. -Creating the foreign table +Creating External Tables ----------------------------- -Based on the source file structure, we we :ref:`create a foreign table` with the appropriate structure, and point it to the file. +Based on the source file structure, we we :ref:`create an external table` with the appropriate structure, and point it to the file. .. code-block:: postgres - CREATE FOREIGN TABLE nba + CREATE EXTERNAL TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), - "Number" tinyint, - "Position" varchar(2), - "Age" tinyint, - "Height" varchar(4), - "Weight" real, - "College" varchar(40), - "Salary" float + Name text, + Team text, + Number tinyint, + Position text, + Age tinyint, + Height text, + Weight real, + College text, + Salary float ) USING FORMAT CSV -- Text file WITH PATH 's3://sqream-demo-data/nba_players.csv' @@ -72,10 +71,10 @@ Based on the source file structure, we we :ref:`create a foreign table SELECT * FROM nba; master=> select * from nba; Record delimiter mismatch during CSV parsing. User defined line delimiter \n does not match the first delimiter \r\n found in s3://sqream-demo-data/nba.csv -* Since the data for a foreign table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against a foreign table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. +* Since the data for an external table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against an external table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. \ No newline at end of file From 4844a06c79d655d503d51bbc884cfe3c4d34d347 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 6 Jul 2022 17:26:09 +0300 Subject: [PATCH 271/300] TPD-221 --- operational_guides/hardware_guide.rst | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/operational_guides/hardware_guide.rst b/operational_guides/hardware_guide.rst index 252b71fc2..5337db9cd 100644 --- a/operational_guides/hardware_guide.rst +++ b/operational_guides/hardware_guide.rst @@ -126,27 +126,6 @@ The following table shows SQream's recommended metadata server specifications: * - Operating System - Red Hat Enterprise Linux v7.x or CentOS v7.x or Amazon Linux -Web User Interface Specifications -~~~~~~~~~~~~~~~~~~~~~~~~~ -The following table shows SQream's recommended web user interface server specifications: - -.. list-table:: - :widths: 15 90 - :header-rows: 1 - - * - Component - - Type - * - Processors - - One Intel i7 16C processor or similar - * - RAM - - 64 GB DDR4 RAM 2x32 GB RDIMM or similar - * - Discs - - 256 GB SATA 6Gb SSD drive or similar - * - Network Card (Corporate) - - Two 1 GbE cards or similar - * - Operating System - - Red Hat Enterprise Linux v7.x or CentOS v7.x or Amazon Linux - .. note:: With a NAS connected over GPFS, Lustre, or NFS, each SQream worker can read data at up to 5GB/s. SQream Studio Server Example @@ -246,4 +225,4 @@ For clustered scale-out installations, SQream relies on NAS/SAN storage. For sta SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla V100 or A100 GPU per 2 users, for full, uninterrupted dedicated access. -Download the full `SQream Reference Architecture `_ document. +Download the full `SQream Reference Architecture `_ document. \ No newline at end of file From 493144cddfa65f82d0a5359b52a05fc990d0c3c1 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 6 Jul 2022 18:40:15 +0300 Subject: [PATCH 272/300] Updated Python Menu Structure and Python API Reference Page --- reference/index.rst | 9 +- reference/python_api_reference_guide.rst | 125 ++++++++++++ .../client_drivers/python/api-reference.rst | 191 ------------------ .../client_drivers/python/index.rst | 6 +- 4 files changed, 131 insertions(+), 200 deletions(-) create mode 100644 reference/python_api_reference_guide.rst delete mode 100644 third_party_tools/client_drivers/python/api-reference.rst diff --git a/reference/index.rst b/reference/index.rst index dc8e2e22f..6dd31abe6 100644 --- a/reference/index.rst +++ b/reference/index.rst @@ -1,17 +1,18 @@ .. _reference: ************************* -Reference Guides +Reference ************************* -The **Reference Guides** section provides reference for using SQream DB's interfaces and SQL features. +This section provides reference for using SQream DB's interfaces and SQL features. .. toctree:: - :maxdepth: 5 + :maxdepth: 1 :caption: In this section: :glob: sql/index catalog_reference cli/index - sql_feature_support \ No newline at end of file + sql_feature_support + python_api_reference_guide diff --git a/reference/python_api_reference_guide.rst b/reference/python_api_reference_guide.rst new file mode 100644 index 000000000..bbcea1300 --- /dev/null +++ b/reference/python_api_reference_guide.rst @@ -0,0 +1,125 @@ +.. _python_api_reference_guide: + +************************* +Python API Reference Guide +************************* +The **Python API Reference Guide** describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +=================== +The SQream Python connector allows Python programs to connect to SQream, and conforms to Python DB-API specifications `PEP-249 `_. The main Python connector module is pysqream, which contains the ``connection`` class. + +The following is the syntax for the ``connect`` class: + +.. code-block:: postgres + + $ connect(host, port, database, username, password, clustered = False, use_ssl = False, service='sqream', reconnect_attempts=3, reconnect_interval=10) + +The ``Connection`` class creates a new ``Connection`` object and connects to SQream. + +The following table describes the ``connect`` object parameters: + +.. list-table:: + :widths: 15 75 + :header-rows: 1 + + * - Parameter + - Description + * - host + - Sets the SQream hostname or IP. + * - port + - Sets the SQream port. + * - database + - Sets the database name. + * - username + - Sets the username for establishing a connection. + * - password + - Sets the password used with your ``username``. + * - clustered + - Connects using either the load balancer or direct to worker (Default: false - direct to worker). + * - use_ssl + - Uses an SSL connection (default: false). + * - service + - (Optional) Sets the service queue (default: 'sqream'). + * - reconnect_attempts + - Sets the number of failed reconnection attempts to attempt before closing the connection. + * - reconnect_interval + - Sets the time in seconds between reconnection attempts. + +.. _connection_object_parameters: + +Connection Object Parameters +=================== +The following table describes the ``Connection`` class parameters: + +.. list-table:: + :widths: 15 117 + :header-rows: 1 + + * - Parameter + - Description + * - arraysize + - Specifies the number of rows to fetch at a time using ``fetchmany()``. Default - ``1``. + * - rowcount + - Not used. Return ``-1``. + * - description + - Displays read-only attributes containing the following result set metadata: + + * ``name`` - Displays the column name. + * ``type_code`` - Displays the internal type code. + * ``display_size`` - Not used, identical to ``internal_size`` below. + * ``internal_size`` - Displays the Data size (bytes). + * ``precision`` - Not used. Displays the precision of numeric data. + * ``scale`` - Not used. Displays the scale for numeric data. + * ``null_ok`` - Specifices whether ``NULL`` values are allowed for the column. + * - execute + - Executes statements (self, query, params=None). Parameters are not supported. + + * ``self`` - :ref:`Connection Object Parameters`. + * ``query`` - Displays a statment or query text. + * ``params`` - Not used. + * - executemany + - Prepares a statement and executes it against all parameter sequences found in ``rows_or_cols`` (self, query, rows_or_cols=None, data_as='rows', amount=None). + + * ``self`` - :ref:`Connection Object Parameters`. + * ``query`` - INSERT statement. + * ``rows_or_cols`` - Data buffer to insert. This should be a sequence of lists or tuples.. + * ``data_as`` - (Optional) Read data as rows or columns. + * ``amount`` - (Optional) count of rows to insert. + * - close + - Closes a statement and connection (self). Closed statements must be reopened by creating a new cursor. + + * ``self`` - :ref:`Connection Object Parameters`. + * - cursor + - Creates a new :ref:`Connection Object Parameters` cursor (self). Recommended - create a new cursor for every statement. + + * ``self`` - :ref:`Connection Object Parameters`. + * - fetchall + - Fetches all remaining records from the result set (self, data_as='rows'). Returns an empty sequence if no more rows are available. + + * ``self`` - :ref:`Connection Object Parameters`. + * ``data_as`` - (Optional) Reads data as rows or columns. + * - fetchone + - Fetches one record from the result set. Returns an empty sequence if no more rows are available. + + * ``self`` - :ref:`Connection Object Parameters`. + * ``size`` - Sets the number of records to fetch. If not set, fetches ``Connection.arraysize`` records (default = 1). + * ``data_as`` - (Optional) Reads data as rows or columns. + * - __iter__() + - Makes the cursor iterable. + +API Level Object Parameters +=================== +The API Level object parameter is a string constant stating the supported API level. The Python connector supports ``apilevel`` 2.0. + +Thread Safety Object Parameters +=================== +The **Thread Safety** object parameter displays the thread safety level the interface supports. The Python connector currently supports ``threadsafety`` level 1, which states that threads can share the module, but not connections. + +Parameter Style Object Parameters +=================== +The **paramstyle** object parameter sets the placeholder marker and is set to to ``qmark``, which is a **question mark** (``?``). \ No newline at end of file diff --git a/third_party_tools/client_drivers/python/api-reference.rst b/third_party_tools/client_drivers/python/api-reference.rst deleted file mode 100644 index 36da33c39..000000000 --- a/third_party_tools/client_drivers/python/api-reference.rst +++ /dev/null @@ -1,191 +0,0 @@ -.. _pysqream_api_reference: - -************************* -pysqream API reference -************************* - -The SQream Python connector allows Python programs to connect to SQream DB. - -pysqream conforms to Python DB-API specifications `PEP-249 `_ - - -The main module is pysqream, which contains the :py:meth:`Connection` class. - -.. method:: connect(host, port, database, username, password, clustered = False, use_ssl = False, service='sqream', reconnect_attempts=3, reconnect_interval=10) - - Creates a new :py:meth:`Connection` object and connects to SQream DB. - - host - SQream DB hostname or IP - - port - SQream DB port - - database - database name - - username - Username to use for connection - - password - Password for ``username`` - - clustered - Connect through load balancer, or direct to worker (Default: false - direct to worker) - - use_ssl - use SSL connection (default: false) - - service - Optional service queue (default: 'sqream') - - reconnect_attempts - Number of reconnection attempts to attempt before closing the connection - - reconnect_interval - Time in seconds between each reconnection attempt - -.. class:: Connection - - .. attribute:: arraysize - - Specifies the number of rows to fetch at a time with :py:meth:`~Connection.fetchmany`. Defaults to 1 - one row at a time. - - .. attribute:: rowcount - - Unused, always returns -1. - - .. attribute:: description - - Read-only attribute that contains result set metadata. - - This attribute is populated after a statement is executed. - - .. list-table:: - :widths: auto - :header-rows: 1 - - * - Value - - Description - * - ``name`` - - Column name - * - ``type_code`` - - Internal type code - * - ``display_size`` - - Not used - same as ``internal_size`` - * - ``internal_size`` - - Data size in bytes - * - ``precision`` - - Precision of numeric data (not used) - * - ``scale`` - - Scale for numeric data (not used) - * - ``null_ok`` - - Specifies if ``NULL`` values are allowed for this column - - .. method:: execute(self, query, params=None) - - Execute a statement. - - Parameters are not supported - - self - :py:meth:`Connection` - - query - statement or query text - - params - Unused - - .. method:: executemany(self, query, rows_or_cols=None, data_as='rows', amount=None) - - Prepares a statement and executes it against all parameter sequences found in ``rows_or_cols``. - - self - :py:meth:`Connection` - - query - INSERT statement - - rows_or_cols - Data buffer to insert. This should be a sequence of lists or tuples. - - data_as - (Optional) Read data as rows or columns - - amount - (Optional) count of rows to insert - - .. method:: close(self) - - Close a statement and connection. - After a statement is closed, it must be reopened by creating a new cursor. - - self - :py:meth:`Connection` - - .. method:: cursor(self) - - Create a new :py:meth:`Connection` cursor. - - We recommend creating a new cursor for every statement. - - self - :py:meth:`Connection` - - .. method:: fetchall(self, data_as='rows') - - Fetch all remaining records from the result set. - - An empty sequence is returned when no more rows are available. - - self - :py:meth:`Connection` - - data_as - (Optional) Read data as rows or columns - - .. method:: fetchone(self, data_as='rows') - - Fetch one record from the result set. - - An empty sequence is returned when no more rows are available. - - self - :py:meth:`Connection` - - data_as - (Optional) Read data as rows or columns - - - .. method:: fetchmany(self, size=[Connection.arraysize], data_as='rows') - - Fetches the next several rows of a query result set. - - An empty sequence is returned when no more rows are available. - - self - :py:meth:`Connection` - - size - Number of records to fetch. If not set, fetches :py:obj:`Connection.arraysize` (1 by default) records - - data_as - (Optional) Read data as rows or columns - - .. method:: __iter__() - - Makes the cursor iterable. - - -.. attribute:: apilevel = '2.0' - - String constant stating the supported API level. The connector supports API "2.0". - -.. attribute:: threadsafety = 1 - - Level of thread safety the interface supports. pysqream currently supports level 1, which states that threads can share the module, but not connections. - -.. attribute:: paramstyle = 'qmark' - - The placeholder marker. Set to ``qmark``, which is a question mark (``?``). diff --git a/third_party_tools/client_drivers/python/index.rst b/third_party_tools/client_drivers/python/index.rst index c2f5911b3..c96ef5f2f 100644 --- a/third_party_tools/client_drivers/python/index.rst +++ b/third_party_tools/client_drivers/python/index.rst @@ -495,8 +495,4 @@ For example: # Execute the command result = engine.execute(ins) -.. toctree:: - :maxdepth: 8 - :caption: Further information - - api-reference +For more information, see the :ref:`python_api_reference_guide`. \ No newline at end of file From fa5dec4cb1cbdcd5aaca3d6c4fb3de53d27dbca3 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 6 Jul 2022 19:11:33 +0300 Subject: [PATCH 273/300] Update index.rst --- reference/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/index.rst b/reference/index.rst index 6dd31abe6..524f5ea60 100644 --- a/reference/index.rst +++ b/reference/index.rst @@ -1,7 +1,7 @@ .. _reference: ************************* -Reference +Reference Guide ************************* This section provides reference for using SQream DB's interfaces and SQL features. @@ -15,4 +15,4 @@ This section provides reference for using SQream DB's interfaces and SQL feature catalog_reference cli/index sql_feature_support - python_api_reference_guide + python_api_reference_guide \ No newline at end of file From 13d391831f1af5aeb4a449fb8371744dfa5a0532 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 7 Jul 2022 07:41:20 +0300 Subject: [PATCH 274/300] Changed Titled --- reference/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/index.rst b/reference/index.rst index 524f5ea60..c21c756ed 100644 --- a/reference/index.rst +++ b/reference/index.rst @@ -1,7 +1,7 @@ .. _reference: ************************* -Reference Guide +Reference Guides ************************* This section provides reference for using SQream DB's interfaces and SQL features. @@ -15,4 +15,4 @@ This section provides reference for using SQream DB's interfaces and SQL feature catalog_reference cli/index sql_feature_support - python_api_reference_guide \ No newline at end of file + python_api_reference_guide From 9c33f0ad01cba4a69364754809d8b0a96ee48a05 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 10 Jul 2022 18:15:00 +0300 Subject: [PATCH 275/300] Added Loading and Unloading Data section to menu --- .../performing_basic_sqream_operations.rst | 7 +++- index.rst | 5 +-- loading_and_unloading_data/index.rst | 36 +++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 loading_and_unloading_data/index.rst diff --git a/getting_started/performing_basic_sqream_operations.rst b/getting_started/performing_basic_sqream_operations.rst index ba0a6fc3f..b46bba95a 100644 --- a/getting_started/performing_basic_sqream_operations.rst +++ b/getting_started/performing_basic_sqream_operations.rst @@ -15,4 +15,9 @@ After installing SQream you can perform the operations described on this page: inserting_rows running_queries deleting_rows - saving_query_results_to_a_csv_or_psv_file \ No newline at end of file + saving_query_results_to_a_csv_or_psv_file + +For more information on other basic SQream operations, see the following: + +* `Creating a Database `_ +* :ref:`data_ingestion` \ No newline at end of file diff --git a/index.rst b/index.rst index 1e69cc36e..a279cbf65 100644 --- a/index.rst +++ b/index.rst @@ -59,7 +59,7 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` - :ref:`2020.2<2020.2>` + :ref:`2020.2<2020.2>` :ref:`2020.1<2020.1>` @@ -99,7 +99,8 @@ If you're looking for an older version of the documentation, versions 1.10 throu getting_started/index installation_guides/index data_ingestion/index - third_party_tools/index + connecting_to_sqream/index + loading_and_unloading_data/index feature_guides/index operational_guides/index sqream_studio_5.4.3/index diff --git a/loading_and_unloading_data/index.rst b/loading_and_unloading_data/index.rst new file mode 100644 index 000000000..e90606719 --- /dev/null +++ b/loading_and_unloading_data/index.rst @@ -0,0 +1,36 @@ +.. _loading_and_unloading_data: + +*********************** +Loading and Unloading Data +*********************** +The **Loading Data** section describes concepts and operations related to importing data into your SQream database: + +* `Overview of loading data `_ - Describes best practices and considerations for loading data into SQream from a variety of sources and locations. + +* `Alternatives to loading data (foreign tables) `_ - Useful for running queries directly on external data without importing into your SQream database. + +* `Supported data types `_ - Overview of supported data types, including descriptions, examples, and relevant aliases. + +* `Ingesting data from external sources `_ - List of data ingestion sources that SQream supports. + +* `Inserting data from external tables `_ - Inserts one or more rows into a table. + +* `Ingesting data from third party client platforms `_ - Gives you direct access to a variety of drivers, connectors, tools, vizualisers, and utilities.. + +* `Using the COPY FROM statement `_ - Used for loading data from files located on a filesystem into SQream tables. + +* `Importing data using Studio `_ - SQream's web-based client providing users with all functionality available from the command line in an intuitive and easy-to-use format. + +* `Loading data using Amazon S3 `_ - Used for loading data from Amazon S3. + +* Troubleshooting - Describes troubleshooting solutions related to importing data from the following: + + * `SAS Viya `_ + + * `Tableau `_ + +The **Unloading Data** section describes concepts and operations related to exporting data from your SQream database: + +* `Overview of unloading data `_ - Describes best practices and considerations for unloading data from SQream to a variety of sources and locations. + +* `The COPY TO statement `_ - Used for unloading data from a SQream database table or query to a file on a filesystem. \ No newline at end of file From fff9f0b84c687b0b08eab9747f1c673b64924dd1 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 10 Jul 2022 18:23:04 +0300 Subject: [PATCH 276/300] Renamed "Third Party Tools" > "Connecting to SQream" --- .../client_drivers/cpp/connect_test.cpp | 0 .../client_drivers/cpp/index.rst | 0 .../client_drivers/cpp/insert_test.cpp | 0 .../client_drivers/index.rst | 0 .../client_drivers/jdbc/index.rst | 0 .../client_drivers/jdbc/sample.java | 0 .../client_drivers/nodejs/index.rst | 0 .../client_drivers/nodejs/sample.js | 0 .../client_drivers/odbc/index.rst | 0 .../odbc/install_configure_odbc_linux.rst | 0 .../odbc/install_configure_odbc_windows.rst | 0 .../client_drivers/python/index.rst | 0 .../client_drivers/python/nba-t10.csv | 0 .../client_drivers/python/test.py | 0 .../client_platforms/connect.sas | 0 .../client_platforms/connect2.sas | 0 .../client_platforms/connect3.sas | 0 .../client_platforms/index.rst | 0 .../client_platforms/informatica.rst | 0 .../client_platforms/microstrategy.rst | 0 .../client_platforms/odbc-sqream.tdc | 0 .../client_platforms/pentaho.rst | 0 .../client_platforms/php.rst | 0 .../client_platforms/power_bi.rst | 0 .../client_platforms/r.rst | 0 .../client_platforms/sas_viya.rst | 0 .../client_platforms/sql_workbench.rst | 0 .../client_platforms/tableau.rst | 0 .../client_platforms/talend.rst | 0 .../client_platforms/test.php | 0 .../client_platforms/tibco_spotfire.rst | 0 .../connectivity_ecosystem.jpg | Bin .../index.rst | 4 ++-- 33 files changed, 2 insertions(+), 2 deletions(-) rename {third_party_tools => connecting_to_sqream}/client_drivers/cpp/connect_test.cpp (100%) rename {third_party_tools => connecting_to_sqream}/client_drivers/cpp/index.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_drivers/cpp/insert_test.cpp (100%) rename {third_party_tools => connecting_to_sqream}/client_drivers/index.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_drivers/jdbc/index.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_drivers/jdbc/sample.java (100%) rename {third_party_tools => connecting_to_sqream}/client_drivers/nodejs/index.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_drivers/nodejs/sample.js (100%) rename {third_party_tools => connecting_to_sqream}/client_drivers/odbc/index.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_drivers/odbc/install_configure_odbc_linux.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_drivers/odbc/install_configure_odbc_windows.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_drivers/python/index.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_drivers/python/nba-t10.csv (100%) rename {third_party_tools => connecting_to_sqream}/client_drivers/python/test.py (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/connect.sas (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/connect2.sas (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/connect3.sas (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/index.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/informatica.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/microstrategy.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/odbc-sqream.tdc (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/pentaho.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/php.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/power_bi.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/r.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/sas_viya.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/sql_workbench.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/tableau.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/talend.rst (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/test.php (100%) rename {third_party_tools => connecting_to_sqream}/client_platforms/tibco_spotfire.rst (100%) rename {third_party_tools => connecting_to_sqream}/connectivity_ecosystem.jpg (100%) rename {third_party_tools => connecting_to_sqream}/index.rst (93%) diff --git a/third_party_tools/client_drivers/cpp/connect_test.cpp b/connecting_to_sqream/client_drivers/cpp/connect_test.cpp similarity index 100% rename from third_party_tools/client_drivers/cpp/connect_test.cpp rename to connecting_to_sqream/client_drivers/cpp/connect_test.cpp diff --git a/third_party_tools/client_drivers/cpp/index.rst b/connecting_to_sqream/client_drivers/cpp/index.rst similarity index 100% rename from third_party_tools/client_drivers/cpp/index.rst rename to connecting_to_sqream/client_drivers/cpp/index.rst diff --git a/third_party_tools/client_drivers/cpp/insert_test.cpp b/connecting_to_sqream/client_drivers/cpp/insert_test.cpp similarity index 100% rename from third_party_tools/client_drivers/cpp/insert_test.cpp rename to connecting_to_sqream/client_drivers/cpp/insert_test.cpp diff --git a/third_party_tools/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst similarity index 100% rename from third_party_tools/client_drivers/index.rst rename to connecting_to_sqream/client_drivers/index.rst diff --git a/third_party_tools/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst similarity index 100% rename from third_party_tools/client_drivers/jdbc/index.rst rename to connecting_to_sqream/client_drivers/jdbc/index.rst diff --git a/third_party_tools/client_drivers/jdbc/sample.java b/connecting_to_sqream/client_drivers/jdbc/sample.java similarity index 100% rename from third_party_tools/client_drivers/jdbc/sample.java rename to connecting_to_sqream/client_drivers/jdbc/sample.java diff --git a/third_party_tools/client_drivers/nodejs/index.rst b/connecting_to_sqream/client_drivers/nodejs/index.rst similarity index 100% rename from third_party_tools/client_drivers/nodejs/index.rst rename to connecting_to_sqream/client_drivers/nodejs/index.rst diff --git a/third_party_tools/client_drivers/nodejs/sample.js b/connecting_to_sqream/client_drivers/nodejs/sample.js similarity index 100% rename from third_party_tools/client_drivers/nodejs/sample.js rename to connecting_to_sqream/client_drivers/nodejs/sample.js diff --git a/third_party_tools/client_drivers/odbc/index.rst b/connecting_to_sqream/client_drivers/odbc/index.rst similarity index 100% rename from third_party_tools/client_drivers/odbc/index.rst rename to connecting_to_sqream/client_drivers/odbc/index.rst diff --git a/third_party_tools/client_drivers/odbc/install_configure_odbc_linux.rst b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst similarity index 100% rename from third_party_tools/client_drivers/odbc/install_configure_odbc_linux.rst rename to connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst diff --git a/third_party_tools/client_drivers/odbc/install_configure_odbc_windows.rst b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst similarity index 100% rename from third_party_tools/client_drivers/odbc/install_configure_odbc_windows.rst rename to connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst diff --git a/third_party_tools/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst similarity index 100% rename from third_party_tools/client_drivers/python/index.rst rename to connecting_to_sqream/client_drivers/python/index.rst diff --git a/third_party_tools/client_drivers/python/nba-t10.csv b/connecting_to_sqream/client_drivers/python/nba-t10.csv similarity index 100% rename from third_party_tools/client_drivers/python/nba-t10.csv rename to connecting_to_sqream/client_drivers/python/nba-t10.csv diff --git a/third_party_tools/client_drivers/python/test.py b/connecting_to_sqream/client_drivers/python/test.py similarity index 100% rename from third_party_tools/client_drivers/python/test.py rename to connecting_to_sqream/client_drivers/python/test.py diff --git a/third_party_tools/client_platforms/connect.sas b/connecting_to_sqream/client_platforms/connect.sas similarity index 100% rename from third_party_tools/client_platforms/connect.sas rename to connecting_to_sqream/client_platforms/connect.sas diff --git a/third_party_tools/client_platforms/connect2.sas b/connecting_to_sqream/client_platforms/connect2.sas similarity index 100% rename from third_party_tools/client_platforms/connect2.sas rename to connecting_to_sqream/client_platforms/connect2.sas diff --git a/third_party_tools/client_platforms/connect3.sas b/connecting_to_sqream/client_platforms/connect3.sas similarity index 100% rename from third_party_tools/client_platforms/connect3.sas rename to connecting_to_sqream/client_platforms/connect3.sas diff --git a/third_party_tools/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst similarity index 100% rename from third_party_tools/client_platforms/index.rst rename to connecting_to_sqream/client_platforms/index.rst diff --git a/third_party_tools/client_platforms/informatica.rst b/connecting_to_sqream/client_platforms/informatica.rst similarity index 100% rename from third_party_tools/client_platforms/informatica.rst rename to connecting_to_sqream/client_platforms/informatica.rst diff --git a/third_party_tools/client_platforms/microstrategy.rst b/connecting_to_sqream/client_platforms/microstrategy.rst similarity index 100% rename from third_party_tools/client_platforms/microstrategy.rst rename to connecting_to_sqream/client_platforms/microstrategy.rst diff --git a/third_party_tools/client_platforms/odbc-sqream.tdc b/connecting_to_sqream/client_platforms/odbc-sqream.tdc similarity index 100% rename from third_party_tools/client_platforms/odbc-sqream.tdc rename to connecting_to_sqream/client_platforms/odbc-sqream.tdc diff --git a/third_party_tools/client_platforms/pentaho.rst b/connecting_to_sqream/client_platforms/pentaho.rst similarity index 100% rename from third_party_tools/client_platforms/pentaho.rst rename to connecting_to_sqream/client_platforms/pentaho.rst diff --git a/third_party_tools/client_platforms/php.rst b/connecting_to_sqream/client_platforms/php.rst similarity index 100% rename from third_party_tools/client_platforms/php.rst rename to connecting_to_sqream/client_platforms/php.rst diff --git a/third_party_tools/client_platforms/power_bi.rst b/connecting_to_sqream/client_platforms/power_bi.rst similarity index 100% rename from third_party_tools/client_platforms/power_bi.rst rename to connecting_to_sqream/client_platforms/power_bi.rst diff --git a/third_party_tools/client_platforms/r.rst b/connecting_to_sqream/client_platforms/r.rst similarity index 100% rename from third_party_tools/client_platforms/r.rst rename to connecting_to_sqream/client_platforms/r.rst diff --git a/third_party_tools/client_platforms/sas_viya.rst b/connecting_to_sqream/client_platforms/sas_viya.rst similarity index 100% rename from third_party_tools/client_platforms/sas_viya.rst rename to connecting_to_sqream/client_platforms/sas_viya.rst diff --git a/third_party_tools/client_platforms/sql_workbench.rst b/connecting_to_sqream/client_platforms/sql_workbench.rst similarity index 100% rename from third_party_tools/client_platforms/sql_workbench.rst rename to connecting_to_sqream/client_platforms/sql_workbench.rst diff --git a/third_party_tools/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst similarity index 100% rename from third_party_tools/client_platforms/tableau.rst rename to connecting_to_sqream/client_platforms/tableau.rst diff --git a/third_party_tools/client_platforms/talend.rst b/connecting_to_sqream/client_platforms/talend.rst similarity index 100% rename from third_party_tools/client_platforms/talend.rst rename to connecting_to_sqream/client_platforms/talend.rst diff --git a/third_party_tools/client_platforms/test.php b/connecting_to_sqream/client_platforms/test.php similarity index 100% rename from third_party_tools/client_platforms/test.php rename to connecting_to_sqream/client_platforms/test.php diff --git a/third_party_tools/client_platforms/tibco_spotfire.rst b/connecting_to_sqream/client_platforms/tibco_spotfire.rst similarity index 100% rename from third_party_tools/client_platforms/tibco_spotfire.rst rename to connecting_to_sqream/client_platforms/tibco_spotfire.rst diff --git a/third_party_tools/connectivity_ecosystem.jpg b/connecting_to_sqream/connectivity_ecosystem.jpg similarity index 100% rename from third_party_tools/connectivity_ecosystem.jpg rename to connecting_to_sqream/connectivity_ecosystem.jpg diff --git a/third_party_tools/index.rst b/connecting_to_sqream/index.rst similarity index 93% rename from third_party_tools/index.rst rename to connecting_to_sqream/index.rst index 818a1dc5a..ecb9e4715 100644 --- a/third_party_tools/index.rst +++ b/connecting_to_sqream/index.rst @@ -1,7 +1,7 @@ -.. _third_party_tools: +.. _connecting_to_sqream: ************************* -Third Party Tools +Connecting to SQream ************************* SQream supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualiztion tools and utilities. The tools described on this page have been tested and approved for use with SQream. Most third party tools that work through JDBC, ODBC, and Python should work. From 4dd2b0c5bace724ec6fe3428b08c10f3f4c52a16 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 10 Jul 2022 18:56:06 +0300 Subject: [PATCH 277/300] Update inserting_data.rst --- data_ingestion/inserting_data.rst | 181 ++++++++++++++++-------------- 1 file changed, 94 insertions(+), 87 deletions(-) diff --git a/data_ingestion/inserting_data.rst b/data_ingestion/inserting_data.rst index 0440ba84b..e20e37920 100644 --- a/data_ingestion/inserting_data.rst +++ b/data_ingestion/inserting_data.rst @@ -3,140 +3,161 @@ *************************** Inserting Data Overview *************************** +The **Inserting Data Overview** page provides basic information useful when ingesting data into SQream from a variety of sources and locations, and describes the following: -The **Inserting Data Overview** page describes how to insert data into SQream, specifically how to insert data from a variety of sources and locations. - -.. contents:: In this topic: +.. contents:: :local: - - + :depth: 1 + Getting Started ================================ +SQream supports ingesting data using the following methods: -SQream supports importing data from the following sources: +* Executing the ``INSERT`` statement using a client driver. -* Using :ref:`insert` with :ref:`a client driver` -* Using :ref:`copy_from`: + :: + +* Executing the ``COPY FROM`` statement or ingesting data from foreign tables: - - Local filesystem and locally mounted network filesystems - - :ref:`s3` - - :ref:`hdfs` + * Local filesystem and locally mounted network filesystems + * Inserting Data using the Amazon S3 object storage service + * Inserting Data using an HDFS data storage system -* Using :ref:`external_tables`: +SQream supports loading files from the following formats: - - Local filesystem and locally mounted network filesystems - - :ref:`s3` - - :ref:`hdfs` +* Text - CSV, TSV, and PSV +* Parquet +* ORC +For more information, see the following: -SQream DB supports loading files in the following formats: +* Using the ``INSERT`` statement - :ref:`insert` -* Text - CSV, TSV, PSV -* Parquet -* ORC +* Using client drivers - :ref:`Client drivers` + +* Using the ``COPY FROM`` statement - :ref:`copy_from` + +* Using the Amazon S3 object storage service - :ref:`s3` + +* Using the HDFS data storage system - :ref:`hdfs` + +* Loading data from foreign tables - :ref:`foreign_tables` Data Loading Considerations ================================ +The **Data Loading Considerations** section describes the following: +.. contents:: + :local: + :depth: 1 + Verifying Data and Performance after Loading ----------------------------------------- +Like many RDBMSs, SQream recommends its own set of best practices for table design and query optimization. When using SQream, verify the following: -Like other RDBMSs, SQream DB has its own set of best practcies for table design and query optimization. - -SQream therefore recommends: +* That your data is structured as you expect (row counts, data types, formatting, content). -* Verify that the data is as you expect it (e.g. row counts, data types, formatting, content) +* That your query performance is adequate. -* The performance of your queries is adequate +* That you followed the table design best practices (:ref:`Optimization and Best Practices`). -* :ref:`Best practices` were followed for table design +* That you've tested and verified that your applications work (such as :ref:`Tableau`). -* Applications such as :ref:`Tableau` and others have been tested, and work - -* Data types were not over-provisioned (e.g. don't use TEXT to store a short string) +* That your data types have not been not over-provisioned. File Soure Location when Loading -------------------------------- +While you are loading data, you can use the ``COPY FROM`` command to let statements run on any worker. If you are running multiple nodes, verify that all nodes can see the source the same. Loading data from a local file that is only on one node and not on shared storage may cause it to fail. If required, you can also control which node a statement runs on using the Workload Manager). -During loading using :ref:`copy_from`, the statement can run on any worker. If you are running multiple nodes, make sure that all nodes can see the source the same. If you load from a local file which is only on 1 node and not on shared storage, it will fail some of the time. (If you need to, you can also control which node a statement runs on using the :ref:`workload_manager`). +For more information, see the following: -Supported load methods +* :ref:`copy_from` + +* :ref:`workload_manager` + +Supported Load Methods ------------------------------- +You can use the ``COPY FROM`` syntax to load CSV files. -SQream DB's :ref:`COPY FROM` syntax can be used to load CSV files, but can't be used for Parquet and ORC. +.. note:: The ``COPY FROM`` cannot be used for loading data from Parquet and ORC files. -:ref:`FOREIGN TABLE` can be used to load text files, Parquet, and ORC files, and can also transform the data prior to materialization as a full table. +You can use foreign tables to load text files, Parquet, and ORC files, and to transform your data before generating a full table, as described in the following table: .. list-table:: :widths: auto :header-rows: 1 :stub-columns: 1 - * - Method / File type + * - Method/File Type - Text (CSV) - Parquet - ORC - - Streaming data - * - :ref:`copy_from` + - Streaming Data + * - COPY FROM - Supported - Not supported - Not supported - Not supported - * - :ref:`foreign_tables` + * - Foreign tables - Supported - Supported - Supported - Not supported - * - :ref:`insert` + * - INSERT - Not supported - Not supported - Not supported - Supported (Python, JDBC, Node.JS) + +For more information, see the following: -Unsupported Data Types ------------------------------ +* :ref:`COPY FROM` -SQream DB doesn't support the entire set of features that some other database systems may have, such as ``ARRAY``, ``BLOB``, ``ENUM``, ``SET``, etc. +* :ref:`Foreign tables` -These data types will have to be converted before load. For example, ``ENUM`` can often be stored as a ``VARCHAR``. +* :ref:`INSERT` + +Unsupported Data Types +----------------------------- +SQream does not support certain features that are supported by other databases, such as ``ARRAY``, ``BLOB``, ``ENUM``, and ``SET``. You must convert these data types before loading them. For example, you can store ``ENUM`` as ``TEXT``. Handing Extended Errors ---------------------------- +While you can use foreign tables to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options and extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. -While :ref:`foreign tables` can be used to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options, as well as extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. +For more information, see :ref:`foreign tables`. Best Practices for CSV ------------------------------ +Text files, such as CSV, rarely conform to `RFC 4180 `_ , so you may need to make the following modifications: -Text files like CSV rarely conform to `RFC 4180 `_ , so alterations may be required: +* Use ``OFFSET 2`` for files containing header rows. -* Use ``OFFSET 2`` for files containing header rows +* You can capture failed rows in a log file for later analysis, or skip them. See :ref:`capturing_rejected_rows` for information on skipping rejected rows. -* Failed rows can be captured in a log file for later analysis, or just to skip them. See :ref:`capturing_rejected_rows` for information on skipping rejected rows. +* You can modify record delimiters (new lines) using the :ref:`RECORD DELIMITER` syntax. -* Record delimiters (new lines) can be modified with the :ref:`RECORD DELIMITER` syntax. +* If the date formats deviate from ISO 8601, refer to the :ref:`copy_date_parsers` section for overriding the default parsing. -* If the date formats differ from ISO 8601, refer to the :ref:`copy_date_parsers` section to see how to override default parsing. +* *(Optional)* You can quote fields in a CSV using double-quotes (``"``). -* - Fields in a CSV can be optionally quoted with double-quotes (``"``). However, any field containing a newline or another double-quote character must be quoted. +.. note:: You must quote any field containing a new line or another double-quote character. - If a field is quoted, any double quote that appears must be double-quoted (similar to the :ref:`string literals quoting rules`. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. - -* Field delimiters don't have a to be a displayable ASCII character. See :ref:`field_delimiters` for all options. +* If a field is quoted, you must double quote any double quote, similar to the **string literals quoting rules**. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. For more information, see :ref:`string literals quoting rules`. +* Field delimiters do not have to be a displayable ASCII character. For all supported field delimiters, see :ref:`field_delimiters`. Best Practices for Parquet -------------------------------- +The following list shows the best practices when inserting data from Parquet files: -* Parquet files are loaded through :ref:`foreign_tables`. The destination table structure has to match in number of columns between the source files. +* You must load Parquet files through :ref:`foreign_tables`. Note that the destination table structure must be identical to the number of columns between the source files. -* Parquet files support predicate pushdown. When a query is issued over Parquet files, SQream DB uses row-group metadata to determine which row-groups in a file need to be read for a particular query and the row indexes can narrow the search to a particular set of rows. +* Parquet files support **predicate pushdown**. When a query is issued over Parquet files, SQream uses row-group metadata to determine which row-groups in a file must be read for a particular query and the row indexes can narrow the search to a particular set of rows. -Type Support and Behavior Notes +Supported Types and Behavior Notes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -* Unlike ORC, the column types should match the data types exactly (see table below). +Unlike the ORC format, the column types should match the data types exactly, as shown in the table below: .. list-table:: :widths: auto @@ -245,30 +266,32 @@ Type Support and Behavior Notes - - Supported [#f4]_ -* If a Parquet file has an unsupported type like ``enum``, ``uuid``, ``time``, ``json``, ``bson``, ``lists``, ``maps``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query), the statement will succeed. If the column is referenced, an error will be thrown to the user, explaining that the type is not supported, but the column may be ommited. +If a Parquet file has an unsupported type, such as ``enum``, ``uuid``, ``time``, ``json``, ``bson``, ``lists``, ``maps``, but the table does not reference this data (i.e., the data does not appear in the :ref:`SELECT` query), the statement will succeed. If the table **does** reference a column, an error will be displayed explaining that the type is not supported, but the column may be omitted. Best Practices for ORC -------------------------------- +The following list shows the best practices when inserting data from ORC files: -* ORC files are loaded through :ref:`foreign_tables`. The destination table structure has to match in number of columns between the source files. +* You must load ORC files through :ref:`foreign_tables`. Note that the destination table structure must be identical to the number of columns between the source files. -* ORC files support predicate pushdown. When a query is issued over ORC files, SQream DB uses ORC metadata to determine which stripes in a file need to be read for a particular query and the row indexes can narrow the search to a particular set of 10,000 rows. +* ORC files support **predicate pushdown**. When a query is issued over ORC files, SQream uses ORC metadata to determine which stripes in a file need to be read for a particular query and the row indexes can narrow the search to a particular set of 10,000 rows. Type Support and Behavior Notes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +You must load ORC files through foreign table. Note that the destination table structure must be identical to the number of columns between the source files. -* ORC files are loaded through :ref:`foreign_tables`. The destination table structure has to match in number of columns between the source files. +For more information, see :ref:`foreign_tables`. -* The types should match to some extent within the same "class" (see table below). +The types should match to some extent within the same "class", as shown in the following table: .. list-table:: :widths: auto :header-rows: 1 :stub-columns: 1 - * - SQream DB type → + * - SQream DB Type → - ORC source + ORC Source - ``BOOL`` - ``TINYINT`` - ``SMALLINT`` @@ -435,23 +458,7 @@ Type Support and Behavior Notes Further Reading and Migration Guides ======================================= - -.. toctree:: - :caption: Data loading guides - :titlesonly: - - migration/csv - migration/parquet - migration/orc - -.. toctree:: - :caption: Migration guides - :titlesonly: - - migration/oracle - - -.. rubric:: See also: +For more information, see the following: * :ref:`copy_from` * :ref:`insert` @@ -459,16 +466,16 @@ Further Reading and Migration Guides .. rubric:: Footnotes -.. [#f0] Text values include ``TEXT``, ``VARCHAR``, and ``NVARCHAR``. +.. [#f0] Text values include ``TEXT``, ``VARCHAR``, and ``NVARCHAR`` -.. [#f2] With UTF8 annotation. +.. [#f2] With UTF8 annotation -.. [#f3] With ``TIMESTAMP_NANOS`` or ``TIMESTAMP_MILLIS`` annotation. +.. [#f3] With ``TIMESTAMP_NANOS`` or ``TIMESTAMP_MILLIS`` annotation .. [#f4] Any microseconds will be rounded down to milliseconds. -.. [#f5] Boolean values are cast to 0, 1. +.. [#f5] Boolean values are cast to 0, 1 -.. [#f6] Will succeed if all values are 0, 1. +.. [#f6] Will succeed if all values are 0, 1 -.. [#f7] Will succeed if all values fit the destination type. +.. [#f7] Will succeed if all values fit the destination type \ No newline at end of file From fc4a29cccb51bd0d6abf80eaa11d98b96dacd4ae Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 11 Jul 2022 14:20:54 +0300 Subject: [PATCH 278/300] Added foreign tables file to fix links pointing to it. --- ...external_tables.rst => foreign_tables.rst} | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) rename operational_guides/{external_tables.rst => foreign_tables.rst} (94%) diff --git a/operational_guides/external_tables.rst b/operational_guides/foreign_tables.rst similarity index 94% rename from operational_guides/external_tables.rst rename to operational_guides/foreign_tables.rst index 5835cfc7e..74c476331 100644 --- a/operational_guides/external_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -1,10 +1,9 @@ -.. _external_tables: +.. _foreign_tables: *********************** -External Tables +Foreign Tables *********************** -External tables can be used to run queries directly on data without inserting it into SQream DB first. - +Foreign tables can be used to run queries directly on data without inserting it into SQream DB first. SQream DB supports read only external tables, so you can query from external tables, but you cannot insert to them, or run deletes or updates on them. Running queries directly on external data is most effectively used for things like one off querying. If you will be repeatedly querying data, the performance will usually be better if you insert the data into SQream DB first. @@ -14,39 +13,39 @@ Although external tables can be used without inserting data into SQream DB, one .. contents:: In this topic: :local: -What Kind of Data is Supported? +Supported Data Formats ===================================== SQream DB supports external tables over: -* text files (e.g. CSV, PSV, TSV) +* Text files (e.g. CSV, PSV, TSV) * ORC * Parquet -What Kind of Data Staging is Supported? +Supported Data Staging ============================================ -SQream DB can stage data from: +SQream can stage data from: * a local filesystem (e.g. ``/mnt/storage/....``) * :ref:`s3` buckets (e.g. ``s3://pp-secret-bucket/users/*.parquet``) * :ref:`hdfs` (e.g. ``hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv``) -Using External Tables - A Practical Example +Using External Tables ============================================== Use an external table to stage data before loading from CSV, Parquet or ORC files. Planning for Data Staging -------------------------------- For the following examples, we will want to interact with a CSV file. Here's a peek at the table contents: - -.. csv-table:: nba-t10 - :file: ../_static/samples/nba-t10.csv + +.. csv-table:: nba.csv + :file: nba-t10.csv :widths: auto :header-rows: 1 The file is stored on :ref:`s3`, at ``s3://sqream-demo-data/nba_players.csv``. We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_TABLE`` statement. -Creating External Tables +Creating an External Table ----------------------------- Based on the source file structure, we we :ref:`create an external table` with the appropriate structure, and point it to the file. @@ -54,14 +53,14 @@ Based on the source file structure, we we :ref:`create an external table Date: Tue, 12 Jul 2022 11:58:38 +0300 Subject: [PATCH 279/300] Delete talend.rst --- .../client_platforms/talend.rst | 204 ------------------ 1 file changed, 204 deletions(-) delete mode 100644 connecting_to_sqream/client_platforms/talend.rst diff --git a/connecting_to_sqream/client_platforms/talend.rst b/connecting_to_sqream/client_platforms/talend.rst deleted file mode 100644 index 2a4d2658a..000000000 --- a/connecting_to_sqream/client_platforms/talend.rst +++ /dev/null @@ -1,204 +0,0 @@ -.. _talend: - -************************* -Connecting to SQream Using Talend -************************* - -.. _top: - -Overview -================= - -This page describes how to use Talend to interact with a SQream DB cluster. The Talend connector is used for reading data from a SQream DB cluster and loading data into SQream DB. - -In addition, this page provides a viability report on Talend's comptability with SQream DB for stakeholders. - -It includes the following: - -* :ref:`A Quick Start guide ` -* :ref:`Information about supported SQream drivers ` -* :ref:`Supported data sources ` and :ref:`tool and operating system versions ` -* :ref:`A description of known issues ` -* :ref:`Related links ` - - -About Talend -================= -Talend is an open-source data integration platform. It provides various software and services for Big Data integration and management, enterprise application integration, data quality and cloud storage. - -For more information about Talend, see `Talend `_. - - -.. _quickstart_guide: - -Quick Start Guide -======================= - -Creating a New Metadata JDBC DB Connection -------------- -**To create a new metadata JDBC DB connection:** - -1. In the **Repository** panel, nagivate to **Metadata** and right-click **Db connections**. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_1.png - -2. Select **Create connection**. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_2.png - -3. In the **Name** field, type a name. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_3.png - -The name cannot contain spaces. - -4. In the **Purpose** field, type a purpose and click **Next**. You cannot go to the next step until you define both a Name and a Purpose. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_4.png - -5. In the **DB Type** field, select **JDBC**. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_5.png - -6. In the **JDBC URL** field, type the relevant connection string. - - For connection string examples, see `Connection Strings `_. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_6.png - -7. In the **Drivers** field, click the **Add** button. - - The **"newLine** entry is added. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_7.png - -8. One the **"newLine** entry, click the ellipsis. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_8.png - -The **Module** window is displayed. - -9. From the Module window, select **Artifact repository(local m2/nexus)** and select **Install a new module**. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_9.png - -10. Click the ellipsis. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_9.5.png - -Your hard drive is displayed. - -11. Navigate to a **JDBC jar file** (such as **sqream-jdbc-4.4.0.jar**)and click **Open**. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_10.png - -12. Click **Detect the module install status**. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_11.5.png - -13. Click **OK**. - -The JDBC that you selected is displayed in the **Driver** field. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_12.png - -14. Click **Select class name**. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_13.png - -15. Click **Test connection**. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_14.png - -If a driver class is not found (for example, you didn't select a JDBC jar file), the following error message is displayed: - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_15.png - -After creating a new metadata JDBC DB connection, you can do the following: - - * Use your new metadata connection. - * Drag it to the **job** screen. - * Build Talend components. - -For more information on loading data from JSON files to the Talend Open Studio, see `How to Load Data from JSON Files in Talend `_. - -:ref:`Back to top ` - -.. _supported_sqream_drivers: - -Supported SQream Drivers -================ - -The following list shows the supported SQream drivers and versions: - -* **JDBC** - Version 4.3.3 and higher. -* **ODBC** - Version 4.0.0. This version requires a Bridge to connect. For more information on the required Bridge, see `Connecting Talend on Windows to an ODBC Database `_. - -:ref:`Back to top ` - - -.. _supported_data_sources: - -Supported Data Sources -============================ -Talend Cloud connectors let you create reusable connections with a wide variety of systems and environments, such as those shown below. This lets you access and read records of a range of diverse data. - -* **Connections:** Connections are environments or systems for storing datasets, including databases, file systems, distributed systems and platforms. Because these systems are reusable, you only need to establish connectivity with them once. - -* **Datasets:** Datasets include database tables, file names, topics (Kafka), queues (JMS) and file paths (HDFS). For more information on the complete list of connectors and datasets that Talend supports, see `Introducing Talend Connectors `_. - -:ref:`Back to top ` - - -.. _supported_tools_os_sys_versions: - -Supported Tool and Operating System Versions -====================== -Talend was tested using the following: - -* Talend version 7.4.1M6 -* Windows 10 -* SQream version 2021.1 -* JDBC version - - - - -:ref:`Back to top ` - - -.. _known_issues: - -Known Issues -=========================== -The the list below describes the following known issues as of 6/1/2021: - -* Schemas not displayed for tables with identical names. - -:ref:`Back to top ` - - -.. _related_links: - -Related Links -=============== -The following is a list of links relevant to the Talend connector: - -* `Talend Home page `_ -* `Talend Community page `_ -* `Talend BugTracker `_ - - -Download Links -================== -The following is a list of download links relevant to the Talend connector: - -* `Talend Open Studio for Big Data `_ -* `Latest version of SQream JDBC `_ - -:ref:`Back to top ` - - - -.. contents:: In this topic: - :local: From ffe26f1ff6daecd1ae276253ed1588e215c5092d Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 12 Jul 2022 18:23:01 +0300 Subject: [PATCH 280/300] SQ-10818 --- reference/sql/sql_statements/index.rst | 7 ++ .../get_role_database_ddl.rst | 61 +++++++++++++++ .../utility_commands/get_role_global_ddl.rst | 61 +++++++++++++++ .../utility_commands/get_role_permissions.rst | 74 +++++++++++++++++++ 4 files changed, 203 insertions(+) create mode 100644 reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst create mode 100644 reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst create mode 100644 reference/sql/sql_statements/utility_commands/get_role_permissions.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index ca4ec0f72..9bc902115 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -152,6 +152,7 @@ Workload Management Access Control Commands ================================ +The following table shows the Access Control commands: .. list-table:: Access Control Commands :widths: auto @@ -167,6 +168,12 @@ Access Control Commands - Creates a roles, which lets a database administrator control permissions on tables and databases * - :ref:`drop_role` - Removes roles + * - :ref:`get_role_permissions` + - Returns all permissions granted to a role in table format + * - :ref:`get_role_global_ddl` + - Returns the definition of a global role in DDL format + * - :ref:`get_role_database_ddl` + - Returns the definition of a database role in DDL format * - :ref:`get_statement_permissions` - Returns a list of permissions required to run a statement or query * - :ref:`grant` diff --git a/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst new file mode 100644 index 000000000..e6b806244 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst @@ -0,0 +1,61 @@ +.. _get_role_database_ddl: + +******************** +GET_ROLE_DATABASE_DDL +******************** +The ``GET_ROLE_DATABASE_DDL`` statement returns the definition of a global role in DDL format. + +The ``GET_ROLE_DATABASE_DDL`` page describes the following: + +.. contents:: + :local: + :depth: 1 + +Syntax +========== +The following is the correct syntax for using the ``GET_ROLE_DATABASE_DDL`` statement: + +.. code-block:: postgres + + select get_role_database_ddl(<'role_name'>) + +Example +=========== +The following is an example of using the ``GET_ROLE_GLOBAL_DDL`` statement: + +.. code-block:: psql + + select get_role_global_ddl('public'); + +Parameters +============ +The following table shows the ``GET_ROLE_DATABASE_DDL`` parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``role_name`` + - The definition of the database role in DDL format. + +Output +========== +The following is an example of the output of the ``GET_ROLE_DATABASE_DDL`` statement: + +.. code-block:: postgres + + grant create, usage on schema "public" to "public" ; alter default schema for "public" to "public"; alter default permissions for "public" for schemas grant superuser to creator_role ; alter default permissions for "public" for tables grant select, insert, delete, ddl to creator_role ; + +Permissions +============= +Using the ``GET_ROLE_DATABASE_DDL`` statement requires no special permissions. + +For more information, see the following: + +* :ref:`get_role_global_ddl` + + :: + +* :ref:`get_role_permissions` \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst b/reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst new file mode 100644 index 000000000..3ba0255d3 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst @@ -0,0 +1,61 @@ +.. _get_role_global_ddl: + +******************** +GET_ROLE_GLOBAL_DDL +******************** +The ``GET_ROLE_GLOBAL_DDL`` statement returns the definition of a global role in DDL format. + +The ``GET_ROLE_GLOBAL_DDL`` page describes the following: + +.. contents:: + :local: + :depth: 1 + +Syntax +========== +The following is the correct syntax for using the ``GET_ROLE_GLOBAL_DDL`` statement: + +.. code-block:: postgres + + select get_role_global_ddl(<'role_name'>) + +Example +=========== +The following is an example of using the ``GET_ROLE_GLOBAL_DDL`` statement: + +.. code-block:: psql + + select get_role_global_ddl('public'); + +Parameters +============ +The following table shows the ``GET_ROLE_GLOBAL_DDL`` parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``role_name`` + - The definition of the global role in DDL format. + +Output +========== +The following is an example of the output of the ``GET_ROLE_GLOBAL_DDL`` statement: + +.. code-block:: postgres + + create role "public"; + +Permissions +============= +Using the ``GET_ROLE_GLOBAL_DDL`` statement requires no special permissions. + +For more information, see the following: + +* :ref:`get_role_database_ddl` + + :: + +* :ref:`get_role_permissions` \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_role_permissions.rst b/reference/sql/sql_statements/utility_commands/get_role_permissions.rst new file mode 100644 index 000000000..8723f98c8 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get_role_permissions.rst @@ -0,0 +1,74 @@ +.. _get_role_permissions: + +******************** +GET_ROLE_PERMISSIONS +******************** +The ``GET_ROLE_PERMISSIONS`` statement returns all permissions granted to a role in table format. + +The ``GET_ROLE_PERMISSIONS`` page describes the following: + +.. contents:: + :local: + :depth: 1 + +Syntax +========== +The following is the correct syntax for using the ``GET_ROLE_PERMISSIONS`` statement: + +.. code-block:: postgres + + select get_role_permissions() + +Example +=========== +The following is an example of using the ``GET_ROLE_PERMISSIONS`` statement: + +.. code-block:: psql + + select get_role_permissions(); + +Parameters +============ +The following table shows the ``GET_ROLE_PERMISSIONS`` parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``()`` + - The permissions belonging to the role. + +Output +========== +The following is an example of the output of the ``GET_ROLE_PERMISSIONS`` statement: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + - Example + * - ``permission_type`` + - The permission type granted to the role. + - SUPERUSER + * - ``object_type`` + - The data object type. + - table + * - ``object_name`` + - The name of the object. + - master.public.nba + +Permissions +============= +Using the ``GET_ROLE_PERMISSIONS`` statement requires no special permissions. + +For more information, see the following: + +* :ref:`get_role_database_ddl` + + :: + +* :ref:`get_role_global_ddl` \ No newline at end of file From 7261919f9f1132546eec62ccc7215c559a873b4e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 13 Jul 2022 08:15:44 +0300 Subject: [PATCH 281/300] Update create_table.rst --- .../sql_statements/ddl_commands/create_table.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index 51f46582b..eb25baa8a 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -74,7 +74,7 @@ Default Value Constraints The ``DEFAULT`` value constraint specifies a value to use if one is not defined in an :ref:`insert` or :ref:`copy_from` statement. -The value may be a literal, which is evaluated at the time the row is created. +The value may either be a literal, **GETDATE()**, or Null, which is evaluated at the time the row is created. .. note:: The ``DEFAULT`` constraint only applies if the column does not have a value specified in the :ref:`insert` or :ref:`copy_from` statement. You can still insert a ``NULL`` into an nullable column by explicitly inserting ``NULL``. For example, ``INSERT INTO cool_animals VALUES (1, 'Gnu', NULL)``. @@ -141,7 +141,7 @@ The following is an example of the syntax used to create a standard table: CREATE TABLE cool_animals ( id INT NOT NULL, - name varchar(30) NOT NULL, + name text(30) NOT NULL, weight FLOAT, is_agressive BOOL ); @@ -155,7 +155,7 @@ The following is an example of the syntax used to create a table with default va CREATE TABLE cool_animals ( id INT NOT NULL, - name varchar(30) NOT NULL, + name text(30) NOT NULL, weight FLOAT, is_agressive BOOL DEFAULT false NOT NULL ); @@ -171,8 +171,8 @@ The following is an example of the syntax used to create a table with an identit CREATE TABLE users ( id BIGINT IDENTITY(0,1) NOT NULL , -- Start with 0, increment by 1 - name VARCHAR(30) NOT NULL, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL + name TEXT(30) NOT NULL, + country TEXT(30) DEFAULT 'Unknown' NOT NULL ); .. note:: @@ -203,9 +203,9 @@ The following is an example of the syntax used to create a table with a clusteri .. code-block:: postgres CREATE TABLE users ( - name VARCHAR(30) NOT NULL, + name TEXT(30) NOT NULL, start_date datetime not null, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL + country TEXT(30) DEFAULT 'Unknown' NOT NULL ) CLUSTER BY start_date; For more information on data clustering, see :ref:`data_clustering`. From 9f43257e882248b1850ef48fa4d6665cc1a3121b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 13 Jul 2022 08:23:34 +0300 Subject: [PATCH 282/300] Update create_table.rst --- .../sql/sql_statements/ddl_commands/create_table.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index eb25baa8a..c5f80c294 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -141,7 +141,7 @@ The following is an example of the syntax used to create a standard table: CREATE TABLE cool_animals ( id INT NOT NULL, - name text(30) NOT NULL, + name varchar(30) NOT NULL, weight FLOAT, is_agressive BOOL ); @@ -155,7 +155,7 @@ The following is an example of the syntax used to create a table with default va CREATE TABLE cool_animals ( id INT NOT NULL, - name text(30) NOT NULL, + name varchar(30) NOT NULL, weight FLOAT, is_agressive BOOL DEFAULT false NOT NULL ); @@ -171,8 +171,8 @@ The following is an example of the syntax used to create a table with an identit CREATE TABLE users ( id BIGINT IDENTITY(0,1) NOT NULL , -- Start with 0, increment by 1 - name TEXT(30) NOT NULL, - country TEXT(30) DEFAULT 'Unknown' NOT NULL + name varchar(30) NOT NULL, + country varchar(30) DEFAULT 'Unknown' NOT NULL ); .. note:: @@ -203,9 +203,9 @@ The following is an example of the syntax used to create a table with a clusteri .. code-block:: postgres CREATE TABLE users ( - name TEXT(30) NOT NULL, + name varchar(30) NOT NULL, start_date datetime not null, - country TEXT(30) DEFAULT 'Unknown' NOT NULL + country varchar(30) DEFAULT 'Unknown' NOT NULL ) CLUSTER BY start_date; For more information on data clustering, see :ref:`data_clustering`. From 8d19be9700fcafc1fb8398b187ac7205b5fbd35f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 19 Jul 2022 19:28:04 +0300 Subject: [PATCH 283/300] SQ-10818 --- reference/catalog_reference.rst | 610 +----------------- .../catalog_reference_additonal_tables.rst | 120 ++++ .../catalog_reference_catalog_tables.rst | 447 +++++++++++++ reference/catalog_reference_examples.rst | 64 ++ reference/catalog_reference_overview.rst | 11 + .../catalog_reference_schema_information.rst | 62 ++ .../alter_default_permissions.rst | 74 ++- .../access_control_commands/grant.rst | 2 +- 8 files changed, 774 insertions(+), 616 deletions(-) create mode 100644 reference/catalog_reference_additonal_tables.rst create mode 100644 reference/catalog_reference_catalog_tables.rst create mode 100644 reference/catalog_reference_examples.rst create mode 100644 reference/catalog_reference_overview.rst create mode 100644 reference/catalog_reference_schema_information.rst diff --git a/reference/catalog_reference.rst b/reference/catalog_reference.rst index 8cfa8e832..8fc0593b8 100644 --- a/reference/catalog_reference.rst +++ b/reference/catalog_reference.rst @@ -1,606 +1,16 @@ .. _catalog_reference: ************************************* -Catalog reference +Catalog Reference Guide ************************************* +The **Catalog Reference Guide** describes the following: -SQream DB contains a schema called ``sqream_catalog`` that contains information about your database's objects - tables, columns, views, permissions, and more. +.. toctree:: + :maxdepth: 1 + :glob: -Some additional catalog tables are used primarily for internal introspection, which could change across SQream DB versions. - - -.. contents:: In this topic: - :local: - -Types of data exposed by ``sqream_catalog`` -============================================== - -.. list-table:: Database objects - :widths: auto - :header-rows: 1 - - * - Object - - Table - * - Clustering keys - - ``clustering_keys`` - * - Columns - - ``columns``, ``external_table_columns`` - * - Databases - - ``databases`` - * - Permissions - - ``table_permissions``, ``database_permissions``, ``schema_permissions``, ``permission_types``, ``udf_permissions`` - * - Roles - - ``roles``, ``roles_memeberships`` - * - Schemas - - ``schemas`` - * - Sequences - - ``identity_key`` - * - Tables - - ``tables``, ``external_tables`` - * - Views - - ``views`` - * - UDFs - - ``user_defined_functions`` - -The catalog contains a few more tables which contain storage details for internal use - -.. list-table:: Storage objects - :widths: auto - :header-rows: 1 - - * - Object - - Table - * - Extents - - ``extents`` - * - Chunks - - ``chunks`` - * - Delete predicates - - ``delete_predicates`` - -Tables in the catalog -======================== - -clustering_keys ------------------------ - -Explicit clustering keys for tables. - -When more than one clustering key is defined, each key is listed in a separate row. - - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database containing the table - * - ``table_id`` - - ID of the table containing the column - * - ``schema_name`` - - Name of the schema containing the table - * - ``table_name`` - - Name of the table containing the column - * - ``clustering_key`` - - Name of the column that is a clustering key for this table - -columns --------- - -Column objects for standard tables - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database containing the table - * - ``schema_name`` - - Name of the schema containing the table - * - ``table_id`` - - ID of the table containing the column - * - ``table_name`` - - Name of the table containing the column - * - ``column_id`` - - Ordinal of the column in the table (begins at 0) - * - ``column_name`` - - Name of the column - * - ``type_name`` - - :ref:`Data type ` of the column - * - ``column_size`` - - The maximum length in bytes. - * - ``has_default`` - - ``NULL`` if the column has no default value. ``1`` if the default is a fixed value, or ``2`` if the default is an :ref:`identity` - * - ``default_value`` - - :ref:`Default value` for the column - * - ``compression_strategy`` - - User-overridden compression strategy - * - ``created`` - - Timestamp when the column was created - * - ``altered`` - - Timestamp when the column was last altered - - -.. _external_tables_table: - -external_tables ----------------- - -``external_tables`` identifies external tables in the database. - -For ``TABLES`` see :ref:`tables ` - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database containing the table - * - ``table_id`` - - Database-unique ID for the table - * - ``schema_name`` - - Name of the schema containing the table - * - ``table_name`` - - Name of the table - * - ``format`` - - - Identifies the foreign data wrapper used. - - ``0`` for csv_fdw, ``1`` for parquet_fdw, ``2`` for orc_fdw. - - * - ``created`` - - Identifies the clause used to create the table - -external_table_columns ------------------------- - -Column objects for external tables - -databases ------------ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_Id`` - - Unique ID of the database - * - ``database_name`` - - Name of the database - * - ``default_disk_chunk_size`` - - Internal use - * - ``default_process_chunk_size`` - - Internal use - * - ``rechunk_size`` - - Internal use - * - ``storage_subchunk_size`` - - Internal use - * - ``compression_chunk_size_threshold`` - - Internal use - -database_permissions ----------------------- - -``database_permissions`` identifies all permissions granted to databases. - -There is one row for each combination of role (grantee) and permission granted to a database. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database the permission applies to - * - ``role_id`` - - ID of the role granted permissions (grantee) - * - ``permission_type`` - - Identifies the permission type - - -identity_key --------------- - - -permission_types ------------------- - -``permission_types`` Identifies the permission names that exist in the database. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``permission_type_id`` - - ID of the permission type - * - ``name`` - - Name of the permission type - -roles ------- - -``roles`` identifies the roles in the database. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``role_id`` - - Database-unique ID of the role - * - ``name`` - - Name of the role - * - ``superuser`` - - Identifies if this role is a superuser. ``1`` for superuser or ``0`` otherwise. - * - ``login`` - - Identifies if this role can be used to log in to SQream DB. ``1`` for yes or ``0`` otherwise. - * - ``has_password`` - - Identifies if this role has a password. ``1`` for yes or ``0`` otherwise. - * - ``can_create_function`` - - Identifies if this role can create UDFs. ``1`` for yes, ``0`` otherwise. - -roles_memberships -------------------- - -``roles_memberships`` identifies the role memberships in the database. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``role_id`` - - Role ID - * - ``member_role_id`` - - ID of the parent role from which this role will inherit - * - ``inherit`` - - Identifies if permissions are inherited. ``1`` for yes or ``0`` otherwise. - -savedqueries ----------------- - -``savedqueries`` identifies the :ref:`saved_queries` in the database. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``name`` - - Saved query name - * - ``num_parameters`` - - Number of parameters to be replaced at run-time - -schemas ----------- - -``schemas`` identifies all the database's schemas. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``schema_id`` - - Unique ID of the schema - * - ``schema_name`` - - Name of the schema - * - ``schema_owner`` - - Name of the role who owns this schema - * - ``rechunker_ignore`` - - Internal use - - -schema_permissions --------------------- - -``schema_permissions`` identifies all permissions granted to schemas. - -There is one row for each combination of role (grantee) and permission granted to a schema. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database containing the schema - * - ``schema_id`` - - ID of the schema the permission applies to - * - ``role_id`` - - ID of the role granted permissions (grantee) - * - ``permission_type`` - - Identifies the permission type - - -.. _tables_table: - -tables ----------- - -``tables`` identifies proper SQream tables in the database. - -For ``EXTERNAL TABLES`` see :ref:`external_tables ` - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database containing the table - * - ``table_id`` - - Database-unique ID for the table - * - ``schema_name`` - - Name of the schema containing the table - * - ``table_name`` - - Name of the table - * - ``row_count_valid`` - - Identifies if the ``row_count`` can be used - * - ``row_count`` - - Number of rows in the table - * - ``rechunker_ignore`` - - Internal use - - -table_permissions ------------------- - -``table_permissions`` identifies all permissions granted to tables. - -There is one row for each combination of role (grantee) and permission granted to a table. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database containing the table - * - ``table_id`` - - ID of the table the permission applies to - * - ``role_id`` - - ID of the role granted permissions (grantee) - * - ``permission_type`` - - Identifies the permission type - - -udf_permissions ------------------- - -user_defined_functions -------------------------- - -``user_defined_functions`` identifies UDFs in the database. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database containing the view - * - ``function_id`` - - Database-unique ID for the UDF - * - ``function_name`` - - Name of the UDF - -views -------- - -``views`` identifies views in the database. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``view_id`` - - Database-unique ID for the view - * - ``view_schema`` - - Name of the schema containing the view - * - ``view_name`` - - Name of the view - * - ``view_data`` - - Internal use - * - ``view_query_text`` - - Identifies the ``AS`` clause used to create the view - - -Additional tables -====================== - -There are additional tables in the catalog that can be used for performance monitoring and inspection. - -The definition for these tables is provided below could change across SQream DB versions. - -extents ----------- - -``extents`` identifies storage extents. - -Each storage extents can contain several chunks. - -.. note:: This is an internal table designed for low-level performance troubleshooting. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the databse containing the extent - * - ``table_id`` - - ID of the table containing the extent - * - ``column_id`` - - ID of the column containing the extent - * - ``extent_id`` - - ID for the extent - * - ``size`` - - Extent size in megabytes - * - ``path`` - - Full path to the extent on the file system - -chunk_columns -------------------- - -``chunk_columns`` lists chunk information by column. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the databse containing the extent - * - ``table_id`` - - ID of the table containing the extent - * - ``column_id`` - - ID of the column containing the extent - * - ``chunk_id`` - - ID for the chunk - * - ``extent_id`` - - ID for the extent - * - ``compressed_size`` - - Actual chunk size in bytes - * - ``uncompressed_size`` - - Uncompressed chunk size in bytes - * - ``compression_type`` - - Actual compression scheme for this chunk - * - ``long_min`` - - Minimum numeric value in this chunk (if exists) - * - ``long_max`` - - Maximum numeric value in this chunk (if exists) - * - ``string_min`` - - Minimum text value in this chunk (if exists) - * - ``string_max`` - - Maximum text value in this chunk (if exists) - * - ``offset_in_file`` - - Internal use - -.. note:: This is an internal table designed for low-level performance troubleshooting. - -chunks -------- - -``chunks`` identifies storage chunks. - -.. note:: This is an internal table designed for low-level performance troubleshooting. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the databse containing the chunk - * - ``table_id`` - - ID of the table containing the chunk - * - ``column_id`` - - ID of the column containing the chunk - * - ``rows_num`` - - Amount of rows contained in the chunk - * - ``deletion_status`` - - When data is deleted from the table, it is first deleted logically. This value identifies how much data is deleted from the chunk. ``0`` for no data, ``1`` for some data, ``2`` to specify the entire chunk is deleted. - -delete_predicates -------------------- - -``delete_predicates`` identifies the existing delete predicates that have not been cleaned up. - -Each :ref:`DELETE ` command may result in several entries in this table. - -.. note:: This is an internal table designed for low-level performance troubleshooting. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the databse containing the predicate - * - ``table_id`` - - ID of the table containing the predicate - * - ``max_chunk_id`` - - Internal use. Placeholder marker for the highest ``chunk_id`` logged during the DELETE operation. - * - ``delete_predicate`` - - Identifies the DELETE predicate - - -Examples -=========== - -List all tables in the database ----------------------------------- - -.. code-block:: psql - - master=> SELECT * FROM sqream_catalog.tables; - database_name | table_id | schema_name | table_name | row_count_valid | row_count | rechunker_ignore - --------------+----------+-------------+----------------+-----------------+-----------+----------------- - master | 1 | public | nba | true | 457 | 0 - master | 12 | public | cool_dates | true | 5 | 0 - master | 13 | public | cool_numbers | true | 9 | 0 - master | 27 | public | jabberwocky | true | 8 | 0 - -List all schemas in the database ------------------------------------- - -.. code-block:: psql - - master=> SELECT * FROM sqream_catalog.schemas; - schema_id | schema_name | schema_owner | rechunker_ignore - ----------+---------------+--------------+----------------- - 0 | public | sqream | false - 1 | secret_schema | mjordan | false - - -List columns and their types for a specific table ---------------------------------------------------- - -.. code-block:: postgres - - SELECT column_name, type_name - FROM sqream_catalog.columns - WHERE table_name='cool_animals'; - -List delete predicates ------------------------- - -.. code-block:: postgres - - SELECT t.table_name, d.* FROM - sqream_catalog.delete_predicates AS d - INNER JOIN sqream_catalog.tables AS t - ON d.table_id=t.table_id; - - -List :ref:`saved_queries` ------------------------------ - -.. code-block:: postgres - - SELECT * FROM sqream_catalog.savedqueries; + catalog_reference_overview + catalog_reference_schema_information + catalog_reference_catalog_tables + catalog_reference_additonal_tables + catalog_reference_examples \ No newline at end of file diff --git a/reference/catalog_reference_additonal_tables.rst b/reference/catalog_reference_additonal_tables.rst new file mode 100644 index 000000000..7d34429d3 --- /dev/null +++ b/reference/catalog_reference_additonal_tables.rst @@ -0,0 +1,120 @@ +.. _catalog_reference_additonal_tables: + +************************************* +Additional Tables +************************************* +The Reference Catalog includes additional tables that can be used for performance monitoring and inspection. The definition for these tables described on this page may change across SQream versions. + +.. contents:: + :local: + :depth: 1 + +Extents +---------- +The ``extents`` storage object identifies storage extents, and each storage extents can contain several chunks. + +.. note:: This is an internal table designed for low-level performance troubleshooting. + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the databse containing the extent. + * - ``table_id`` + - Shows the ID of the table containing the extent. + * - ``column_id`` + - Shows the ID of the column containing the extent. + * - ``extent_id`` + - Shows the ID for the extent. + * - ``size`` + - Shows the extent size in megabytes. + * - ``path`` + - Shows the full path to the extent on the file system. + +Chunk Columns +------------------- +The ``chunk_columns`` storage object lists chunk information by column. + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the databse containing the extent. + * - ``table_id`` + - Shows the ID of the table containing the extent. + * - ``column_id`` + - Shows the ID of the column containing the extent. + * - ``chunk_id`` + - Shows the chunk ID. + * - ``extent_id`` + - Shows the extent ID. + * - ``compressed_size`` + - Shows the compressed chunk size in bytes. + * - ``uncompressed_size`` + - Shows the uncompressed chunk size in bytes. + * - ``compression_type`` + - Shows the chunk's actual compression scheme. + * - ``long_min`` + - Shows the minimum numeric value in the chunk (if one exists). + * - ``long_max`` + - Shows the maximum numeric value in the chunk (if one exists). + * - ``string_min`` + - Shows the minimum text value in the chunk (if one exists). + * - ``string_max`` + - Shows the maximum text value in the chunk (if one exists). + * - ``offset_in_file`` + - Reserved for internal use. + +.. note:: This is an internal table designed for low-level performance troubleshooting. + +Chunks +------- +The ``chunks`` storage object identifies storage chunks. + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the databse containing the chunk. + * - ``table_id`` + - Shows the ID of the table containing the chunk. + * - ``column_id`` + - Shows the ID of the column containing the chunk. + * - ``rows_num`` + - Shows the amount of rows in the chunk. + * - ``deletion_status`` + - Determines what data to logically delete from the table first, and identifies how much data to delete from the chunk. The value ``0`` is ued for no data, ``1`` for some data, and ``2`` to delete the entire chunk. + +.. note:: This is an internal table designed for low-level performance troubleshooting. + +Delete Predicates +------------------- +The ``delete_predicates`` storage object identifies the existing delete predicates that have not been cleaned up. + +Each :ref:`DELETE ` command may result in several entries in this table. + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the databse containing the predicate. + * - ``table_id`` + - Shows the ID of the table containing the predicate. + * - ``max_chunk_id`` + - Reserved for internal use, this is a placeholder marker for the highest ``chunk_id`` logged during the ``DELETE`` operation. + * - ``delete_predicate`` + - Identifies the DELETE predicate. + +.. note:: This is an internal table designed for low-level performance troubleshooting. \ No newline at end of file diff --git a/reference/catalog_reference_catalog_tables.rst b/reference/catalog_reference_catalog_tables.rst new file mode 100644 index 000000000..5a5b77fec --- /dev/null +++ b/reference/catalog_reference_catalog_tables.rst @@ -0,0 +1,447 @@ +.. _catalog_reference_catalog_tables: + +************************************* +Catalog Tables +************************************* +The ``sqream_catalog`` includes the following tables: + +.. contents:: + :local: + :depth: 1 + +.. _clustering_keys: + +Clustering Keys +---------------- +The ``clustering_keys`` data object is used for explicit clustering keys for tables. If you define more than one clustering key, each key is listed in a separate row, and is described in the following table: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database containing the table. + * - ``table_id`` + - Shows the ID of the table containing the column. + * - ``schema_name`` + - Shows the name of the schema containing the table. + * - ``table_name`` + - Shows the name of the table containing the column. + * - ``clustering_key`` + - Shows the name of the column used as a clustering key for this table. + +.. _columns: + +Columns +---------------- +The **Columns** database object shows the following tables: + +.. contents:: + :local: + :depth: 1 + +Columns +*********** +The ``column`` data object is used with standard tables and is described in the following table: + +.. list-table:: + :widths: 20 150 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database containing the table. + * - ``schema_name`` + - Shows the name of the schema containing the table. + * - ``table_id`` + - Shows the ID of the table containing the column. + * - ``table_name`` + - Shows the name of the table containing the column. + * - ``column_id`` + - Shows the ordinal number of the column in the table (begins at **0**). + * - ``column_name`` + - Shows the column's name. + * - ``type_name`` + - Shows the column's data type. For more information see :ref:`Supported Data Types `. + * - ``column_size`` + - Shows the maximum length in bytes. + * - ``has_default`` + - Shows ``NULL`` if the column has no default value, ``1`` if the default is a fixed value, or ``2`` if the default is an identity. For more information, see :ref:`identity`. + * - ``default_value`` + - Shows the column's default value. For more information, see :ref:`Default Value Constraints`. + * - ``compression_strategy`` + - Shows the compression strategy that a user has overridden. + * - ``created`` + - Shows the timestamp displaying when the column was created. + * - ``altered`` + - Shows the timestamp displaying when the column was last altered. + +External Table Columns +*********** +The ``external_table_columns`` is used for viewing data from foreign tables. + +For more information on foreign tables, see :ref:`CREATE FOREIGN TABLE`. + +.. _databases: + +Databases +---------------- +The ``databases`` data object is used for displaying database information, and is described in the following table: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_Id`` + - Shows the database's unique ID. + * - ``database_name`` + - Shows the database's name. + * - ``default_disk_chunk_size`` + - Reserved for internal use. + * - ``default_process_chunk_size`` + - Reserved for internal use. + * - ``rechunk_size`` + - Reserved for internal use. + * - ``storage_subchunk_size`` + - Reserved for internal use. + * - ``compression_chunk_size_threshold`` + - Reserved for internal use. + +.. _permissions: + +Permissions +---------------- +The ``permissions`` data object is used for displaying permissions information, such as roles (also known as **grantees**), and is described in the following tables: + +.. contents:: + :local: + :depth: 1 + +Permission Types +*********** +The ``permission_types`` object identifies the permission names existing in the database. + +The following table describes the ``permission_types`` data object: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``permission_type_id`` + - Shows the permission type's ID. + * - ``name`` + - Shows the name of the permission type. + +Default Permissions +*********** +The commands included in the **Default Permissions** section describe how to check the following default permissions: + +.. contents:: + :local: + :depth: 1 + +Default Table Permissions +~~~~~~~~~~~~~~~~ +The ``sqream_catalog.table_default_permissions`` command shows the columns described below: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the database that the default permission rule applies to. + * - ``schema_id`` + - Shows the schema that the rule applies to, or ``NULL`` if the ``ALTER`` statement does not specify a schema. + * - ``modifier_role_id`` + - Shows the role to apply the rule to. + * - ``getter_role_id`` + - Shows the role that the permission is granted to. + * - ``permission_type`` + - Shows the type of permission granted. + +Default Schema Permissions +~~~~~~~~~~~~~~~~ +The ``sqream_catalog.schema_default_permissions`` command shows the columns described below: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the database that the default permission rule applies to. + * - ``modifier_role_id`` + - Shows the role to apply the rule to. + * - ``getter_role_id`` + - Shows the role that the permission is granted to. + * - ``permission_type`` + - Shows the type of permission granted. + +For an example of using the ``sqream_catalog.table_default_permissions`` command, see `Granting Default Table Permissions `_. + +Table Permissions +*********** +The ``table_permissions`` data object identifies all permissions granted to tables. Each role-permission combination displays one row. + +The following table describes the ``table_permissions`` data object: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database containing the table. + * - ``table_id`` + - Shows the ID of the table the permission applies to. + * - ``role_id`` + - Shows the ID of the role granted permissions. + * - ``permission_type`` + - Identifies the permission type. + +Database Permissions +*********** +The ``database_permissions`` data object identifies all permissions granted to databases. Each role-permission combination displays one row. + +The following table describes the ``database_permissions`` data object: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database the permission applies to + * - ``role_id`` + - Shows the ID of the role granted permissions. + * - ``permission_type`` + - Identifies the permission type. + +Schema Permissions +*********** +The ``schema_permissions`` data object identifies all permissions granted to schemas. Each role-permission combination displays one row. + +The following table describes the ``schema_permissions`` data object: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database containing the schema. + * - ``schema_id`` + - Shows the ID of the schema the permission applies to. + * - ``role_id`` + - Shows the ID of the role granted permissions. + * - ``permission_type`` + - Identifies the permission type. + +.. _queries: + +Queries +---------------- +The ``savedqueries`` data object identifies the saved_queries in the database, as shown in the following table: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``name`` + - Shows the saved query name. + * - ``num_parameters`` + - Shows the number of parameters to be replaced at run-time. + +For more information, see :ref:`saved_queries`. + +.. _roles: + +Roles +---------------- +The ``roles`` data object is used for displaying role information, and is described in the following tables: + +.. contents:: + :local: + :depth: 1 + +Roles +*********** +The ``roles`` data object identifies the roles in the database, as shown in the following table: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``role_id`` + - Shows the role's database-unique ID. + * - ``name`` + - Shows the role's name. + * - ``superuser`` + - Identifies whether the role is a superuser (``1`` - superuser, ``0`` - regular user). + * - ``login`` + - Identifies whether the role can be used to log in to SQream (``1`` - yes, ``0`` - no). + * - ``has_password`` + - Identifies whether the role has a password (``1`` - yes, ``0`` - no). + * - ``can_create_function`` + - Identifies whether role can create UDFs (``1`` - yes, ``0`` - no). + +Role Memberships +*********** +The ``roles_memberships`` data object identifies the role memberships in the database, as shown below: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``role_id`` + - Shows the role ID. + * - ``member_role_id`` + - Shows the ID of the parent role that this role inherits from. + * - ``inherit`` + - Identifies whether permissions are inherited (``1`` - yes, ``0`` - no). + +.. _schemas: + +Schemas +---------------- +The ``schemas`` data object identifies all the database's schemas, as shown below: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``schema_id`` + - Shows the schema's unique ID. + * - ``schema_name`` + - Shows the schema's name. + * - ``schema_owner`` + - Shows the name of the role that owns the schema. + * - ``rechunker_ignore`` + - Reserved for internal use. + +.. _sequences: + +Sequences +---------------- +The ``sequences`` data object is used for displaying identity key information. + +.. _tables: + +Tables +---------------- +The ``tables`` data object is used for displaying table information, and is described in the following tables: + +.. contents:: + :local: + :depth: 1 + +Tables +*********** +The ``tables`` data object identifies proper (**Comment** - *What does "proper" mean?*) SQream tables in the database, as shown in the following table: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database containing the table. + * - ``table_id`` + - Shows the table's database-unique ID. + * - ``schema_name`` + - Shows the name of the schema containing the table. + * - ``table_name`` + - Shows the name of the table. + * - ``row_count_valid`` + - Identifies whether the ``row_count`` can be used. + * - ``row_count`` + - Shows the number of rows in the table. + * - ``rechunker_ignore`` + - Relevant for internal use. + +Foreign Tables +*********** +The ``external_tables`` data object identifies foreign tables in the database, as shown below: + +.. list-table:: + :widths: 20 200 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database containing the table. + * - ``table_id`` + - Shows the table's database-unique ID. + * - ``schema_name`` + - Shows the name of the schema containing the table. + * - ``table_name`` + - Shows the name of the table. + * - ``format`` + - Identifies the foreign data wrapper used. ``0`` for ``csv_fdw``, ``1`` for ``parquet_fdw``, ``2`` for ``orc_fdw``. + * - ``created`` + - Identifies the clause used to create the table. + +.. _views: + +Views +---------------- +The ``views`` data object is used for displaying views in the database, as shown below: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``view_id`` + - Shows the view's database-unique ID. + * - ``view_schema`` + - Shows the name of the schema containing the view. + * - ``view_name`` + - Shows the name of the view. + * - ``view_data`` + - Reserved for internal use. + * - ``view_query_text`` + - Identifies the ``AS`` clause used to create the view. + +.. _udfs: + +User Defined Functions +---------------- +The ``udf`` data object is used for displaying UDFs in the database, as shown below: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database containing the view. + * - ``function_id`` + - Shows the UDF's database-unique ID. + * - ``function_name`` + - Shows the name of the UDF. \ No newline at end of file diff --git a/reference/catalog_reference_examples.rst b/reference/catalog_reference_examples.rst new file mode 100644 index 000000000..4531dfefc --- /dev/null +++ b/reference/catalog_reference_examples.rst @@ -0,0 +1,64 @@ +.. _catalog_reference_examples: + +************************************* +Examples +************************************* +The **Examples** page includes the following examples: + +.. contents:: + :local: + :depth: 1 + +Listing All Tables in a Database +---------------------------------- + +.. code-block:: psql + + master=> SELECT * FROM sqream_catalog.tables; + database_name | table_id | schema_name | table_name | row_count_valid | row_count | rechunker_ignore + --------------+----------+-------------+----------------+-----------------+-----------+----------------- + master | 1 | public | nba | true | 457 | 0 + master | 12 | public | cool_dates | true | 5 | 0 + master | 13 | public | cool_numbers | true | 9 | 0 + master | 27 | public | jabberwocky | true | 8 | 0 + +Listing All Schemas in a Database +------------------------------------ + +.. code-block:: psql + + master=> SELECT * FROM sqream_catalog.schemas; + schema_id | schema_name | schema_owner | rechunker_ignore + ----------+---------------+--------------+----------------- + 0 | public | sqream | false + 1 | secret_schema | mjordan | false + + +Listing Columns and Their Types for a Specific Table +--------------------------------------------------- + +.. code-block:: postgres + + SELECT column_name, type_name + FROM sqream_catalog.columns + WHERE table_name='cool_animals'; + +Listing Delete Predicates +------------------------ + +.. code-block:: postgres + + SELECT t.table_name, d.* FROM + sqream_catalog.delete_predicates AS d + INNER JOIN sqream_catalog.tables AS t + ON d.table_id=t.table_id; + + +Listing Saved Queries +----------------------------- + +.. code-block:: postgres + + SELECT * FROM sqream_catalog.savedqueries; + +For more information, see :ref:`saved_queries`. \ No newline at end of file diff --git a/reference/catalog_reference_overview.rst b/reference/catalog_reference_overview.rst new file mode 100644 index 000000000..b74663509 --- /dev/null +++ b/reference/catalog_reference_overview.rst @@ -0,0 +1,11 @@ +.. _catalog_reference_overview: + +************************************* +Overview +************************************* +The SQream database uses a schema called ``sqream_catalog`` that contains information about your database's objects, such tables, columns, views, and permissions. Some additional catalog tables are used primarily for internal analysis and which may be different across SQream versions. + +* :ref:`catalog_reference_schema_information` +* :ref:`catalog_reference_catalog_tables` +* :ref:`catalog_reference_additonal_tables` +* :ref:`catalog_reference_examples` \ No newline at end of file diff --git a/reference/catalog_reference_schema_information.rst b/reference/catalog_reference_schema_information.rst new file mode 100644 index 000000000..6cd43ab6a --- /dev/null +++ b/reference/catalog_reference_schema_information.rst @@ -0,0 +1,62 @@ +.. _catalog_reference_schema_information: + +************************************* +What Information Does the Schema Contain? +************************************* +The schema includes tables designated and relevant for both external and internal use: + +.. contents:: + :local: + :depth: 1 + +External Tables +----------------- +The following table shows the data objects contained in the ``sqream_catalog`` schema designated for external use: + +.. list-table:: Database Objects + :widths: 20 180 + :header-rows: 1 + + * - Database Object + - Table + * - :ref:`Clustering Keys` + - ``clustering_keys`` + * - :ref:`Columns` + - ``columns``, ``external_table_columns`` + * - :ref:`Databases` + - ``databases`` + * - :ref:`Permissions` + - ``table_permissions``, ``database_permissions``, ``schema_permissions``, ``permission_types``, ``udf_permissions``, ``sqream_catalog.table_default_permissions`` + * - :ref:`Queries` + - ``saved_queries`` + * - :ref:`Roles` + - ``roles``, ``roles_memeberships`` + * - :ref:`Schemas` + - ``schemas`` + * - :ref:`Sequences` + - ``identity_key`` + * - :ref:`Tables` + - ``tables``, ``external_tables`` + * - :ref:`Views` + - ``views`` + * - :ref:`User Defined Functions` + - ``user_defined_functions`` + +Internal Tables +----------------- +The following table shows the data objects contained in the ``sqream_catalog`` schema designated for internal use: + +.. list-table:: Storage Objects + :widths: 20 180 + :header-rows: 1 + + * - Database Object + - Table + * - Extents + - Shows ``extents``. + * - Chunk columns + - Shows ``chunks_columns``. + * - Chunks + - Shows ``chunks``. + * - Delete predicates + - Shows ``delete_predicates``. For more information, see :ref:`Deleting Data`. \ No newline at end of file diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index bef17f22f..4c04c5105 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -3,22 +3,27 @@ ***************************** ALTER DEFAULT PERMISSIONS ***************************** +The **ALTER DEFAULT PERMISSIONS** page describes the following: -``ALTER DEFAULT PERMISSIONS`` allows granting automatic permissions to future objects. +.. contents:: + :local: + :depth: 1 -By default, if one user creates a table, another user will not have ``SELECT`` permissions on it. -By modifying the target role's default permissions, a database administrator can ensure that -all objects created by that role will be accessible to others. +Overview +============= +The ``ALTER DEFAULT PERMISSIONS`` command lets you grant automatic permissions to future objects. + +By default, users do not have ``SELECT`` permissions on tables created by other users. Database administrators can grant access to other users by modifying the target role default permissions. -Learn more about the permission system in the :ref:`access control guide`. +For more information about access control, see :ref:`Access Control`. Permissions ============= - -To alter default permissions, the current role must have the ``SUPERUSER`` permission. +The ``SUPERUSER`` permission is required to alter default permissions. Syntax ========== +The following is the syntax for altering default permissions: .. code-block:: postgres @@ -55,31 +60,70 @@ Syntax :start-line: 127 :end-line: 180 - Examples ============ +This section includes the following examples: -Automatic permissions for newly created schemas +.. contents:: + :local: + :depth: 1 + +Granting Default Table Permissions ------------------------------------------------- +This example is based on the roles **r1** and **r2**, created as follows: -When role ``demo`` creates a new schema, roles u1,u2 will get USAGE and CREATE permissions in the new schema: +.. code-block:: postgres + + create role r1; + create role r2; + alter default permissions for r1 for tables grant select to r2; + +Once created, you can build and run the following query based on the above: .. code-block:: postgres - ALTER DEFAULT PERMISSIONS FOR demo FOR SCHEMAS GRANT USAGE, CREATE TO u1,u2; + select + tdp.database_name as "database_name", + ss.schema_name as "schema_name", + rs1.name as "table_creator", + rs2.name as "grant_to", + pts.name as "permission_type" + from sqream_catalog.table_default_permissions tdp + inner join sqream_catalog.roles rs1 on tdp.modifier_role_id = rs1.role_id + inner join sqream_catalog.roles rs2 on tdp.getter_role_id = rs2.role_id + left join sqream_catalog.schemas ss on tdp.schema_id = ss.schema_id + inner join sqream_catalog.permission_types pts on pts.permission_type_id=tdp.permission_type + ; + +The following is an example of the output generated from the above queries: ++-----------------------+----------------------+-------------------+--------------+------------------------------+ +| **database_name** | **schema_name** | **table_creator** | **grant_to** | **permission_type** | ++-----------------------+----------------------+-------------------+--------------+------------------------------+ +| master | NULL | public | public | select | ++-----------------------+----------------------+-------------------+--------------+------------------------------+ -Automatic permissions for newly created tables in a schema ----------------------------------------------------------------- +For more information about default permissions, see `Default Permissions `_. + +Granting Automatic Permissions for Newly Created Schemas +------------------------------------------------- +When the role ``demo`` creates a new schema, roles **u1,u2** are granted ``USAGE`` and ``CREATE`` permissions in the new schema, as shown below: -When role ``demo`` creates a new table in schema ``s1``, roles u1,u2 wil be granted with SELECT on it: +.. code-block:: postgres + + ALTER DEFAULT PERMISSIONS FOR demo FOR SCHEMAS GRANT USAGE, CREATE TO u1,u2; + +Granting Automatic Permissions for Newly Created Tables in a Schema +---------------------------------------------------------------- +When the role ``demo`` creates a new table in schema ``s1``, roles **u1,u2** are granted ``SELECT`` permissions, as shown below: .. code-block:: postgres ALTER DEFAULT PERMISSIONS FOR demo IN s1 FOR TABLES GRANT SELECT TO u1,u2; -Revoke (``DROP GRANT``) permissions for newly created tables +Revoking Permissions from Newly Created Tables --------------------------------------------------------------- +Revoking permissions refers to using the ``DROP GRANT`` command, as shown below: .. code-block:: postgres diff --git a/reference/sql/sql_statements/access_control_commands/grant.rst b/reference/sql/sql_statements/access_control_commands/grant.rst index dfb48c212..ceac48f7a 100644 --- a/reference/sql/sql_statements/access_control_commands/grant.rst +++ b/reference/sql/sql_statements/access_control_commands/grant.rst @@ -126,7 +126,7 @@ Parameters .. include from here -Supported permissions +Supported Permissions ======================= .. list-table:: From 20babdd79cc619b5a0269ce4e28af18b0c08ec7e Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 20 Jul 2022 14:29:22 +0300 Subject: [PATCH 284/300] Update tableau.rst --- connecting_to_sqream/client_platforms/tableau.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst index e43c8f893..705f90824 100644 --- a/connecting_to_sqream/client_platforms/tableau.rst +++ b/connecting_to_sqream/client_platforms/tableau.rst @@ -96,7 +96,7 @@ Note the following when installing the JDBC driver: Based on the installation method that you used, your Tableau driver directory is located in one of the following places: * **Tableau Desktop on Windows:** *C:\\Users\\\\My Tableau Repository\\Connectors* - * **Tableau Desktop on Windows:** *~/My Tableau Repository/Connectors* + * **Tableau Desktop on Mac:** *~/My Tableau Repository/Connectors* :: @@ -449,4 +449,4 @@ If Tableau cannot locate the SQream JDBC driver, do the following: * **For Windows** - add an environment variable for the classpath. -If you experience issues after restarting Tableau, see the `SQream support portal `_. \ No newline at end of file +If you experience issues after restarting Tableau, see the `SQream support portal `_. From 6ee5c449c2daddfbd4dd77cdd2418350de30a575 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 21 Jul 2022 12:04:13 +0300 Subject: [PATCH 285/300] Added Talend --- .../client_platforms/index.rst | 2 +- .../client_platforms/talend.rst | 123 ++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 connecting_to_sqream/client_platforms/talend.rst diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 1ed2874ed..51b6e77d5 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -31,7 +31,7 @@ If you are looking for a tool that is not listed, SQream and our partners can he informatica r php - xxtalend + talend xxdiagnosing_common_connectivity_issues .. image:: /_static/images/connectivity_ecosystem.png \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/talend.rst b/connecting_to_sqream/client_platforms/talend.rst new file mode 100644 index 000000000..1d0fb51b9 --- /dev/null +++ b/connecting_to_sqream/client_platforms/talend.rst @@ -0,0 +1,123 @@ +.. _talend: + +************************* +Connecting to SQream Using Talend +************************* + +Overview +================= +This page describes how to use Talend to interact with a SQream cluster. The Talend connector is used for reading data from a SQream cluster and loading data into SQream. In addition, this page provides a viability report on Talend's comptability with SQream for stakeholders. + +The **Connecting to SQream Using Talend** describes the following: + +.. contents:: + :local: + :depth: 1 + +Creating a New Metadata JDBC DB Connection +---------------- +**To create a new metadata JDBC DB connection:** + +1. In the **Repository** panel, nagivate to **Metadata** and right-click **Db connections**. + + :: + +2. Select **Create connection**. + + :: + +3. In the **Name** field, type a name. + + :: + + Note that the name cannot contain spaces. + +4. In the **Purpose** field, type a purpose and click **Next**. + + Note that you cannot continue to the next step until you define both a Name and a Purpose. + + :: + +5. In the **DB Type** field, select **JDBC**. + + :: + +6. In the **JDBC URL** field, type the relevant connection string. + + For connection string examples, see `Connection Strings `_. + +7. In the **Drivers** field, click the **Add** button. + + The **"newLine"** entry is added. + +8. One the **"newLine'** entry, click the ellipsis. + + The **Module** window is displayed. + +9. From the Module window, select **Artifact repository(local m2/nexus)** and select **Install a new module**. + + :: + +10. Click the ellipsis. + + Your hard drive is displayed. + +11. Navigate to a **JDBC jar file** (such as **sqream-jdbc-4.5.3.jar**)and click **Open**. + + :: + +12. Click **Detect the module install status**. + + :: + +13. Click **OK**. + + The JDBC that you selected is displayed in the **Driver** field. + +14. Click **Select class name**. + + :: + +15. Click **Test connection**. + + If a driver class is not found (for example, you didn't select a JDBC jar file), the following error message is displayed: + + After creating a new metadata JDBC DB connection, you can do the following: + + * Use your new metadata connection. + + :: + + * Drag it to the **job** screen. + + :: + + * Build Talend components. + + For more information on loading data from JSON files to the Talend Open Studio, see `How to Load Data from JSON Files in Talend `_. + +Supported SQream Drivers +---------------- +The following list shows the supported SQream drivers and versions: + +* **JDBC** - Version 4.3.3 and higher. + + :: + +* **ODBC** - Version 4.0.0. This version requires a Bridge to connect. For more information on the required Bridge, see `Connecting Talend on Windows to an ODBC Database `_. + +Supported Data Sources +---------------- +Talend Cloud connectors let you create reusable connections with a wide variety of systems and environments, such as those shown below. This lets you access and read records of a range of diverse data. + +* **Connections:** Connections are environments or systems for storing datasets, including databases, file systems, distributed systems and platforms. Because these systems are reusable, you only need to establish connectivity with them once. + + :: + +* **Datasets:** Datasets include database tables, file names, topics (Kafka), queues (JMS) and file paths (HDFS). For more information on the complete list of connectors and datasets that Talend supports, see `Introducing Talend Connectors `_. + +Known Issues +---------------- +As of 6/1/2021 schemas were not displayed for tables with identical names. + +If you experience issues using Talend, see the `SQream support portal `_. \ No newline at end of file From 5607f33a64ed1f3944ac12fe35fd97b73dfbdb29 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 21 Jul 2022 12:18:10 +0300 Subject: [PATCH 286/300] Alphabetized --- connecting_to_sqream/client_platforms/index.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 51b6e77d5..ac5f567ad 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -21,17 +21,17 @@ If you are looking for a tool that is not listed, SQream and our partners can he :caption: In this section: :titlesonly: + informatica + microstrategy + pentaho + php power_bi - tibco_spotfire + r sas_viya sql_workbench tableau - pentaho - microstrategy - informatica - r - php talend + tibco_spotfire xxdiagnosing_common_connectivity_issues .. image:: /_static/images/connectivity_ecosystem.png \ No newline at end of file From e8823e0338f2ca52d52919d15dd2ed995d11640f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 21 Jul 2022 13:05:37 +0300 Subject: [PATCH 287/300] Update tableau.rst --- .../client_platforms/tableau.rst | 321 +++--------------- 1 file changed, 42 insertions(+), 279 deletions(-) diff --git a/connecting_to_sqream/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst index 705f90824..1d2ca17b6 100644 --- a/connecting_to_sqream/client_platforms/tableau.rst +++ b/connecting_to_sqream/client_platforms/tableau.rst @@ -1,4 +1,4 @@ -.. _connect_to_tableau: +.. _tableau: ************************* Connecting to SQream Using Tableau @@ -6,9 +6,9 @@ Connecting to SQream Using Tableau Overview ===================== -SQream's Tableau connector plugin, based on standard JDBC, enables storing and fast querying large volumes of data. +SQream's Tableau connector plugin, based on standard JDBC, enables storing and fast querying large volumes of data. -The **Connecting to SQream Using Tableau** page is a Quick Start Guide that describes how install Tableau and the JDBC and ODBC drivers and connect to SQream using the JDBC and ODBC drivers for data analysis. It also describes using best practices and troubleshoot issues that may occur while installing Tableau. SQream supports both Tableau Desktop and Tableau Server on Windows, MacOS, and Linux distributions. +The **Connecting to SQream Using Tableau** page is a Quick Start Guide that describes how install Tableau and the JDBC driver and connect to SQream for data analysis. It also describes using best practices and troubleshoot issues that may occur while installing Tableau. SQream supports both Tableau Desktop and Tableau Server on Windows, MacOS, and Linux distributions. For more information on SQream's integration with Tableau, see `Tableau's Extension Gallery `_. @@ -16,295 +16,67 @@ The Connecting to SQream Using Tableau page describes the following: .. contents:: :local: + :depth: 1 Installing the JDBC Driver and Tableau Connector Plugin ------------------- This section describes how to install the JDBC driver using the fully-integrated Tableau connector plugin (Tableau Connector, or **.taco** file). SQream has been tested with Tableau versions 9.2 and newer. -**To connect to SQream using Tableau:** - -#. Install the Tableau Desktop application. - - For more information about installing the Tableau Desktop application, see the `Tableau products page `_ and click **Download Free Trial**. Note that Tableau offers a 14-day trial version. - - :: - -#. Do one of the following: - - * **For Windows** - See :ref:`Installing Tableau Using the Windows Installer `. - * **For MacOS or Linux** - See :ref:`Installing the JDBC Driver Manually `. - -.. note:: For Tableau **2019.4 versions and later**, SQream recommends installing the JDBC driver instead of the previously recommended ODBC driver. - -.. _tableau_windows_installer: - -Installing the JDBC Driver Using the Windows Installer -~~~~~~~~~~~~~~~~~~ -If you are using Windows, after installing the Tableau Desktop application you can install the JDBC driver using the Windows installer. The Windows installer is an installation wizard that guides you through the JDBC driver installation steps. When the driver is installed, you can connect to SQream. - -**To install Tableau using the Windows installer**: - -#. Close Tableau Desktop. - - :: - -#. Download the most current version of the `SQream JDBC driver `_. - - :: - -#. Do the following: - - #. Start the installer. - #. Verify that the **Tableau Desktop connector** item is selected. - #. Follow the installation steps. +You can connect to SQream using Tableau by doing one of the following: - :: - -You can now restart Tableau Desktop or Server to begin using the SQream driver by :ref:`connecting to SQream `. + * **For MacOS or Linux** - See :ref:`Installing the JDBC Driver `. .. _tableau_jdbc_installer: - -Installing the JDBC Driver Manually -~~~~~~~~~~~~~ + +Installing the JDBC Driver +------------------- If you are using MacOS, Linux, or the Tableau server, after installing the Tableau Desktop application you can install the JDBC driver manually. When the driver is installed, you can connect to SQream. -**To install the JDBC driver manually:** +**To install the JDBC driver:** 1. Download the JDBC installer and SQream Tableau connector (.taco) file from the :ref:`from the client drivers page`. :: -#. Install the JDBC driver by unzipping the JDBC driver into a Tableau driver directory. - - Based on the installation method that you used, your Tableau driver directory is located in one of the following places: +2. Based on your operating system, your Tableau driver directory is located in one of the following places: - * **Tableau Desktop on Windows:** *C:\\Program Files\\Tableau\\Drivers* * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* - * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* - -.. note:: If the driver includes only a single .jar file, copy it to *C:\\Program Files\\Tableau/Drivers*. If the driver includes multiple files, create a subfolder *A* in *C:\\Program Files\\Tableau/Drivers* and copy all files to folder *A*. - -Note the following when installing the JDBC driver: - -* You must have read permissions on the .jar file. -* Tableau requires a JDBC 4.0 or later driver. -* Tableau requires a Type 4 JDBC driver. -* The latest 64-bit version of Java 8 is installed. - -3. Install the **SQreamDB.taco** file by moving the SQreamDB.taco file into the Tableau connectors directory. - - Based on the installation method that you used, your Tableau driver directory is located in one of the following places: - - * **Tableau Desktop on Windows:** *C:\\Users\\\\My Tableau Repository\\Connectors* - * **Tableau Desktop on Mac:** *~/My Tableau Repository/Connectors* :: -4. *Optional* - If you are using the Tableau Server, do the following: - - 1. Create a directory for Tableau connectors and give it a descriptive name, such as *C:\\tableau_connectors*. - - This directory needs to exist on all Tableau servers. - - :: - - 2. Copy the SQreamDB.taco file into the new directory. - - :: - - 3. Set the **native_api.connect_plugins_path** option to ``tsm`` as shown in the following example: - - .. code-block:: console - - $ tsm configuration set -k native_api.connect_plugins_path -v C:/tableau_connectors - - If a configuration error is displayed, add ``--force-keys`` to the end of the command as shown in the following example: - - .. code-block:: console - - $ tsm configuration set -k native_api.connect_plugins_path -v C:/tableau_connectors--force-keys - - 4. To apply the pending configuration changes, run the following command: - - .. code-block:: console - - $ tsm pending-changes apply + * **Tableau Desktop on Windows:** *C:\\Program Files\\Tableau\\Drivers* - .. warning:: This restarts the server. - -You can now restart Tableau Desktop or Server to begin using the SQream driver by :ref:`connecting to SQream ` as described in the section below. - -.. _tableau_connect_to_sqream: - - -Installing the ODBC Driver for Tableau Versions 2019.3 and Earlier --------------- - - -This section describes the installation method for Tableau version 2019.3 or earlier and describes the following: - -.. contents:: - :local: - -.. note:: SQream recommends installing the JDBC driver to provide improved connectivity. - -Automatically Reconfiguring the ODBC Driver After Initial Installation -~~~~~~~~~~~~~~~~~~ -If you've already installed the SQream ODBC driver and installed Tableau, SQream recommends reinstalling the ODBC driver with the **.TDC Tableau Settings for SQream DB** configuration shown in the image below: - -.. image:: /_static/images/odbc_windows_installer_tableau.png - -SQream recommends this configuration because Tableau creates temporary tables and runs several discovery queries that may impact performance. The ODBC driver installer avoids this by automatically reconfiguring Tableau. - -For more information about reinstalling the ODBC driver installer, see :ref:`Install and Configure ODBC on Windows `. - -If you want to manually reconfigure the ODBC driver, see :ref:`Manually Reconfiguring the ODBC Driver After Initial Installation ` below. - -.. _manually_reconfigure_odbc_driver: - -Manually Reconfiguring the ODBC Driver After Initial Installation -~~~~~~~~~~~~~~~~~~ -The file **Tableau Datasource Customization (TDC)** file lets you use Tableau make full use of SQream DB's features and capabilities. - -**To manually reconfigure the ODBC driver after initial installation:** - -1. Do one of the following: - - 1. Download the :download:`odbc-sqream.tdc ` file to your machine and open it in a text editor. - - :: - - 2. Copy the text below into a text editor: - - .. literalinclude:: odbc-sqream.tdc - :language: xml - :caption: SQream ODBC TDC File - :emphasize-lines: 2 - -#. Check which version of Tableau you are using. - - :: - -#. In the text of the file shown above, in the highlighted line, replace the version number with the **major** version of Tableau that you are using. - - For example, if you are using Tableau vesion **2019.2.1**, replace it with **2019.2**. - - :: - -#. Do one of the following: - - * If you are using **Tableau Desktop** - save the TDC file to *C:\\Users\\\\Documents\\My Tableau Repository\\Datasources*, where ```` is the Windows username that you have installed Tableau under. - - :: - - * If you are using the **Tableau Server** - save the TDC file to *C:\\ProgramData\\Tableau\\Tableau Server\\data\\tabsvc\\vizqlserver\\Datasources*. - -Configuring the ODBC Connection -~~~~~~~~~~~~ -The ODBC connection uses a DSN when connecting to ODBC data sources, and each DSN represents one SQream database. - -**To configure the ODBC connection:** - -1. Create an ODBC DSN. - - :: - -#. Open the Windows menu by pressing the Windows button (:kbd:`⊞ Win`) or clicking the **Windows** menu button. - - :: - -#. Type **ODBC** and select **ODBC Data Sources (64-bit)**. - - During installation, the installer created a sample user DSN named **SQreamDB**. - - :: + :: -#. *Optional* - Do one or both of the following: + * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* + + Note the following when installing the JDBC driver: - * Modify the DSN name. + * You must have read permissions on the .jar file. :: - - * Create a new DSN name by clicking **Add** and selecting **SQream ODBC Driver**. + + * Tableau requires a JDBC 4.0 or later driver. -.. image:: /_static/images/odbc_windows_dsns.png + :: + + * Tableau requires a Type 4 JDBC driver. + :: -5. Click **Finish**. - - :: + * The latest 64-bit version of Java 8 is installed. -6. Enter your connection parameters. - - The following table describes the connection parameters: - - .. list-table:: - :widths: 15 38 38 - :header-rows: 1 +3. Install the **SQreamDB.taco** file by moving the SQreamDB.taco file into the Tableau connectors directory. - * - Item - - Description - - Example - * - Data Source Name - - The Data Source Name. SQream recommends using a descriptive and easily recognizable name for referencing your DSN. Once set, the Data Source Name cannot be changed. - - - * - Description - - The description of your DSN. This field is optional. - - - * - User - - The username of a role to use for establishing the connection. - - ``rhendricks`` - * - Password - - The password of the selected role. - - ``Tr0ub4dor`` - * - Database - - The database name to connect to. For example, ``master`` - - ``master`` - * - Service - - The :ref:`service queue` to use. - - For example, ``etl``. For the default service ``sqream``, leave blank. - * - Server - - The hostname of the SQream worker. - - ``127.0.0.1`` or ``sqream.mynetwork.co`` - * - Port - - The TCP port of the SQream worker. - - ``5000`` or ``3108`` - * - User Server Picker - - Uses the load balancer when establishing a connection. Use only if exists, and check port. - - - * - SSL - - Uses SSL when establishing a connection. - - - * - Logging Options - - Lets you modify your logging options when tracking the ODBC connection for connection issues. - - - -.. tip:: Test the connection by clicking **Test** before saving your DSN. - -7. Save the DSN by clicking **OK.** - -Connecting Tableau to SQream -~~~~~~~~~~~~ -**To connect Tableau to SQream:** - -1. Start Tableau Desktop. - - :: - -#. In the **Connect** menu, in the **To a server** sub-menu, click **More Servers** and select **Other Databases (ODBC)**. + Based on the installation method that you used, your Tableau driver directory is located in one of the following places: - The **Other Databases (ODBC)** window is displayed. + * **Tableau Desktop on Windows:** *C:\\Users\\\\My Tableau Repository\\Connectors* - :: - -#. In the Other Databases (ODBC) window, select the DSN that you created in :ref:`Setting Up SQream Tables as Data Sources `. - - Tableau may display the **Sqream ODBC Driver Connection Dialog** window and prompt you to provide your username and password. - -#. Provide your username and password and click **OK**. - -.. _tableau_connect_to_sqream_db: + :: + + * **Tableau Desktop on MacOS:** *~/My Tableau Repository/Connectors* +You can now restart Tableau Desktop or Server to begin using the SQream driver by connecting to SQream as described in the section below. Connecting to SQream --------------------- @@ -362,10 +134,7 @@ After installing the JDBC driver you can connect to SQream. - The connection is established and the data source page is displayed. - -.. tip:: - Tableau automatically assigns your connection a default name based on the DSN and table. SQream recommends giving the connection a more descriptive name. - + .. _set_up_sqream_tables_as_data_sources: Setting Up SQream Tables as Data Sources @@ -388,9 +157,6 @@ After connecting to SQream you must set up the SQream tables as data sources. #. Open a new sheet to analyze data. -.. tip:: - For more information about configuring data sources, joining, filtering, see Tableau's `Set Up Data Sources `_ tutorials. - Tableau Best Practices and Troubleshooting --------------- This section describes the following best practices and troubleshooting procedures when connecting to SQream using Tableau: @@ -398,16 +164,6 @@ This section describes the following best practices and troubleshooting procedur .. contents:: :local: -Inserting Only Required Data -~~~~~~~~~~~~~~~~~~ -When using Tableau, SQream recommends using only data that you need, as described below: - -* Insert only the data sources you need into Tableau, excluding tables that don't require analysis. - - :: - -* To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQream database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyze and increases query performance. - Using Tableau's Table Query Syntax ~~~~~~~~~~~~~~~~~~~ Dragging your desired tables into the main area in Tableau builds queries based on its own syntax. This helps ensure increased performance, while using views or custom SQL may degrade performance. In addition, SQream recommends using the :ref:`create_view` to create pre-optimized views, which your datasources point to. @@ -437,7 +193,13 @@ If Tableau cannot locate the SQream JDBC driver, do the following: 1. Verify that the JDBC driver is located in the correct directory: * **Tableau Desktop on Windows:** *C:\Program Files\Tableau\Drivers* + + :: + * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* + + :: + * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* 2. Find the file path for the JDBC driver and add it to the Java classpath: @@ -446,7 +208,8 @@ If Tableau cannot locate the SQream JDBC driver, do the following: :: - * **For Windows** - add an environment variable for the classpath. - + * **For Windows** - add an environment variable for the classpath: + + .. image:: /_static/images/Third_Party_Connectors/tableau/envrionment_variable_for_classpath.png -If you experience issues after restarting Tableau, see the `SQream support portal `_. +If you experience issues after restarting Tableau, see the `SQream support portal `_. \ No newline at end of file From 45ced26b068a9cfb5e7a9ae3628ab9dac9221f47 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 21 Jul 2022 14:21:29 +0300 Subject: [PATCH 288/300] Added SAP BO --- .../client_platforms/index.rst | 1 + .../client_platforms/sap_businessobjects.rst | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 connecting_to_sqream/client_platforms/sap_businessobjects.rst diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index ac5f567ad..15047ab54 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -27,6 +27,7 @@ If you are looking for a tool that is not listed, SQream and our partners can he php power_bi r + sap_businessobjects sas_viya sql_workbench tableau diff --git a/connecting_to_sqream/client_platforms/sap_businessobjects.rst b/connecting_to_sqream/client_platforms/sap_businessobjects.rst new file mode 100644 index 000000000..285c8de5e --- /dev/null +++ b/connecting_to_sqream/client_platforms/sap_businessobjects.rst @@ -0,0 +1,60 @@ +.. _sap_businessobjects: + +************************* +Connecting to SQream Using SAP BusinessObjects +************************* +The **Connecting to SQream Using SAP BusinessObjects** guide includes the following sections: + +.. contents:: + :local: + :depth: 1 + +Overview +========== +The **Connecting to SQream Using SAP BusinessObjects** guide describes the best practices for configuring a connection between SQream and the SAP BusinessObjects BI platform. SAP BO's multi-tier architecture includes both client and server components, and this guide describes integrating SQream with SAP BO's object client tools using a generic JDBC connector. The instructions in this guide are relevant to both the **Universe Design Tool (UDT)** and the **Information Design Tool (IDT)**. This document only covers how to establish a connection using the generic out-of-the-box JDBC connectors, and does not cover related business object products, such as the **Business Objects Data Integrator**. + +The **Define a new connection** window below shows the generic JDBC driver, which you can use to establish a new connection to a database. + +.. image:: /_static/images/SAP_BO_2.png + +SAP BO also lets you customize the interface to include a SQream data source. + +Establising a New Connection Using a Generic JDCB Connector +========== +This section shows an example of using a generic JDBC connector to establish a new connection. + +**To establish a new connection using a generic JDBC connector:** + +1. In the fields, provide a user name, password, database URL, and JDBC class. + + The following is the correct format for the database URL: + + .. code-block:: console + +

jdbc:Sqream://:3108/
+	  
+   SQream recommends quickly testing your connection to SQream by selecting the Generic JDBC data source in the **Define a new connection** window. When you connect using a generic JDBC data source you do not need to modify your configuration files, but are limited to the out-of-the-box settings defined in the default **jdbc.prm** file.
+   
+   .. note:: Modifying the jdbc.prm file for the generic driver impacts all other databases using the same driver.
+
+   For more information, see `Connection String Examples `_.
+
+2. (Optonal)If you are using the generic JDBC driver specific to SQream, modify the jdbc.sbo file to include the SQream JDBC driver location by adding the following lines under the Database section of the file:
+
+   .. code-block:: console
+
+      Database Active="Yes" Name="SQream JDBC data source">
+      
+      
+      C:\Program Files\SQream Technologies\JDBC Driver\2021.2.0-4.5.3\sqream-jdbc-4.5.3.jar
+      
+      
+      
+      com.sqream.jdbc.SQDriver
+
+      
+      
+
+3. Restart the BusinessObjects server.
+
+   When the connection is established, **SQream** is listed as a driver selection.
\ No newline at end of file

From 8cbbf0e837ecf8d63f43432d51a93510a73ca6d7 Mon Sep 17 00:00:00 2001
From: Yaniv Gerowitz 
Date: Thu, 21 Jul 2022 14:32:11 +0300
Subject: [PATCH 289/300] Added images

---
 _static/images/SAP_BO.png   | Bin 0 -> 112881 bytes
 _static/images/SAP_BO_2.png | Bin 0 -> 25160 bytes
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 _static/images/SAP_BO.png
 create mode 100644 _static/images/SAP_BO_2.png

diff --git a/_static/images/SAP_BO.png b/_static/images/SAP_BO.png
new file mode 100644
index 0000000000000000000000000000000000000000..413ce7d0e4731668b9320ab6a6139177329c1af6
GIT binary patch
literal 112881
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          .
+03/22/2022  12:47 PM              ..
+03/13/2022  11:57 AM               440 admin_cluster_flags.rst
+03/09/2022  10:31 AM               403 admin_flags.rst
+03/09/2022  11:19 AM             3,561 admin_regular_flags.rst
+03/09/2022  10:31 AM               813 admin_worker_flags.rst
+03/09/2022  11:22 AM               615 bin_sizes.rst
+03/09/2022  12:10 PM               368 cache_disk_dir.rst
+03/09/2022  12:14 PM               340 cache_disk_gb.rst
+03/09/2022  11:59 AM               378 cache_eviction_milliseconds.rst
+03/09/2022  11:42 AM               344 cache_partitions.rst
+03/09/2022  12:02 PM               402 cache_persistent_dir.rst
+03/09/2022  12:13 PM               377 cache_persistent_gb.rst
+03/09/2022  11:53 AM               337 cache_ram_gb.rst
+03/09/2022  11:23 AM               381 check_cuda_memory.rst
+03/09/2022  11:24 AM               394 compiler_gets_only_ufs.rst
+03/08/2022  05:38 PM               570 configuration_flags.rst
+03/08/2022  05:38 PM               605 configuration_methods.rst
+03/09/2022  11:24 AM               403 copy_to_restrict_utf8.rst
+03/09/2022  11:38 AM               408 cpu_reduce_hashtable_size.rst
+03/09/2022  11:25 AM               344 csv_limit_row_length.rst
+03/09/2022  11:25 AM               424 cuda_mem_cpy_max_size_bytes.rst
+03/09/2022  11:26 AM               369 cuda_mem_cpy_synchronous.rst
+03/09/2022  11:26 AM               374 cuda_mem_quota.rst
+03/20/2022  11:02 AM            24,433 current_configuration_method.rst
+03/09/2022  11:27 AM               331 developer_mode.rst
+03/09/2022  11:27 AM               397 enable_device_debug_messages.rst
+03/09/2022  11:28 AM               383 enable_log_debug.rst
+03/09/2022  11:28 AM               372 enable_nv_prof_markers.rst
+03/09/2022  11:29 AM               302 end_log_message.rst
+03/09/2022  10:31 AM               363 extent_storage_file_size_mb.rst
+03/22/2022  12:47 PM                 0 files_and_folders.txt
+03/09/2022  11:29 AM               377 flip_join_order.rst
+03/09/2022  11:30 AM               536 gather_mem_stat.rst
+03/09/2022  10:31 AM               344 generic_flags.rst
+03/09/2022  12:14 PM             1,837 generic_regular_flags.rst
+03/09/2022  10:36 AM               381 generic_worker_flags.rst
+03/09/2022  11:30 AM               410 increase_chunk_size_before_reduce.rst
+03/09/2022  11:30 AM               379 increase_mem_factors.rst
+03/09/2022  10:31 AM               308 index.rst
+03/09/2022  11:31 AM               332 level_db_write_buffer_size.rst
+03/09/2022  11:31 AM               385 limit_query_memory_gb.rst
+03/09/2022  11:32 AM               441 log_sys_level.rst
+03/09/2022  11:32 AM               328 machine_ip.rst
+03/09/2022  11:33 AM               424 max_avg_blob_size_to_compress_on_gpu.rst
+03/13/2022  04:54 PM               422 max_pinned_percentage_of_total_ram.rst
+03/09/2022  11:33 AM               388 memory_reset_trigger_mb.rst
+03/09/2022  11:33 AM               573 metadata_server_port.rst
+03/09/2022  11:34 AM               371 mt_read.rst
+03/09/2022  11:34 AM               367 mt_read_workers.rst
+03/09/2022  11:35 AM               395 orc_implicit_casts.rst
+03/08/2022  07:27 PM             9,074 previous_configuration_method.rst
+03/09/2022  12:09 PM               313 session_tag.rst
+03/09/2022  10:31 AM             2,822 spooling.rst
+03/09/2022  11:35 AM               340 spool_memory_gb.rst
+03/09/2022  11:35 AM               428 statement_lock_timeout.rst
+03/09/2022  11:36 AM               487 use_config_ip.rst
+03/09/2022  11:37 AM               494 use_legacy_decimal_literals.rst
+03/13/2022  12:21 PM               461 use_legacy_string_literals.rst
+03/09/2022  11:37 AM               354 varchar_identifiers.rst
+              58 File(s)         63,002 bytes
+               2 Dir(s)  898,522,271,744 bytes free
diff --git a/configuration_guides/generic_flags.rst b/configuration_guides/generic_flags.rst
index 2f17e8202..cb0241e31 100644
--- a/configuration_guides/generic_flags.rst
+++ b/configuration_guides/generic_flags.rst
@@ -11,7 +11,4 @@ The **Generic Flags** page describes the following flag types, which can be modi
    :glob:
 
    generic_regular_flags
-   generic_cluster_flags
-   generic_worker_flags
-
-
+   generic_worker_flags
\ No newline at end of file
diff --git a/configuration_guides/generic_regular_flags.rst b/configuration_guides/generic_regular_flags.rst
index 224ebf88e..b78ae3808 100644
--- a/configuration_guides/generic_regular_flags.rst
+++ b/configuration_guides/generic_regular_flags.rst
@@ -6,11 +6,11 @@ Regular Generic Flags
 
 The **Regular Generic Flags** page describes **Regular** modification type flags, which can be modified by standard users on a session basis:
 
-* `Flipping Join Order to Force Equijoins `_
-* `Determining Client Level `_
-* `Setting CPU to Compress Defined Columns `_
-* `Setting Query Memory Processing Limit `_
-* `Setting the Spool Memory `_
+* `Flipping Join Order to Force Equijoins `_
+* `Determining Client Level `_
+* `Setting CPU to Compress Defined Columns `_
+* `Setting Query Memory Processing Limit `_
+* `Setting the Spool Memory `_
 * `Setting Cache Partitions `_
 * `Setting Cache Flushing `_
 * `Setting InMemory Spool Memory `_
diff --git a/configuration_guides/healer_max_inactivity_hours.rst b/configuration_guides/healer_max_inactivity_hours.rst
new file mode 100644
index 000000000..d05d46014
--- /dev/null
+++ b/configuration_guides/healer_max_inactivity_hours.rst
@@ -0,0 +1,14 @@
+.. _healer_max_inactivity_hours:
+
+*************************
+Query Healer
+*************************
+The ``healerMaxInactivityHours`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU.
+
+The following describes the ``healerMaxInactivityHours`` flag:
+
+* **Data type** - size_t
+* **Default value** - ``5``
+* **Allowed values** - 1-4000000000
+
+For related flags, see :ref:`is_healer_on`.
\ No newline at end of file
diff --git a/configuration_guides/index.rst b/configuration_guides/index.rst
index 6a65853f0..6805bc188 100644
--- a/configuration_guides/index.rst
+++ b/configuration_guides/index.rst
@@ -11,8 +11,6 @@ The **Configuration Guides** page describes the following configuration informat
    :glob:
 
    spooling
-   configuration_methods
+   configuring_sqream
    configuration_flags
-
-
-
+   previous_configuration_method
\ No newline at end of file
diff --git a/configuration_guides/is_healer_on.rst b/configuration_guides/is_healer_on.rst
new file mode 100644
index 000000000..8b90654ec
--- /dev/null
+++ b/configuration_guides/is_healer_on.rst
@@ -0,0 +1,14 @@
+.. _is_healer_on:
+
+*************************
+Enabling the Query Healer
+*************************
+The ``is_healer_on`` flag enables the Query Healer, which periodically examines the progress of running statements and logs statements exceeding the ``healerMaxInactivityHours`` flag setting.
+
+The following describes the ``is_healer_on`` flag:
+
+* **Data type** - boolean
+* **Default value** - ``true``
+* **Allowed values** - ``true``, ``false``
+
+For related flags, see :ref:`healer_max_inactivity_hours`.
\ No newline at end of file
diff --git a/configuration_guides/login_max_retries.rst b/configuration_guides/login_max_retries.rst
new file mode 100644
index 000000000..bf3ae6d40
--- /dev/null
+++ b/configuration_guides/login_max_retries.rst
@@ -0,0 +1,11 @@
+.. _login_max_retries:
+
+*************************
+Adjusting Permitted Log-in Attempts
+*************************
+The ``loginMaxRetries`` flag sets the permitted log-in attempts.
+
+The following describes the ``loginMaxRetries`` flag:
+
+* **Data type** - size_t
+* **Default value** - ``5``
\ No newline at end of file
diff --git a/configuration_guides/max_pinned_percentage_of_total_ram.rst b/configuration_guides/max_pinned_percentage_of_total_ram.rst
new file mode 100644
index 000000000..9ced5bde9
--- /dev/null
+++ b/configuration_guides/max_pinned_percentage_of_total_ram.rst
@@ -0,0 +1,12 @@
+.. _max_pinned_percentage_of_total_ram:
+
+*************************
+Maximum Pinned Percentage of Total RAM
+*************************
+The ``maxPinnedPercentageOfTotalRAM`` flag sets the maximum percentage out of the available total CPU RAM that can be used by **pinned memory**.
+
+The following describes the ``machineIP`` flag:
+
+* **Data type** - uint
+* **Default value** - ``70``
+* **Allowed values** - ``0-100``
\ No newline at end of file
diff --git a/configuration_guides/spooling.rst b/configuration_guides/spooling.rst
index e96928c6f..88d5a7980 100644
--- a/configuration_guides/spooling.rst
+++ b/configuration_guides/spooling.rst
@@ -65,5 +65,5 @@ The following is an example of setting ``spoolMemoryGB`` value in the previous c
 
 For more information about configuring the ``spoolMemoryGB`` flag, see the following:
 
-* `Current configuration method `_
-* `Previous configuration method `_
\ No newline at end of file
+* `Current configuration method `_
+* `Previous configuration method `_
\ No newline at end of file
diff --git a/configuration_guides/varchar_identifiers.rst b/configuration_guides/varchar_identifiers.rst
new file mode 100644
index 000000000..889e5c16e
--- /dev/null
+++ b/configuration_guides/varchar_identifiers.rst
@@ -0,0 +1,12 @@
+.. _varchar_identifiers:
+
+*************************
+Interpreting VARCHAR as TEXT
+*************************
+The ``varcharIdentifiers`` flag activates using **varchar** as an identifier.
+
+The following describes the ``varcharIdentifiers`` flag:
+
+* **Data type** - boolean
+* **Default value** - ``true``
+* **Allowed values** - ``true``, ``false``
\ No newline at end of file

From 77d73e48a75e1a20709e960477ad3eabf065d734 Mon Sep 17 00:00:00 2001
From: Yaniv Gerowitz 
Date: Mon, 8 Aug 2022 12:56:00 +0300
Subject: [PATCH 298/300] Removed Incorrect Files

---
 configuration_guides/admin_worker_flags.rst        |  5 +----
 .../healer_max_inactivity_hours.rst                | 14 --------------
 configuration_guides/is_healer_on.rst              | 14 --------------
 configuration_guides/login_max_retries.rst         | 11 -----------
 4 files changed, 1 insertion(+), 43 deletions(-)
 delete mode 100644 configuration_guides/healer_max_inactivity_hours.rst
 delete mode 100644 configuration_guides/is_healer_on.rst
 delete mode 100644 configuration_guides/login_max_retries.rst

diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst
index c126c8457..412955510 100644
--- a/configuration_guides/admin_worker_flags.rst
+++ b/configuration_guides/admin_worker_flags.rst
@@ -8,7 +8,4 @@ The **Worker Administration Flags** page describes **Worker** modification type
 * `Setting Total Device Memory Usage in SQream Instance `_
 * `Enabling Manually Setting Reported IP `_
 * `Setting Port Used for Metadata Server Connection `_
-* `Assigning Local Network IP `_
-* `Enabling the Query Healer `_
-* `Configuring the Query Healer `_
-* `Adjusting Permitted Log-in Attempts `_
\ No newline at end of file
+* `Assigning Local Network IP `_
\ No newline at end of file
diff --git a/configuration_guides/healer_max_inactivity_hours.rst b/configuration_guides/healer_max_inactivity_hours.rst
deleted file mode 100644
index d05d46014..000000000
--- a/configuration_guides/healer_max_inactivity_hours.rst
+++ /dev/null
@@ -1,14 +0,0 @@
-.. _healer_max_inactivity_hours:
-
-*************************
-Query Healer
-*************************
-The ``healerMaxInactivityHours`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU.
-
-The following describes the ``healerMaxInactivityHours`` flag:
-
-* **Data type** - size_t
-* **Default value** - ``5``
-* **Allowed values** - 1-4000000000
-
-For related flags, see :ref:`is_healer_on`.
\ No newline at end of file
diff --git a/configuration_guides/is_healer_on.rst b/configuration_guides/is_healer_on.rst
deleted file mode 100644
index 8b90654ec..000000000
--- a/configuration_guides/is_healer_on.rst
+++ /dev/null
@@ -1,14 +0,0 @@
-.. _is_healer_on:
-
-*************************
-Enabling the Query Healer
-*************************
-The ``is_healer_on`` flag enables the Query Healer, which periodically examines the progress of running statements and logs statements exceeding the ``healerMaxInactivityHours`` flag setting.
-
-The following describes the ``is_healer_on`` flag:
-
-* **Data type** - boolean
-* **Default value** - ``true``
-* **Allowed values** - ``true``, ``false``
-
-For related flags, see :ref:`healer_max_inactivity_hours`.
\ No newline at end of file
diff --git a/configuration_guides/login_max_retries.rst b/configuration_guides/login_max_retries.rst
deleted file mode 100644
index bf3ae6d40..000000000
--- a/configuration_guides/login_max_retries.rst
+++ /dev/null
@@ -1,11 +0,0 @@
-.. _login_max_retries:
-
-*************************
-Adjusting Permitted Log-in Attempts
-*************************
-The ``loginMaxRetries`` flag sets the permitted log-in attempts.
-
-The following describes the ``loginMaxRetries`` flag:
-
-* **Data type** - size_t
-* **Default value** - ``5``
\ No newline at end of file

From 070d671bb71932c5592cf4feb7707e6fec7edb64 Mon Sep 17 00:00:00 2001
From: Yaniv Gerowitz 
Date: Mon, 8 Aug 2022 21:22:43 +0300
Subject: [PATCH 299/300] SQ-11376

---
 .../client_drivers/python/index.rst           | 454 ++++++++++--------
 1 file changed, 262 insertions(+), 192 deletions(-)

diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst
index c96ef5f2f..e03df343d 100644
--- a/connecting_to_sqream/client_drivers/python/index.rst
+++ b/connecting_to_sqream/client_drivers/python/index.rst
@@ -3,27 +3,34 @@
 *************************
 Python (pysqream)
 *************************
+The **Python** connector page describes the following:
 
+.. contents:: 
+   :local:
+   :depth: 1
+
+Overview
+=============
 The SQream Python connector is a set of packages that allows Python programs to connect to SQream DB.
 
 * ``pysqream`` is a pure Python connector. It can be installed with ``pip`` on any operating system, including Linux, Windows, and macOS.
 
 * ``pysqream-sqlalchemy`` is a SQLAlchemy dialect for ``pysqream``
 
-The connector supports Python 3.6.5 and newer.
+The connector supports Python 3.6.5 and newer. The base ``pysqream`` package conforms to Python DB-API specifications `PEP-249 `_.
 
-The base ``pysqream`` package conforms to Python DB-API specifications `PEP-249 `_.
-
-.. contents:: In this topic:
-   :local:
-
-Installing the Python connector
+Installing the Python Connector
 ==================================
 
 Prerequisites
 ----------------
+Installing the Python connector includes the following prerequisites:
+
+.. contents:: 
+   :local:
+   :depth: 1
 
-1. Python
+Python
 ^^^^^^^^^^^^
 
 The connector requires Python 3.6.5 or newer. To verify your version of Python:
@@ -38,7 +45,7 @@ The connector requires Python 3.6.5 or newer. To verify your version of Python:
 
 .. warning:: If you're running on an older version, ``pip`` will fetch an older version of ``pysqream``, with version <3.0.0. This version is currently not supported.
 
-2. PIP
+PIP
 ^^^^^^^^^^^^
 The Python connector is installed via ``pip``, the Python package manager and installer.
 
@@ -60,35 +67,24 @@ We recommend upgrading to the latest version of ``pip`` before installing. To ve
    * On macOS, you may want to use virtualenv to install Python and the connector, to ensure compatibility with the built-in Python environment
    *  If you encounter an error including ``SSLError`` or ``WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.`` - please be sure to reinstall Python with SSL enabled, or use virtualenv or Anaconda.
 
-3. OpenSSL for Linux
+OpenSSL for Linux
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 Some distributions of Python do not include OpenSSL. The Python connector relies on OpenSSL for secure connections to SQream DB.
 
 * To install OpenSSL on RHEL/CentOS
 
-   .. code-block:: console
+  .. code-block:: console
    
-      $ sudo yum install -y libffi-devel openssl-devel
+     $ sudo yum install -y libffi-devel openssl-devel
 
 * To install OpenSSL on Ubuntu
 
-   .. code-block:: console
-   
-      $ sudo apt-get install libssl-dev libffi-dev -y
-
-4. Cython (optional)
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-Optional but highly recommended is Cython, which improves performance of Python applications.
-
-   .. code-block:: console
+  .. code-block:: console
    
-      $ pip install cython
+     $ sudo apt-get install libssl-dev libffi-dev -y
 
-Install via pip
+Installing via PIP
 -----------------
-
 The Python connector is available via `PyPi `_.
 
 Install the connector with ``pip``:
@@ -99,49 +95,59 @@ Install the connector with ``pip``:
 
 ``pip`` will automatically install all necessary libraries and modules.
 
-Upgrading an existing installation
+Upgrading an Existing Installation
 --------------------------------------
-
-The Python drivers are updated periodically.
-To upgrade an existing pysqream installation, use pip's ``-U`` flag.
+The Python drivers are updated periodically. To upgrade an existing pysqream installation, use pip's ``-U`` flag:
 
 .. code-block:: console
    
    $ pip install pysqream pysqream-sqlalchemy -U
 
-
-Validate the installation
+Validating Your Installation
 -----------------------------
+This section describes how to validate your installation.
 
-Create a file called ``test.py``, containing the following:
+**To validate your installation**:
+
+1. Create a file called ``test.py``, containing the following:
 
 .. literalinclude:: test.py
     :language: python
     :caption: pysqream Validation Script
     :linenos:
 
-Make sure to replace the parameters in the connection with the respective parameters for your SQream DB installation.
+2. Verify that the parameters in the connection have been replaced with your respective SQream installation parameters.
 
-Run the test file to verify that you can connect to SQream DB:
+    ::
 
-.. code-block:: console
+3. Run the test file to verify that you can connect to SQream:
+
+   .. code-block:: console
    
-   $ python test.py
-   Version: v2020.1
+      $ python test.py
+      Version: v2020.1
+
+   If the validation was successful, you can build an application using the SQream Python connector. If you receive a connection error, verify the following:
 
-If all went well, you are now ready to build an application using the SQream DB Python connector!
+   * You have access to a running SQream database.
 
-If any connection error appears, verify that you have access to a running SQream DB and that the connection parameters are correct.
+      ::
 
-SQLAlchemy examples
+   * The connection parameters are correct.
+
+SQLAlchemy Examples
 ========================
+SQLAlchemy is an **Object-Relational Mapper (ORM) for Python. When you install the SQream dialect (``pysqream-sqlalchemy``) you can use frameworks such as Pandas, TensorFlow, and Alembic to query SQream directly.
 
-SQLAlchemy is an ORM for Python.
+This section includes the following examples:
 
-When you install the SQream DB dialect (``pysqream-sqlalchemy``) you can use frameworks like Pandas, TensorFlow, and Alembic to query SQream DB directly.
+.. contents:: 
+   :local:
+   :depth: 1
 
-A simple connection example
+Standard Connection Example
 ---------------------------------
+The following is a standard connection example:
 
 .. code-block:: python
 
@@ -162,10 +168,9 @@ A simple connection example
    res = engine.execute('insert into test values (5), (6)')
    res = engine.execute('select * from test')
 
-Pulling a table into Pandas
+Pulling a Table into Pandas
 ---------------------------------
-
-In this example, we use the URL method to create the connection string.
+The following example shows how to pull a table in Pandas. This examples uses the URL method to create the connection string:
 
 .. code-block:: python
 
@@ -186,72 +191,76 @@ In this example, we use the URL method to create the connection string.
    
    table_df = pd.read_sql("select * from nba", con=engine)
 
-
 API Examples
 ===============
+This section includes the following examples:
+
+.. contents:: 
+   :local:
+   :depth: 1
 
-Explaining the connection example
+Describing Your Connection
 ---------------------------------------
+This example shows how to describe the connection.
 
-First, import the package and create a connection
+**Describing your connection**:
 
-.. code-block:: python
+1. Import the package and create a connection:
+
+   .. code-block:: python
    
-   # Import pysqream package
+      # Import pysqream package
    
-   import pysqream
+      import pysqream
 
-   """
-   Connection parameters include:
-   * IP/Hostname
-   * Port
-   * database name
-   * username
-   * password 
-   * Connect through load balancer, or direct to worker (Default: false - direct to worker)
-   * use SSL connection (default: false)
-   * Optional service queue (default: 'sqream')
-   """
-   
-   # Create a connection object
-   
-   con = pysqream.connect(host='127.0.0.1', port=3108, database='raviga'
-                      , username='rhendricks', password='Tr0ub4dor&3'
-                      , clustered=True)
+      """
+      Connection parameters include:
+      * IP/Hostname
+      * Port
+      * database name
+      * username
+      * password 
+      * Connect through load balancer, or direct to worker (Default: false - direct to worker)
+      * use SSL connection (default: false)
+      * Optional service queue (default: 'sqream')
+      """
+   
+     # Create a connection object
 
-Then, run a query and fetch the results
+     con = pysqream.connect(host='127.0.0.1', port=3108, database='raviga'
+                   , username='rhendricks', password='Tr0ub4dor&3'
+                   , clustered=True)
 
-.. code-block:: python
+2. Run a query and fetch the results:
+
+   .. code-block:: python
 
-   cur = con.cursor()  # Create a new cursor
-   # Prepare and execute a query
-   cur.execute('select show_version()')
+      cur = con.cursor()  # Create a new cursor
+      # Prepare and execute a query
+      cur.execute('select show_version()')
    
-   result = cur.fetchall() # `fetchall` gets the entire data set
+      result = cur.fetchall() # `fetchall` gets the entire data set
    
-   print (f"Version: {result[0][0]}")
+      print (f"Version: {result[0][0]}")
 
-This should print the SQream DB version. For example ``v2020.1``.
+   The SQream version should be output, such as ``v2020.1``.
 
-Finally, we will close the connection
+3. Close the connection:
 
-.. code-block:: python
+   .. code-block:: python
    
-   con.close()
+      con.close()
 
-Using the cursor
+Using the Cursor
 --------------------------------------------
-
-The DB-API specification includes several methods for fetching results from the cursor.
-
-We will use the ``nba`` example. Here's a peek at the table contents:
+The DB-API specification includes several methods for fetching results from the cursor. This sections shows an example using the ``nba`` table, which looks as follows:
 
 .. csv-table:: nba
    :file: nba-t10.csv
    :widths: auto
    :header-rows: 1 
 
-Like before, we will import the library and create a :py:meth:`~Connection`, followed by :py:meth:`~Connection.execute` on a simple ``SELECT *`` query.
+As before, you must import the library and create a :py:meth:`~Connection`, followed by :py:meth:`~Connection.execute` on a simple ``SELECT *`` query:
 
 .. code-block:: python
    
@@ -265,9 +274,9 @@ Like before, we will import the library and create a :py:meth:`~Connection`, fol
    statement = 'SELECT * FROM nba'
    cur.execute(statement)
 
-After executing the statement, we have a :py:meth:`Connection` cursor object waiting. A cursor is iterable, meaning that everytime we fetch, it advances the cursor to the next row.
+When the statement has finished executing, you have a :py:meth:`Connection` cursor object waiting. A cursor is iterable, meaning that it advances the cursor to the next row when fetched.
 
-Use :py:meth:`~Connection.fetchone` to get one record at a time:
+You can use :py:meth:`~Connection.fetchone` to fetch one record at a time:
 
 .. code-block:: python
    
@@ -275,14 +284,14 @@ Use :py:meth:`~Connection.fetchone` to get one record at a time:
    
    second_row = cur.fetchone() # Fetch one row at a time (second row)
 
-To get several rows at a time, use :py:meth:`~Connection.fetchmany`:
+To fetch several rows at a time, use :py:meth:`~Connection.fetchmany`:
 
 .. code-block:: python
    
    # executing `fetchone` twice is equivalent to this form:
    third_and_fourth_rows = cur.fetchmany(2)
 
-To get all rows at once, use :py:meth:`~Connection.fetchall`:
+To fetch all rows at once, use :py:meth:`~Connection.fetchall`:
 
 .. code-block:: python
    
@@ -292,7 +301,7 @@ To get all rows at once, use :py:meth:`~Connection.fetchall`:
    # Close the connection when done
    con.close()
 
-Here are the contents of the row variables we used:
+The following is an example of the contents of the row variables used in our examples:
 
 .. code-block:: pycon
    
@@ -308,12 +317,11 @@ Here are the contents of the row variables we used:
 
 .. note:: Calling a fetch command after all rows have been fetched will return an empty array (``[]``).
 
-Reading result metadata
+Reading Result Metadata
 ----------------------------
+When you execute a statement, the connection object also contains metadata about the result set, such as **column names**, **types**, etc).
 
-When executing a statement, the connection object also contains metadata about the result set (e.g.column names, types, etc).
-
-The metadata is stored in the :py:attr:`Connection.description` object of the cursor.
+The metadata is stored in the :py:attr:`Connection.description` object of the cursor:
 
 .. code-block:: pycon
    
@@ -328,78 +336,112 @@ The metadata is stored in the :py:attr:`Connection.description` object of the cu
    >>> print(cur.description)
    [('Name', 'STRING', 24, 24, None, None, True), ('Team', 'STRING', 22, 22, None, None, True), ('Number', 'NUMBER', 1, 1, None, None, True), ('Position', 'STRING', 2, 2, None, None, True), ('Age (as of 2018)', 'NUMBER', 1, 1, None, None, True), ('Height', 'STRING', 4, 4, None, None, True), ('Weight', 'NUMBER', 2, 2, None, None, True), ('College', 'STRING', 21, 21, None, None, True), ('Salary', 'NUMBER', 4, 4, None, None, True)]
 
-To get a list of column names, iterate over the ``description`` list:
+You can fetch a list of column names by iterating over the ``description`` list:
    
 .. code-block:: pycon
    
    >>> [ i[0] for i in cur.description ]
    ['Name', 'Team', 'Number', 'Position', 'Age (as of 2018)', 'Height', 'Weight', 'College', 'Salary']
 
-Loading data into a table
+Loading Data into a Table
 ---------------------------
+This example shows how to load 10,000 rows of dummy data to an instance of SQream.
 
-This example loads 10,000 rows of dummy data to a SQream DB instance
+**To load data 10,000 rows of dummy data to an instance of SQream:**
 
-.. code-block:: python
+1. Run the following:
+
+   .. code-block:: python
    
-   import pysqream
-   from datetime import date, datetime
-   from time import time
+      import pysqream
+      from datetime import date, datetime
+      from time import time
 
-   con = pysqream.connect(host='127.0.0.1', port=3108, database='master'
-                      , username='rhendricks', password='Tr0ub4dor&3'
-                      , clustered=True)
+      con = pysqream.connect(host='127.0.0.1', port=3108, database='master'
+                         , username='rhendricks', password='Tr0ub4dor&3'
+                         , clustered=True)
    
-   # Create a table for loading
-   create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s varchar(12), ss text, dt date, dtt datetime)'
-   con.execute(create)
+2. Create a table for loading:
 
-   # After creating the table, we can load data into it with the INSERT command
+   .. code-block:: python
 
-   # Create dummy data which matches the table we created
-   data = (False, 2, 12, 145, 84124234, 3.141, -4.3, "Marty McFly" , u"キウイは楽しい鳥です" , date(2019, 12, 17), datetime(1955, 11, 4, 1, 23, 0, 0))
-   
-   
-   row_count = 10**4
+      create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s varchar(12), ss text, dt date, dtt datetime)'
+      con.execute(create)
+
+3. Load your data into table using the ``INSERT`` command.
+
+    ::
+
+4. Create dummy data matching the table you created:
+
+   .. code-block:: python
 
-   # Get a new cursor
-   cur = con.cursor()
-   insert = 'insert into perf values (?,?,?,?,?,?,?,?,?,?,?)'
-   start = time()
-   cur.executemany(insert, [data] * row_count)
-   print (f"Total insert time for {row_count} rows: {time() - start} seconds")
+      data = (False, 2, 12, 145, 84124234, 3.141, -4.3, "Marty McFly" , u"キウイは楽しい鳥です" , date(2019, 12, 17), datetime(1955, 11, 4, 1, 23, 0, 0))
+      
+      row_count = 10**4
 
-   # Close this cursor
-   cur.close()
+5. Get a new cursor:
+
+   .. code-block:: python
+
+      cur = con.cursor()
+      insert = 'insert into perf values (?,?,?,?,?,?,?,?,?,?,?)'
+      start = time()
+      cur.executemany(insert, [data] * row_count)
+      print (f"Total insert time for {row_count} rows: {time() - start} seconds")
+
+6. Close this cursor:
+
+   .. code-block:: python
+
+      cur.close()
    
-   # Verify that the data was inserted correctly
-   # Get a new cursor
-   cur = con.cursor()
-   cur.execute('select count(*) from perf')
-   result = cur.fetchall() # `fetchall` collects the entire data set
-   print (f"Count of inserted rows: {result[0][0]}")
+7. Verify that the data was inserted correctly.
+
+    ::
+
+8. Get a new cursor:
 
-   # When done, close the cursor
-   cur.close()
+   .. code-block:: python
+
+      cur = con.cursor()
+      cur.execute('select count(*) from perf')
+      result = cur.fetchall() # `fetchall` collects the entire data set
+      print (f"Count of inserted rows: {result[0][0]}")
+
+9. Close the cursor:
+
+   .. code-block:: python
+
+       cur.close()
    
-   # Close the connection
-   con.close()
+10. Close the connection:
+
+   .. code-block:: python
+
+      con.close()
 
-Reading data from a CSV file for load into a table
+Reading Data from a CSV File for Loading into a Table
 ----------------------------------------------------------
+This example shows how to write a helper function to create an :ref:`insert` statement, by reading an existing table's metadata.
 
-We will write a helper function to create an :ref:`insert` statement, by reading an existing table's metadata.
+**To read data from a CSV file for loading into a table:**
 
-.. code-block:: python
+1. Run the following:
+
+   .. code-block:: python
    
-   import pysqream
-   import datetime
+      import pysqream
+      import datetime
 
-   def insert_from_csv(cur, table_name, csv_filename, field_delimiter = ',', null_markers = []):
-      """
-      We will first ask SQream DB for some table information.
-      This is important for understanding the number of columns, and will help
-      to create a matching INSERT statement
+      def insert_from_csv(cur, table_name, csv_filename, field_delimiter = ',', null_markers = []):
+         """
+2. Ask SQream for some table information.
+
+   This is important for determining the number of columns, and helps create a matching ``INSERT`` statement:
+   
+   .. code-block:: python
+   
       """
 
       column_info = cur.execute(f"SELECT * FROM {table_name} LIMIT 0").description
@@ -414,85 +456,113 @@ We will write a helper function to create an :ref:`insert` statement, by reading
                except ValueError:
                   return datetime.datetime.strptime(row[i], '%Y-%m-%d')
 
-      # Create enough placeholders (`?`) for the INSERT query string
+3. Create enough placeholders (`?`) for the ``INSERT`` query string:
+
+
+   .. code-block:: python
+
       qstring = ','.join(['?'] * len(column_info))
       insert_statement = f"insert into {table_name} values ({qstring})"
 
-      # Open the CSV file
+4. Open the CSV file:
+
+   .. code-block:: python
+
       with open(csv_filename, mode='r') as csv_file:
          csv_reader = csv.reader(csv_file, delimiter=field_delimiter)
 
-      # Execute the INSERT statement with the CSV data
+5. Execute the ``INSERT`` statement with the CSV data:
+
+   .. code-block:: python
+
       cur.executemany(insert_statement, [row for row in csv_reader])
 
 
-   con = pysqream.connect(host='127.0.0.1', port=3108, database='master'
+      con = pysqream.connect(host='127.0.0.1', port=3108, database='master'
                       , username='rhendricks', password='Tr0ub4dor&3'
                       , clustered=True)
    
-   cur = con.cursor()
-   insert_from_csv(cur, 'nba', 'nba.csv', field_delimiter = ',', null_markers = [])
+      cur = con.cursor()
+      insert_from_csv(cur, 'nba', 'nba.csv', field_delimiter = ',', null_markers = [])
    
-   con.close()
+      con.close()
 
-
-Using SQLAlchemy ORM to create tables and fill them with data
+Using SQLAlchemy ORM to Create and Populate Tables
 -----------------------------------------------------------------------
+This section shows how to use the ORM to create and populate tables from Python objects.
 
-You can also use the ORM to create tables and insert data to them from Python objects.
+**To use SQLAlchemy ORM to create and populate tables:**
 
-For example:
+1. Run the following:
 
-.. code-block:: python
-   
-   import sqlalchemy as sa
-   import pandas as pd
-   from sqlalchemy.engine.url import URL
+   .. code-block:: python
+      
+      import sqlalchemy as sa
+      import pandas as pd
+      from sqlalchemy.engine.url import URL
 
 
-   engine_url = URL('sqream'
-                 , username='rhendricks'
-                 , password='secret_passwor"
-                 , host='localhost'
-                 , port=5000
-                 , database='raviga'
-                 , query={'use_ssl': False})
+      engine_url = URL('sqream'
+                    , username='rhendricks'
+                    , password='secret_passwor"
+                    , host='localhost'
+                    , port=5000
+                    , database='raviga'
+                    , query={'use_ssl': False})
 
-   engine = sa.create_engine(engine_url)
+      engine = sa.create_engine(engine_url)
+   
+2. Build a metadata object and bind it:
+
+   .. code-block:: python
    
-   # Build a metadata object and bind it
+      metadata = sa.MetaData()
+      metadata.bind = engine
    
-   metadata = sa.MetaData()
-   metadata.bind = engine
+3. Create a table in the local metadata:
    
-   # Create a table in the local metadata
+   .. code-block:: python
    
-   employees = sa.Table(
-   'employees'
-   , metadata 
-   , sa.Column('id', sa.Integer)
-   , sa.Column('name', sa.VARCHAR(32))
-   , sa.Column('lastname', sa.VARCHAR(32))
-   , sa.Column('salary', sa.Float)
-   )
+      employees = sa.Table(
+      'employees'
+      , metadata 
+      , sa.Column('id', sa.Integer)
+      , sa.Column('name', sa.VARCHAR(32))
+      , sa.Column('lastname', sa.VARCHAR(32))
+      , sa.Column('salary', sa.Float)
+      )
 
-   # The create_all() function uses the SQream DB engine object
-   # to create all the defined table objects.
+   The ``create_all()`` function uses the SQream engine object.
 
-   metadata.create_all(engine)
+4. Create all the defined table objects:
+
+   .. code-block:: python
+
+      metadata.create_all(engine)
    
-   # Now that the table exists, we can insert data into it.
+5. Populate your table.
+
+    ::
    
-   # Build the data rows
-   insert_data = [ {'id': 1, 'name': 'Richard','lastname': 'Hendricks',   'salary': 12000.75}
-                  ,{'id': 3,  'name': 'Bertram', 'lastname': 'Gilfoyle', 'salary': 8400.0}
-                  ,{'id': 8,  'name': 'Donald', 'lastname': 'Dunn', 'salary': 6500.40}
-                 ]
+6. Build the data rows:
 
-   # Build the insert command
-   ins = employees.insert(insert_data)
+   .. code-block:: python
+
+      insert_data = [ {'id': 1, 'name': 'Richard','lastname': 'Hendricks',   'salary': 12000.75}
+                     ,{'id': 3,  'name': 'Bertram', 'lastname': 'Gilfoyle', 'salary': 8400.0}
+                     ,{'id': 8,  'name': 'Donald', 'lastname': 'Dunn', 'salary': 6500.40}
+                    ]
+
+7. Build the ``INSERT`` command:
+   
+   .. code-block:: python
+
+      ins = employees.insert(insert_data)
    
-   # Execute the command
-   result = engine.execute(ins)
+8. Execute the command:
+
+   .. code-block:: python
+
+      result = engine.execute(ins)
 
 For more information, see the :ref:`python_api_reference_guide`.
\ No newline at end of file

From 8ecec15107dc13119e7ae94d9b0564bfcc49be16 Mon Sep 17 00:00:00 2001
From: Yaniv Gerowitz 
Date: Tue, 9 Aug 2022 16:10:01 +0300
Subject: [PATCH 300/300] Update 2020.3_index.rst

---
 releases/2020.3_index.rst | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/releases/2020.3_index.rst b/releases/2020.3_index.rst
index e54d1d615..28a0fb4bf 100644
--- a/releases/2020.3_index.rst
+++ b/releases/2020.3_index.rst
@@ -3,7 +3,7 @@
 **************************
 Release Notes 2020.3
 **************************
-The 2020.3 release notes describe the following releases:
+The 2020.3 Release Notes describe the following releases:
 
 .. contents:: 
    :local:
@@ -14,5 +14,6 @@ The 2020.3 release notes describe the following releases:
    :glob:
 
    2020.3.2.1
+   2020.3.2
    2020.3.1
    2020.3
\ No newline at end of file

pLD2D_$vWC+{e~$c+6bxRmwn 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 Z{{yVFQ$#+Xs)hgn002ovPDHLkV1g9&3}^rV literal 0 HcmV?d00001 diff --git a/_static/images/SAP_BO_2.png b/_static/images/SAP_BO_2.png new file mode 100644 index 0000000000000000000000000000000000000000..91bc53d1a98462d50718f5cada0b2149d55b04bb GIT binary patch literal 25160 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 }(bbAR8C%mz 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 Date: Thu, 21 Jul 2022 15:34:00 +0300 Subject: [PATCH 290/300] Moved Hardware Guide --- {operational_guides => getting_started}/hardware_guide.rst | 0 getting_started/index.rst | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) rename {operational_guides => getting_started}/hardware_guide.rst (100%) diff --git a/operational_guides/hardware_guide.rst b/getting_started/hardware_guide.rst similarity index 100% rename from operational_guides/hardware_guide.rst rename to getting_started/hardware_guide.rst diff --git a/getting_started/index.rst b/getting_started/index.rst index f9a57a460..860c7a7a7 100644 --- a/getting_started/index.rst +++ b/getting_started/index.rst @@ -13,4 +13,5 @@ The **Getting Started** page describes the following things you need to start us installing_sqream creating_a_database executing_statements_in_sqream - performing_basic_sqream_operations \ No newline at end of file + performing_basic_sqream_operations + hardware_guide \ No newline at end of file From f83d080db488e3b9dbb04311f706fa98211f8666 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 24 Jul 2022 17:12:53 +0300 Subject: [PATCH 291/300] TPD-233 --- operational_guides/access_control.rst | 584 ++++++++++++++++++ .../alter_default_permissions.rst | 1 + .../access_control_commands/grant.rst | 43 +- 3 files changed, 610 insertions(+), 18 deletions(-) create mode 100644 operational_guides/access_control.rst diff --git a/operational_guides/access_control.rst b/operational_guides/access_control.rst new file mode 100644 index 000000000..ffe687213 --- /dev/null +++ b/operational_guides/access_control.rst @@ -0,0 +1,584 @@ +.. _access_control: + +************** +Access Control +************** + +.. contents:: + :local: + :depth: 1 + +Overview +========== +Access control provides authentication and authorization in SQream DB. SQream DB manages authentication and authorization using a role-based access control system (RBAC), like ANSI SQL and other SQL products. + +SQream DB has a default permissions system which is inspired by Postgres, but with more power. In most cases, this allows an administrator to set things up so that every object gets permissions set automatically. In SQream DB, users log in from any worker which verifies their roles and permissions from the metadata server. Each statement issues commands as the currently logged in role. + +Roles are defined at the cluster level, meaning they are valid for all databases in the cluster. To bootstrap SQream DB, a new install will always have one ``SUPERUSER`` role, typically named ``sqream``. To create more roles, you should first connect as this role. + +The following: + +* **Role** - a role can be a user, a group, or both. Roles can own database objects (e.g. tables), and can assign permissions on those objects to other roles. Roles can be members of other roles, meaning a user role can inherit permissions from its parent role. + + :: + +* **Authentication** - verifying the identity of the role. User roles have usernames (:term:`role names`) and passwords. + + :: + +* **Authorization** - checking the role has permissions to do a particular thing. The :ref:`grant` command is used for this. + +Managing Roles +===== +Roles are used for both users and groups. Roles are global across all databases in the SQream DB cluster. To use a ``ROLE`` as a user, it should have a password, the login permission, and connect permissions to the relevant databases. + +The Roles section describes the following role-related operations: + +.. contents:: + :local: + :depth: 1 + +Creating New Roles (Users) +------------------------------ +A user role can log in to the database, so it should have ``LOGIN`` permissions, as well as a password. + +For example: + +.. code-block:: postgres + + CREATE ROLE role_name ; + GRANT LOGIN to role_name ; + GRANT PASSWORD 'new_password' to role_name ; + GRANT CONNECT ON DATABASE database_name to role_name ; + +Examples: + +.. code-block:: postgres + + CREATE ROLE new_role_name ; + GRANT LOGIN TO new_role_name; + GRANT PASSWORD 'my_password' TO new_role_name; + GRANT CONNECT ON DATABASE master TO new_role_name; + +A database role may have a number of permissions that define what tasks it can perform. These are assigned using the :ref:`grant` command. + +Dropping Users +--------------- + +.. code-block:: postgres + + DROP ROLE role_name ; + +Examples: + +.. code-block:: postgres + + DROP ROLE admin_role ; + +Altering a User Name +------------------------ + +Renaming a user's role: + +.. code-block:: postgres + + ALTER ROLE role_name RENAME TO new_role_name ; + +Examples: + +.. code-block:: postgres + + ALTER ROLE admin_role RENAME TO copy_role ; + +.. _change_password: + +Changing User Passwords +-------------------------- + +To change a user role's password, grant the user a new password. + +.. code-block:: postgres + + GRANT PASSWORD 'new_password' TO rhendricks; + +.. note:: Granting a new password overrides any previous password. Changing the password while the role has an active running statement does not affect that statement, but will affect subsequent statements. + +Altering Public Role Permissions +----------- + +There is a public role which always exists. Each role is granted to the ``PUBLIC`` role (i.e. is a member of the public group), and this cannot be revoked. You can alter the permissions granted to the public role. + +The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, new users can create, :ref:`insert`, :ref:`delete`, and :ref:`select` from objects in the ``PUBLIC`` schema. + + +Altering Role Membership (Groups) +------------------------- + +Many database administrators find it useful to group user roles together. By grouping users, permissions can be granted to, or revoked from a group with one command. In SQream DB, this is done by creating a group role, granting permissions to it, and then assigning users to that group role. + +To use a role purely as a group, omit granting it ``LOGIN`` and ``PASSWORD`` permissions. + +The ``CONNECT`` permission can be given directly to user roles, and/or to the groups they are part of. + +.. code-block:: postgres + + CREATE ROLE my_group; + +Once the group role exists, you can add user roles (members) using the ``GRANT`` command. For example: + +.. code-block:: postgres + + -- Add my_user to this group + GRANT my_group TO my_user; + + +To manage object permissions like databases and tables, you would then grant permissions to the group-level role (see :ref:`the permissions table` below. + +All member roles then inherit the permissions from the group. For example: + +.. code-block:: postgres + + -- Grant all group users connect permissions + GRANT CONNECT ON DATABASE a_database TO my_group; + + -- Grant all permissions on tables in public schema + GRANT ALL ON all tables IN schema public TO my_group; + +Removing users and permissions can be done with the ``REVOKE`` command: + +.. code-block:: postgres + + -- remove my_other_user from this group + REVOKE my_group FROM my_other_user; + +.. _permissions_table: + +Permissions +=========== +The following table displays the access control permissions: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Object/layer + - Permission + - Description + + * - all databases + - ``LOGIN`` + - use role to log into the system (the role also needs connect permission on the database it is connecting to) + + * - all databases + - ``PASSWORD`` + - the password used for logging into the system + + * - all databases + - ``SUPERUSER`` + - no permission restrictions on any activity + + * - database + - ``SUPERUSER`` + - no permission restrictions on any activity within that database (this does not include modifying roles or permissions) + + * - database + - ``CONNECT`` + - connect to the database + + * - database + - ``CREATE`` + - create schemas in the database + + * - database + - ``CREATE FUNCTION`` + - create and drop functions + + * - schema + - ``USAGE`` + - allows additional permissions within the schema + + * - schema + - ``CREATE`` + - create tables in the schema + + * - table + - ``SELECT`` + - :ref:`select` from the table + + * - table + - ``INSERT`` + - :ref:`insert` into the table + + * - table + - ``UPDATE`` + - :ref:`update` the value of certain columns in existing rows without creating a table + + * - table + - ``DELETE`` + - :ref:`delete` and :ref:`truncate` on the table + + * - table + - ``DDL`` + - drop and alter on the table + + * - table + - ``ALL`` + - all the table permissions + + * - function + - ``EXECUTE`` + - use the function + + * - function + - ``DDL`` + - drop and alter on the function + + * - function + - ``ALL`` + - all function permissions + +GRANT +----- + +:ref:`grant` gives permissions to a role, shown in the following syntax example: + +.. code-block:: postgres + + -- Grant permissions at the instance/ storage cluster level: + GRANT + + { SUPERUSER + | LOGIN + | PASSWORD '' + } + TO [, ...] + + -- Grant permissions at the database level: + GRANT {{CREATE | CONNECT| DDL | SUPERUSER | CREATE FUNCTION} [, ...] | ALL [PERMISSIONS]} + + ON DATABASE [, ...] + TO [, ...] + + -- Grant permissions at the schema level: + GRANT {{ CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [ + PERMISSIONS ]} + ON SCHEMA [, ...] + TO [, ...] + + -- Grant permissions at the object level: + GRANT {{SELECT | INSERT | DELETE | DDL } [, ...] | ALL [PERMISSIONS]} + ON { TABLE [, ...] | ALL TABLES IN SCHEMA [, ...]} + TO [, ...] + + -- Grant execute function permission: + GRANT {ALL | EXECUTE | DDL} ON FUNCTION function_name + TO role; + + -- Allows role2 to use permissions granted to role1 + GRANT [, ...] + TO + + -- Also allows the role2 to grant role1 to other roles: + GRANT [, ...] + TO + WITH ADMIN OPTION + +The following are some ``GRANT`` examples: + +.. code-block:: postgres + + GRANT LOGIN,superuser TO admin; + + GRANT CREATE FUNCTION ON database master TO admin; + + GRANT SELECT ON TABLE admin.table1 TO userA; + + GRANT EXECUTE ON FUNCTION my_function TO userA; + + GRANT ALL ON FUNCTION my_function TO userA; + + GRANT DDL ON admin.main_table TO userB; + + GRANT ALL ON all tables IN schema public TO userB; + + GRANT admin TO userC; + + GRANT superuser ON schema demo TO userA + + GRANT admin_role TO userB; + +REVOKE +------ + +:ref:`revoke` removes permissions from a role, shown in the following syntax example: + +.. code-block:: postgres + + -- Revoke permissions at the instance/ storage cluster level: + REVOKE + { SUPERUSER + | LOGIN + | PASSWORD + } + FROM [, ...] + + -- Revoke permissions at the database level: + REVOKE {{CREATE | CONNECT | DDL | SUPERUSER | CREATE FUNCTION}[, ...] |ALL [PERMISSIONS]} + ON DATABASE [, ...] + FROM [, ...] + + -- Revoke permissions at the schema level: + REVOKE { { CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [PERMISSIONS]} + ON SCHEMA [, ...] + FROM [, ...] + + -- Revoke permissions at the object level: + REVOKE { { SELECT | INSERT | DELETE | DDL } [, ...] | ALL } + ON { [ TABLE ] [, ...] | ALL TABLES IN SCHEMA + + [, ...] } + FROM [, ...] + + -- Removes access to permissions in role1 by role 2 + REVOKE [, ...] FROM [, ...] WITH ADMIN OPTION + + -- Removes permissions to grant role1 to additional roles from role2 + REVOKE [, ...] FROM [, ...] WITH ADMIN OPTION + + +Examples: + +.. code-block:: postgres + + REVOKE superuser on schema demo from userA; + + REVOKE delete on admin.table1 from userB; + + REVOKE login from role_test; + + REVOKE CREATE FUNCTION FROM admin; + +Default Permissions +------------------- + +The default permissions system (See :ref:`alter_default_permissions`) +can be used to automatically grant permissions to newly +created objects (See the departmental example below for one way it can be used). + +A default permissions rule looks for a schema being created, or a +table (possibly by schema), and is table to grant any permission to +that object to any role. This happens when the create table or create +schema statement is run. + + +.. code-block:: postgres + + + ALTER DEFAULT PERMISSIONS FOR target_role_name + [IN schema_name, ...] + FOR { TABLES | SCHEMAS } + { grant_clause | DROP grant_clause} + TO ROLE { role_name | public }; + + grant_clause ::= + GRANT + { CREATE FUNCTION + | SUPERUSER + | CONNECT + | CREATE + | USAGE + | SELECT + | INSERT + | UPDATE + | DELETE + | DDL + | EXECUTE + | ALL + } + + +Departmental Example +======================= + +You work in a company with several departments. + +The example below shows you how to manage permissions in a database shared by multiple departments, where each department has different roles for the tables by schema. It walks you through how to set the permissions up for existing objects and how to set up default permissions rules to cover newly created objects. + +The concept is that you set up roles for each new schema with the correct permissions, then the existing users can use these roles. + +A superuser must do new setup for each new schema which is a limitation, but superuser permissions are not needed at any other time, and neither are explicit grant statements or object ownership changes. + +In the example, the database is called ``my_database``, and the new or existing schema being set up to be managed in this way is called ``my_schema``. + +.. figure:: /_static/images/access_control_department_example.png + :scale: 60 % + + Our departmental example has four user group roles and seven users roles + +There will be a group for this schema for each of the following: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Group + - Activities + + * - database designers + - create, alter and drop tables + + * - updaters + - insert and delete data + + * - readers + - read data + + * - security officers + - add and remove users from these groups + +Setting up the department permissions +------------------------------------------ + +As a superuser, you connect to the system and run the following: + +.. code-block:: postgres + + -- create the groups + + CREATE ROLE my_schema_security_officers; + CREATE ROLE my_schema_database_designers; + CREATE ROLE my_schema_updaters; + CREATE ROLE my_schema_readers; + + -- grant permissions for each role + -- we grant permissions for existing objects here too, + -- so you don't have to start with an empty schema + + -- security officers + + GRANT connect ON DATABASE my_database TO my_schema_security_officers; + GRANT usage ON SCHEMA my_schema TO my_schema_security_officers; + + GRANT my_schema_database_designers TO my_schema_security_officers WITH ADMIN OPTION; + GRANT my_schema_updaters TO my_schema_security_officers WITH ADMIN OPTION; + GRANT my_schema_readers TO my_schema_security_officers WITH ADMIN OPTION; + + -- database designers + + GRANT connect ON DATABASE my_database TO my_schema_database_designers; + GRANT usage ON SCHEMA my_schema TO my_schema_database_designers; + + GRANT create,ddl ON SCHEMA my_schema TO my_schema_database_designers; + + -- updaters + + GRANT connect ON DATABASE my_database TO my_schema_updaters; + GRANT usage ON SCHEMA my_schema TO my_schema_updaters; + + GRANT SELECT,INSERT,DELETE ON ALL TABLES IN SCHEMA my_schema TO my_schema_updaters; + + -- readers + + GRANT connect ON DATABASE my_database TO my_schema_readers; + GRANT usage ON SCHEMA my_schema TO my_schema_readers; + + GRANT SELECT ON ALL TABLES IN SCHEMA my_schema TO my_schema_readers; + GRANT EXECUTE ON ALL FUNCTIONS TO my_schema_readers; + + + -- create the default permissions for new objects + + ALTER DEFAULT PERMISSIONS FOR my_schema_database_designers IN my_schema + FOR TABLES GRANT SELECT,INSERT,DELETE TO my_schema_updaters; + + -- For every table created by my_schema_database_designers, give access to my_schema_readers: + + ALTER DEFAULT PERMISSIONS FOR my_schema_database_designers IN my_schema + FOR TABLES GRANT SELECT TO my_schema_readers; + +.. note:: + * This process needs to be repeated by a user with ``SUPERUSER`` permissions each time a new schema is brought into this permissions management approach. + + * + By default, any new object created will not be accessible by our new ``my_schema_readers`` group. + Running a ``GRANT SELECT ...`` only affects objects that already exist in the schema or database. + + If you're getting a ``Missing the following permissions: SELECT on table 'database.public.tablename'`` error, make sure that + you've altered the default permissions with the ``ALTER DEFAULT PERMISSIONS`` statement. + +Creating new users in the departments +----------------------------------------- + +After the group roles have been created, you can now create user roles for each of your users. + +.. code-block:: postgres + + -- create the new database designer users + + CREATE ROLE ecodd; + GRANT LOGIN TO ecodd; + GRANT PASSWORD 'ecodds_secret_password' TO ecodd; + GRANT CONNECT ON DATABASE my_database TO ecodd; + GRANT my_schema_database_designers TO ecodd; + + CREATE ROLE ebachmann; + GRANT LOGIN TO ebachmann; + GRANT PASSWORD 'another_secret_password' TO ebachmann; + GRANT CONNECT ON DATABASE my_database TO ebachmann; + GRANT my_database_designers TO ebachmann; + + -- If a user already exists, we can assign that user directly to the group + + GRANT my_schema_updaters TO rhendricks; + + -- Create users in the readers group + + CREATE ROLE jbarker; + GRANT LOGIN TO jbarker; + GRANT PASSWORD 'action_jack' TO jbarker; + GRANT CONNECT ON DATABASE my_database TO jbarker; + GRANT my_schema_readers TO jbarker; + + CREATE ROLE lbream; + GRANT LOGIN TO lbream; + GRANT PASSWORD 'artichoke123' TO lbream; + GRANT CONNECT ON DATABASE my_database TO lbream; + GRANT my_schema_readers TO lbream; + + CREATE ROLE pgregory; + GRANT LOGIN TO pgregory; + GRANT PASSWORD 'c1ca6a' TO pgregory; + GRANT CONNECT ON DATABASE my_database TO pgregory; + GRANT my_schema_readers TO pgregory; + + -- Create users in the security officers group + + CREATE ROLE hoover; + GRANT LOGIN TO hoover; + GRANT PASSWORD 'mintchip' TO hoover; + GRANT CONNECT ON DATABASE my_database TO hoover; + GRANT my_schema_security_officers TO hoover; + + +.. todo: + create some example users + show that they have the right permission + try out the with admin option. we can't really do a security officer because + only superusers can create users and logins. see what can be done + need 1-2 users in each group, for at least 2 schemas/departments + this example will be very big just to show what this setup can do ... + example: a security officer for a department which will only have + read only access to a schema can only get that with admin option + access granted to them + +After this setup: + +* Database designers will be able to run any ddl on objects in the schema and create new objects, including ones created by other database designers +* Updaters will be able to insert and delete to existing and new tables +* Readers will be able to read from existing and new tables + +All this will happen without having to run any more ``GRANT`` statements. + +Any security officer will be able to add and remove users from these +groups. Creating and dropping login users themselves must be done by a +superuser. diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index 4c04c5105..a49e53f88 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -43,6 +43,7 @@ The following is the syntax for altering default permissions: | USAGE | SELECT | INSERT + | UPDATE | DELETE | DDL | EXECUTE diff --git a/reference/sql/sql_statements/access_control_commands/grant.rst b/reference/sql/sql_statements/access_control_commands/grant.rst index ceac48f7a..d86522900 100644 --- a/reference/sql/sql_statements/access_control_commands/grant.rst +++ b/reference/sql/sql_statements/access_control_commands/grant.rst @@ -15,13 +15,9 @@ Learn more about the permission system in the :ref:`access control guide Date: Sun, 24 Jul 2022 17:25:02 +0300 Subject: [PATCH 292/300] Removed HW Guide from Index --- operational_guides/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 048efb06f..0d45dcb88 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -25,4 +25,3 @@ This section summarizes the following operational guides: seeing_system_objects_as_ddl configuration optimization_best_practices - hardware_guide From aeb46bc0a578a49bf378843a4fc34022b8aefb5e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 27 Jul 2022 10:54:18 +0300 Subject: [PATCH 293/300] Updated Menu Access Control - granularity Operational Guides - moved External Data to new External Storage Platforms section Created required redirects --- .../hdfs.rst | 0 external_storage_platforms/index.rst | 25 + .../s3.rst | 0 index.rst | 16 +- operational_guides/access_control.rst | 583 +----------------- .../access_control_departmental_example.rst | 185 ++++++ .../access_control_managing_roles.rst | 124 ++++ .../access_control_overview.rst | 20 + .../access_control_permissions.rst | 218 +++++++ operational_guides/external_data.rst | 25 - operational_guides/index.rst | 2 - 11 files changed, 589 insertions(+), 609 deletions(-) rename {operational_guides => external_storage_platforms}/hdfs.rst (100%) create mode 100644 external_storage_platforms/index.rst rename {operational_guides => external_storage_platforms}/s3.rst (100%) create mode 100644 operational_guides/access_control_departmental_example.rst create mode 100644 operational_guides/access_control_managing_roles.rst create mode 100644 operational_guides/access_control_overview.rst create mode 100644 operational_guides/access_control_permissions.rst delete mode 100644 operational_guides/external_data.rst diff --git a/operational_guides/hdfs.rst b/external_storage_platforms/hdfs.rst similarity index 100% rename from operational_guides/hdfs.rst rename to external_storage_platforms/hdfs.rst diff --git a/external_storage_platforms/index.rst b/external_storage_platforms/index.rst new file mode 100644 index 000000000..92c35ee63 --- /dev/null +++ b/external_storage_platforms/index.rst @@ -0,0 +1,25 @@ +.. _external_storage_platforms: + +*********************** +External Storage Platforms +*********************** +SQream supports the following external storage platforms: + +.. toctree:: + :maxdepth: 1 + :titlesonly: + + s3 + hdfs + +For more information, see the following: + +* :ref:`foreign_tables` + + :: + +* :ref:`copy_from` + + :: + +* :ref:`copy_to` diff --git a/operational_guides/s3.rst b/external_storage_platforms/s3.rst similarity index 100% rename from operational_guides/s3.rst rename to external_storage_platforms/s3.rst diff --git a/index.rst b/index.rst index a279cbf65..6ac36eaa8 100644 --- a/index.rst +++ b/index.rst @@ -35,7 +35,7 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau`_ :ref:`Best practices` - :ref:`connect_to_tableau` + `Connecting to Tableau `_ * - **Releases** - **Driver and Deployment** - **Help and Support** - * - + * - :ref:`2020.3<2020.3>` - :ref:`2020.2<2020.2>` + :ref:`2020.2<2020.2>` :ref:`2020.1<2020.1>` @@ -68,9 +68,8 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` - :ref:`Third party tools integration` + `Connecting to SQream `_ - :ref:`connect_to_tableau` - `Troubleshooting Page `_ @@ -78,6 +77,8 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau`_ for additional support. @@ -100,6 +101,7 @@ If you're looking for an older version of the documentation, versions 1.10 throu installation_guides/index data_ingestion/index connecting_to_sqream/index + external_storage_platforms loading_and_unloading_data/index feature_guides/index operational_guides/index diff --git a/operational_guides/access_control.rst b/operational_guides/access_control.rst index ffe687213..c8ffe3097 100644 --- a/operational_guides/access_control.rst +++ b/operational_guides/access_control.rst @@ -3,582 +3,15 @@ ************** Access Control ************** +The **Access Control** page describes the following: -.. contents:: - :local: - :depth: 1 +.. toctree:: + :maxdepth: 1 + :titlesonly: -Overview -========== -Access control provides authentication and authorization in SQream DB. SQream DB manages authentication and authorization using a role-based access control system (RBAC), like ANSI SQL and other SQL products. + access_control_overview + access_control_managing_roles + access_control_permissions + access_control_departmental_example -SQream DB has a default permissions system which is inspired by Postgres, but with more power. In most cases, this allows an administrator to set things up so that every object gets permissions set automatically. In SQream DB, users log in from any worker which verifies their roles and permissions from the metadata server. Each statement issues commands as the currently logged in role. -Roles are defined at the cluster level, meaning they are valid for all databases in the cluster. To bootstrap SQream DB, a new install will always have one ``SUPERUSER`` role, typically named ``sqream``. To create more roles, you should first connect as this role. - -The following: - -* **Role** - a role can be a user, a group, or both. Roles can own database objects (e.g. tables), and can assign permissions on those objects to other roles. Roles can be members of other roles, meaning a user role can inherit permissions from its parent role. - - :: - -* **Authentication** - verifying the identity of the role. User roles have usernames (:term:`role names`) and passwords. - - :: - -* **Authorization** - checking the role has permissions to do a particular thing. The :ref:`grant` command is used for this. - -Managing Roles -===== -Roles are used for both users and groups. Roles are global across all databases in the SQream DB cluster. To use a ``ROLE`` as a user, it should have a password, the login permission, and connect permissions to the relevant databases. - -The Roles section describes the following role-related operations: - -.. contents:: - :local: - :depth: 1 - -Creating New Roles (Users) ------------------------------- -A user role can log in to the database, so it should have ``LOGIN`` permissions, as well as a password. - -For example: - -.. code-block:: postgres - - CREATE ROLE role_name ; - GRANT LOGIN to role_name ; - GRANT PASSWORD 'new_password' to role_name ; - GRANT CONNECT ON DATABASE database_name to role_name ; - -Examples: - -.. code-block:: postgres - - CREATE ROLE new_role_name ; - GRANT LOGIN TO new_role_name; - GRANT PASSWORD 'my_password' TO new_role_name; - GRANT CONNECT ON DATABASE master TO new_role_name; - -A database role may have a number of permissions that define what tasks it can perform. These are assigned using the :ref:`grant` command. - -Dropping Users ---------------- - -.. code-block:: postgres - - DROP ROLE role_name ; - -Examples: - -.. code-block:: postgres - - DROP ROLE admin_role ; - -Altering a User Name ------------------------- - -Renaming a user's role: - -.. code-block:: postgres - - ALTER ROLE role_name RENAME TO new_role_name ; - -Examples: - -.. code-block:: postgres - - ALTER ROLE admin_role RENAME TO copy_role ; - -.. _change_password: - -Changing User Passwords --------------------------- - -To change a user role's password, grant the user a new password. - -.. code-block:: postgres - - GRANT PASSWORD 'new_password' TO rhendricks; - -.. note:: Granting a new password overrides any previous password. Changing the password while the role has an active running statement does not affect that statement, but will affect subsequent statements. - -Altering Public Role Permissions ------------ - -There is a public role which always exists. Each role is granted to the ``PUBLIC`` role (i.e. is a member of the public group), and this cannot be revoked. You can alter the permissions granted to the public role. - -The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, new users can create, :ref:`insert`, :ref:`delete`, and :ref:`select` from objects in the ``PUBLIC`` schema. - - -Altering Role Membership (Groups) -------------------------- - -Many database administrators find it useful to group user roles together. By grouping users, permissions can be granted to, or revoked from a group with one command. In SQream DB, this is done by creating a group role, granting permissions to it, and then assigning users to that group role. - -To use a role purely as a group, omit granting it ``LOGIN`` and ``PASSWORD`` permissions. - -The ``CONNECT`` permission can be given directly to user roles, and/or to the groups they are part of. - -.. code-block:: postgres - - CREATE ROLE my_group; - -Once the group role exists, you can add user roles (members) using the ``GRANT`` command. For example: - -.. code-block:: postgres - - -- Add my_user to this group - GRANT my_group TO my_user; - - -To manage object permissions like databases and tables, you would then grant permissions to the group-level role (see :ref:`the permissions table` below. - -All member roles then inherit the permissions from the group. For example: - -.. code-block:: postgres - - -- Grant all group users connect permissions - GRANT CONNECT ON DATABASE a_database TO my_group; - - -- Grant all permissions on tables in public schema - GRANT ALL ON all tables IN schema public TO my_group; - -Removing users and permissions can be done with the ``REVOKE`` command: - -.. code-block:: postgres - - -- remove my_other_user from this group - REVOKE my_group FROM my_other_user; - -.. _permissions_table: - -Permissions -=========== -The following table displays the access control permissions: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Object/layer - - Permission - - Description - - * - all databases - - ``LOGIN`` - - use role to log into the system (the role also needs connect permission on the database it is connecting to) - - * - all databases - - ``PASSWORD`` - - the password used for logging into the system - - * - all databases - - ``SUPERUSER`` - - no permission restrictions on any activity - - * - database - - ``SUPERUSER`` - - no permission restrictions on any activity within that database (this does not include modifying roles or permissions) - - * - database - - ``CONNECT`` - - connect to the database - - * - database - - ``CREATE`` - - create schemas in the database - - * - database - - ``CREATE FUNCTION`` - - create and drop functions - - * - schema - - ``USAGE`` - - allows additional permissions within the schema - - * - schema - - ``CREATE`` - - create tables in the schema - - * - table - - ``SELECT`` - - :ref:`select` from the table - - * - table - - ``INSERT`` - - :ref:`insert` into the table - - * - table - - ``UPDATE`` - - :ref:`update` the value of certain columns in existing rows without creating a table - - * - table - - ``DELETE`` - - :ref:`delete` and :ref:`truncate` on the table - - * - table - - ``DDL`` - - drop and alter on the table - - * - table - - ``ALL`` - - all the table permissions - - * - function - - ``EXECUTE`` - - use the function - - * - function - - ``DDL`` - - drop and alter on the function - - * - function - - ``ALL`` - - all function permissions - -GRANT ------ - -:ref:`grant` gives permissions to a role, shown in the following syntax example: - -.. code-block:: postgres - - -- Grant permissions at the instance/ storage cluster level: - GRANT - - { SUPERUSER - | LOGIN - | PASSWORD '' - } - TO [, ...] - - -- Grant permissions at the database level: - GRANT {{CREATE | CONNECT| DDL | SUPERUSER | CREATE FUNCTION} [, ...] | ALL [PERMISSIONS]} - - ON DATABASE [, ...] - TO [, ...] - - -- Grant permissions at the schema level: - GRANT {{ CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [ - PERMISSIONS ]} - ON SCHEMA [, ...] - TO [, ...] - - -- Grant permissions at the object level: - GRANT {{SELECT | INSERT | DELETE | DDL } [, ...] | ALL [PERMISSIONS]} - ON { TABLE [, ...] | ALL TABLES IN SCHEMA [, ...]} - TO [, ...] - - -- Grant execute function permission: - GRANT {ALL | EXECUTE | DDL} ON FUNCTION function_name - TO role; - - -- Allows role2 to use permissions granted to role1 - GRANT [, ...] - TO - - -- Also allows the role2 to grant role1 to other roles: - GRANT [, ...] - TO - WITH ADMIN OPTION - -The following are some ``GRANT`` examples: - -.. code-block:: postgres - - GRANT LOGIN,superuser TO admin; - - GRANT CREATE FUNCTION ON database master TO admin; - - GRANT SELECT ON TABLE admin.table1 TO userA; - - GRANT EXECUTE ON FUNCTION my_function TO userA; - - GRANT ALL ON FUNCTION my_function TO userA; - - GRANT DDL ON admin.main_table TO userB; - - GRANT ALL ON all tables IN schema public TO userB; - - GRANT admin TO userC; - - GRANT superuser ON schema demo TO userA - - GRANT admin_role TO userB; - -REVOKE ------- - -:ref:`revoke` removes permissions from a role, shown in the following syntax example: - -.. code-block:: postgres - - -- Revoke permissions at the instance/ storage cluster level: - REVOKE - { SUPERUSER - | LOGIN - | PASSWORD - } - FROM [, ...] - - -- Revoke permissions at the database level: - REVOKE {{CREATE | CONNECT | DDL | SUPERUSER | CREATE FUNCTION}[, ...] |ALL [PERMISSIONS]} - ON DATABASE [, ...] - FROM [, ...] - - -- Revoke permissions at the schema level: - REVOKE { { CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [PERMISSIONS]} - ON SCHEMA [, ...] - FROM [, ...] - - -- Revoke permissions at the object level: - REVOKE { { SELECT | INSERT | DELETE | DDL } [, ...] | ALL } - ON { [ TABLE ] [, ...] | ALL TABLES IN SCHEMA - - [, ...] } - FROM [, ...] - - -- Removes access to permissions in role1 by role 2 - REVOKE [, ...] FROM [, ...] WITH ADMIN OPTION - - -- Removes permissions to grant role1 to additional roles from role2 - REVOKE [, ...] FROM [, ...] WITH ADMIN OPTION - - -Examples: - -.. code-block:: postgres - - REVOKE superuser on schema demo from userA; - - REVOKE delete on admin.table1 from userB; - - REVOKE login from role_test; - - REVOKE CREATE FUNCTION FROM admin; - -Default Permissions -------------------- - -The default permissions system (See :ref:`alter_default_permissions`) -can be used to automatically grant permissions to newly -created objects (See the departmental example below for one way it can be used). - -A default permissions rule looks for a schema being created, or a -table (possibly by schema), and is table to grant any permission to -that object to any role. This happens when the create table or create -schema statement is run. - - -.. code-block:: postgres - - - ALTER DEFAULT PERMISSIONS FOR target_role_name - [IN schema_name, ...] - FOR { TABLES | SCHEMAS } - { grant_clause | DROP grant_clause} - TO ROLE { role_name | public }; - - grant_clause ::= - GRANT - { CREATE FUNCTION - | SUPERUSER - | CONNECT - | CREATE - | USAGE - | SELECT - | INSERT - | UPDATE - | DELETE - | DDL - | EXECUTE - | ALL - } - - -Departmental Example -======================= - -You work in a company with several departments. - -The example below shows you how to manage permissions in a database shared by multiple departments, where each department has different roles for the tables by schema. It walks you through how to set the permissions up for existing objects and how to set up default permissions rules to cover newly created objects. - -The concept is that you set up roles for each new schema with the correct permissions, then the existing users can use these roles. - -A superuser must do new setup for each new schema which is a limitation, but superuser permissions are not needed at any other time, and neither are explicit grant statements or object ownership changes. - -In the example, the database is called ``my_database``, and the new or existing schema being set up to be managed in this way is called ``my_schema``. - -.. figure:: /_static/images/access_control_department_example.png - :scale: 60 % - - Our departmental example has four user group roles and seven users roles - -There will be a group for this schema for each of the following: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Group - - Activities - - * - database designers - - create, alter and drop tables - - * - updaters - - insert and delete data - - * - readers - - read data - - * - security officers - - add and remove users from these groups - -Setting up the department permissions ------------------------------------------- - -As a superuser, you connect to the system and run the following: - -.. code-block:: postgres - - -- create the groups - - CREATE ROLE my_schema_security_officers; - CREATE ROLE my_schema_database_designers; - CREATE ROLE my_schema_updaters; - CREATE ROLE my_schema_readers; - - -- grant permissions for each role - -- we grant permissions for existing objects here too, - -- so you don't have to start with an empty schema - - -- security officers - - GRANT connect ON DATABASE my_database TO my_schema_security_officers; - GRANT usage ON SCHEMA my_schema TO my_schema_security_officers; - - GRANT my_schema_database_designers TO my_schema_security_officers WITH ADMIN OPTION; - GRANT my_schema_updaters TO my_schema_security_officers WITH ADMIN OPTION; - GRANT my_schema_readers TO my_schema_security_officers WITH ADMIN OPTION; - - -- database designers - - GRANT connect ON DATABASE my_database TO my_schema_database_designers; - GRANT usage ON SCHEMA my_schema TO my_schema_database_designers; - - GRANT create,ddl ON SCHEMA my_schema TO my_schema_database_designers; - - -- updaters - - GRANT connect ON DATABASE my_database TO my_schema_updaters; - GRANT usage ON SCHEMA my_schema TO my_schema_updaters; - - GRANT SELECT,INSERT,DELETE ON ALL TABLES IN SCHEMA my_schema TO my_schema_updaters; - - -- readers - - GRANT connect ON DATABASE my_database TO my_schema_readers; - GRANT usage ON SCHEMA my_schema TO my_schema_readers; - - GRANT SELECT ON ALL TABLES IN SCHEMA my_schema TO my_schema_readers; - GRANT EXECUTE ON ALL FUNCTIONS TO my_schema_readers; - - - -- create the default permissions for new objects - - ALTER DEFAULT PERMISSIONS FOR my_schema_database_designers IN my_schema - FOR TABLES GRANT SELECT,INSERT,DELETE TO my_schema_updaters; - - -- For every table created by my_schema_database_designers, give access to my_schema_readers: - - ALTER DEFAULT PERMISSIONS FOR my_schema_database_designers IN my_schema - FOR TABLES GRANT SELECT TO my_schema_readers; - -.. note:: - * This process needs to be repeated by a user with ``SUPERUSER`` permissions each time a new schema is brought into this permissions management approach. - - * - By default, any new object created will not be accessible by our new ``my_schema_readers`` group. - Running a ``GRANT SELECT ...`` only affects objects that already exist in the schema or database. - - If you're getting a ``Missing the following permissions: SELECT on table 'database.public.tablename'`` error, make sure that - you've altered the default permissions with the ``ALTER DEFAULT PERMISSIONS`` statement. - -Creating new users in the departments ------------------------------------------ - -After the group roles have been created, you can now create user roles for each of your users. - -.. code-block:: postgres - - -- create the new database designer users - - CREATE ROLE ecodd; - GRANT LOGIN TO ecodd; - GRANT PASSWORD 'ecodds_secret_password' TO ecodd; - GRANT CONNECT ON DATABASE my_database TO ecodd; - GRANT my_schema_database_designers TO ecodd; - - CREATE ROLE ebachmann; - GRANT LOGIN TO ebachmann; - GRANT PASSWORD 'another_secret_password' TO ebachmann; - GRANT CONNECT ON DATABASE my_database TO ebachmann; - GRANT my_database_designers TO ebachmann; - - -- If a user already exists, we can assign that user directly to the group - - GRANT my_schema_updaters TO rhendricks; - - -- Create users in the readers group - - CREATE ROLE jbarker; - GRANT LOGIN TO jbarker; - GRANT PASSWORD 'action_jack' TO jbarker; - GRANT CONNECT ON DATABASE my_database TO jbarker; - GRANT my_schema_readers TO jbarker; - - CREATE ROLE lbream; - GRANT LOGIN TO lbream; - GRANT PASSWORD 'artichoke123' TO lbream; - GRANT CONNECT ON DATABASE my_database TO lbream; - GRANT my_schema_readers TO lbream; - - CREATE ROLE pgregory; - GRANT LOGIN TO pgregory; - GRANT PASSWORD 'c1ca6a' TO pgregory; - GRANT CONNECT ON DATABASE my_database TO pgregory; - GRANT my_schema_readers TO pgregory; - - -- Create users in the security officers group - - CREATE ROLE hoover; - GRANT LOGIN TO hoover; - GRANT PASSWORD 'mintchip' TO hoover; - GRANT CONNECT ON DATABASE my_database TO hoover; - GRANT my_schema_security_officers TO hoover; - - -.. todo: - create some example users - show that they have the right permission - try out the with admin option. we can't really do a security officer because - only superusers can create users and logins. see what can be done - need 1-2 users in each group, for at least 2 schemas/departments - this example will be very big just to show what this setup can do ... - example: a security officer for a department which will only have - read only access to a schema can only get that with admin option - access granted to them - -After this setup: - -* Database designers will be able to run any ddl on objects in the schema and create new objects, including ones created by other database designers -* Updaters will be able to insert and delete to existing and new tables -* Readers will be able to read from existing and new tables - -All this will happen without having to run any more ``GRANT`` statements. - -Any security officer will be able to add and remove users from these -groups. Creating and dropping login users themselves must be done by a -superuser. diff --git a/operational_guides/access_control_departmental_example.rst b/operational_guides/access_control_departmental_example.rst new file mode 100644 index 000000000..0a6b55e54 --- /dev/null +++ b/operational_guides/access_control_departmental_example.rst @@ -0,0 +1,185 @@ +.. _access_control_departmental_example: + +************** +Departmental Example +************** + +You work in a company with several departments. + +The example below shows you how to manage permissions in a database shared by multiple departments, where each department has different roles for the tables by schema. It walks you through how to set the permissions up for existing objects and how to set up default permissions rules to cover newly created objects. + +The concept is that you set up roles for each new schema with the correct permissions, then the existing users can use these roles. + +A superuser must do new setup for each new schema which is a limitation, but superuser permissions are not needed at any other time, and neither are explicit grant statements or object ownership changes. + +In the example, the database is called ``my_database``, and the new or existing schema being set up to be managed in this way is called ``my_schema``. + +Our departmental example has four user group roles and seven users roles + +There will be a group for this schema for each of the following: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Group + - Activities + + * - database designers + - create, alter and drop tables + + * - updaters + - insert and delete data + + * - readers + - read data + + * - security officers + - add and remove users from these groups + +Setting up the department permissions +------------------------------------------ + +As a superuser, you connect to the system and run the following: + +.. code-block:: postgres + + -- create the groups + + CREATE ROLE my_schema_security_officers; + CREATE ROLE my_schema_database_designers; + CREATE ROLE my_schema_updaters; + CREATE ROLE my_schema_readers; + + -- grant permissions for each role + -- we grant permissions for existing objects here too, + -- so you don't have to start with an empty schema + + -- security officers + + GRANT connect ON DATABASE my_database TO my_schema_security_officers; + GRANT usage ON SCHEMA my_schema TO my_schema_security_officers; + + GRANT my_schema_database_designers TO my_schema_security_officers WITH ADMIN OPTION; + GRANT my_schema_updaters TO my_schema_security_officers WITH ADMIN OPTION; + GRANT my_schema_readers TO my_schema_security_officers WITH ADMIN OPTION; + + -- database designers + + GRANT connect ON DATABASE my_database TO my_schema_database_designers; + GRANT usage ON SCHEMA my_schema TO my_schema_database_designers; + + GRANT create,ddl ON SCHEMA my_schema TO my_schema_database_designers; + + -- updaters + + GRANT connect ON DATABASE my_database TO my_schema_updaters; + GRANT usage ON SCHEMA my_schema TO my_schema_updaters; + + GRANT SELECT,INSERT,DELETE ON ALL TABLES IN SCHEMA my_schema TO my_schema_updaters; + + -- readers + + GRANT connect ON DATABASE my_database TO my_schema_readers; + GRANT usage ON SCHEMA my_schema TO my_schema_readers; + + GRANT SELECT ON ALL TABLES IN SCHEMA my_schema TO my_schema_readers; + GRANT EXECUTE ON ALL FUNCTIONS TO my_schema_readers; + + + -- create the default permissions for new objects + + ALTER DEFAULT PERMISSIONS FOR my_schema_database_designers IN my_schema + FOR TABLES GRANT SELECT,INSERT,DELETE TO my_schema_updaters; + + -- For every table created by my_schema_database_designers, give access to my_schema_readers: + + ALTER DEFAULT PERMISSIONS FOR my_schema_database_designers IN my_schema + FOR TABLES GRANT SELECT TO my_schema_readers; + +.. note:: + * This process needs to be repeated by a user with ``SUPERUSER`` permissions each time a new schema is brought into this permissions management approach. + + * + By default, any new object created will not be accessible by our new ``my_schema_readers`` group. + Running a ``GRANT SELECT ...`` only affects objects that already exist in the schema or database. + + If you're getting a ``Missing the following permissions: SELECT on table 'database.public.tablename'`` error, make sure that + you've altered the default permissions with the ``ALTER DEFAULT PERMISSIONS`` statement. + +Creating new users in the departments +----------------------------------------- + +After the group roles have been created, you can now create user roles for each of your users. + +.. code-block:: postgres + + -- create the new database designer users + + CREATE ROLE ecodd; + GRANT LOGIN TO ecodd; + GRANT PASSWORD 'ecodds_secret_password' TO ecodd; + GRANT CONNECT ON DATABASE my_database TO ecodd; + GRANT my_schema_database_designers TO ecodd; + + CREATE ROLE ebachmann; + GRANT LOGIN TO ebachmann; + GRANT PASSWORD 'another_secret_password' TO ebachmann; + GRANT CONNECT ON DATABASE my_database TO ebachmann; + GRANT my_database_designers TO ebachmann; + + -- If a user already exists, we can assign that user directly to the group + + GRANT my_schema_updaters TO rhendricks; + + -- Create users in the readers group + + CREATE ROLE jbarker; + GRANT LOGIN TO jbarker; + GRANT PASSWORD 'action_jack' TO jbarker; + GRANT CONNECT ON DATABASE my_database TO jbarker; + GRANT my_schema_readers TO jbarker; + + CREATE ROLE lbream; + GRANT LOGIN TO lbream; + GRANT PASSWORD 'artichoke123' TO lbream; + GRANT CONNECT ON DATABASE my_database TO lbream; + GRANT my_schema_readers TO lbream; + + CREATE ROLE pgregory; + GRANT LOGIN TO pgregory; + GRANT PASSWORD 'c1ca6a' TO pgregory; + GRANT CONNECT ON DATABASE my_database TO pgregory; + GRANT my_schema_readers TO pgregory; + + -- Create users in the security officers group + + CREATE ROLE hoover; + GRANT LOGIN TO hoover; + GRANT PASSWORD 'mintchip' TO hoover; + GRANT CONNECT ON DATABASE my_database TO hoover; + GRANT my_schema_security_officers TO hoover; + + +.. todo: + create some example users + show that they have the right permission + try out the with admin option. we can't really do a security officer because + only superusers can create users and logins. see what can be done + need 1-2 users in each group, for at least 2 schemas/departments + this example will be very big just to show what this setup can do ... + example: a security officer for a department which will only have + read only access to a schema can only get that with admin option + access granted to them + +After this setup: + +* Database designers will be able to run any ddl on objects in the schema and create new objects, including ones created by other database designers +* Updaters will be able to insert and delete to existing and new tables +* Readers will be able to read from existing and new tables + +All this will happen without having to run any more ``GRANT`` statements. + +Any security officer will be able to add and remove users from these +groups. Creating and dropping login users themselves must be done by a +superuser. \ No newline at end of file diff --git a/operational_guides/access_control_managing_roles.rst b/operational_guides/access_control_managing_roles.rst new file mode 100644 index 000000000..373b9a212 --- /dev/null +++ b/operational_guides/access_control_managing_roles.rst @@ -0,0 +1,124 @@ +.. _access_control_managing_roles: + +************** +Managing Roles +************** +Roles are used for both users and groups, and are global across all databases in the SQream cluster. For a ``ROLE`` to be used as a user, it requires a password and log-in and connect permissionss to the relevant databases. + +The Managing Roles section describes the following role-related operations: + +.. contents:: + :local: + :depth: 1 + +Creating New Roles (Users) +------------------------------ +A user role logging in to the database requires ``LOGIN`` permissions and as a password. + +The following is the syntax for creating a new role: + +.. code-block:: postgres + + CREATE ROLE ; + GRANT LOGIN to ; + GRANT PASSWORD <'new_password'> to ; + GRANT CONNECT ON DATABASE to ; + +The following is an example of creating a new role: + +.. code-block:: postgres + + CREATE ROLE new_role_name ; + GRANT LOGIN TO new_role_name; + GRANT PASSWORD 'my_password' to new_role_name; + GRANT CONNECT ON DATABASE master to new_role_name; + +A database role may have a number of permissions that define what tasks it can perform, which are assigned using the :ref:`grant` command. + +Dropping a User +------------------------------ +The following is the syntax for dropping a user: + +.. code-block:: postgres + + DROP ROLE ; + +The following is an example of dropping a user: + +.. code-block:: postgres + + DROP ROLE admin_role ; + +Altering a User Name +------------------------------ +The following is the syntax for altering a user name: + +.. code-block:: postgres + + ALTER ROLE RENAME TO ; + +The following is an example of altering a user name: + +.. code-block:: postgres + + ALTER ROLE admin_role RENAME TO copy_role ; + +Changing a User Password +------------------------------ +You can change a user role's password by granting the user a new password. + +The following is an example of changing a user password: + +.. code-block:: postgres + + GRANT PASSWORD <'new_password'> TO rhendricks; + +.. note:: Granting a new password overrides any previous password. Changing the password while the role has an active running statement does not affect that statement, but will affect subsequent statements. + +Altering Public Role Permissions +------------------------------ + +There is a public role which always exists. Each role is granted to the ``PUBLIC`` role (i.e. is a member of the public group), and this cannot be revoked. You can alter the permissions granted to the public role. + +The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, new users can create, :ref:`insert`, :ref:`delete`, and :ref:`select` from objects in the ``PUBLIC`` schema. + + +Altering Role Membership (Groups) +------------------------------ + +Many database administrators find it useful to group user roles together. By grouping users, permissions can be granted to, or revoked from a group with one command. In SQream DB, this is done by creating a group role, granting permissions to it, and then assigning users to that group role. + +To use a role purely as a group, omit granting it ``LOGIN`` and ``PASSWORD`` permissions. + +The ``CONNECT`` permission can be given directly to user roles, and/or to the groups they are part of. + +.. code-block:: postgres + + CREATE ROLE my_group; + +Once the group role exists, you can add user roles (members) using the ``GRANT`` command. For example: + +.. code-block:: postgres + + -- Add my_user to this group + GRANT my_group TO my_user; + + +To manage object permissions like databases and tables, you would then grant permissions to the group-level role (see :ref:`the permissions table` below. + +All member roles then inherit the permissions from the group. For example: + +.. code-block:: postgres + + -- Grant all group users connect permissions + GRANT CONNECT ON DATABASE a_database TO my_group; + + -- Grant all permissions on tables in public schema + GRANT ALL ON all tables IN schema public TO my_group; + +Removing users and permissions can be done with the ``REVOKE`` command: + +.. code-block:: postgres + + -- remove my_other_user from this group + REVOKE my_group FROM my_other_user; \ No newline at end of file diff --git a/operational_guides/access_control_overview.rst b/operational_guides/access_control_overview.rst new file mode 100644 index 000000000..080797fec --- /dev/null +++ b/operational_guides/access_control_overview.rst @@ -0,0 +1,20 @@ +.. _access_control_overview: + +************** +Overview +************** +Access control refers to SQream's authentication and authorization operations, managed using a **Role-Based Access Control (RBAC)** system, such as ANSI SQL or other SQL products. SQream's default permissions system is similar to Postgres, but is more powerful. SQream's method lets administrators prepare the system to automatically provide objects with their required permissions. + +SQream users can log in from any worker, which verify their roles and permissions from the metadata server. Each statement issues commands as the role that you're currently logged into. Roles are defined at the cluster level, and are valid for all databases in the cluster. To bootstrap SQream, new installations require one ``SUPERUSER`` role, typically named ``sqream``. You can only create new roles by connecting as this role. + +Access control refers to the following basic concepts: + + * **Role** - A role can be a user, a group, or both. Roles can own database objects (such as tables) and can assign permissions on those objects to other roles. Roles can be members of other roles, meaning a user role can inherit permissions from its parent role. + + :: + + * **Authentication** - Verifies the identity of the role. User roles have usernames (or **role names**) and passwords. + + :: + + * **Authorization** - Checks that a role has permissions to perform a particular operation, such as the :ref:`grant` command. \ No newline at end of file diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst new file mode 100644 index 000000000..5afc23009 --- /dev/null +++ b/operational_guides/access_control_permissions.rst @@ -0,0 +1,218 @@ +.. _access_control_permissions: + +************** +Permissions +************** + +The following table displays the access control permissions: + ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Permission** | **Description** | ++====================+=========================================================================================================================+ +| **Object/Layer: All Databases** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``LOGIN`` | use role to log into the system (the role also needs connect permission on the database it is connecting to) | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``PASSWORD`` | the password used for logging into the system | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SUPERUSER`` | no permission restrictions on any activity | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Object/Layer: Database** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SUPERUSER`` | no permission restrictions on any activity within that database (this does not include modifying roles or permissions) | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``CONNECT`` | connect to the database | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``CREATE`` | create schemas in the database | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``CREATE FUNCTION``| create and drop functions | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Object/Layer: Schema** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``USAGE`` | allows additional permissions within the schema | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``CREATE`` | create tables in the schema | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Object/Layer: Table** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SELECT`` | :ref:`select` from the table | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``INSERT`` | :ref:`insert` into the table | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``UPDATE`` | UPDATE the value of certain columns in existing rows without creating a table | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DELETE`` | :ref:`delete` and :ref:`truncate` on the table | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | drop and alter on the table | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``ALL`` | all the table permissions | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Object/Layer: Function** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``EXECUTE`` | use the function | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | drop and alter on the function | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``ALL`` | all function permissions | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ + + + + +GRANT +----- + +:ref:`grant` gives permissions to a role. + +.. code-block:: postgres + + -- Grant permissions at the instance/ storage cluster level: + GRANT + + { SUPERUSER + | LOGIN + | PASSWORD '' + } + TO [, ...] + + -- Grant permissions at the database level: + GRANT {{CREATE | CONNECT| DDL | SUPERUSER | CREATE FUNCTION} [, ...] | ALL [PERMISSIONS]} + + ON DATABASE [, ...] + TO [, ...] + + -- Grant permissions at the schema level: + GRANT {{ CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [ + PERMISSIONS ]} + ON SCHEMA [, ...] + TO [, ...] + + -- Grant permissions at the object level: + GRANT {{SELECT | INSERT | DELETE | DDL } [, ...] | ALL [PERMISSIONS]} + ON { TABLE [, ...] | ALL TABLES IN SCHEMA [, ...]} + TO [, ...] + + -- Grant execute function permission: + GRANT {ALL | EXECUTE | DDL} ON FUNCTION function_name + TO role; + + -- Allows role2 to use permissions granted to role1 + GRANT [, ...] + TO + + -- Also allows the role2 to grant role1 to other roles: + GRANT [, ...] + TO + WITH ADMIN OPTION + +``GRANT`` examples: + +.. code-block:: postgres + + GRANT LOGIN,superuser TO admin; + + GRANT CREATE FUNCTION ON database master TO admin; + + GRANT SELECT ON TABLE admin.table1 TO userA; + + GRANT EXECUTE ON FUNCTION my_function TO userA; + + GRANT ALL ON FUNCTION my_function TO userA; + + GRANT DDL ON admin.main_table TO userB; + + GRANT ALL ON all tables IN schema public TO userB; + + GRANT admin TO userC; + + GRANT superuser ON schema demo TO userA + + GRANT admin_role TO userB; + +REVOKE +------ + +:ref:`revoke` removes permissions from a role. + +.. code-block:: postgres + + -- Revoke permissions at the instance/ storage cluster level: + REVOKE + { SUPERUSER + | LOGIN + | PASSWORD + } + FROM [, ...] + + -- Revoke permissions at the database level: + REVOKE {{CREATE | CONNECT | DDL | SUPERUSER | CREATE FUNCTION}[, ...] |ALL [PERMISSIONS]} + ON DATABASE [, ...] + FROM [, ...] + + -- Revoke permissions at the schema level: + REVOKE { { CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [PERMISSIONS]} + ON SCHEMA [, ...] + FROM [, ...] + + -- Revoke permissions at the object level: + REVOKE { { SELECT | INSERT | DELETE | DDL } [, ...] | ALL } + ON { [ TABLE ] [, ...] | ALL TABLES IN SCHEMA + + [, ...] } + FROM [, ...] + + -- Removes access to permissions in role1 by role 2 + REVOKE [, ...] FROM [, ...] WITH ADMIN OPTION + + -- Removes permissions to grant role1 to additional roles from role2 + REVOKE [, ...] FROM [, ...] WITH ADMIN OPTION + + +Examples: + +.. code-block:: postgres + + REVOKE superuser on schema demo from userA; + + REVOKE delete on admin.table1 from userB; + + REVOKE login from role_test; + + REVOKE CREATE FUNCTION FROM admin; + +Default permissions +------------------- + +The default permissions system (See :ref:`alter_default_permissions`) +can be used to automatically grant permissions to newly +created objects (See the departmental example below for one way it can be used). + +A default permissions rule looks for a schema being created, or a +table (possibly by schema), and is table to grant any permission to +that object to any role. This happens when the create table or create +schema statement is run. + + +.. code-block:: postgres + + + ALTER DEFAULT PERMISSIONS FOR target_role_name + [IN schema_name, ...] + FOR { TABLES | SCHEMAS } + { grant_clause | DROP grant_clause} + TO ROLE { role_name | public }; + + grant_clause ::= + GRANT + { CREATE FUNCTION + | SUPERUSER + | CONNECT + | CREATE + | USAGE + | SELECT + | INSERT + | DELETE + | DDL + | EXECUTE + | ALL + } \ No newline at end of file diff --git a/operational_guides/external_data.rst b/operational_guides/external_data.rst deleted file mode 100644 index 8bf51f108..000000000 --- a/operational_guides/external_data.rst +++ /dev/null @@ -1,25 +0,0 @@ -.. _external_data: - -********************************** -Working with External Data -********************************** -SQream supports the following external data sources: - -.. toctree:: - :maxdepth: 1 - :titlesonly: - - s3 - hdfs - -For more information, see the following: - -* :ref:`external_tables` - - :: - -* :ref:`copy_from` - - :: - -* :ref:`copy_to` \ No newline at end of file diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 0d45dcb88..e72ff27c8 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -14,7 +14,6 @@ This section summarizes the following operational guides: access_control creating_or_cloning_a_storage_cluster - external_data foreign_tables delete_guide exporting_data @@ -23,5 +22,4 @@ This section summarizes the following operational guides: security saved_queries seeing_system_objects_as_ddl - configuration optimization_best_practices From 31f4fde505fa3f9230d4d762b52d9afbc6fac5a9 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 1 Aug 2022 12:22:18 +0300 Subject: [PATCH 294/300] Corrected Title --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 56ebea9a5..e0e88fbd2 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -1,7 +1,7 @@ .. _client_drivers: ************************************ -Client Drivers for |latest_version| +Client Drivers for Version 2020.3.2.1 ************************************ The guides on this page describe how to use the Sqream DB client drivers and client applications with SQream. From 440dd575b7c6da9b3c611ae229657d5780c99d32 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 1 Aug 2022 18:54:34 +0300 Subject: [PATCH 295/300] Added External Storage Platforms --- index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.rst b/index.rst index 6ac36eaa8..e6cdb5be6 100644 --- a/index.rst +++ b/index.rst @@ -101,7 +101,7 @@ If you're looking for an older version of the documentation, versions 1.10 throu installation_guides/index data_ingestion/index connecting_to_sqream/index - external_storage_platforms + external_storage_platforms/index loading_and_unloading_data/index feature_guides/index operational_guides/index From 05e0ed25167b6561deafc23fca8c6008a366219d Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 2 Aug 2022 17:48:55 +0300 Subject: [PATCH 296/300] Removed Access Control from Feature Guides --- feature_guides/access_control.rst | 597 ------------------------------ feature_guides/index.rst | 1 - 2 files changed, 598 deletions(-) delete mode 100644 feature_guides/access_control.rst diff --git a/feature_guides/access_control.rst b/feature_guides/access_control.rst deleted file mode 100644 index 7f92f8eaf..000000000 --- a/feature_guides/access_control.rst +++ /dev/null @@ -1,597 +0,0 @@ -.. _access_control: - -************** -Access Control -************** - -.. contents:: In this topic: - :local: - -Overview -========== - -Access control provides authentication and authorization in SQream DB. - -SQream DB manages authentication and authorization using a role-based access control system (RBAC), like ANSI SQL and other SQL products. - -SQream DB has a default permissions system which is inspired by Postgres, but with more power. In most cases, this allows an administrator to set things up so that every object gets permissions set automatically. - -In SQream DB, users log in from any worker which verifies their roles and permissions from the metadata server. Each statement issues commands as the currently logged in role. - -Roles are defined at the cluster level, meaning they are valid for all databases in the cluster. - -To bootstrap SQream DB, a new install will always have one ``SUPERUSER`` role, typically named ``sqream``. To create more roles, you should first connect as this role. - - -Terminology -================ - -Roles ----------- - -:term:`Role` : a role can be a user, a group, or both. - -Roles can own database objects (e.g. tables), and can assign permissions on those objects to other roles. - -Roles can be members of other roles, meaning a user role can inherit permissions from its parent role. - -Authentication --------------------- - -:term:`Authentication` : verifying the identity of the role. User roles have usernames (:term:`role names`) and passwords. - - -Authorization ----------------- - -:term:`Authorization` : checking the role has permissions to do a particular thing. The :ref:`grant` command is used for this. - - -Roles -===== - -Roles are used for both users and groups. - -Roles are global across all databases in the SQream DB cluster. - -To use a ``ROLE`` as a user, it should have a password, the login permission, and connect permissions to the relevant databases. - -Creating new roles (users) ------------------------------- - -A user role can log in to the database, so it should have ``LOGIN`` permissions, as well as a password. - -For example: - -.. code-block:: postgres - - CREATE ROLE role_name ; - GRANT LOGIN to role_name ; - GRANT PASSWORD 'new_password' to role_name ; - GRANT CONNECT ON DATABASE database_name to role_name ; - -Examples: - -.. code-block:: postgres - - CREATE ROLE new_role_name ; - GRANT LOGIN TO new_role_name; - GRANT PASSWORD 'my_password' TO new_role_name; - GRANT CONNECT ON DATABASE master TO new_role_name; - -A database role may have a number of permissions that define what tasks it can perform. These are assigned using the :ref:`grant` command. - -Dropping a user ---------------- - -.. code-block:: postgres - - DROP ROLE role_name ; - -Examples: - -.. code-block:: postgres - - DROP ROLE admin_role ; - -Altering a user name ------------------------- - -Renaming a user's role: - -.. code-block:: postgres - - ALTER ROLE role_name RENAME TO new_role_name ; - -Examples: - -.. code-block:: postgres - - ALTER ROLE admin_role RENAME TO copy_role ; - -.. _change_password: - -Changing user passwords --------------------------- - -To change a user role's password, grant the user a new password. - -.. code-block:: postgres - - GRANT PASSWORD 'new_password' TO rhendricks; - -.. note:: Granting a new password overrides any previous password. Changing the password while the role has an active running statement does not affect that statement, but will affect subsequent statements. - -Public Role ------------ - -There is a public role which always exists. Each role is granted to the ``PUBLIC`` role (i.e. is a member of the public group), and this cannot be revoked. You can alter the permissions granted to the public role. - -The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, new users can create, :ref:`insert`, :ref:`delete`, and :ref:`select` from objects in the ``PUBLIC`` schema. - - -Role membership (groups) -------------------------- - -Many database administrators find it useful to group user roles together. By grouping users, permissions can be granted to, or revoked from a group with one command. In SQream DB, this is done by creating a group role, granting permissions to it, and then assigning users to that group role. - -To use a role purely as a group, omit granting it ``LOGIN`` and ``PASSWORD`` permissions. - -The ``CONNECT`` permission can be given directly to user roles, and/or to the groups they are part of. - -.. code-block:: postgres - - CREATE ROLE my_group; - -Once the group role exists, you can add user roles (members) using the ``GRANT`` command. For example: - -.. code-block:: postgres - - -- Add my_user to this group - GRANT my_group TO my_user; - - -To manage object permissions like databases and tables, you would then grant permissions to the group-level role (see :ref:`the permissions table` below. - -All member roles then inherit the permissions from the group. For example: - -.. code-block:: postgres - - -- Grant all group users connect permissions - GRANT CONNECT ON DATABASE a_database TO my_group; - - -- Grant all permissions on tables in public schema - GRANT ALL ON all tables IN schema public TO my_group; - -Removing users and permissions can be done with the ``REVOKE`` command: - -.. code-block:: postgres - - -- remove my_other_user from this group - REVOKE my_group FROM my_other_user; - -.. _permissions_table: - -Permissions -=========== - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Object/layer - - Permission - - Description - - * - all databases - - ``LOGIN`` - - use role to log into the system (the role also needs connect permission on the database it is connecting to) - - * - all databases - - ``PASSWORD`` - - the password used for logging into the system - - * - all databases - - ``SUPERUSER`` - - no permission restrictions on any activity - - * - database - - ``SUPERUSER`` - - no permission restrictions on any activity within that database (this does not include modifying roles or permissions) - - * - database - - ``CONNECT`` - - connect to the database - - * - database - - ``CREATE`` - - create schemas in the database - - * - database - - ``CREATE FUNCTION`` - - create and drop functions - - * - schema - - ``USAGE`` - - allows additional permissions within the schema - - * - schema - - ``CREATE`` - - create tables in the schema - - * - table - - ``SELECT`` - - :ref:`select` from the table - - * - table - - ``INSERT`` - - :ref:`insert` into the table - - * - table - - ``DELETE`` - - :ref:`delete` and :ref:`truncate` on the table - - * - table - - ``DDL`` - - drop and alter on the table - - * - table - - ``ALL`` - - all the table permissions - - * - function - - ``EXECUTE`` - - use the function - - * - function - - ``DDL`` - - drop and alter on the function - - * - function - - ``ALL`` - - all function permissions - -GRANT ------ - -:ref:`grant` gives permissions to a role. - -.. code-block:: postgres - - -- Grant permissions at the instance/ storage cluster level: - GRANT - - { SUPERUSER - | LOGIN - | PASSWORD '' - } - TO [, ...] - - -- Grant permissions at the database level: - GRANT {{CREATE | CONNECT| DDL | SUPERUSER | CREATE FUNCTION} [, ...] | ALL [PERMISSIONS]} - - ON DATABASE [, ...] - TO [, ...] - - -- Grant permissions at the schema level: - GRANT {{ CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [ - PERMISSIONS ]} - ON SCHEMA [, ...] - TO [, ...] - - -- Grant permissions at the object level: - GRANT {{SELECT | INSERT | DELETE | DDL } [, ...] | ALL [PERMISSIONS]} - ON { TABLE [, ...] | ALL TABLES IN SCHEMA [, ...]} - TO [, ...] - - -- Grant execute function permission: - GRANT {ALL | EXECUTE | DDL} ON FUNCTION function_name - TO role; - - -- Allows role2 to use permissions granted to role1 - GRANT [, ...] - TO - - -- Also allows the role2 to grant role1 to other roles: - GRANT [, ...] - TO - WITH ADMIN OPTION - -``GRANT`` examples: - -.. code-block:: postgres - - GRANT LOGIN,superuser TO admin; - - GRANT CREATE FUNCTION ON database master TO admin; - - GRANT SELECT ON TABLE admin.table1 TO userA; - - GRANT EXECUTE ON FUNCTION my_function TO userA; - - GRANT ALL ON FUNCTION my_function TO userA; - - GRANT DDL ON admin.main_table TO userB; - - GRANT ALL ON all tables IN schema public TO userB; - - GRANT admin TO userC; - - GRANT superuser ON schema demo TO userA - - GRANT admin_role TO userB; - -REVOKE ------- - -:ref:`revoke` removes permissions from a role. - -.. code-block:: postgres - - -- Revoke permissions at the instance/ storage cluster level: - REVOKE - { SUPERUSER - | LOGIN - | PASSWORD - } - FROM [, ...] - - -- Revoke permissions at the database level: - REVOKE {{CREATE | CONNECT | DDL | SUPERUSER | CREATE FUNCTION}[, ...] |ALL [PERMISSIONS]} - ON DATABASE [, ...] - FROM [, ...] - - -- Revoke permissions at the schema level: - REVOKE { { CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [PERMISSIONS]} - ON SCHEMA [, ...] - FROM [, ...] - - -- Revoke permissions at the object level: - REVOKE { { SELECT | INSERT | DELETE | DDL } [, ...] | ALL } - ON { [ TABLE ] [, ...] | ALL TABLES IN SCHEMA - - [, ...] } - FROM [, ...] - - -- Removes access to permissions in role1 by role 2 - REVOKE [, ...] FROM [, ...] WITH ADMIN OPTION - - -- Removes permissions to grant role1 to additional roles from role2 - REVOKE [, ...] FROM [, ...] WITH ADMIN OPTION - - -Examples: - -.. code-block:: postgres - - REVOKE superuser on schema demo from userA; - - REVOKE delete on admin.table1 from userB; - - REVOKE login from role_test; - - REVOKE CREATE FUNCTION FROM admin; - -Default permissions -------------------- - -The default permissions system (See :ref:`alter_default_permissions`) -can be used to automatically grant permissions to newly -created objects (See the departmental example below for one way it can be used). - -A default permissions rule looks for a schema being created, or a -table (possibly by schema), and is table to grant any permission to -that object to any role. This happens when the create table or create -schema statement is run. - - -.. code-block:: postgres - - - ALTER DEFAULT PERMISSIONS FOR target_role_name - [IN schema_name, ...] - FOR { TABLES | SCHEMAS } - { grant_clause | DROP grant_clause} - TO ROLE { role_name | public }; - - grant_clause ::= - GRANT - { CREATE FUNCTION - | SUPERUSER - | CONNECT - | CREATE - | USAGE - | SELECT - | INSERT - | DELETE - | DDL - | EXECUTE - | ALL - } - - -Departmental Example -======================= - -You work in a company with several departments. - -The example below shows you how to manage permissions in a database shared by multiple departments, where each department has different roles for the tables by schema. It walks you through how to set the permissions up for existing objects and how to set up default permissions rules to cover newly created objects. - -The concept is that you set up roles for each new schema with the correct permissions, then the existing users can use these roles. - -A superuser must do new setup for each new schema which is a limitation, but superuser permissions are not needed at any other time, and neither are explicit grant statements or object ownership changes. - -In the example, the database is called ``my_database``, and the new or existing schema being set up to be managed in this way is called ``my_schema``. - -.. figure:: /_static/images/access_control_department_example.png - :scale: 60 % - - Our departmental example has four user group roles and seven users roles - -There will be a group for this schema for each of the following: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Group - - Activities - - * - database designers - - create, alter and drop tables - - * - updaters - - insert and delete data - - * - readers - - read data - - * - security officers - - add and remove users from these groups - -Setting up the department permissions ------------------------------------------- - -As a superuser, you connect to the system and run the following: - -.. code-block:: postgres - - -- create the groups - - CREATE ROLE my_schema_security_officers; - CREATE ROLE my_schema_database_designers; - CREATE ROLE my_schema_updaters; - CREATE ROLE my_schema_readers; - - -- grant permissions for each role - -- we grant permissions for existing objects here too, - -- so you don't have to start with an empty schema - - -- security officers - - GRANT connect ON DATABASE my_database TO my_schema_security_officers; - GRANT usage ON SCHEMA my_schema TO my_schema_security_officers; - - GRANT my_schema_database_designers TO my_schema_security_officers WITH ADMIN OPTION; - GRANT my_schema_updaters TO my_schema_security_officers WITH ADMIN OPTION; - GRANT my_schema_readers TO my_schema_security_officers WITH ADMIN OPTION; - - -- database designers - - GRANT connect ON DATABASE my_database TO my_schema_database_designers; - GRANT usage ON SCHEMA my_schema TO my_schema_database_designers; - - GRANT create,ddl ON SCHEMA my_schema TO my_schema_database_designers; - - -- updaters - - GRANT connect ON DATABASE my_database TO my_schema_updaters; - GRANT usage ON SCHEMA my_schema TO my_schema_updaters; - - GRANT SELECT,INSERT,DELETE ON ALL TABLES IN SCHEMA my_schema TO my_schema_updaters; - - -- readers - - GRANT connect ON DATABASE my_database TO my_schema_readers; - GRANT usage ON SCHEMA my_schema TO my_schema_readers; - - GRANT SELECT ON ALL TABLES IN SCHEMA my_schema TO my_schema_readers; - GRANT EXECUTE ON ALL FUNCTIONS TO my_schema_readers; - - - -- create the default permissions for new objects - - ALTER DEFAULT PERMISSIONS FOR my_schema_database_designers IN my_schema - FOR TABLES GRANT SELECT,INSERT,DELETE TO my_schema_updaters; - - -- For every table created by my_schema_database_designers, give access to my_schema_readers: - - ALTER DEFAULT PERMISSIONS FOR my_schema_database_designers IN my_schema - FOR TABLES GRANT SELECT TO my_schema_readers; - -.. note:: - * This process needs to be repeated by a user with ``SUPERUSER`` permissions each time a new schema is brought into this permissions management approach. - - * - By default, any new object created will not be accessible by our new ``my_schema_readers`` group. - Running a ``GRANT SELECT ...`` only affects objects that already exist in the schema or database. - - If you're getting a ``Missing the following permissions: SELECT on table 'database.public.tablename'`` error, make sure that - you've altered the default permissions with the ``ALTER DEFAULT PERMISSIONS`` statement. - -Creating new users in the departments ------------------------------------------ - -After the group roles have been created, you can now create user roles for each of your users. - -.. code-block:: postgres - - -- create the new database designer users - - CREATE ROLE ecodd; - GRANT LOGIN TO ecodd; - GRANT PASSWORD 'ecodds_secret_password' TO ecodd; - GRANT CONNECT ON DATABASE my_database TO ecodd; - GRANT my_schema_database_designers TO ecodd; - - CREATE ROLE ebachmann; - GRANT LOGIN TO ebachmann; - GRANT PASSWORD 'another_secret_password' TO ebachmann; - GRANT CONNECT ON DATABASE my_database TO ebachmann; - GRANT my_database_designers TO ebachmann; - - -- If a user already exists, we can assign that user directly to the group - - GRANT my_schema_updaters TO rhendricks; - - -- Create users in the readers group - - CREATE ROLE jbarker; - GRANT LOGIN TO jbarker; - GRANT PASSWORD 'action_jack' TO jbarker; - GRANT CONNECT ON DATABASE my_database TO jbarker; - GRANT my_schema_readers TO jbarker; - - CREATE ROLE lbream; - GRANT LOGIN TO lbream; - GRANT PASSWORD 'artichoke123' TO lbream; - GRANT CONNECT ON DATABASE my_database TO lbream; - GRANT my_schema_readers TO lbream; - - CREATE ROLE pgregory; - GRANT LOGIN TO pgregory; - GRANT PASSWORD 'c1ca6a' TO pgregory; - GRANT CONNECT ON DATABASE my_database TO pgregory; - GRANT my_schema_readers TO pgregory; - - -- Create users in the security officers group - - CREATE ROLE hoover; - GRANT LOGIN TO hoover; - GRANT PASSWORD 'mintchip' TO hoover; - GRANT CONNECT ON DATABASE my_database TO hoover; - GRANT my_schema_security_officers TO hoover; - - -.. todo: - create some example users - show that they have the right permission - try out the with admin option. we can't really do a security officer because - only superusers can create users and logins. see what can be done - need 1-2 users in each group, for at least 2 schemas/departments - this example will be very big just to show what this setup can do ... - example: a security officer for a department which will only have - read only access to a schema can only get that with admin option - access granted to them - -After this setup: - -* Database designers will be able to run any ddl on objects in the schema and create new objects, including ones created by other database designers -* Updaters will be able to insert and delete to existing and new tables -* Readers will be able to read from existing and new tables - -All this will happen without having to run any more ``GRANT`` statements. - -Any security officer will be able to add and remove users from these -groups. Creating and dropping login users themselves must be done by a -superuser. diff --git a/feature_guides/index.rst b/feature_guides/index.rst index 89383a049..1639ea378 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -12,7 +12,6 @@ This section describes the following features: :titlesonly: - access_control compression python_functions saved_queries From 7ad4589bc1aaedaafd2ccca77106aa57e57d44a6 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 8 Aug 2022 12:40:48 +0300 Subject: [PATCH 297/300] New Config Menu Structure --- configuration_guides/admin_regular_flags.rst | 3 +- configuration_guides/admin_worker_flags.rst | 5 +- .../configuration_methods.rst | 19 - configuration_guides/configuring_sqream.rst | 22 + .../current_configuration_method.rst | 728 ------------------ .../current_method_all_configurations.rst | 354 +++++++++ .../current_method_command_examples.rst | 36 + .../current_method_configuration_levels.rst | 33 + .../current_method_configuration_roles.rst | 17 + ...thod_configuring_your_parameter_values.rst | 40 + .../current_method_flag_types.rst | 20 + .../current_method_modification_methods.rst | 50 ++ ...showing_all_flags_in_the_catalog_table.rst | 21 + configuration_guides/files_and_folders.txt | 67 ++ configuration_guides/generic_flags.rst | 5 +- .../generic_regular_flags.rst | 10 +- .../healer_max_inactivity_hours.rst | 14 + configuration_guides/index.rst | 6 +- configuration_guides/is_healer_on.rst | 14 + configuration_guides/login_max_retries.rst | 11 + .../max_pinned_percentage_of_total_ram.rst | 12 + configuration_guides/spooling.rst | 4 +- configuration_guides/varchar_identifiers.rst | 12 + 23 files changed, 739 insertions(+), 764 deletions(-) delete mode 100644 configuration_guides/configuration_methods.rst create mode 100644 configuration_guides/configuring_sqream.rst delete mode 100644 configuration_guides/current_configuration_method.rst create mode 100644 configuration_guides/current_method_all_configurations.rst create mode 100644 configuration_guides/current_method_command_examples.rst create mode 100644 configuration_guides/current_method_configuration_levels.rst create mode 100644 configuration_guides/current_method_configuration_roles.rst create mode 100644 configuration_guides/current_method_configuring_your_parameter_values.rst create mode 100644 configuration_guides/current_method_flag_types.rst create mode 100644 configuration_guides/current_method_modification_methods.rst create mode 100644 configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst create mode 100644 configuration_guides/files_and_folders.txt create mode 100644 configuration_guides/healer_max_inactivity_hours.rst create mode 100644 configuration_guides/is_healer_on.rst create mode 100644 configuration_guides/login_max_retries.rst create mode 100644 configuration_guides/max_pinned_percentage_of_total_ram.rst create mode 100644 configuration_guides/varchar_identifiers.rst diff --git a/configuration_guides/admin_regular_flags.rst b/configuration_guides/admin_regular_flags.rst index d3296e1e4..1391e6370 100644 --- a/configuration_guides/admin_regular_flags.rst +++ b/configuration_guides/admin_regular_flags.rst @@ -28,4 +28,5 @@ The **Regular Administration Flags** page describes **Regular** modification typ * `Setting Implicit Casts in ORC Files `_ * `Setting Timeout Limit for Locking Objects before Executing Statements `_ * `Interpreting Decimal Literals as Double Instead of Numeric `_ -* `VARCHAR Identifiers `_ \ No newline at end of file +* `Interpreting VARCHAR as TEXT `_ +* `VARCHAR Identifiers `_ diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst index 412955510..c126c8457 100644 --- a/configuration_guides/admin_worker_flags.rst +++ b/configuration_guides/admin_worker_flags.rst @@ -8,4 +8,7 @@ The **Worker Administration Flags** page describes **Worker** modification type * `Setting Total Device Memory Usage in SQream Instance `_ * `Enabling Manually Setting Reported IP `_ * `Setting Port Used for Metadata Server Connection `_ -* `Assigning Local Network IP `_ \ No newline at end of file +* `Assigning Local Network IP `_ +* `Enabling the Query Healer `_ +* `Configuring the Query Healer `_ +* `Adjusting Permitted Log-in Attempts `_ \ No newline at end of file diff --git a/configuration_guides/configuration_methods.rst b/configuration_guides/configuration_methods.rst deleted file mode 100644 index 00a70ab5c..000000000 --- a/configuration_guides/configuration_methods.rst +++ /dev/null @@ -1,19 +0,0 @@ -.. _configuration_methods: - -************************* -Configuration Methods -************************* -SQream provides two methods for configuration your instance of SQream. The current configuration method is based on cluster and session-based configuration, described in more detail below. Users can also use the previous configuration method done using a configuration file. - -The **Configuration Methods** page describes the following configurations methods: - -.. toctree:: - :maxdepth: 1 - :glob: - :titlesonly: - - current_configuration_method - previous_configuration_method - - - diff --git a/configuration_guides/configuring_sqream.rst b/configuration_guides/configuring_sqream.rst new file mode 100644 index 000000000..901af9e3d --- /dev/null +++ b/configuration_guides/configuring_sqream.rst @@ -0,0 +1,22 @@ +.. _configuring_sqream: + +************************* +Configuring SQream +************************* +The **Configuring SQream** page describes the following configuration topics: + +.. toctree:: + :maxdepth: 1 + :glob: + :titlesonly: + + current_method_configuration_levels + current_method_flag_types + current_method_configuration_roles + current_method_modification_methods + current_method_configuring_your_parameter_values + current_method_command_examples + current_method_showing_all_flags_in_the_catalog_table + current_method_all_configurations + + diff --git a/configuration_guides/current_configuration_method.rst b/configuration_guides/current_configuration_method.rst deleted file mode 100644 index 238626279..000000000 --- a/configuration_guides/current_configuration_method.rst +++ /dev/null @@ -1,728 +0,0 @@ -.. _current_configuration_method: - -************************** -Configuring SQream -************************** -The **Configuring SQream** page describes SQream’s method for configuring your instance of SQream and includes the following topics: - -.. contents:: - :local: - :depth: 1 - -Overview ------ -Modifications that you make to your configurations are persistent based on whether they are made at the session or cluster level. Persistent configurations are modifications made to attributes that are retained after shutting down your system. - -Modifying Your Configuration ----- -The **Modifying Your Configuration** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Modifying Your Configuration Using the Worker Configuration File -~~~~~~~~~~~ -You can modify your configuration using the **worker configuration file (config.json)**. Changes that you make to worker configuration files are persistent. Note that you can only set the attributes in your worker configuration file **before** initializing your SQream worker, and while your worker is active these attributes are read-only. - -The following is an example of a worker configuration file: - -.. code-block:: postgres - - { - “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, - “gpu”: 0, - “licensePath”: “home/test_user/SQream/tests/license.enc”, - “machineIP”: “127.0.0.1”, - “metadataServerIp”: “127.0.0.1”, - “metadataServerPort”: “3105, - “port”: 5000, - “useConfigIP”” true, - “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” - } - -You can access the legacy configuration file from the ``legacyConfigFilePath`` parameter shown above. If all (or most) of your workers require the same flag settings, you can set the ``legacyConfigFilePath`` attribute to the same legacy file. - -Modifying Your Configuration Using a Legacy Configuration File -~~~~~~~~~~~ -You can modify your configuration using a legacy configuration file. - -The Legacy configuration file provides access to the read/write flags used in SQream’s previous configuration method. A link to this file is provided in the **legacyConfigFilePath** parameter in the worker configuration file. - -The following is an example of the legacy configuration file: - -.. code-block:: postgres - - { - “developerMode”: true, - “reextentUse”: false, - “useClientLog”: true, - “useMetadataServer”” false - } - -Session vs Cluster Based Configuration -============================== -.. contents:: - :local: - :depth: 1 - -Cluster-Based Configuration --------------- -SQream uses cluster-based configuration, enabling you to centralize configurations for all workers on the cluster. Only flags set to the regular or cluster flag type have access to cluster-based configuration. Configurations made on the cluster level are persistent and stored at the metadata level. The parameter settings in this file are applied globally to all workers connected to it. - -For more information, see the following: - -* `Using SQream SQL `_ - modifying flag attributes from the CLI. -* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. - -For more information on flag-based access to cluster-based configuration, see **Configuration Flag Types** below. - -Session-Based Configuration ----------------- -Session-based configurations are not persistent and are deleted when your session ends. This method enables you to modify all required configurations while avoiding conflicts between flag attributes modified on different devices at different points in time. - -The **SET flag_name** command is used to modify flag attributes. Any modifications you make with the **SET flag_name** command apply only to your open session, and are not saved when it ends - -For example, when the query below has completed executing, the values configured will be restored to its previous setting: - -.. code-block:: console - - set spoolMemoryGB=700; - select * from table a where date='2021-11-11' - -For more information, see the following: - -* `Using SQream SQL `_ - modifying flag attributes from the CLI. -* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. - -Configuration Flag Types -========== -The flag type attribute can be set for each flag and determines its write access as follows: - -* **Administration:** session-based read/write flags that can be stored in the metadata file. -* **Cluster:** global cluster-based read/write flags that can be stored in the metadata file. -* **Worker:** single worker-based read-only flags that can be stored in the worker configuration file. - -The flag type determines which files can be accessed and which commands or commands sets users can run. - -The following table describes the file or command modification rights for each flag type: - -.. list-table:: - :widths: 20 20 20 20 - :header-rows: 1 - - * - **Flag Type** - - **Legacy Configuration File** - - **ALTER SYSTEM SET** - - **Worker Configuration File** - * - :ref:`Regular` - - Can modify - - Can modify - - Cannot modify - * - :ref:`Cluster` - - Cannot modify - - Can modify - - Cannot modify - * - :ref:`Worker` - - Cannot modify - - Cannot modify - - Can modify - -.. _regular_flag_types: - -Regular Flag Types ---------------------- -The following is an example of the correct syntax for running a **Regular** flag type command: - -.. code-block:: console - - SET spoolMemoryGB= 11; - executed - -The following table describes the Regular flag types: - -.. list-table:: - :widths: 2 5 10 - :header-rows: 1 - - * - **Command** - - **Description** - - **Example** - * - ``SET `` - - Used for modifying flag attributes. - - ``SET developerMode=true`` - * - ``SHOW / ALL`` - - Used to preset either a specific flag value or all flag values. - - ``SHOW `` - * - ``SHOW ALL LIKE`` - - Used as a wildcard character for flag names. - - ``SHOW `` - * - ``show_conf_UF`` - - Used to print all flags with the following attributes: - - * Flag name - * Default value - * Is developer mode (Boolean) - * Flag category - * Flag type - - ``rechunkThreshold,90,true,RND,regular`` - * - ``show_conf_extended UF`` - - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. - - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` - ``utility functions names,boolean,true,false`` - * - ``show_md_flag UF`` - - Used to show a specific flag/all flags stored in the metadata file. - - - * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` - * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` - * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` - -.. _cluster_flag_types: - -Cluster Flag Types ---------------------- -The following is an example of the correct syntax for running a **Cluster** flag type command: - -.. code-block:: console - - ALTER SYSTEM RESET useMetadataServer; - executed - -The following table describes the Cluster flag types: - -.. list-table:: - :widths: 1 5 10 - :header-rows: 1 - - * - **Command** - - **Description** - - **Example** - * - ``ALTER SYSTEM SET `` - - Used to storing or modifying flag attributes in the metadata file. - - ``ALTER SYSTEM SET `` - * - ``ALTER SYSTEM RESET `` - - Used to remove a flag or all flag attributes from the metadata file. - - ``ALTER SYSTEM RESET `` - * - ``SHOW / ALL`` - - Used to print the value of a specified value or all flag values. - - ``SHOW `` - * - ``SHOW ALL LIKE`` - - Used as a wildcard character for flag names. - - ``SHOW `` - * - ``show_conf_UF`` - - Used to print all flags with the following attributes: - - * Flag name - * Default value - * Is developer mode (Boolean) - * Flag category - * Flag type - - ``rechunkThreshold,90,true,RND,regular`` - * - ``show_conf_extended UF`` - - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. - - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` - ``utility functions names,boolean,true,false`` - * - ``show_md_flag UF`` - - Used to show a specific flag/all flags stored in the metadata file. - - - * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` - * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` - * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` - -.. _worker_flag_types: - -Worker Flag Types ---------------------- -The following is an example of the correct syntax for running a **Worker** flag type command: - -.. code-block:: console - - SHOW spoolMemoryGB; - -The following table describes the Worker flag types: - -.. list-table:: - :widths: 1 5 10 - :header-rows: 1 - - * - **Command** - - **Description** - - **Example** - * - ``ALTER SYSTEM SET `` - - Used to storing or modifying flag attributes in the metadata file. - - ``ALTER SYSTEM SET `` - * - ``ALTER SYSTEM RESET `` - - Used to remove a flag or all flag attributes from the metadata file. - - ``ALTER SYSTEM RESET `` - * - ``SHOW / ALL`` - - Used to print the value of a specified value or all flag values. - - ``SHOW `` - * - ``SHOW ALL LIKE`` - - Used as a wildcard character for flag names. - - ``SHOW `` - * - ``show_conf_UF`` - - Used to print all flags with the following attributes: - - * Flag name - * Default value - * Is developer mode (Boolean) - * Flag category - * Flag type - - ``rechunkThreshold,90,true,RND,regular`` - * - ``show_conf_extended UF`` - - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. - - - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` - ``utility functions names,boolean,true,false`` - * - ``show_md_flag UF`` - - Used to show a specific flag/all flags stored in the metadata file. - - - * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` - * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` - * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` - -All Configurations ---------------------- -The following table describes the **Generic** and **Administration** configuration flags: - -.. list-table:: - :header-rows: 1 - :widths: 1 2 1 15 1 20 - :class: my-class - :name: my-name - - * - Flag Name - - Access Control - - Modification Type - - Description - - Data Type - - Default Value - - * - ``binSizes`` - - Administration - - Regular - - Sets the custom bin size in the cache to enable high granularity bin control. - - string - - - ``16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,`` - ``131072,262144,524288,1048576,2097152,4194304,8388608,16777216,`` - ``33554432,67108864,134217728,268435456,536870912,786432000,107374,`` - ``1824,1342177280,1610612736,1879048192,2147483648,2415919104,`` - ``2684354560,2952790016,3221225472`` - - * - ``cacheDiskDir`` - - Generic - - Regular - - Sets the ondisk directory location for the spool to save files on. - - size_t - - Any legal string - - - * - ``cacheDiskGB`` - - Generic - - Regular - - Sets the amount of memory (GB) to be used by Spool on the disk. - - size_t - - ``128`` - - * - ``cacheEvictionMilliseconds`` - - Generic - - Regular - - Sets how long the cache stores contents before being flushed. - - size_t - - ``2000`` - - * - ``cachePartitions`` - - Generic - - Regular - - Sets the number of partitions that the cache is split into. - - size_t - - ``4`` - - - * - ``cachePersistentDir`` - - Generic - - Regular - - Sets the persistent directory location for the spool to save files on. - - string - - Any legal string - - - * - ``cachePersistentGB`` - - Generic - - Regular - - Sets the amount of data (GB) for the cache to store persistently. - - size_t - - ``128`` - - - * - ``cacheRamGB`` - - Generic - - Regular - - Sets the amount of memory (GB) to be used by Spool InMemory. - - size_t - - ``16`` - - * - ``checkCudaMemory`` - - Administration - - Regular - - Sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. - - boolean - - ``FALSE`` - - * - ``compilerGetsOnlyUFs`` - - Administration - - Regular - - Sets the runtime to pass only utility functions names to the compiler. - - boolean - - ``FALSE`` - - * - ``copyToRestrictUtf8`` - - Administration - - Regular - - Sets the custom bin size in the cache to enable high granularity bin control. - - boolean - - ``FALSE`` - - * - ``cpuReduceHashtableSize`` - - Administration - - Regular - - Sets the hash table size of the CpuReduce. - - uint - - ``10000`` - - * - ``csvLimitRowLength`` - - Administration - - Cluster - - Sets the maximum supported CSV row length. - - uint - - ``100000`` - - * - ``cudaMemcpyMaxSizeBytes`` - - Administration - - Regular - - Sets the chunk size for copying from CPU to GPU. If set to 0, do not divide. - - uint - - ``0`` - - * - ``CudaMemcpySynchronous`` - - Administration - - Regular - - Indicates if copying from/to GPU is synchronous. - - boolean - - ``FALSE`` - - * - ``cudaMemQuota`` - - Administration - - Worker - - Sets the percentage of total device memory to be used by the instance. - - uint - - ``90`` - - * - ``developerMode`` - - Administration - - Regular - - Enables modifying R&D flags. - - boolean - - ``FALSE`` - - * - ``enableDeviceDebugMessages`` - - Administration - - Regular - - Activates the Nvidia profiler (nvprof) markers. - - boolean - - ``FALSE`` - - * - ``enableLogDebug`` - - Administration - - Regular - - Enables creating and logging in the clientLogger_debug file. - - boolean - - ``TRUE`` - - * - ``enableNvprofMarkers`` - - Administration - - Regular - - Activates the Nvidia profiler (nvprof) markers. - - boolean - - ``FALSE`` - - * - ``endLogMessage`` - - Administration - - Regular - - Appends a string at the end of every log line. - - string - - ``EOM`` - - - - - - - - - * - ``extentStorageFileSizeMB`` - - Administration - - Cluster - - Sets the minimum size in mebibytes of extents for table bulk data. - - uint - - ``20`` - - * - ``flipJoinOrder`` - - Generic - - Regular - - Reorders join to force equijoins and/or equijoins sorted by table size. - - boolean - - ``FALSE`` - - - - * - ``gatherMemStat`` - - Administration - - Regular - - Monitors all pinned allocations and all **memcopies** to/from device, and prints a report of pinned allocations that were not memcopied to/from the device using the **dump_pinned_misses** utility function. - - boolean - - ``FALSE`` - - * - ``increaseChunkSizeBeforeReduce`` - - Administration - - Regular - - Increases the chunk size to reduce query speed. - - boolean - - ``FALSE`` - - * - ``increaseMemFactors`` - - Administration - - Regular - - Adds rechunker before expensive chunk producer. - - boolean - - ``TRUE`` - - * - ``leveldbWriteBufferSize`` - - Administration - - Regular - - Sets the buffer size. - - uint - - ``524288`` - - * - ``limitQueryMemoryGB`` - - Generic - - Worker - - Prevents a query from processing more memory than the flag’s value. - - uint - - ``100000`` - - * - ``logSysLevel`` - - Generic - - Regular - - - Determines the client log level: - 0 - L_SYSTEM, - 1 - L_FATAL, - 2 - L_ERROR, - 3 - L_WARN, - 4 - L_INFO, - 5 - L_DEBUG, - 6 - L_TRACE - - uint - - ``100000`` - - * - ``machineIP`` - - Administration - - Worker - - Manual setting of reported IP. - - string - - ``127.0.0.1`` - - - - * - ``maxAvgBlobSizeToCompressOnGpu`` - - Generic - - Regular - - Sets the CPU to compress columns with size above (flag’s value) * (row count). - - uint - - ``120`` - - - * - ``memoryResetTriggerMB`` - - Administration - - Regular - - Sets the size of memory used during a query to trigger aborting the server. - - uint - - ``0`` - - * - ``metadataServerPort`` - - Administration - - Worker - - Sets the port used to connect to the metadata server. SQream recommends using port ranges above 1024† because ports below 1024 are usually reserved, although there are no strict limitations. Any positive number (1 - 65535) can be used. - - uint - - ``3105`` - - * - ``mtRead`` - - Administration - - Regular - - Splits large reads to multiple smaller ones and executes them concurrently. - - boolean - - ``FALSE`` - - * - ``mtReadWorkers`` - - Administration - - Regular - - Sets the number of workers to handle smaller concurrent reads. - - uint - - ``30`` - - * - ``orcImplicitCasts`` - - Administration - - Regular - - Sets the implicit cast in orc files, such as **int** to **tinyint** and vice versa. - - boolean - - ``TRUE`` - - - * - ``sessionTag`` - - Generic - - Regular - - Sets the name of the session tag. - - string - - Any legal string - - - - * - ``spoolMemoryGB`` - - Generic - - Regular - - Sets the amount of memory (GB) to be used by the server for spooling. - - uint - - ``8`` - - * - ``statementLockTimeout`` - - Administration - - Regular - - Sets the timeout (seconds) for acquiring object locks before executing statements. - - uint - - ``3`` - - - * - ``useConfigIP`` - - Administration - - Worker - - Activates the machineIP (true). Setting to false ignores the machineIP and automatically assigns a local network IP. This cannot be activated in a cloud scenario (on-premises only). - - boolean - - ``FALSE`` - - * - ``useLegacyDecimalLiterals`` - - Administration - - Regular - - Interprets decimal literals as **Double** instead of **Numeric**. Used to preserve legacy behavior in existing customers. - - boolean - - ``FALSE`` - - * - ``useLegacyStringLiterals`` - - Administration - - Regular - - Interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. Used to preserve legacy behavior in existing customers. - - boolean - - ``FALSE`` - - * - ``varcharIdentifiers`` - - Administration - - Regular - - Activates using varchar as an identifier. - - boolean - - ``true` - -Configuration Commands -========== -The configuration commands are associated with particular flag types based on permissions. - -The following table describes the commands or command sets that can be run based on their flag type. Note that the flag names described in the following table are described in the :ref:`Configuration Roles` section below. - -.. list-table:: - :header-rows: 1 - :widths: 1 2 10 17 - :class: my-class - :name: my-name - - * - Flag Type - - Command - - Description - - Example - * - Regular - - ``SET `` - - Used for modifying flag attributes. - - ``SET developerMode=true`` - * - Cluster - - ``ALTER SYSTEM SET `` - - Used to storing or modifying flag attributes in the metadata file. - - ``ALTER SYSTEM SET `` - * - Cluster - - ``ALTER SYSTEM RESET `` - - Used to remove a flag or all flag attributes from the metadata file. - - ``ALTER SYSTEM RESET `` - * - Regular, Cluster, Worker - - ``SHOW / ALL`` - - Used to print the value of a specified value or all flag values. - - ``SHOW `` - * - Regular, Cluster, Worker - - ``SHOW ALL LIKE`` - - Used as a wildcard character for flag names. - - ``SHOW `` - * - Regular, Cluster, Worker - - ``show_conf_UF`` - - Used to print all flags with the following attributes: - - * Flag name - * Default value - * Is developer mode (Boolean) - * Flag category - * Flag type - - - - - ``rechunkThreshold,90,true,RND,regular`` - * - Regular, Cluster, Worker - - ``show_conf_extended UF`` - - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. - - ``spoolMemoryGB,15,false,generic,regular,Amount of memory (GB)`` - ``the server can use for spooling,”Statement that perform “”group by””,`` - ``“”order by”” or “”join”” operation(s) on large set of data will run`` - ``much faster if given enough spool memory, otherwise disk spooling will`` - ``be used resulting in performance hit.”,uint,,0-5000`` - * - Regular, Cluster, Worker - - ``show_md_flag UF`` - - Used to show a specific flag/all flags stored in the metadata file. - - - * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` - * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` - * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` - -.. _configuration_roles: - -Configuration Roles -=========== -SQream divides flags into the following roles, each with their own set of permissions: - -* `Administration flags `_: can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command. -* `Generic flags `_: can be modified by standard users on a session basis. - -Showing All Flags in the Catalog Table -======= -SQream uses the **sqream_catalog.parameters** catalog table for showing all flags, providing the scope (default, cluster and session), description, default value and actual value. - -The following is the correct syntax for a catalog table query: - -.. code-block:: console - - SELECT * FROM sqream_catalog.settings - -The following is an example of a catalog table query: - -.. code-block:: console - - externalTableBlobEstimate, 100, 100, default, - varcharEncoding, ascii, ascii, default, Changes the expected encoding for Varchar columns - useCrcForTextJoinKeys, true, true, default, - hiveStyleImplicitStringCasts, false, false, default, - -This guide covers the configuration files and the ``SET`` statement. \ No newline at end of file diff --git a/configuration_guides/current_method_all_configurations.rst b/configuration_guides/current_method_all_configurations.rst new file mode 100644 index 000000000..00ad944c7 --- /dev/null +++ b/configuration_guides/current_method_all_configurations.rst @@ -0,0 +1,354 @@ +.. _current_method_all_configurations: + +************************** +All Configurations +************************** +The following table describes all **Generic** and **Administration** configuration flags: + +.. list-table:: + :header-rows: 1 + :widths: 1 2 1 15 1 20 + :class: my-class + :name: my-name + + * - Flag Name + - Access Control + - Modification Type + - Description + - Data Type + - Default Value + + * - ``binSizes`` + - Admin + - Regular + - Sets the custom bin size in the cache to enable high granularity bin control. + - string + - + ``16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,`` + ``131072,262144,524288,1048576,2097152,4194304,8388608,16777216,`` + ``33554432,67108864,134217728,268435456,536870912,786432000,107374,`` + ``1824,1342177280,1610612736,1879048192,2147483648,2415919104,`` + ``2684354560,2952790016,3221225472`` + + * - ``checkCudaMemory`` + - Admin + - Regular + - Sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. + - boolean + - ``FALSE`` + + * - ``compilerGetsOnlyUFs`` + - Admin + - Regular + - Sets the runtime to pass only utility functions names to the compiler. + - boolean + - ``FALSE`` + + * - ``copyToRestrictUtf8`` + - Admin + - Regular + - Sets the custom bin size in the cache to enable high granularity bin control. + - boolean + - ``FALSE`` + + * - ``cpuReduceHashtableSize`` + - Admin + - Regular + - Sets the hash table size of the CpuReduce. + - uint + - ``10000`` + + * - ``csvLimitRowLength`` + - Admin + - Cluster + - Sets the maximum supported CSV row length. + - uint + - ``100000`` + + * - ``cudaMemcpyMaxSizeBytes`` + - Admin + - Regular + - Sets the chunk size for copying from CPU to GPU. If set to 0, do not divide. + - uint + - ``0`` + + * - ``CudaMemcpySynchronous`` + - Admin + - Regular + - Indicates if copying from/to GPU is synchronous. + - boolean + - ``FALSE`` + + * - ``cudaMemQuota`` + - Admin + - Worker + - Sets the percentage of total device memory to be used by the instance. + - uint + - ``90`` + + * - ``developerMode`` + - Admin + - Regular + - Enables modifying R&D flags. + - boolean + - ``FALSE`` + + * - ``enableDeviceDebugMessages`` + - Admin + - Regular + - Activates the Nvidia profiler (nvprof) markers. + - boolean + - ``FALSE`` + + * - ``enableLogDebug`` + - Admin + - Regular + - Enables creating and logging in the clientLogger_debug file. + - boolean + - ``TRUE`` + + * - ``enableNvprofMarkers`` + - Admin + - Regular + - Activates the Nvidia profiler (nvprof) markers. + - boolean + - ``FALSE`` + + * - ``endLogMessage`` + - Admin + - Regular + - Appends a string at the end of every log line. + - string + - ``EOM`` + + + + * - ``varcharIdentifiers`` + - Admin + - Regular + - Activates using varchar as an identifier. + - boolean + - ``true`` + + + + * - ``extentStorageFileSizeMB`` + - Admin + - Cluster + - Sets the minimum size in mebibytes of extents for table bulk data. + - uint + - ``20`` + + * - ``gatherMemStat`` + - Admin + - Regular + - Monitors all pinned allocations and all **memcopies** to/from device, and prints a report of pinned allocations that were not memcopied to/from the device using the **dump_pinned_misses** utility function. + - boolean + - ``FALSE`` + + * - ``increaseChunkSizeBeforeReduce`` + - Admin + - Regular + - Increases the chunk size to reduce query speed. + - boolean + - ``FALSE`` + + * - ``increaseMemFactors`` + - Admin + - Regular + - Adds rechunker before expensive chunk producer. + - boolean + - ``TRUE`` + + * - ``leveldbWriteBufferSize`` + - Admin + - Regular + - Sets the buffer size. + - uint + - ``524288`` + + * - ``machineIP`` + - Admin + - Worker + - Manual setting of reported IP. + - string + - ``127.0.0.1`` + + + + + * - ``memoryResetTriggerMB`` + - Admin + - Regular + - Sets the size of memory used during a query to trigger aborting the server. + - uint + - ``0`` + + * - ``metadataServerPort`` + - Admin + - Worker + - Sets the port used to connect to the metadata server. SQream recommends using port ranges above 1024† because ports below 1024 are usually reserved, although there are no strict limitations. Any positive number (1 - 65535) can be used. + - uint + - ``3105`` + + * - ``mtRead`` + - Admin + - Regular + - Splits large reads to multiple smaller ones and executes them concurrently. + - boolean + - ``FALSE`` + + * - ``mtReadWorkers`` + - Admin + - Regular + - Sets the number of workers to handle smaller concurrent reads. + - uint + - ``30`` + + * - ``orcImplicitCasts`` + - Admin + - Regular + - Sets the implicit cast in orc files, such as **int** to **tinyint** and vice versa. + - boolean + - ``TRUE`` + + * - ``statementLockTimeout`` + - Admin + - Regular + - Sets the timeout (seconds) for acquiring object locks before executing statements. + - uint + - ``3`` + + * - ``useConfigIP`` + - Admin + - Worker + - Activates the machineIP (true). Setting to false ignores the machineIP and automatically assigns a local network IP. This cannot be activated in a cloud scenario (on-premises only). + - boolean + - ``FALSE`` + + * - ``useLegacyDecimalLiterals`` + - Admin + - Regular + - Interprets decimal literals as **Double** instead of **Numeric**. Used to preserve legacy behavior in existing customers. + - boolean + - ``FALSE`` + + * - ``useLegacyStringLiterals`` + - Admin + - Regular + - Interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. Used to preserve legacy behavior in existing customers. + - boolean + - ``FALSE`` + + * - ``flipJoinOrder`` + - Generic + - Regular + - Reorders join to force equijoins and/or equijoins sorted by table size. + - boolean + - ``FALSE`` + + * - ``limitQueryMemoryGB`` + - Generic + - Worker + - Prevents a query from processing more memory than the flag’s value. + - uint + - ``100000`` + + * - ``cacheEvictionMilliseconds`` + - Generic + - Regular + - Sets how long the cache stores contents before being flushed. + - size_t + - ``2000`` + + + * - ``cacheDiskDir`` + - Generic + - Regular + - Sets the ondisk directory location for the spool to save files on. + - size_t + - Any legal string + + + * - ``cacheDiskGB`` + - Generic + - Regular + - Sets the amount of memory (GB) to be used by Spool on the disk. + - size_t + - ``128`` + + * - ``cachePartitions`` + - Generic + - Regular + - Sets the number of partitions that the cache is split into. + - size_t + - ``4`` + + + * - ``cachePersistentDir`` + - Generic + - Regular + - Sets the persistent directory location for the spool to save files on. + - string + - Any legal string + + + * - ``cachePersistentGB`` + - Generic + - Regular + - Sets the amount of data (GB) for the cache to store persistently. + - size_t + - ``128`` + + + * - ``cacheRamGB`` + - Generic + - Regular + - Sets the amount of memory (GB) to be used by Spool InMemory. + - size_t + - ``16`` + + + + + + + + * - ``logSysLevel`` + - Generic + - Regular + - + Determines the client log level: + 0 - L_SYSTEM, + 1 - L_FATAL, + 2 - L_ERROR, + 3 - L_WARN, + 4 - L_INFO, + 5 - L_DEBUG, + 6 - L_TRACE + - uint + - ``100000`` + + * - ``maxAvgBlobSizeToCompressOnGpu`` + - Generic + - Regular + - Sets the CPU to compress columns with size above (flag’s value) * (row count). + - uint + - ``120`` + + + * - ``sessionTag`` + - Generic + - Regular + - Sets the name of the session tag. + - string + - Any legal string + + + + * - ``spoolMemoryGB`` + - Generic + - Regular + - Sets the amount of memory (GB) to be used by the server for spooling. + - uint + - ``8`` \ No newline at end of file diff --git a/configuration_guides/current_method_command_examples.rst b/configuration_guides/current_method_command_examples.rst new file mode 100644 index 000000000..2f75a4711 --- /dev/null +++ b/configuration_guides/current_method_command_examples.rst @@ -0,0 +1,36 @@ +.. _current_method_command_examples: + +************************** +Command Examples +************************** +This section includes the following command examples: + +.. contents:: + :local: + :depth: 1 + +Running a Regular Flag Type Command +--------------------- +The following is an example of running a **Regular** flag type command: + +.. code-block:: console + + SET spoolMemoryGB= 11; + executed + +Running a Worker Flag Type Command +--------------------- +The following is an example of running a **Worker** flag type command: + +.. code-block:: console + + SHOW spoolMemoryGB; + +Running a Cluster Flag Type Command +--------------------- +The following is an example of running a **Cluster** flag type command: + +.. code-block:: console + + ALTER SYSTEM RESET useMetadataServer; + executed \ No newline at end of file diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst new file mode 100644 index 000000000..47ccf32b3 --- /dev/null +++ b/configuration_guides/current_method_configuration_levels.rst @@ -0,0 +1,33 @@ +.. _current_method_configuration_levels: + +************************** +Configuration Levels +************************** +SQream's configuration parameters are based on the following hierarchy: + +.. contents:: + :local: + :depth: 1 + +Cluster-Based Configuration +-------------- +Cluster-based configuration lets you centralize configurations for all workers on the cluster. Only Regular and Cluster flag types can be modified on the cluster level. These modifications are persistent and stored at the metadata level, which are applied globally to all workers in the cluster. + +.. note:: While cluster-based configuration was designed for configuring Workers, you can only configure Worker values set to the Regular or Cluster type. + +Worker-Based Configuration +-------------- +Worker-based configuration lets you modify the configuration belong to individual workers from the worker configuration file. + +For more information on making configurations from the worker configuration file, see `Modifying Your Configuration Using a Legacy Configuration File `_. + +Session-Based Configuration +-------------- +Session-based configurations are not persistent and are deleted when your session ends. This method enables you to modify all required configurations while avoiding conflicts between flag attributes modified on different devices at different points in time. The **SET flag_name** command is used to modify flag values on the session level. Any modifications you make with the **SET flag_name** command apply only to your open session, and are not saved when it ends. + +For example, when the query below has completed executing, the values configured will be restored to its previous setting: + +.. code-block:: console + + set spoolMemoryGB=700; + select * from table a where date='2021-11-11' \ No newline at end of file diff --git a/configuration_guides/current_method_configuration_roles.rst b/configuration_guides/current_method_configuration_roles.rst new file mode 100644 index 000000000..11b7e4bfb --- /dev/null +++ b/configuration_guides/current_method_configuration_roles.rst @@ -0,0 +1,17 @@ +.. _current_method_configuration_roles: + +************************** +Configuration Roles +************************** +SQream divides flags into the following roles, each with their own set of permissions: + +* :ref:`admin_flags` - can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: **Comment** - *I don't think we need to mention the command here, as it's described below, and also not mentioned for Generic Flags.* + + * Regular + * Worker + * Cluster + +* :ref:`generic_flags` - can be modified by standard users on a session basis: + + * Regular + * Worker \ No newline at end of file diff --git a/configuration_guides/current_method_configuring_your_parameter_values.rst b/configuration_guides/current_method_configuring_your_parameter_values.rst new file mode 100644 index 000000000..d082db693 --- /dev/null +++ b/configuration_guides/current_method_configuring_your_parameter_values.rst @@ -0,0 +1,40 @@ +.. _current_method_configuring_your_parameter_values: + +************************** +Configuring Your Parameter Values +************************** +The method you must use to configure your parameter values depends on the configuration level. Each configuration level has its own command or set of commands used to configure values, as shown below: + ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| **Configuration Level** | ++=================================================================================================================================================================================================================================================================================================================+ +| **Regular, Worker, and Cluster** | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| **Command** | **Description** | **Example** | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``SET `` | Used for modifying flag attributes. | ``SET developerMode=true`` | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``SHOW / ALL`` | Used to preset either a specific flag value or all flag values. | ``SHOW `` | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``SHOW ALL LIKE`` | Used as a wildcard character for flag names. | ``SHOW `` | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``show_conf_UF`` | Used to print all flags with the following attributes: | ``rechunkThreshold,90,true,RND,regular`` | +| | | | +| | * Flag name | | +| | * Default value | | +| | * Is Developer Mode (Boolean) | | +| | * Flag category | | +| | * Flag type | | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``show_conf_extended UF`` | Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. | ``rechunkThreshold,90,true,RND,regular`` | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``show_md_flag UF`` | Used to show a specific flag/all flags stored in the metadata file. |* Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` | +| | |* Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` | +| | |* Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| **Worker and Cluster** | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``ALTER SYSTEM SET `` | Used for storing or modifying flag attributes in the metadata file. | ``ALTER SYSTEM SET `` | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``ALTER SYSTEM RESET `` | Used to remove a flag or all flag attributes from the metadata file. | ``ALTER SYSTEM RESET `` | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ \ No newline at end of file diff --git a/configuration_guides/current_method_flag_types.rst b/configuration_guides/current_method_flag_types.rst new file mode 100644 index 000000000..b1bedecba --- /dev/null +++ b/configuration_guides/current_method_flag_types.rst @@ -0,0 +1,20 @@ +.. _current_method_flag_types: + +************************** +Flag Types +************************** +SQream uses three flag types, **Cluster**, **Worker**, and **Regular**. Each of these flag types is associated with one of three hierarchical configuration levels described earlier, making it easier to configure your system. + +The highest level in the hierarchy is Cluster, which lets you set configurations across all workers in a given cluster. Modifying cluster values is **persistent**, meaning that any configurations you set are retained after shutting down your system. Configurations set at the Cluster level take the highest priority and override settings made on the Regular and Worker level **Comment** - *Confirm*. This is known as **cluster-based configuration**. Note that Cluster-based configuration lets you modify Cluster *and* Regular flag types. An example of a Cluster flag is **persisting your cache directory.** + +The second level is Worker, which lets you configure individual workers. Modifying Worker values are also **persistent**. This is known as **worker-based configuration**. Some examples of Worker flags includes **setting total device memory usage** and **setting metadata server connection port**. + +The lowest level is Regular, which means that modifying values of Regular flags affects only your current session and are not persistent. This means that they are automatically restored to their default value when the session ends. This is known as **session-based configuration**. Some examples of Regular flags includes **setting your bin size** and **setting CUDA memory**. + +To see each flag's default value, see one of the following: + +* The **Default Value** column in the :ref:`All Configurations` section. + + :: + +* The flag's individual description page, such as :ref:`Setting CUDA Memory`. \ No newline at end of file diff --git a/configuration_guides/current_method_modification_methods.rst b/configuration_guides/current_method_modification_methods.rst new file mode 100644 index 000000000..05825b07a --- /dev/null +++ b/configuration_guides/current_method_modification_methods.rst @@ -0,0 +1,50 @@ +.. _current_method_modification_methods: + +************************** +Modification Methods +************************** +SQream provides two different ways to modify your configurations. The current method is based on hierarchical configuration as described above. This method is based on making modifications on the **worker configuration file**, while you can still make modifications using the previous method using the **legacy configuration file**, both described below: + +.. contents:: + :local: + :depth: 1 + +Modifying Your Configuration Using the Worker Configuration File +------------------- +You can modify your configuration using the **worker configuration file (config.json)**. Changes that you make to worker configuration files are persistent. Note that you can only set the attributes in your worker configuration file **before** initializing your SQream worker, and while your worker is active these attributes are read-only. + +The following is an example of a worker configuration file: + +.. code-block:: postgres + + { + “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, + “gpu”: 0, + “licensePath”: “home/test_user/SQream/tests/license.enc”, + “machineIP”: “127.0.0.1”, + “metadataServerIp”: “127.0.0.1”, + “metadataServerPort”: “3105, + “port”: 5000, + “useConfigIP”” true, + “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” + } + +You can access the legacy configuration file from the ``legacyConfigFilePath`` parameter shown above. If all (or most) of your workers require the same flag settings, you can set the ``legacyConfigFilePath`` attribute to the same legacy file. + +Modifying Your Configuration Using a Legacy Configuration File +--------------------- +You can modify your configuration using a legacy configuration file. + +The Legacy configuration file provides access to the read/write flags used in SQream’s previous configuration method. A link to this file is provided in the **legacyConfigFilePath** parameter in the worker configuration file. + +The following is an example of the legacy configuration file: + +.. code-block:: postgres + + { + “developerMode”: true, + “reextentUse”: false, + “useClientLog”: true, + “useMetadataServer”” false + } +For more information on using the previous configuration method, see :ref:`previous_configuration_method`. \ No newline at end of file diff --git a/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst b/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst new file mode 100644 index 000000000..647a401b6 --- /dev/null +++ b/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst @@ -0,0 +1,21 @@ +.. _current_method_showing_all_flags_in_the_catalog_table: + +************************** +Showing All Flags in the Catalog Table +************************** +SQream uses the **sqream_catalog.parameters** catalog table for showing all flags, providing the scope (default, cluster and session), description, default value and actual value. + +The following is the correct syntax for a catalog table query: + +.. code-block:: console + + SELECT * FROM sqream_catalog.settings + +The following is an example of a catalog table query: + +.. code-block:: console + + externalTableBlobEstimate, 100, 100, default, + varcharEncoding, ascii, ascii, default, Changes the expected encoding for Varchar columns + useCrcForTextJoinKeys, true, true, default, + hiveStyleImplicitStringCasts, false, false, default, \ No newline at end of file diff --git a/configuration_guides/files_and_folders.txt b/configuration_guides/files_and_folders.txt new file mode 100644 index 000000000..0c8411b1b --- /dev/null +++ b/configuration_guides/files_and_folders.txt @@ -0,0 +1,67 @@ + Volume in drive C is Windows + Volume Serial Number is 565C-23BD + + Directory of C:\Users\Yaniv\Desktop\Local Reorganization Folder\configuration_guides + +03/22/2022 12:47 PM