在安装和运转Trino后,你首要学到了关于Trino中一流SQL支撑的核心特性,能够回到“SQL with Trino”中再次检查该内容,假如你需求一个概览或提示。

在第6章有关衔接器的内容中,你了解到在Trino中能够运用SQL查询许多数据源。

在这一章中,你将深化了解Trino的SQL支撑细节,包含一组用于创立和操作数据库方针(如方法、表、列和视图)的数据界说言语(DDL)句子。你将更具体地了解支撑的数据类型和SQL句子。在第9章,你将学习有关运算符和函数的更高档用法。

整体而言,这一章的方针不是作为SQL的参阅攻略,而是展现Trino中的SQL功用。有关Trino上SQL的最新和最完好信息,你能够参阅官方Trino文档。

Trino句子

在深化查询Trino中的数据之前,了解可用的数据、方位以及数据类型是十分重要的。Trino句子答应你收集这类信息以及更多。Trino句子查询体系表和有关已装备的目录、方法等的元数据信息。这些句子在一切SQL句子的相同上下文中作业。

句子中的FROM和FOR子句需求一个彻底限定的表、目录或方法的输入,除非运用USE设置了默许值。

能够运用LIKE子句来约束成果,它运用相似SQL LIKE指令的方法匹配语法。

以下是可用的Trino句子:

  • SHOW CATALOGS [ LIKE pattern ]:列出可用的目录。
  • SHOW SCHEMAS [ FROM catalog ] [ LIKE pattern ]:列出目录中的方法。
  • SHOW TABLES [ FROM schema ] [ LIKE pattern ]:列出方法中的表。
  • SHOW FUNCTIONS [ LIKE pattern ]:显现可用的SQL函数列表。
  • SHOW COLUMNS FROM tableDESCRIBE table:列出表中的列以及它们的数据类型和其他特点。
  • USE catalog.schemaUSE schema:将会话更新为运用指定的目录和方法作为默许值。假如未指定目录,则运用当时目录解析方法。
  • SHOW STATS FOR table_name:显现特定表中的数据巨细和计数等核算信息。
  • EXPLAIN query:生成查询方案并具体阐明指定SQL查询的各个步骤。

让咱们看一些在实践运用中或许会派上用场的示例:

SHOW SCHEMAS IN tpch LIKE '%3%';
 Schema
---------
 sf300
 sf3000
 sf30000
(3 rows)
DESCRIBE tpch.tiny.nation;
  Column   |     Type     | Extra | Comment
----------- -------------- ------- --------
 nationkey | bigint       |       |
 name      | varchar(25)  |       |
 regionkey | bigint       |       |
 comment   | varchar(152) |       |
(4 rows)

EXPLAIN句子实践上比前面列表中所示的更强壮。以下是完好的语法:

EXPLAIN [ ( option [, ...] ) ] <query>
    options: FORMAT { TEXT | GRAPHVIZ | JSON}
             TYPE { LOGICAL | DISTRIBUTED | IO | VALIDATE }

你能够运用EXPLAIN句子显现查询方案:

EXPLAIN
SELECT name FROM tpch.tiny.region;

查询方案的输出能够协助功用调优,更好地了解Trino将怎么处理你的查询。你能够在第4章和第12章中了解更多信息。

EXPLAIN的一个十分简略的用例是检查你的查询语法是否有用:

EXPLAIN (TYPE VALIDATE)
SELECT name FROM tpch.tiny.region;
 Valid
 ------
 true
(1 row)

Trino体系表

Trino体系表无需运用目录文件进行装备。一切方法和表都会主动在体系目录中可用。

您能够运用在“Trino Statements”中评论的句子查询方法和表,以了解有关运转中的Trino实例的更多信息。可用的信息包含有关运转时、节点、目录等的数据。检查可用的信息能够协助您更好地了解和在运转时运用Trino。

体系表包含以下方法:

SHOW SCHEMAS IN system;
       Schema
--------------------
 information_schema
 jdbc
 metadata
 runtime
(4 rows)

关于查询调优的意图,最有用的表之一是system.runtime.queriessystem.runtime.tasks

DESCRIBE system.runtime.queries;
      Column       |            Type             | Extra | Comment
------------------- ----------------------------- ------- ---------
 query_id          | varchar                     |       |
 state             | varchar                     |       |
 user              | varchar                     |       |
 source            | varchar                     |       |
 query             | varchar                     |       |
 resource_group_id | array(varchar)              |       |
 queued_time_ms    | bigint                      |       |
 analysis_time_ms  | bigint                      |       |
 planning_time_ms  | bigint                      |       |
 created           | timestamp(3) with time zone |       |
 started           | timestamp(3) with time zone |       |
 last_heartbeat    | timestamp(3) with time zone |       |
 end               | timestamp(3) with time zone |       |
 error_type        | varchar                     |       |
 error_code        | varchar                     |       |
(15 rows)
DESCRIBE system.runtime.tasks;
        Column          |            Type             | Extra | Comment
------------------------- ----------------------------- ------- ---------
 node_id                 | varchar                     |       |
 task_id                 | varchar                     |       |
 stage_id                | varchar                     |       |
 query_id                | varchar                     |       |
 state                   | varchar                     |       |
 splits                  | bigint                      |       |
 queued_splits           | bigint                      |       |
 running_splits          | bigint                      |       |
 completed_splits        | bigint                      |       |
 split_scheduled_time_ms | bigint                      |       |
 split_cpu_time_ms       | bigint                      |       |
 split_blocked_time_ms   | bigint                      |       |
 raw_input_bytes         | bigint                      |       |
 raw_input_rows          | bigint                      |       |
 processed_input_bytes   | bigint                      |       |
 processed_input_rows    | bigint                      |       |
 output_bytes            | bigint                      |       |
 output_rows             | bigint                      |       |
 physical_input_bytes    | bigint                      |       |
 physical_written_bytes  | bigint                      |       |
 created                 | timestamp(3) with time zone |       |
 start                   | timestamp(3) with time zone |       |
 last_heartbeat          | timestamp(3) with time zone |       |
 end                     | timestamp(3) with time zone |       |
(24 rows)

上述表的描绘展现了在“运用Trino Web UI监控”中更具体解说的底层数据。system.runtime.queries表供给有关Trino中履行的当时和曩昔查询的信息。system.runtime.tasks表为Trino中的使命供给了更底层的具体信息。这相似于Trino Web UI的查询详情页面上的信息输出。

以下是从体系表查询的一些有用示例。

列出Trino集群中的节点:

SELECT * FROM system.runtime.nodes;

显现一切失利的查询:

SELECT * FROM system.runtime.queries WHERE state='FAILED';

显现一切运转中的查询,包含它们的query_id:

SELECT * FROM system.runtime.queries WHERE state='RUNNING';

体系表还供给了一种经过QUERY_ID停止正在运转的查询的机制:

CALL system.runtime.kill_query(query_id => 'QUERY_ID', message => 'Killed');

除了有关Trino在运转时、集群、作业节点等的一切信息外,Trino衔接器还能够揭露有关衔接的数据源的体系数据。例如,在“面向分布式存储数据源的Hive衔接器”中评论的Hive衔接器能够装备为datalake目录中的衔接器。它会主动在体系表中揭露有关Hive的数据:

SHOW TABLES FROM datalake.system;

这些信息包含已运用的分区等方面。

Catalogs

Trino目录表明运用衔接器装备的目录特点文件的数据源,如第6章所评论的。目录包含一个或多个方法,它们供给了一组表的调集。

例如,您能够装备一个目录以拜访PostgreSQL上的联系型数据库。或许,您能够装备一个目录以经过JMX衔接器供给对JMX信息的拜访。其他目录的示例包含运用Iceberg衔接器的目录,以Iceberg表格局衔接到方针存储数据源,或许装备为拜访实时分布式OLAP数据存储的Pinot衔接器。当在Trino中运转SQL句子时,您是针对一个或多个目录运转它。

能够运用相同的衔接器具有多个目录。例如,您能够创立两个独立的目录来揭露运转在同一服务器上的两个PostgreSQL数据库。

在Trino中引证表时,彻底限定的表名一直以目录为根。例如,彻底限定的表名datalake.test_data.test指的是datalake目录中test_data方法中的test表。该目录能够运用任何衔接器。因而,关于用户来说,底层体系大部分都是笼统的。

您能够经过拜访体系数据来检查Trino服务器中可用的目录列表:

SHOW CATALOGS;
 Catalog
 ---------
 abyss
 datalake
 monitor
 salesdb
 stream
 system
(6 rows)

假如您想知道目录中运用的衔接器是什么,您需求查询体系目录:

SELECT *
FROM system.metadata.catalogs
WHERE catalog_name='brain';
 catalog_name | connector_id | connector_name
-------------- -------------- ----------------
 brain        | brain        | memory
(1 row)

目录、方法和表的信息不会被Trino存储;Trino没有自己的永久存储体系。这是衔接器的责任,它要向Trino供给此信息。一般,这是经过从底层数据库查询目录、与方针存储别离的元数据存储,或衔接器中的其他装备来完结的。衔接器处理此过程,仅在恳求时向Trino供给信息。

Schemas

在一个目录中,Trino包含方法。方法包含表、视图和各种其他方针,是安排表的一种办法。目录和方法一起界说了能够查询的一组表。

当运用Trino拜访联系型数据库(如PostgreSQL)时,一个方法在方针数据库中对应于相同的概念。其他类型的衔接器或许会挑选以适合底层数据源的办法将表安排到方法中。衔接器的完成决定了方法在目录中的映射办法。例如,关于Hive衔接器,在Trino中将Hive中的数据库露出为一个方法。

一般,在装备目录时,方法现已存在。可是,Trino也答应创立和对方法进行其他操作。

让咱们看一下创立方法的SQL句子:

CREATE SCHEMA [ IF NOT EXISTS ] schema_name
[ WITH ( property_name = expression [, ...] ) ]

WITH子句可用于将特点与方法相关。例如,关于Hive衔接器,创立方法实践上会在Hive中创立一个数据库。有时,希望掩盖hive.metastore.warehouse.dir指定的数据库的默许方位:

CREATE SCHEMA datalake.web
WITH (location = 's3://example-org/web/')

请参阅最新的Trino文档以获取方法特点列表,或在Trino中查询装备的特点列表:

SELECT * FROM system.metadata.schema_properties;
-[ RECORD 1 ]- ------------------------------
catalog_name  | datalake
property_name | location
default_value |
type          | varchar
description   | Base file system location URI

您能够更改现有方法的称号:

ALTER SCHEMA name RENAME TO new_name

还支撑删去方法:

DROP SCHEMA [ IF EXISTS ] schema_name

在删去方法之前,您需求删去其间的表。一些数据库体系支撑CASCADE关键字,该关键字表明DROP句子会删去方针(如方法)中的一切内容。在当时阶段,Trino不支撑CASCADE。

Information Schema

信息方法是SQL规范的一部分,在Trino中作为一组视图的方法供给关于目录中的方法、表、列、视图和其他方针的元数据。这些视图包含在一个名为information_schema的方法中。每个Trino目录都有自己的information_schema。比如SHOW TABLES、SHOW SCHEMA等指令是获取与information_schema中相同信息的简写。

information_schema关于运用比如商业智能东西之类的第三方东西是至关重要的。许多这些东西会查询information_schema,以了解存在哪些方针。

information_schema有九个总的视图。这些在每个衔接器中都是相同的。关于一些不支撑某些功用的衔接器(例如,人物),对该衔接器中information_schema的查询或许会导致不支撑的过错:

SHOW TABLES IN system.information_schema;
             Table
--------------------------------
 applicable_roles
 columns
 enabled_roles
 role_authorization_descriptors
 roles
 schemata
 table_privileges
 tables
 views
(9 rows)

您能够查询方法中的表列表。请留意,information_schema表也会回来:

SELECT * FROM datalake.information_schema.tables;
 table_catalog |    table_schema    |    table_name    | table_type
 --------------- -------------------- ------------------ ----------
 datalake      | web                | nation           | BASE TABLE
 datalake      | information_schema | enabled_roles    | BASE TABLE
 datalake      | information_schema | roles            | BASE TABLE
 datalake      | information_schema | columns          | BASE TABLE
 datalake      | information_schema | tables           | BASE TABLE
 datalake      | information_schema | views            | BASE TABLE
 datalake      | information_schema | applicable_roles | BASE TABLE
 datalake      | information_schema | table_privileges | BASE TABLE
 datalake      | information_schema | schemata         | BASE TABLE
(9 rows)

此外,您能够经过在这些查询中运用WHERE子句检查特定表的列:

SELECT table_catalog, table_schema, table_name, column_name
FROM datalake.information_schema.columns
WHERE table_name = 'nation';
 table_catalog |    table_schema    |    table_name    |  column_name
--------------- -------------------- ------------------ -------------
 datalake      | web                | nation           | regionkey
 datalake      | web                | nation           | comment
 datalake      | web                | nation           | nationkey
 datalake      | web                | nation           | name
...

现在您了解了目录和方法,让咱们了解一下Trino中的表界说。表是一组无序的行,这些行以具有特定数据类型的命名列进行安排。这与任何联系数据库中的状况相同,其间表由行、列和这些列的数据类型组成。从源数据到表的映射是由目录界说的。

衔接器完成确定了怎么将表映射到方法。例如,将PostgreSQL表露出给Trino一般是比较直接的,由于PostgreSQL本地支撑SQL和表的概念。唯一的区别一般在于可用和运用的数据类型方面。可是,关于其他体系的衔接器的完成需求更多的创意,特别是假如它们在规划上缺少严厉的表概念。例如,Apache Kafka衔接器将Kafka主题露出为Trino中的表。

在SQL查询中经过运用彻底合格的称号(例如,catalog-name.schema-name.table-name)拜访表。

让咱们看一下在Trino中创立表的CREATE TABLE句子:

CREATE TABLE [ IF NOT EXISTS ]
table_name (
  { column_name data_type [ COMMENT comment ]
  [ WITH ( property_name = expression [, ...] ) ]
  | LIKE existing_table_name [ { INCLUDING | EXCLUDING } PROPERTIES ] }
  [, ...]
)
[ COMMENT table_comment ]
[ WITH ( property_name = expression [, ...] ) ]

假如您了解SQL,这个通用语法应该很熟悉。在Trino中,可选的WITH子句具有重要的用处。其他体系(例如Hive)现已扩展了SQL言语,以便用户能够指定在规范SQL中无法表达的逻辑或数据。选用这种办法违反了Trino的根本理念,即尽或许接近SQL规范。这也使得支撑许多衔接器变得难以办理,因而现已被替换为运用WITH子句运用表和列特点。

创立表后,您能够运用规范SQL中的INSERT INTO句子。例如,在iris数据集创立脚本中,首要创立了一个表;拜见“Iris数据集”。然后直接从查询中刺进值:

CREATE TABLE iris (
  sepal_length_cm real,
  sepal_width_cm real,
  petal_length_cm real,
  petal_width_cm real,
  species varchar(10)
);
INSERT INTO iris (
  sepal_length_cm,
  sepal_width_cm,
  petal_length_cm,
  petal_width_cm,
  species )
VALUES
  ( ... )

假如数据经过独自的查询可用,能够运用SELECT和INSERT。例如,您想要将内存目录中的数据仿制到PostgreSQL中的现有表:

INSERT INTO postgresql.flowers.iris
SELECT * FROM brain.default.iris;

假如方针目录中尚不存在表,则能够运用CREATE TABLE AS SELECT语法。这一般被称为CTAS查询:

CREATE TABLE postgresql.flowers.iris AS
SELECT * FROM brain.default.iris;

SELECT句子能够包含条件和句子支撑的任何其他特性。

表和列特点

让咱们经过运用“Hive Connector for Distributed Storage Data Sources”(拜见表8-1)中的Hive衔接器来学习怎么运用WITH子句创立表。

《Trino威望攻略》第八章:在Trino中运用SQL

运用表8-1中的特点,让咱们运用Trino在Hive中创立与Hive中创立表相同的表。

首要运用Hive语法:

CREATE EXTERNAL TABLE page_views(
  view_time INT,
  user_id BIGINT,
  page_url STRING,
  view_date DATE,
  country STRING)
 STORED AS ORC
 LOCATION 's3://example-org/web/page_views/';

与在Trino中运用SQL进行比较:

CREATE TABLE datalake.web.page_views(
  view_time timestamp,
  user_id BIGINT,
  page_url VARCHAR,
  view_date DATE,
  country VARCHAR
)
WITH (
  format = 'ORC',
  external_location = 's3://example-org/web/page_views'
);

正如您所见,Hive DDL已扩展了SQL规范。可是,Trino运用相同意图的特点,因而遵从SQL规范。

您能够查询Trino的体系元数据以列出装备的表特点:

SELECT * FROM system.metadata.table_properties;

要列出装备的列特点,能够运转以下查询:

SELECT * FROM system.metadata.column_properties;

仿制现有表

您能够经过运用现有表作为模板来创立新表。LIKE子句创立具有与现有表相同列界说的表。默许状况下,不会仿制表和列特点。由于特点在Trino中很重要,咱们建议在语法中运用INCLUDING PROPERTIES 以便将它们一起仿制。在运用Trino履行数据转化时,此功用十分有用:

CREATE TABLE datalake.web.page_view_bucketed(
  comment VARCHAR,
  LIKE datalake.web.page_views INCLUDING PROPERTIES
)
WITH (
  bucketed_by = ARRAY['user_id'],
  bucket_count = 50
)

运用SHOW句子检查新创立的表界说:

SHOW CREATE TABLE datalake.web.page_view_bucketed;

创立的表界说与原始表进行比较:

SHOW CREATE TABLE datalake.web2.page_views;

从查询成果创立新表

运用CREATE TABLE AS SELECT(CTAS)句子能够创立一个新表,其间包含SELECT查询的成果。表的列界说是经过动态检查查询的成果列数据而创立的。该句子可用于创立临时表或作为创立转化表的过程的一部分:

CREATE TABLE [ IF NOT EXISTS ] table_name [ ( column_alias, ... ) ]
[ COMMENT table_comment ]
[ WITH ( property_name = expression [, ...] ) ]
AS query
[ WITH [ NO ] DATA ]

默许状况下,新表将运用查询的成果数据填充。

CTAS可用于转化表和数据。实质上,您正在运用Trino进行ETL作业负载,能够在一个目录或乃至在不同目录之间,也就是不同的数据源之间进行,如“提取、转化、加载和联合查询”中所评论的。例如,您能够将TEXTFILE格局的未分区数据加载到具有ORC格局数据的新分区表中:

CREATE TABLE datalake.web.page_views_orc_part
WITH (
   format = 'ORC',
   partitioned_by = ARRAY['view_date','country']
)
AS
SELECT *
FROM datalake.web.page_view_text

下一个示例展现了从page_views表的成果会话化查询中创立表:

CREATE TABLE datalake.web.user_sessions
AS
SELECT user_id,
       view_time,
       sum(session_boundary)
         OVER (
           PARTITION BY user_id
           ORDER BY view_time) AS session_id
FROM (SELECT user_id,
             view_time,
             CASE
                WHEN to_unixtime(view_time) -
                     lag(to_unixtime(view_time), 1)
                        OVER(
                           PARTITION BY user_id
                           ORDER BY view_time) >= 30
             THEN 1
             ELSE 0
             END AS session_boundary
      FROM page_views) T
ORDER BY user_id,
         session_id

修正表

ALTER TABLE句子能够履行比如重命名表、增加列、删去列或在表中重命名列等操作:

ALTER TABLE name RENAME TO new_name
ALTER TABLE name ADD COLUMN column_name data_type
  [ COMMENT comment ] [ WITH ( property_name = expression [, ...] ) ]
ALTER TABLE name DROP COLUMN column_name
ALTER TABLE name RENAME COLUMN column_name TO new_column_name

需求留意的是,依据衔接器和衔接器的授权模型,运用默许行为时或许不答应履行这些操作。例如,Hive衔接器默许状况下约束了这些操作。

删去表

运用DROP TABLE句子,您能够删去一个表:

DROP TABLE  [ IF EXISTS ] table_name

依据衔接器完成的不同,这或许会或或许不会删去底层数据。您应该参阅衔接器文档以获取更多解说。 在某些状况下,您或许只想删去表中的数据,一起保存表自身以便增加新数据。Trino支撑TRUNCATE TABLE来完成这个意图:

TRUNCATE TABLE table_name

关于不支撑TRUNCATE的衔接器,您有必要运用DROP TABLE,然后再运用CREATE TABLE。

衔接器中对表的约束

在本章中,咱们现已评论了Trino支撑的各种SQL句子。可是,并不是说Trino中的每个数据源都支撑一切句子和语法或许性,或供给相同的语义。

衔接器的完成以及底层数据源的才能和语义对这些或许性有很大的影响。

假如测验运用特定衔接器不支撑的句子或操作,Trino将回来一个过错。例如,体系方法和表用于揭露有关Trino体系的信息。它不支撑创立表,由于关于内部体系数据表来说,这根本没有意义。假如测验创立表,您将收到一个过错:

CREATE TABLE system.runtime.foo(a int);

查询失利:此衔接器不支撑创立表

假如运用不支撑写操作的衔接器刺进数据,或许在不支撑视图的衔接器中创立视图或资料化视图等,将显现相似的过错。请查阅每个衔接器文档中的SQL支撑部分,了解衔接器支撑的句子的具体信息。

视图

视图是依据SQL查询成果集的虚拟表。在许多联系型数据库办理体系中,对视图的支撑十分好。可是,在Trino中,状况更为杂乱。

Trino将来自底层数据源的视图视为表。这使您能够将视图用于一些十分有用的意图:

  • 在更易于消费的视图中揭露来自多个表的数据
  • 经过具有受约束的列和/或行的视图来约束可用的数据
  • 方便地供给经过处理、转化的数据

此功用依赖于在衔接的数据源中创立和办理这些视图的支撑。运用视图主动要求底层数据源彻底具有视图中的数据,因而需求进行创立视图和坚持其更新的处理。因而,运用视图能够使您在几个步骤内将查询的处理推送到联系型数据库办理体系:

  1. 发现在Trino上运转的表数据上的SQL查询存在功用问题。
  2. 经过检查履行的EXPLAIN方案来对体系进行毛病扫除。
  3. 意识到特定子查询导致功用瓶颈。
  4. 创立预处理子查询的视图。
  5. 在SQL查询中运用该视图,替换表。
  6. 享用功用的好处。

Trino还支撑在Trino自身创立视图。在Trino中,视图仅仅界说视图的SQL句子和视图的称号。要在Trino中创立和运用视图,您需求一个运用Hive衔接器或任何其他装备Hive元数据存储服务或相似元数据存储体系的衔接器的目录。这是必要的,由于Trino自身没有任何集成的元数据存储。界说视图中的数据的SQL查询能够拜访任何目录,乃至多个目录。视图是在包含元数据存储的目录中创立和运用的,即使界说视图的查询拜访不同的目录。

当用户查询视图时,界说从元数据存储加载,并运转界说视图的SQL查询,就好像用户提交了实践查询。这答应用户创立更简略的查询,一起拜访潜在的许多目录、方法、表和特定列,并躲藏查询的一切杂乱性。

资料化视图是更强壮的功用,由Iceberg衔接器支撑。资料化视图是一个具有缓存数据的视图。在首次创立时,有必要运转界说资料化视图的SQL句子,以便获取数据并存储在独自的表中。随后的查询能够直接拜访缓存的数据,因而查询速度或许要快得多。对底层数据进行任何更改的副作用是,有必要定期改写资料化视图。

另一种特殊状况是Hive视图。这些是来自传统Hive体系的视图,以Hive查询言语编写。这些Hive视图也存储在Hive元数据存储中。乍一看,Hive查询言语与SQL十分相似。可是,由于存在差异,Hive视图无法直接解析和履行为SQL句子。可是,Trino用户能够运用Hive衔接器以及内置的转化库Coral来运用这些视图。

整体而言,能够看出视图能够显着改善拜访杂乱数据的便利性,而且在Trino中是一个得到很好支撑的功用。

会话信息和装备

在运用Trino时,一切装备都在一个称为会话的用户特定上下文中保护。该会话包含表明用于当时用户与Trino交互的许多方面装备的键值对。

您能够运用SQL指令与该信息进行交互。首要,您能够检查当时装备,乃至运用LIKE方法缩小您感兴趣的选项:

SHOW SESSION LIKE 'query%';

此查询回来有关许多特点的信息,例如query_max_cpu_time、query_max_execution_time、query_max_planning_time,包含当时值、默许值、数据类型(整数、布尔值或varchar)以及特点的扼要描绘。

特点列表很长,包含Trino行为的许多装备选项,例如查询的内存和CPU约束、查询方案算法以及依据本钱的优化器的运用。

作为用户,您能够更改这些特点,然后影响当时用户会话的功用。您能够为特定的查询或作业负载设置特定的选项,或许将它们测验为用于集群的主文件为根底的Trino装备文件(由集群运用的config.properties)的全局推出。

例如,您能够激活运用共位衔接的查询规划的实验性算法:

SET SESSION colocated_join = true;

您能够确认该设置是否有用:

SHOW SESSION LIKE 'colocated_join';

吊销设置并回来默许值,您能够重置会话特点:

RESET SESSION colocated_join;

除了全局会话特点之外,一些目录装备特点能够修正为特定的用户会话。例如,PostgreSQL衔接器支撑特点unsupported-type-handling。它默许为IGNORE,因而将省掉具有不受支撑的数据类型的列的数据。

此特点还可用作目录会话特点,名为unsupported_type_handling。请留意,与目录装备特点相比,目录会话特点运用相似的称号,用下划线替换破折号。您能够运用此特点更改crm目录和会话的列处理,并运用以下查询将数据转化为VARCHAR:

SET SESSION crm.unsupported_type_handling='CONVERT_TO_VARCHAR';

现在,数据不再被忽略,而是在Trino查询中作为字符串可用,您能够运用各种字符串、日期、JSON和其他格局相关特点修正数据,乃至将其转化为所需的Trino数据类型。

数据类型

Trino支撑SQL规范中描绘的大多数数据类型,这些类型也得到许多联系数据库的支撑。在本节中,咱们评论了Trino中的数据类型支撑。

并非一切的Trino衔接器都支撑一切的Trino数据类型。而且Trino或许不支撑底层数据源的一切类型。数据类型是如安在底层数据源和Trino之间进行转化的,这取决于衔接器的完成。底层数据源或许不支撑相同的类型,或许相同的类型或许具有不同的命名。例如,MySQL衔接器将Trino的REAL类型映射到MySQL的FLOAT类型。

在某些状况下,数据类型需求进行转化。一些衔接器将不受支撑的类型转化为Trino的VARCHAR类型,根本上是源数据的字符串表明,或许彻底忽略读取该列。有关每个衔接器文档和源代码中类型映射部分的具体具体信息,请参阅。

回到彻底支撑的数据类型的长列表。表8-2到表8-6描绘了Trino中的数据类型,并在适用的状况下供给了示例数据。

《Trino威望攻略》第八章:在Trino中运用SQL

与VARCHAR不同,CHAR一直分配n个字符。以下是一些您应该了解的特性和过错:

  • 假如将具有少于n个字符的字符字符串转化,将增加尾随空格。
  • 假如将具有多于n个字符的字符字符串转化,它将被截断而不会犯错。
  • 假如将长度超过列界说的VARCHAR或CHAR刺进到表中,将产生过错。
  • 假如将长度短于在列中界说的CHAR刺进到表中,该值将填充空格以匹配界说的长度。
  • 假如将长度短于在列中界说的VARCHAR刺进到表中,将存储字符串的切当长度。在比较CHAR值时,包含前导和尾随空格。

以下示例突显了这些行为:

SELECT length(cast('hello world' AS char(100)));
-- 成果:
-- _col0
-- -----
-- 100
SELECT cast('hello world' AS char(15)) || '~';
-- 成果:
-- _col0
-- ----------------
-- hello world    ~
SELECT cast('hello world' AS char(5));
-- 成果:
-- _col0
-- -------
-- hello
SELECT length(cast('hello world' AS varchar(15)));
-- 成果:
-- _col0
-- -------
-- 11
SELECT cast('hello world' AS varchar(15)) || '~';
-- 成果:
-- _col0
-- --------------
-- hello world~
SELECT cast('hello world' as char(15)) = cast('hello world' as char(14));
-- 成果:
-- _col0
-- -------
-- true
SELECT cast('hello world' as varchar(15)) = cast('hello world' as varchar(14));
-- 成果:
-- _col0
-- -------
-- true
USE brain.default;
CREATE TABLE varchars(col varchar(5));
-- 创立表
INSERT INTO varchars values('1234');
-- 刺进值
INSERT INTO varchars values('123456');
-- 过错:在INSERT期间,将varchar(6)转化为varchar(5)时无法截断非空格字符

调集数据类型

随着数据变得越来越庞大和杂乱,有时它会以更杂乱的数据类型(例如数组和映射)的方法存储。许多联系数据库办理体系(RDBMS)以及一些NoSQL体系自身就原生支撑杂乱数据类型。Trino支撑其间一些调集数据类型,详见表8-7。它还供给了对”Unnesting Complex Data Types”(解构杂乱数据类型)中具体阐明的UNNEST操作的支撑。

《Trino威望攻略》第八章:在Trino中运用SQL

时间数据类型

表格8-8描绘了与日期和时间相关的时间数据类型。

《Trino威望攻略》第八章:在Trino中运用SQL

在Trino中,TIMESTAMP表明为Java Instant类型,表明距离Java纪元之前或之后的时间量。关于最终用户来说,这应该是透明的,由于值会以不同的格局解析和显现。

关于不包含时区信息的类型,值将依据Trino会话时区进行解析和显现。关于包含时区信息的类型,值将运用时区进行解析和显现。

字符串文字能够由Trino解析为TIMESTAMP、TIMESTAMP WITH TIMEZONE、TIME、TIME WITH TIMEZONE或DATE。表8-9到8-11描绘了可用于解析的格局。假如要运用ISO 8601,能够运用from_iso8601_timestamp或from_iso8601_date函数。

《Trino威望攻略》第八章:在Trino中运用SQL

在打印TIMESTAMP、TIMESTAMP WITH TIMEZONE、TIME、TIME WITH TIMEZONE或DATE的输出时,Trino运用表8-12中的输出格局。假如要以严厉的ISO 8601格局输出,能够运用to_iso8601函数。

《Trino威望攻略》第八章:在Trino中运用SQL

时区

时区增加了重要的额外时间信息。Trino支撑TIME WITH TIMEZONE,但最好运用带有DATE或TIMESTAMP的时区。这能够经过DATE格局来考虑夏令时。时区有必要表明为数值UTC偏移值:

08:00 -10:00

让咱们看一些比如:

SELECT TIME '02:56:15' AS utc;
   utc
 ---------
 02:56:15
(1 row)
SELECT TIME '02:56:15' AT TIME ZONE ' 08:00' AS perth_time;
   perth_time
 ---------------
 17:56:15 08:00
SELECT TIME '02:56:15' AT TIME ZONE '-08:00' AS sf_time;
    sf_time
 ---------------
 01:56:15-08:00
(1 row)
SELECT TIMESTAMP '1983-10-19 07:30:05.123456';
           _col0
 ---------------------------
 1983-10-19 07:30:05.123456
(1 row)
SELECT TIMESTAMP '1983-10-19 17:30:05.123456' AT TIME ZONE '-08:00';
            _col0
 ----------------------------
 1983-10-19 06:30:05.123456 -08:00
(1 row)

距离(Intervals)

数据类型 INTERVAL 能够是 YEAR TO MONTH 或 DAY TO SECOND,如表 8-13 和 8-14 所示。

《Trino威望攻略》第八章:在Trino中运用SQL

以下示例突出了咱们描绘的一些行为:

SELECT INTERVAL '1-2' YEAR TO MONTH;
 _col0
 ------
 1-2
(1 row)
SELECT INTERVAL '4' MONTH;
 _col0
 -------
 0-4
(1 row)
SELECT INTERVAL '4-1' DAY TO SECOND;
Query xyz failed: '4-1' is not a valid interval literal
SELECT INTERVAL '4' DAY TO SECOND;
     _col0
 ----------------
 4 00:00:00.000
(1 row)
SELECT INTERVAL '4 01:03:05.44' DAY TO SECOND;
     _col0
 ----------------
 4 01:03:05.440
(1 row)
SELECT INTERVAL '05.44' SECOND;
     _col0
 ----------------
 0 00:00:05.440
(1 row)

类型转化

有时需求明确地将值或文字转化为不同的数据类型。这称为类型转化,能够运用CAST函数履行:

CAST(value AS type)

现在假定您需求将列view_date与数据类型DATE与日期2019-01-01进行比较,这是一个文字字符串:

SELECT *
FROM datalake.web.page_views
WHERE view_date > '2019-01-01';

此查询失利,由于Trino没有一个能够比较日期和字符串文字的大于(>)比较运算符。可是,它有一个比较函数,知道怎么比较两个日期。因而,咱们需求运用CAST函数强制转化其间一个类型。在这个比如中,将字符串转化为日期是最合理的:

SELECT *
FROM datalake.web.page_views
WHERE view_date > CAST('2019-01-01' AS DATE);

Trino还供给了另一个转化函数try_cast。它测验履行类型强制转化,但与CAST不同,假如转化失利,则try_cast回来一个空值。当不需求过错时,这或许很有用:

try_cast(value AS type)

让咱们以将字符文字强制转化为数字类型为例:

SELECT CAST('1' AS INTEGER);
_col0
-------
     1
(1 row)
SELECT CAST('a' AS INTEGER);
Query failed: Cannot cast 'a' to INT
SELECT TRY_CAST('a' AS INTEGER);
_col0
------
 NULL
(1 row)

SELECT句子根底常识

SELECT句子至关重要,由于它答应你以表格格局从一个或多个表中回来数据,最少能够减少到一行,或许潜在地仅回来一个值。 在Trino中,带有多个不同目录和方法的表,即彻底不同的数据源,会使SELECT查询具有额外的杂乱性,你在“Trino中的查询联邦”中学到了这一点。 现在,让咱们深化了解并学习一切可用的强壮功用。让咱们从语法概述开始:

[ WITH with_query [, ...] ]
SELECT [ ALL | DISTINCT ] select_expr [, ...]
[ FROM from_item [, ...] ]
[ WHERE condition ]
[ GROUP BY [ ALL | DISTINCT ] grouping_element [, ...] ]
[ HAVING condition]
[ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] select ]
[ ORDER BY expression [ ASC | DESC ] [, ...] ]
[ LIMIT [ count | ALL ] ]

select_expr代表以表列、派生表列、常量或零行、一行或多行的方法回来的查询数据。通用表达式能够包含函数、运算符、列和常量。你能够运转一个只要SELECT select_expr的查询,用于测验,但其用处有限:

SELECT 1, 1 1, upper('lower');
 _col0 | _col1 | _col2
------- ------- ------
     1 |     2 | LOWER
(1 row)

SELECT select_expr [, ...] FROM from_item是查询的最根本方法。它答应你从底层表中检索一切数据或仅挑选的列。它还答应你在底层数据上核算表达式。 假定咱们有两个表,也称为联系,nation和customer。这些示例取自TPC-H,详见“Trino TPC-H和TPC-DS Connectors”。为简练起见,示例表被截短为仅有几行和几列。咱们在整个本章的多个挑选查询示例中运用这些数据。 你能够回来sf1方法中nation表的挑选列和数据:

SELECT nationkey, name, regionkey
FROM tpch.sf1.nation;
 nationkey |      name      | regionkey
----------- ---------------- -----------
         0 | ALGERIA        |         0
         1 | ARGENTINA      |         1
         2 | BRAZIL         |         1
         3 | CANADA         |         1
         4 | EGYPT          |         4
         5 | ETHIOPIA       |         0
...

现在是customer表的一些示例数据:

SELECT custkey, nationkey, phone, acctbal, mktsegment
FROM tpch.tiny.customer;
 custkey | nationkey |      phone      | acctbal | mktsegment
--------- ----------- ----------------- --------- ------------
     751 |         0 | 10-658-550-2257 | 2130.98 | FURNITURE
     752 |         8 | 18-924-993-6038 | 8363.66 | MACHINERY
     753 |        17 | 27-817-126-3646 | 8114.44 | HOUSEHOLD
     754 |         0 | 10-646-595-5871 | -566.86 | BUILDING
     755 |        16 | 26-395-247-2207 | 7631.94 | HOUSEHOLD
...

除了仅回来挑选数据外,咱们还能够运用函数转化数据并回来成果:

SELECT acctbal, round(acctbal) FROM tpch.sf1.customer;
 acctbal | _col1
--------- --------
 7470.96 | 7471.0
 8462.17 | 8462.0
 2757.45 | 2757.0
 -588.38 | -588.0
 9091.82 | 9092.0
...

where条件

WHERE子句在SELECT查询顶用作过滤器。它包含一个评价为TRUE、FALSE或UNKNOWN的条件。在查询履行过程中,该条件针对每一行进行评价。假如评价成果不等于TRUE,该行将被越过并从成果会集省掉。否则,该行将被宣布并作为成果的一部分发送给用户或用于进一步处理。

WHERE子句条件由一个或多个布尔表达式组成,这些表达式由衔接性的AND和OR衔接:

SELECT custkey, acctbal
FROM tpch.sf1.customer WHERE acctbal < 0;
 custkey | acctbal
--------- ---------
   75016 | -735.89
   75027 | -399.78
   75028 | -222.92
   75034 | -679.38
   75037 | -660.07
...
SELECT custkey, acctbal FROM tpch.sf1.customer
WHERE acctbal > 0 AND acctbal < 500;
 custkey | acctbal
--------- ---------
   75011 |  165.71
   75012 |   41.65
   75021 |   176.2
   75022 |  348.24
   75026 |   78.64
...

WHERE子句条件很重要,由于它用于多个查询优化。在“查询方案”中,你能够了解有关查询方案和优化的更多信息。当查询多个表时,能够经过WHERE子句中的条件将它们衔接起来。Trino运用此信息来确定高效的查询履行方案。

GROUP BY 和 HAVING 条件

GROUP BY和HAVING子句一般在剖析查询中运用。GROUP BY用于将相同值的行合并为一行:

SELECT mktsegment
FROM tpch.sf1.customer
GROUP BY mktsegment;
 mktsegment
 -----------
 MACHINERY
 AUTOMOBILE
 HOUSEHOLD
 BUILDING
 FURNITURE
(5 rows)

在Trino中的剖析查询中,GROUP BY一般与聚合函数结合运用。这些函数是从构成单个组的行中核算的。以下查询核算一切客户的总账户余额,按商场细分进行拆分:

SELECT mktsegment, round(sum(acctbal) / 1000000, 3) AS acctbal_millions
FROM tpch.sf1.customer
GROUP BY mktsegment;
 mktsegment | acctbal_millions
------------ ------------------
 MACHINERY  |          134.439
 AUTOMOBILE |          133.867
 BUILDING   |          135.889
 FURNITURE  |          134.259
 HOUSEHOLD  |          135.873

聚合函数也能够在没有运用GROUP BY子句的状况下运用。在这种状况下,整个联系作为聚合函数的输入,因而咱们能够核算整体账户余额:

SELECT round(sum(acctbal) / 1000000, 3) AS acctbal_millions
FROM tpch.sf1.customer;
 acctbal_millions
------------------
          674.327

HAVING子句相似于WHERE子句。它对每一行进行评价,仅当条件评价为TRUE时才宣布行。HAVING子句在GROUP BY之后进行评价并在分组的行上操作。WHERE子句在GROUP BY之前进行评价并在单个行上评价。

以下是完好的查询:

SELECT mktsegment,
      round(sum(acctbal), 1) AS acctbal_per_mktsegment
FROM tpch.tiny.customer
GROUP BY mktsegment;
 mktsegment | acctbal_per_mktsegment
------------ ------------------------
 BUILDING   |              1444587.8
 HOUSEHOLD  |              1279340.7
 AUTOMOBILE |              1395695.7
 FURNITURE  |              1265282.8
 MACHINERY  |              1296958.6
(5 rows)

这是在分组数据上运用条件的过滤成果:

 SELECT mktsegment,
       round(sum(acctbal), 1) AS acctbal_per_mktsegment
FROM tpch.tiny.customer
GROUP BY mktsegment
HAVING round(sum(acctbal), 1) > 1300000;
 mktsegment | acctbal_per_mktsegment
------------ ------------------------
 AUTOMOBILE |              1395695.7
 BUILDING   |              1444587.8
(2 rows)

ORDER BY 和 LIMIT 条件

ORDER BY子句包含用于对成果进行排序的表达式。该子句能够包含多个表达式,从左到右进行评价。一般在左侧表达式关于多行的状况下具有相同值时,会运用多个表达式来解决排名的问题。这些表达式能够指示排序顺序,能够是升序(例如,A-Z,1-100)或降序(例如,Z-A,100-1)。

LIMIT子句用于仅回来指定数量的行。与ORDER BY子句一起运用,LIMIT可用于查找有序集的前N个成果:

SELECT mktsegment,
       round(sum(acctbal), 2) AS acctbal_per_mktsegment
FROM tpch.sf1.customer
GROUP BY mktsegment
HAVING sum(acctbal) > 0
ORDER BY acctbal_per_mktsegment DESC
LIMIT 3;
 mktsegment | acctbal_per_mktsegment
 ----------- ------------------------
 BUILDING   |         1.3588862194E8
 HOUSEHOLD  |         1.3587334117E8
 MACHINERY  |         1.3443886167E8
(3 rows)

一般,Trino能够将履行ORDER BY和LIMIT作为一个组合步骤而不是分开履行。

能够在没有ORDER BY子句的状况下运用LIMIT,但它们一般一起运用。原因是SQL规范,因而也是Trino,不保证成果的任何顺序。这意味着在没有ORDER BY子句的状况下运用LIMIT或许会在每次运转相同查询时回来不同的非确定性成果。在Trino这样的分布式体系中,这变得更加显着。

JOIN句子

SQL答应你运用JOIN句子将来自不同表的数据组合在一起。Trino支撑SQL规范的衔接,如INNER JOIN、LEFT OUTER JOIN、RIGHT OUTER JOIN、FULL OUTER JOIN和CROSS JOIN。JOIN句子的全面讨论超出了本书的范围,但在许多其他书本中有具体介绍。

让咱们专注于一些比如,并讨论与Trino相关的特定细节:

SELECT custkey, mktsegment, nation.name AS nation
FROM tpch.tiny.nation JOIN tpch.tiny.customer
ON nation.nationkey = customer.nationkey;
 custkey | mktsegment |     nation
 -------- ------------ ----------------
     745 | FURNITURE  | CHINA
     746 | MACHINERY  | SAUDI ARABIA
     747 | FURNITURE  | INDIA
     748 | AUTOMOBILE | UNITED KINGDOM
     749 | MACHINERY  | UNITED STATES
...

Trino还有一个隐式的穿插衔接:表的列表用逗号分隔,而且衔接在WHERE子句中界说条件:

SELECT custkey, mktsegment, nation.name AS nation
FROM tpch.tiny.nation, tpch.tiny.customer
WHERE nation.nationkey = customer.nationkey;
 custkey | mktsegment |     nation
 -------- ------------ ----------------
    1210 | AUTOMOBILE | MOZAMBIQUE
    1211 | HOUSEHOLD  | CHINA
    1212 | HOUSEHOLD  | RUSSIA
    1213 | HOUSEHOLD  | GERMANY
    1214 | BUILDING   | EGYPT
...

衔接或许是查询处理中最贵重的操作之一。当查询中存在多个衔接时,衔接能够经过不同的排列进行处理。TPC-H基准测验的Q09查询是这样一个杂乱查询的很好的比如:

SELECT
  nation,
  o_year,
  sum(amount) AS sum_profit
FROM (
       SELECT
         N.name AS nation,
         extract(YEAR FROM o.orderdate) AS o_year,
         l.extendedprice * (1 - l.discount) - ps.supplycost * l.quantity
             AS amount
       FROM
         part AS p,
         supplier AS s,
         lineitem AS l,
         partsupp AS ps,
         orders AS o,
         nation AS n
       WHERE
         s.suppkey = l.suppkey
         AND ps.suppkey = l.suppkey
         AND ps.partkey = l.partkey
         AND p.partkey = l.partkey
         AND o.orderkey = l.orderkey
         AND s.nationkey = n.nationkey
         AND p.name LIKE '%green%'
     ) AS profit
GROUP BY
  nation,
  o_year
ORDER BY
  nation,
  o_year DESC;

UNION、INTERSECT和EXCEPT子句

UNION、INTERSECT和EXCEPT在SQL中被称为调集操作。它们用于将多个SQL句子的数据合并成一个单一的成果集。

尽管你能够运用衔接和条件来完成相同的语义,但一般运用调集操作更简单。Trino比等效的SQL更高效地履行它们。

当你学习调集操作的语义时,一般从根本的整数开始会更简单。你能够从UNION开始,它将一切值组合并去除重复项:

SELECT * FROM (VALUES 1, 2)
UNION
SELECT * FROM (VALUES 2, 3);

成果:

_col0
------
     2
     3
     1
(3 rows)

UNION ALL保存一切重复项:

SELECT * FROM (VALUES 1, 2)
UNION ALL
SELECT * FROM (VALUES 2, 3);

成果:

_col0
 -----
     1
     2
     2
     3
(4 rows)

INTERSECT回来两个查询中都找到的一切元素:

SELECT * FROM (VALUES 1, 2)
INTERSECT
SELECT * FROM (VALUES 2, 3);

成果:

_col0
------
     2
(1 row)

EXCEPT回来在第一个查询中找到的元素,去除了在第二个查询中找到的一切元素:

SELECT * FROM (VALUES 1, 2)
EXCEPT
SELECT * FROM (VALUES 2, 3);

成果:

_col0
------
     1
(1 row)

每个调集操作都支撑运用可选的修饰符ALL或DISTINCT。DISTINCT关键字是默许的,不需求指定。ALL关键字用作保存重复项的一种办法。

分组操作

你现已学过根本的 GROUP BY 和聚合。Trino 还支撑 SQL 规范的高档分组操作。运用 GROUPING SETS、CUBE 和 ROLLUP,用户能够在单个查询中对多个调集履行聚合。

Grouping sets 答应你在同一个查询中对多个列列表进行分组。例如,假定咱们想要在 (state, city, street)、(state, city) 和 (state) 上进行分组。假如没有 grouping sets,你有必要在每个组中运转独自的查询,然后将成果组合起来。有了 grouping sets,Trino 核算每个调集的分组。成果方法是跨调集的列的并集。关于不属于组的列,增加了一个空值。

ROLLUP 和 CUBE 能够运用 GROUPING SETS 表达,而且是一种简写。ROLLUP 用于依据层次结构生成组集。例如,ROLLUP(a, b, c) 生成组集 (a, b, c)、(a, b)、(a)、()。CUBE 操作生成分组的一切或许组合。例如,CUBE(a, b, c) 生成组集 (a, b, c)、(a, b)、(a, c)、(b, c)、(a)、(b)、(c)、()。

例如,假定你想要核算每个商场细分的账户余额总额,并核算一切商场细分的总账户余额:

sqlCopy code
SELECT mktsegment,
  round(sum(acctbal), 2) AS total_acctbal,
  GROUPING(mktsegment) AS id
FROM tpch.tiny.customer
GROUP BY ROLLUP (mktsegment)
ORDER BY id, total_acctbal;

运用 ROLLUP,你能够核算不同组的聚合。在这个比如中,前五行表明每个商场细分的账户余额总额。最后一行表明一切账户余额的总和。由于没有 mktsegment 的组,所以它被留为空值。GROUPING 函数用于标识哪些行属于哪些组。

假如没有 ROLLUP,你有必要将其作为两个独自的查询运转并组合它们。在这个比如中,咱们能够运用 UNION,它能够协助你概念上了解 ROLLUP 在做什么:

sqlCopy code
SELECT mktsegment,
       round(sum(acctbal), 2) AS total_acctbal,
       0 AS id
FROM tpch.tiny.customer
GROUP BY mktsegment
UNION
SELECT NULL, round(sum(acctbal), 2), 1
FROM tpch.tiny.customer
ORDER BY id, total_acctbal;

with句子

WITH 子句用于在单个查询中界说内联视图。这一般用于使查询更易读,由于查询或许需求屡次包含相同的嵌套查询。

在此查询中,让咱们找出总账户余额大于商场细分平均值的商场细分:

sqlCopy code
SELECT mktsegment,
       total_per_mktsegment,
       average
FROM
  (
    SELECT mktsegment,
       round(sum(acctbal)) AS total_per_mktsegment
    FROM tpch.tiny.customer
    GROUP BY 1
  ),
  (
    SELECT round(avg(total_per_mktsegment)) AS average
    FROM
      (
        SELECT mktsegment,
           sum(acctbal) AS total_per_mktsegment
        FROM tpch.tiny.customer
        GROUP BY 1
      )
  )
WHERE total_per_mktsegment > average;

正如你所看到的,这个查询有点杂乱。运用 WITH 子句,咱们能够简化它如下:

sqlCopy code
WITH
total AS (
  SELECT mktsegment,
    round(sum(acctbal)) AS total_per_mktsegment
  FROM tpch.tiny.customer
  GROUP BY 1
),
average AS (
  SELECT round(avg(total_per_mktsegment)) AS average
  FROM total
)
SELECT mktsegment,
  total_per_mktsegment,
  average
FROM total,
  average
WHERE total_per_mktsegment > average;

在这个比如中,第二个内联视图引证了第一个。你能够看到 WITH 内联视图被履行了两次。目前,Trino 不会将成果物化以在多个履行之间共享。实践上,这将取决于查询的杂乱性的依据本钱的决策,由于屡次履行查询或许比存储和检索成果更有用。

子查询

Trino支撑许多常见的子查询用法。子查询是一个充当更高档别表达式输入的表达式。在SQL中,子查询能够分为三类:

  • 标量子查询
  • ANY/SOME
  • ALL

每个类别都有两种类型,即无相关和相关。相关子查询是引证子查询外部其他列的子查询。

标量子查询

标量子查询是指回来单个值的查询,即一行一列:

SELECT regionkey, name
FROM tpch.tiny.nation
WHERE regionkey =
  (SELECT regionkey FROM tpch.tiny.region WHERE name = 'AMERICA');

在这个标量示例中,子查询的成果是1。WHERE条件实质上变成了regionkey = 1,并对每一行进行评价。从逻辑上讲,子查询对nation表中的每一行都进行评价,例如,关于一百行,会评价一百次。可是,Trino满足智能,只对子查询进行一次评价,并在其他一切状况下运用静态值。

EXISTS子查询

一个存在子查询在存在任何行时评价为true。这些查询一般用作相关子查询。尽管存在无相关子查询的或许性,但这并不太实践,由于回来单行的任何内容都会被评价为true:

SELECT
  EXISTS(
      SELECT t.*
      FROM tpch.tiny.region AS r
      WHERE r.name = 'ASIA'
      AND t.name = 'CHINA'),
  t.name
FROM tpch.tiny.nation AS t;

另一种常见的存在子查询方法是NOT EXISTS。可是,这仅仅对存在子查询成果应用否定。

量化子查询

ANY子查询选用表达式 操作符 量化器 (子查询) 的方法。有用的操作符值包含 <、>、<=、>=、= 或 <>。能够运用SOME代替ANY。这种类型查询的最常见方法是 expression IN subquery,它等效于 expression = ANY subquery。

SELECT name
FROM nation
WHERE regionkey = ANY (SELECT regionkey FROM region)

此查询等效于以下方法,其间IN是简写方法:

SELECT name
FROM nation
WHERE regionkey IN (SELECT regionkey FROM region)

子查询有必要回来切当的一列。目前,Trino不支撑比较多于一列的行表达式子查询。在语义上,关于外部查询的给定行,将评价子查询并将表达式与子查询的每个成果行进行比较。假如这些比较中至少有一个评价为TRUE,则ANY子查询条件的成果为TRUE。假如没有比较评价为TRUE,则成果为FALSE。关于外部查询的每一行都会重复这个过程。

需求留意一些微妙之处。假如表达式为NULL,则IN表达式的成果为NULL。此外,假如没有比较评价为TRUE,但子查询中有NULL值,则IN表达式将评价为NULL。在大多数状况下,这一般不会引起留意,由于FALSE或NULL的成果会过滤掉该行。可是,假如此IN表达式将作为输入传递给对NULL值敏感的外围表达式(例如,用NOT围住),那么这将很重要。

ALL子查询与ANY相似。关于外部查询的给定行,将评价子查询并将表达式与子查询的每个成果行进行比较。假如一切比较都评价为TRUE,则ALL的成果为TRUE。假如至少有一个FALSE评价,ALL的成果为FALSE。

与ANY一样,一些微妙之处一开始或许不太显着。当子查询为空且不回来任何行时,ALL将评价为TRUE。假如没有比较回来FALSE,而且至少有一个比较回来NULL,则ALL的成果为NULL。ALL的最常见方法是<> ALL,它等效于NOT IN。

从表中删去数据

DELETE句子能够从表中删去数据行。该句子供给一个可选的WHERE子句,用于约束删去哪些行。假如没有WHERE子句,将删去表中的一切数据:

DELETE FROM table_name [ WHERE condition ]

各种衔接器对删去操作的支撑有限或根本不支撑。例如,Kafka衔接器不支撑删去操作。Hive衔接器仅在WHERE子句指定能够用于删去整个分区的分区键时才支撑删去操作:

DELETE FROM datalake.web.page_views
WHERE view_date = DATE '2019-01-14' AND country = 'US'

总结

在Trino中运用SQL能够做的工作是令人振奋的,不是吗?经过本章的常识,您现已能够编写十分杂乱的查询并对露出给Trino的任何数据进行一些适当杂乱的剖析了。

当然,还有更多。所以,请继续阅览第9章,了解运用Trino查询数据的函数、操作符和其他功用。