Table API 和 SQL 集成在一个 API 中。这个 API 用作查询、输入和输出的表。本文档展示了带有 Table API 和 SQL 查询的程序的公共结构、如何注册表、如何查询表以及如何写入表。

目录

两个Planner之间的主要区别

Table API and SQL的结构

创建一个TableEnvironment

在 Calalog 中注册表

注册 Table

注册 TableSource

注册 TableSink

注册外部Calalog

查询表

Table API

SQL

混合使用 Table API & SQL

写表

转化并执行查询

Old Planner

Blink Planner

与DataStream和DataSet API集成

Scala的隐式转换

将DataStream和DataSet注册为表

将DataStream和DataSet转换为表

将表转换为DataStream或DataSet

将表转换为DataStream

将表转换为DataSet

数据类型到表模式的映射

基于位置映射

基于名称映射

原子类型

元组(Scala和Java)和Case类(仅限Scala)

POJO (Java and Scala)

Row

优化查询

解释表


 

两个Planner之间的主要区别

  1. Blink 将批作业看作一个特殊的流。因此,Table 和 DataSet 之间不能转换,批处理作业不会被转换为 DateSet 程序,而是转换为 DataStream 程序,与流作业相同。
  2. Blink planner 不支持 BatchTableSource,所以要使用 StreamTableSource。
  3. Blink planner 支持新的 Catalog,不支持 ExternalCatalog。
  4. 旧 planner 和 Blink planner 的 FilterableTableSource 实现是互不兼容的,旧的把 PlannerExpressions 下发给 FilterableTableSource,Blink planner 下发给 Expressions。
  5. 基于字符串的键值配置选项仅用于 Blink planner,详情参阅://TODO。
  6. 两个 planner 中 PlannerConfig 的实现(CalciteConfig)是不同的。
  7. Blink planner 将优化多个 sink 到一个 DAG 中(只支持 TableEnvironment)。旧 planner 一个 sink 对应一个新的 DAG,每个 DAG 都是相对独立的。
  8. 旧 planner 不支持 catalog,Blink planner支持。

Table API and SQL的结构

所有用于批处理和流处理的 Table API & SQL 程序都遵循相同的模式。下面的代码示例显示了 Table API & SQL 程序的公共结构。

// create a TableEnvironment for specific planner batch or streaming
val tableEnv = ... // see "Create a TableEnvironment" section// register a Table
tableEnv.registerTable("table1", ...)           // or
tableEnv.registerTableSource("table2", ...)     // or
tableEnv.registerExternalCatalog("extCat", ...)
// register an output Table
tableEnv.registerTableSink("outputTable", ...);// create a Table from a Table API query
val tapiResult = tableEnv.scan("table1").select(...)
// create a Table from a SQL query
val sqlResult  = tableEnv.sqlQuery("SELECT ... FROM table2 ...")// emit a Table API result Table to a TableSink, same for SQL result
tapiResult.insertInto("outputTable")// execute
tableEnv.execute("scala_job")

注意:Table API & SQL 查询可以很容易地与 DataStream 或 DataSet 程序集成并嵌入其中。查阅下方:与DataStream和DataSet API集成,了解如何将数据流和数据集转换为表。

创建一个TableEnvironment

TableEnvironment 是 Table API & SQL 集成的核心概念。负责::

 表总是绑定在特定的 TableEnvironment 上,在同一个查询中组合不同 TableEnvironment 的表是不可能的,例如,join 或 union 它们。

使用 StreamExecutionEnvironment 或 ExecutionEnvironment 和可选的 TableConfig 调用静态 BatchTableEnvironment.create()或 StreamTableEnvironment .create()方法创建 TableEnvironment。TableConfig 可以用来配置 TableEnvironment 或 自定义优化查询(详情见下:查询优化)

BatchTableEnvironment/StreamTableEnvironment 指定匹配的 planner。

如果两个 planner 的jar都存在,则需要在程序中显式指定 planner,如下:

// **********************
// FLINK STREAMING QUERY
// **********************
import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment
import org.apache.flink.table.api.EnvironmentSettings
import org.apache.flink.table.api.scala.StreamTableEnvironmentval fsSettings = EnvironmentSettings.newInstance().useOldPlanner().inStreamingMode().build()
val fsEnv = StreamExecutionEnvironment.getExecutionEnvironment
val fsTableEnv = StreamTableEnvironment.create(fsEnv, fsSettings)
// or val fsTableEnv = TableEnvironment.create(fsSettings)// ******************
// FLINK BATCH QUERY
// ******************
import org.apache.flink.api.scala.ExecutionEnvironment
import org.apache.flink.table.api.scala.BatchTableEnvironmentval fbEnv = ExecutionEnvironment.getExecutionEnvironment
val fbTableEnv = BatchTableEnvironment.create(fbEnv)// **********************
// BLINK STREAMING QUERY
// **********************
import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment
import org.apache.flink.table.api.EnvironmentSettings
import org.apache.flink.table.api.scala.StreamTableEnvironmentval bsEnv = StreamExecutionEnvironment.getExecutionEnvironment
val bsSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build()
val bsTableEnv = StreamTableEnvironment.create(bsEnv, bsSettings)
// or val bsTableEnv = TableEnvironment.create(bsSettings)// ******************
// BLINK BATCH QUERY
// ******************
import org.apache.flink.table.api.{EnvironmentSettings, TableEnvironment}val bbSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inBatchMode().build()
val bbTableEnv = TableEnvironment.create(bbSettings)

注意:如果/lib目录中只有一个planner jar,那么可以使用 useAnyPlanner(use_any_planner for python)创建特定的 EnvironmentSettings

在 Calalog 中注册表

TableEnvironment 维护按名称注册的表的目录。有两种类型的表,输入表和输出表。输入表可以在 Table API & SQL 查询中引用,并提供输入数据。输出表可用于将 Table API & SQL 查询的结果输出到外部系统。

输入表的注册支持各种各样的数据源:

使用 TableSink 注册输入表。

注册 Table

  1. // get a TableEnvironment

  2. val tableEnv = ... // see "Create a TableEnvironment" section

  3.  
  4. // table is the result of a simple projection query

  5. val projTable: Table = tableEnv.scan("X").select(...)

  6.  
  7. // register the Table projTable as table "projectedTable"

  8. tableEnv.registerTable("projectedTable", projTable)

  9.  

 注意:注册表的处理类似于关系数据库系统中的视图,即,定义表的查询未进行优化,但当另一个查询引用已注册表时,将内联该查询。如果多个查询引用了相同注册表,它将为每个引用查询内联并执行多次,即,已注册表的结果将不会共享。 

注册 TableSource

TableSource提供了访问外部数据,诸如,数据库(MySQL, HBase, …),特定编码的文件(CSV, Apache [Parquet, Avro, ORC], …),消息系统(Apache Kafka, RabbitMQ, …)。

Flink 旨在为常见的数据格式和存储系统提供 TableSources。查阅://TODO,了解支持的 Table Source 列表及如何构建自定义 Table Source。

  1. // get a TableEnvironment

  2. val tableEnv = ... // see "Create a TableEnvironment" section

  3.  
  4. // create a TableSource

  5. val csvSource: TableSource = new CsvTableSource("/path/to/file", ...)

  6.  
  7. // register the TableSource as table "CsvTable"

  8. tableEnv.registerTableSource("CsvTable", csvSource)

注意:用于 Blink planner 的 TableEnvironment 只接受 StreamTableSource、LookupableTableSource 和 InputFormatTableSource,并且必须绑定用于批量 Blink planner 的流表资源。 

注册 TableSink

已注册的 TableSink 可以用于将 Table API & SQL 查询的结果输出到外部存储系统,诸如,数据库(MySQL, HBase, …),特定编码的文件(CSV, Apache [Parquet, Avro, ORC], …),消息系统(Apache Kafka, RabbitMQ, …)。

  1. // get a TableEnvironment

  2. val tableEnv = ... // see "Create a TableEnvironment" section

  3.  
  4. // create a TableSink

  5. val csvSink: TableSink = new CsvTableSink("/path/to/file", ...)

  6.  
  7. // define the field names and types

  8. val fieldNames: Array[String] = Array("a", "b", "c")

  9. val fieldTypes: Array[TypeInformation[_]] = Array(Types.INT, Types.STRING, Types.LONG)

  10.  
  11. // register the TableSink as table "CsvSinkTable"

  12. tableEnv.registerTableSink("CsvSinkTable", fieldNames, fieldTypes, csvSink)

注册外部Calalog

外部目录可以提供关于外部数据库和表的信息,比如它们的名称、模式、统计信息,以及如何访问存储在外部数据库、表或文件中的数据的信息。

外部目录可以通过实现 ExternalCatalog 接口创建,并在 TableEnvironment 中注册样例如下:

  1. // get a TableEnvironment

  2. val tableEnv = ... // see "Create a TableEnvironment" section

  3.  
  4. // create an external catalog

  5. val catalog: ExternalCatalog = new InMemoryExternalCatalog

  6.  
  7. // register the ExternalCatalog catalog

  8. tableEnv.registerExternalCatalog("InMemCatalog", catalog)

在 TableEnvironment 中注册后,可以通过指定 Table API 或 SQL 查询的完整路径(如:catalog.database.table)访问 ExternalCatalog 中定义的所有表。

目前,Flink 提供了一个用于演示和测试目的的 InMemoryExternalCatalog。然而,ExternalCatalog 接口还可以用于将 HCatalog 或 Metastore 之类的目录连接到 Table API。

注意:Blink planner 不支持外部目录

查询表

Table API

Table API 是一个用于Scala和Java的语言集成查询 API。与 SQL 相反,查询没有指定为sql,而是在程序中逐步拼接成。

Table API 基于 Table 类, 表示一个表(流或批处理),并提供应用关系操作的方法。这些方法生成一个新的表对象,表示在输入表的基础上计算完成后的结果。一些计算由多个方法组成,如,table.groupBy(...).select()。

更多关于 Table API 的使用请查阅://TODO

  1. // get a TableEnvironment

  2. val tableEnv = ... // see "Create a TableEnvironment" section

  3.  
  4. // register Orders table

  5.  
  6. // scan registered Orders table

  7. val orders = tableEnv.scan("Orders")

  8. // compute revenue for all customers from France

  9. val revenue = orders

  10. .filter('cCountry === "FRANCE")

  11. .groupBy('cID, 'cName)

  12. .select('cID, 'cName, 'revenue.sum AS 'revSum)

  13.  
  14. // emit or convert Table

  15. // execute query

注意:Scala Table API 使用一个单引号(')来表示引用表。Table API使用的是 Scala 隐式,必须导入org.apache.flink.api.scala._ 和 org.apache.flink.table.api.scala._

SQL

Flink SQL 的集成基于 Apache Calcite,Calcite 实现了 SQL 标准,SQL 查询被指定为sql字符串。

下面的例子展示了如何指定一个查询,并返回结果数据表:

  1. // get a TableEnvironment

  2. val tableEnv = ... // see "Create a TableEnvironment" section

  3.  
  4. // register Orders table

  5.  
  6. // compute revenue for all customers from France

  7. val revenue = tableEnv.sqlQuery("""

  8. |SELECT cID, cName, SUM(revenue) AS revSum

  9. |FROM Orders

  10. |WHERE cCountry = 'FRANCE'

  11. |GROUP BY cID, cName

  12. """.stripMargin)

  13.  
  14. // emit or convert Table

  15. // execute query

下面的示例显示如何指定将结果插入已注册表的 update 查询:

  1. // get a TableEnvironment

  2. val tableEnv = ... // see "Create a TableEnvironment" section

  3.  
  4. // register "Orders" table

  5. // register "RevenueFrance" output table

  6.  
  7. // compute revenue for all customers from France and emit to "RevenueFrance"

  8. tableEnv.sqlUpdate("""

  9. |INSERT INTO RevenueFrance

  10. |SELECT cID, cName, SUM(revenue) AS revSum

  11. |FROM Orders

  12. |WHERE cCountry = 'FRANCE'

  13. |GROUP BY cID, cName

  14. """.stripMargin)

  15.  
  16. // execute query

混合使用 Table API & SQL

因为 Table API 和 SQL 返回的都是 Table 对象,所以他们是可以混合使用的。

写表

Table 是通过 TableSink 将数据写出的。TableSink 是一个通用的接口,支持多种文件格式(CSV, Apache Parquet, Apache Avro),存储系统(JDBC, Apache HBase, Apache Cassandra, Elasticsearch),消息系统(Apache Kafka, RabbitMQ)。

批处理表只能写入 BatchTableSink,而流表需要 AppendStreamTableSink、RetractStreamTableSink 或 UpsertStreamTableSink。

有关可用 Sink 的详细信息,以及如何实现自定义 TableSink 的说明,请参阅://TODO。

Table.insertInto(String tableName) 方法将一个 Table 写入到已经注册的 TableSink。该方法通过名称在 catalog 中查询 TableSink 并验证 Table Schema 和 TableSink Schema 是否一致。

  1. // get a TableEnvironment

  2. val tableEnv = ... // see "Create a TableEnvironment" section

  3.  
  4. // create a TableSink

  5. val sink: TableSink = new CsvTableSink("/path/to/file", fieldDelim = "|")

  6.  
  7. // register the TableSink with a specific schema

  8. val fieldNames: Array[String] = Array("a", "b", "c")

  9. val fieldTypes: Array[TypeInformation] = Array(Types.INT, Types.STRING, Types.LONG)

  10. tableEnv.registerTableSink("CsvSinkTable", fieldNames, fieldTypes, sink)

  11.  
  12. // compute a result Table using Table API operators and/or SQL queries

  13. val result: Table = ...

  14.  
  15. // emit the result Table to the registered TableSink

  16. result.insertInto("CsvSinkTable")

  17.  
  18. // execute the program

转化并执行查询

对于现有的两个 planner,转化和执行查询是不相同的。

Old Planner

Table API 和 SQL 查询根据其输入是流输入还是批输入被转换为 DataStream 或 DataSet 程序。查询在内部表示为逻辑查询计划,并分两个阶段解释:

  1. 优化逻辑计划
  2. 转换为 DataStream 或 DataSet 程序

Table API 或 SQL 查询在以下情况下转化:

转换后,Table API 或 SQL 查询的处理方式与常规 DataStream 或 DataSet 程序类似,并在调用 StreamExecutionEnvironment.execute()或 ExecutionEnvironment.execute()时执行。

Blink Planner

Table API 和 SQL 查询被转换为数据流程序或批处理程序。查询在内部表示为逻辑查询计划,并分两个阶段转换:

  1. 优化逻辑计划
  2. 转换为 DataStream 程序

对于 TableEnvironment 和 StreamTableEnvironment,转换查询是不同的。对于 TableEnvironment,当调用TableEnvironment.execute()时,将转换 Table API 或 SQL 查询,因为 TableEnvironment 将把多个 Sink 优化为一个DAG。

而对于 StreamTableEnvironment,当以下情况发生时,Table API 和 SQL 才会被转换:

一旦转换完成,Table API 或 SQL 查询就像普通的 DataStream 程序一样处理,并在调用 TableEnvironment.execute() 或 StreamExecutionEnvironment.execute() 时执行。

与DataStream和DataSet API集成

流上的两个 planner 都可以与 DataStream API 集成。只有老的 planner 才能与 DataSet API 集成,批量上的 Blink planner 不能同时与两者结合。注意:下面讨论的 DataSet API 只适用于旧的批处理 planner。

Table API 和 SQL 查询可以很容易地与 DataStream 和 DataSet 程序集成并嵌入其中。例如,可以查询外部表(例如,RDBMS),做一些预处理,如 filtering, projecting, aggregating, joining 元数据,然后进一步处理 DataStream 数据或 DataSet 的API(任何构建在这些api之上的库,如 CEP 或 Gelly)。相反,Table API 或 SQL 查询也可以应用在 DataStream 或 DataSet 程序的结果上。

这种交互可以通过将 DataStream 或 DataSet 转换为表来实现,反之亦然。

Scala的隐式转换

Scala Table API 为 DataSet、DataStream 和 Table 类提供隐式转换。通过导入org.apache.flink.table.api.scala包,可以启用这些转换。除了org.apache.flink.api.scala。_用于Scala DataStream API。

将DataStream和DataSet注册为表

DataStream 或 DataSet 可以在 TableEnvironment 中注册为表。结果表的模式取决于已注册的 DataStream 或 DataSet 的数据类型。有关数据类型到表模式的映射的详细信息,请参阅:数据类型到表模式的映射。

  1. // get TableEnvironment

  2. // registration of a DataSet is equivalent

  3. val tableEnv: StreamTableEnvironment = ... // see "Create a TableEnvironment" section

  4.  
  5. val stream: DataStream[(Long, String)] = ...

  6.  
  7. // register the DataStream as Table "myTable" with fields "f0", "f1"

  8. tableEnv.registerDataStream("myTable", stream)

  9.  
  10. // register the DataStream as table "myTable2" with fields "myLong", "myString"

  11. tableEnv.registerDataStream("myTable2", stream, 'myLong, 'myString)

注意:DataStream Table 名称不能与 ^_DataStreamTable_[0-9]+ 相匹配,DataSet Table 名称不能与 ^_DataSetTable_[0-9]+ 相匹配。因为他们仅提供给内部使用。 

将DataStream和DataSet转换为表

不需要在 TableEnvironment 中注册 DataStream 或 DataSet,它还可以直接转换为表。

  1. // get TableEnvironment

  2. // registration of a DataSet is equivalent

  3. val tableEnv = ... // see "Create a TableEnvironment" section

  4.  
  5. val stream: DataStream[(Long, String)] = ...

  6.  
  7. // convert the DataStream into a Table with default fields '_1, '_2

  8. val table1: Table = tableEnv.fromDataStream(stream)

  9.  
  10. // convert the DataStream into a Table with fields 'myLong, 'myString

  11. val table2: Table = tableEnv.fromDataStream(stream, 'myLong, 'myString)

将表转换为DataStream或DataSet

表可以转换为 DataStream 或 DataSet。通过这种方式,可以对 Table API 或 SQL 查询的结果运行自定义 DataStream 或 DataSet 程序。

在将表转换为 DataStream 或 DataSet 时,需要指定结果 DataStream 或 DataSet 的数据类型,即,要将表的行转换成的数据类型。通常最方便的转换类型是 Row。以下是不同选项的功能概览:

将表转换为DataStream

流查询的结果表将被动态更新,即,随着新记录到达查询的输入流,它也在发生变化。因此,将这样的动态查询转换成的 DataStream 需要对表的更新进行编码。

将表转换为 DataStream 有两种模式:

  1. 追加:只有动态表被 insert 修改时,该模式才可用。它只追加数据,之前写入的数据不会被修改。
  2. 撤回:这种模式总是可以使用。它使用 boolean 标志对插入和删除更改进行编码。
  1. // get TableEnvironment.

  2. // registration of a DataSet is equivalent

  3. val tableEnv: StreamTableEnvironment = ... // see "Create a TableEnvironment" section

  4.  
  5. // Table with two fields (String name, Integer age)

  6. val table: Table = ...

  7.  
  8. // convert the Table into an append DataStream of Row

  9. val dsRow: DataStream[Row] = tableEnv.toAppendStream[Row](table)

  10.  
  11. // convert the Table into an append DataStream of Tuple2[String, Int]

  12. val dsTuple: DataStream[(String, Int)] dsTuple =

  13. tableEnv.toAppendStream[(String, Int)](table)

  14.  
  15. // convert the Table into a retract DataStream of Row.

  16. // A retract stream of type X is a DataStream[(Boolean, X)].

  17. // The boolean field indicates the type of the change.

  18. // True is INSERT, false is DELETE.

  19. val retractStream: DataStream[(Boolean, Row)] = tableEnv.toRetractStream[Row](table)

注意:关于动态表及其属性的详细讨论在动态表文档中给出(//TODO)。 

将表转换为DataSet

将表转换为 DataSet 的过程如下:

  1. // get TableEnvironment

  2. // registration of a DataSet is equivalent

  3. val tableEnv = BatchTableEnvironment.create(env)

  4.  
  5. // Table with two fields (String name, Integer age)

  6. val table: Table = ...

  7.  
  8. // convert the Table into a DataSet of Row

  9. val dsRow: DataSet[Row] = tableEnv.toDataSet[Row](table)

  10.  
  11. // convert the Table into a DataSet of Tuple2[String, Int]

  12. val dsTuple: DataSet[(String, Int)] = tableEnv.toDataSet[(String, Int)](table)

数据类型到表模式的映射

Flink 的 DataStream 和 DataSet APIs 支持不同的类型。复合类型如元组(内置Scala和Flink Java元组)、pojo、Scala case类和Flink 的 Row 类型,允许嵌套数据结构,其中包含多个字段,可以在 table 表达式中访问。其他类型被视为原子类型。在下面的文章中,我们将描述 Table API 如何将这些类型转换为内部行表示,并展示将 DataStream 转换为表的示例。

数据类型到表模式的映射可以通过两种方式进行:基于字段位置或基于字段名称

基于位置映射

基于位置的映射可用于在保持字段顺序的同时赋予字段更有意义的名称。此映射可用于具有已定义字段顺序的组合数据类型和原子类型。元组、行和case类等组合数据类型具有这样的字段顺序。但是,必须根据字段名映射POJO的字段(请参阅下一节)。字段可以被投影出来,但不能使用别名重命名。

在定义基于位置的映射时,输入数据类型中必须不存在指定的名称,否则API将假定映射应该基于字段名称进行。如果没有指定字段名,则使用组合类型的默认字段名和字段顺序,或者使用f0表示原子类型。

  1. // get a TableEnvironment

  2. val tableEnv: StreamTableEnvironment = ... // see "Create a TableEnvironment" section

  3.  
  4. val stream: DataStream[(Long, Int)] = ...

  5.  
  6. // convert DataStream into Table with default field names "_1" and "_2"

  7. val table: Table = tableEnv.fromDataStream(stream)

  8.  
  9. // convert DataStream into Table with field "myLong" only

  10. val table: Table = tableEnv.fromDataStream(stream, 'myLong)

  11.  
  12. // convert DataStream into Table with field names "myLong" and "myInt"

  13. val table: Table = tableEnv.fromDataStream(stream, 'myLong, 'myInt)

基于名称映射

基于名称的映射可以用于任何数据类型,包括pojo。这是定义表模式映射最灵活的方法。映射中的所有字段都按名称引用,可以使用别名 as 重命名。字段可以重新排序并投影出来。

如果没有指定字段名,则使用组合类型的默认字段名和字段顺序,或者使用f0表示原子类型。

  1. // get a TableEnvironment

  2. val tableEnv: StreamTableEnvironment = ... // see "Create a TableEnvironment" section

  3.  
  4. val stream: DataStream[(Long, Int)] = ...

  5.  
  6. // convert DataStream into Table with default field names "_1" and "_2"

  7. val table: Table = tableEnv.fromDataStream(stream)

  8.  
  9. // convert DataStream into Table with field "_2" only

  10. val table: Table = tableEnv.fromDataStream(stream, '_2)

  11.  
  12. // convert DataStream into Table with swapped fields

  13. val table: Table = tableEnv.fromDataStream(stream, '_2, '_1)

  14.  
  15. // convert DataStream into Table with swapped fields and field names "myInt" and "myLong"

  16. val table: Table = tableEnv.fromDataStream(stream, '_2 as 'myInt, '_1 as 'myLong)

原子类型

Flink 将基本类型(IntegerDoubleString)或泛型类型(不能分析和分解的类型)视为原子类型。原子类型的 DataStream 或 DataStream 被转换为具有单个属性的表。属性的类型从原子类型推断,可以指定属性的名称。

  1. // get a TableEnvironment

  2. val tableEnv: StreamTableEnvironment = ... // see "Create a TableEnvironment" section

  3.  
  4. val stream: DataStream[Long] = ...

  5.  
  6. // convert DataStream into Table with default field name "f0"

  7. val table: Table = tableEnv.fromDataStream(stream)

  8.  
  9. // convert DataStream into Table with field name "myLong"

  10. val table: Table = tableEnv.fromDataStream(stream, 'myLong)

元组(Scala和Java)和Case类(仅限Scala)

Flink支持Scala的内置元组,并为Java提供了自己的元组类。这两种元组的数据流和数据集都可以转换为表。可以通过为所有字段提供名称(基于位置的映射)来重命名字段。如果没有指定字段名,则使用默认字段名。如果引用原始字段名(Flink元组的f0、f1、…和Scala元组的_1、_2、…),则API假定映射是基于名称的,而不是基于位置的。基于名称的映射允许使用别名(as)对字段和投影进行重新排序。

  1. // get a TableEnvironment

  2. val tableEnv: StreamTableEnvironment = ... // see "Create a TableEnvironment" section

  3.  
  4. val stream: DataStream[(Long, String)] = ...

  5.  
  6. // convert DataStream into Table with renamed default field names '_1, '_2

  7. val table: Table = tableEnv.fromDataStream(stream)

  8.  
  9. // convert DataStream into Table with field names "myLong", "myString" (position-based)

  10. val table: Table = tableEnv.fromDataStream(stream, 'myLong, 'myString)

  11.  
  12. // convert DataStream into Table with reordered fields "_2", "_1" (name-based)

  13. val table: Table = tableEnv.fromDataStream(stream, '_2, '_1)

  14.  
  15. // convert DataStream into Table with projected field "_2" (name-based)

  16. val table: Table = tableEnv.fromDataStream(stream, '_2)

  17.  
  18. // convert DataStream into Table with reordered and aliased fields "myString", "myLong" (name-based)

  19. val table: Table = tableEnv.fromDataStream(stream, '_2 as 'myString, '_1 as 'myLong)

  20.  
  21. // define case class

  22. case class Person(name: String, age: Int)

  23. val streamCC: DataStream[Person] = ...

  24.  
  25. // convert DataStream into Table with default field names 'name, 'age

  26. val table = tableEnv.fromDataStream(streamCC)

  27.  
  28. // convert DataStream into Table with field names 'myName, 'myAge (position-based)

  29. val table = tableEnv.fromDataStream(streamCC, 'myName, 'myAge)

  30.  
  31. // convert DataStream into Table with reordered and aliased fields "myAge", "myName" (name-based)

  32. val table: Table = tableEnv.fromDataStream(stream, 'age as 'myAge, 'name as 'myName)

POJO (Java and Scala)

Flink支持将pojo作为复合类型。请查阅:Flink基础之API,DataSet、DataStream、批、流

在不指定字段名的情况下将POJO DataStream或DataSet转换为表时,将使用原始POJO字段的名称。名称映射需要原始名称,不能通过位置来完成。字段可以使用别名(带as关键字)重命名、重新排序和投影。

  1. // get a TableEnvironment

  2. val tableEnv: StreamTableEnvironment = ... // see "Create a TableEnvironment" section

  3.  
  4. // Person is a POJO with field names "name" and "age"

  5. val stream: DataStream[Person] = ...

  6.  
  7. // convert DataStream into Table with default field names "age", "name" (fields are ordered by name!)

  8. val table: Table = tableEnv.fromDataStream(stream)

  9.  
  10. // convert DataStream into Table with renamed fields "myAge", "myName" (name-based)

  11. val table: Table = tableEnv.fromDataStream(stream, 'age as 'myAge, 'name as 'myName)

  12.  
  13. // convert DataStream into Table with projected field "name" (name-based)

  14. val table: Table = tableEnv.fromDataStream(stream, 'name)

  15.  
  16. // convert DataStream into Table with projected and renamed field "myName" (name-based)

  17. val table: Table = tableEnv.fromDataStream(stream, 'name as 'myName)

Row

行数据类型支持任意数量的字段和具有空值的字段。字段名可以通过RowTypeInfo指定,也可以在将行DataStream或DataSet转换为表时指定。行类型支持按位置和名称映射字段。字段可以通过为所有字段提供名称(基于位置的映射)来重命名,或者单独选择投影/排序/重命名(基于名称的映射)。

  1. // get a TableEnvironment

  2. val tableEnv: StreamTableEnvironment = ... // see "Create a TableEnvironment" section

  3.  
  4. // DataStream of Row with two fields "name" and "age" specified in `RowTypeInfo`

  5. val stream: DataStream[Row] = ...

  6.  
  7. // convert DataStream into Table with default field names "name", "age"

  8. val table: Table = tableEnv.fromDataStream(stream)

  9.  
  10. // convert DataStream into Table with renamed field names "myName", "myAge" (position-based)

  11. val table: Table = tableEnv.fromDataStream(stream, 'myName, 'myAge)

  12.  
  13. // convert DataStream into Table with renamed fields "myName", "myAge" (name-based)

  14. val table: Table = tableEnv.fromDataStream(stream, 'name as 'myName, 'age as 'myAge)

  15.  
  16. // convert DataStream into Table with projected field "name" (name-based)

  17. val table: Table = tableEnv.fromDataStream(stream, 'name)

  18.  
  19. // convert DataStream into Table with projected and renamed field "myName" (name-based)

  20. val table: Table = tableEnv.fromDataStream(stream, 'name as 'myName)

优化查询

Old planner

Apache Flink 利用Apache Calcite 优化和解释查询。当前执行的优化包括 projection and filter push-down, subquery decorrelation, and other kinds of query rewriting。Old planner还没有优化 join 顺序,但是会按照查询中定义的顺序执行它们(FROM子句中的表顺序和/或WHERE子句中的连接谓词顺序)。

通过提供一个 CalciteConfig 对象,可以调整应用于不同阶段的优化规则集。这可以通过调用 calciteConfig . createbuilder()通过构建器创建,并通过调用 tableEnv.getConfig.setPlannerConfig(calciteConfig)提供给 TableEnvironment。

Blink Planner

Apache Flink 利用并扩展了 Apache Calcite 来执行复杂的查询优化。这包括一系列基于规则和成本的优化,如:

基于Apache Calcite 的子查询

  1. 将其转换为左半连接
  2. 将NOT IN和NOT EXISTS转换为左反连接
  1. 启用table.optimizer.join-reorder-enabled

注意:IN/EXISTS/NOT IN/NOT EXISTS目前只支持子查询重写中的连接条件。

优化器不仅基于计划,还基于数据源提供的丰富统计信息和每个算子(如io、cpu、网络和内存)的细粒度成本做出智能决策。 

高级用户可以通过 CalciteConfig 对象提供自定义优化,该对象可以通过调用 TableEnvironment#getConfig#setPlannerConfig 提供给表环境。

解释表

Table API 提供了一种机制来解释计算表的逻辑和优化查询计划。这是通过 TableEnvironment.explain(table)方法或 TableEnvironment.explain()方法完成的。explain(table)返回给定表的计划。Table.explain()返回多 sink 计划的结果,主要用于Blink planner。它返回一个字符串,描述三个计划:

  1. 关系查询的抽象语法树,即,未经优化的逻辑查询计划
  2. 优化的逻辑查询计划
  3. 物理执行计划

下面的代码显示了一个示例和使用explain(Table)给出的表的相应输出:

  1. val env = StreamExecutionEnvironment.getExecutionEnvironment

  2. val tEnv = StreamTableEnvironment.create(env)

  3.  
  4. val table1 = env.fromElements((1, "hello")).toTable(tEnv, 'count, 'word)

  5. val table2 = env.fromElements((1, "hello")).toTable(tEnv, 'count, 'word)

  6. val table = table1

  7. .where('word.like("F%"))

  8. .unionAll(table2)

  9.  
  10. val explanation: String = tEnv.explain(table)

  11. println(explanation)

  1. == Abstract Syntax Tree ==

  2. LogicalUnion(all=[true])

  3. LogicalFilter(condition=[LIKE($1, _UTF-16LE'F%')])

  4. FlinkLogicalDataStreamScan(id=[1], fields=[count, word])

  5. FlinkLogicalDataStreamScan(id=[2], fields=[count, word])

  6.  
  7. == Optimized Logical Plan ==

  8. DataStreamUnion(all=[true], union all=[count, word])

  9. DataStreamCalc(select=[count, word], where=[LIKE(word, _UTF-16LE'F%')])

  10. DataStreamScan(id=[1], fields=[count, word])

  11. DataStreamScan(id=[2], fields=[count, word])

  12.  
  13. == Physical Execution Plan ==

  14. Stage 1 : Data Source

  15. content : collect elements with CollectionInputFormat

  16.  
  17. Stage 2 : Data Source

  18. content : collect elements with CollectionInputFormat

  19.  
  20. Stage 3 : Operator

  21. content : from: (count, word)

  22. ship_strategy : REBALANCE

  23.  
  24. Stage 4 : Operator

  25. content : where: (LIKE(word, _UTF-16LE'F%')), select: (count, word)

  26. ship_strategy : FORWARD

  27.  
  28. Stage 5 : Operator

  29. content : from: (count, word)

  30. ship_strategy : REBALANCE

  1. val settings = EnvironmentSettings.newInstance.useBlinkPlanner.inStreamingMode.build

  2. val tEnv = TableEnvironment.create(settings)

  3.  
  4. val fieldNames = Array("count", "word")

  5. val fieldTypes = Array[TypeInformation[_]](Types.INT, Types.STRING)

  6. tEnv.registerTableSource("MySource1", new CsvTableSource("/source/path1", fieldNames, fieldTypes))

  7. tEnv.registerTableSource("MySource2", new CsvTableSource("/source/path2",fieldNames, fieldTypes))

  8. tEnv.registerTableSink("MySink1", new CsvTableSink("/sink/path1").configure(fieldNames, fieldTypes))

  9. tEnv.registerTableSink("MySink2", new CsvTableSink("/sink/path2").configure(fieldNames, fieldTypes))

  10.  
  11. val table1 = tEnv.scan("MySource1").where("LIKE(word, 'F%')")

  12. table1.insertInto("MySink1")

  13.  
  14. val table2 = table1.unionAll(tEnv.scan("MySource2"))

  15. table2.insertInto("MySink2")

  16.  
  17. val explanation = tEnv.explain(false)

  18. println(explanation)

 多 sink 计划的结果是:

  1. == Abstract Syntax Tree ==

  2. LogicalSink(name=[MySink1], fields=[count, word])

  3. +- LogicalFilter(condition=[LIKE($1, _UTF-16LE'F%')])

  4. +- LogicalTableScan(table=[[default_catalog, default_database, MySource1, source: [CsvTableSource(read fields: count, word)]]])

  5.  
  6. LogicalSink(name=[MySink2], fields=[count, word])

  7. +- LogicalUnion(all=[true])

  8. :- LogicalFilter(condition=[LIKE($1, _UTF-16LE'F%')])

  9. : +- LogicalTableScan(table=[[default_catalog, default_database, MySource1, source: [CsvTableSource(read fields: count, word)]]])

  10. +- LogicalTableScan(table=[[default_catalog, default_database, MySource2, source: [CsvTableSource(read fields: count, word)]]])

  11.  
  12. == Optimized Logical Plan ==

  13. Calc(select=[count, word], where=[LIKE(word, _UTF-16LE'F%')], reuse_id=[1])

  14. +- TableSourceScan(table=[[default_catalog, default_database, MySource1, source: [CsvTableSource(read fields: count, word)]]], fields=[count, word])

  15.  
  16. Sink(name=[MySink1], fields=[count, word])

  17. +- Reused(reference_id=[1])

  18.  
  19. Sink(name=[MySink2], fields=[count, word])

  20. +- Union(all=[true], union=[count, word])

  21. :- Reused(reference_id=[1])

  22. +- TableSourceScan(table=[[default_catalog, default_database, MySource2, source: [CsvTableSource(read fields: count, word)]]], fields=[count, word])

  23.  
  24. == Physical Execution Plan ==

  25. Stage 1 : Data Source

  26. content : collect elements with CollectionInputFormat

  27.  
  28. Stage 2 : Operator

  29. content : CsvTableSource(read fields: count, word)

  30. ship_strategy : REBALANCE

  31.  
  32. Stage 3 : Operator

  33. content : SourceConversion(table:Buffer(default_catalog, default_database, MySource1, source: [CsvTableSource(read fields: count, word)]), fields:(count, word))

  34. ship_strategy : FORWARD

  35.  
  36. Stage 4 : Operator

  37. content : Calc(where: (word LIKE _UTF-16LE'F%'), select: (count, word))

  38. ship_strategy : FORWARD

  39.  
  40. Stage 5 : Operator

  41. content : SinkConversionToRow

  42. ship_strategy : FORWARD

  43.  
  44. Stage 6 : Operator

  45. content : Map

  46. ship_strategy : FORWARD

  47.  
  48. Stage 8 : Data Source

  49. content : collect elements with CollectionInputFormat

  50.  
  51. Stage 9 : Operator

  52. content : CsvTableSource(read fields: count, word)

  53. ship_strategy : REBALANCE

  54.  
  55. Stage 10 : Operator

  56. content : SourceConversion(table:Buffer(default_catalog, default_database, MySource2, source: [CsvTableSource(read fields: count, word)]), fields:(count, word))

  57. ship_strategy : FORWARD

  58.  
  59. Stage 12 : Operator

  60. content : SinkConversionToRow

  61. ship_strategy : FORWARD

  62.  
  63. Stage 13 : Operator

  64. content : Map

  65. ship_strategy : FORWARD

  66.  
  67. Stage 7 : Data Sink

  68. content : Sink: CsvTableSink(count, word)

  69. ship_strategy : FORWARD

  70.  
  71. Stage 14 : Data Sink

  72. content : Sink: CsvTableSink(count, word)

  73. ship_strategy : FORWARD

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. React阶段 - 自动化构建项目 create-react-app

    自动化构建项目 通过前面 script 的方式虽然也能完成 React.js 的开发(上一篇的文章中的方式) 但是,却存在这很大的问题,模块化怎么实现 create-react-app Create React App 基于 Node.js 编写的命令行工具,通过它可以快速生成 React.js 项目 内置了 Babel、Webpack 等工具…...

    2024/4/16 13:25:20
  2. 截取随意区域的图片

    截取随意区域的图片 #!/usr/bin/python3 # -*- coding: utf-8 -*- """ @File : test9-1.py @Author: Li,hui @Date : 2020/7/3 4:45 下午 @Desc : """ import os, time from PIL import Imagedef test1(x1, y1, x2, y2, save_pic):os.system(…...

    2024/5/2 1:05:04
  3. Unity_UGUI VertexHelper

    图形学的基础知识:1、所有的渲染对象都是由网格(Mesh)构成,Mesh的绘制单位是图元(点、线、三角形)。意思也就是说所有的游戏对象都是在绘制一些点、线、三角形的集合。2、顶点数据中最主要的是位置,颜色,纹理坐标,法线等。也就是说顶点中保存着其位置、颜色、纹理坐标…...

    2024/5/1 22:02:01
  4. pom文件中资源过滤

    SpringBoot中的配置文件pom <!-- 添加此节点,mybatis的mapper.xml文件将不会被漏掉。 --><resources><resource><directory>src/main/java</directory><includes><include>**/*.yml</include><include>**/*.properties&…...

    2024/5/2 0:09:29
  5. 球球速刷LC-字典树

    基本概念 https://www.cxyxiaowu.com/2425.html...

    2024/5/2 2:28:36
  6. Neo4j学习笔记(1)——使用Java API实现简单的增删改查

    阅读目录项目的创建及配置使用嵌入式数据库创建节点和关系查询及更新删除关系和节点完整代码参考资料 回到顶部项目的创建及配置因为Neo4j依赖的jar包比较多,所以推荐使用Maven来管理。首先创建一个Maven Project,添加依赖:<dependency><groupId>org.neo4j</…...

    2024/4/16 16:21:45
  7. STL注意事项一(front()引用)

    写代码的时候,使用front()函数,未判断容器是否为空,导致程序崩溃。使用标准库中的list、vector等中的front()函数时候需要判断该变量是否为空。 front()返回容器首元素的引用,在空容器中使用front()是未定义的,程序会崩溃。 详见 cppreference以后还是要多看看标准库文档吖…...

    2024/4/19 17:10:06
  8. 【Flink】Flink写入es报错failed to get node info for request_id time out out after

    1.美图2.背景 windows下开发flink程序,连接本地的es,启动的时候报错如下,重启一下es就好了。 INFO [elasticsearch[_ client_ _] [generic] [T#1]] - failed to get node info for (#transport#-1 ) (b0Rgx4DoSBWxUFCRBkgJWA (localhost) (127.0.0.1:9200), disconnecting. …...

    2024/4/20 17:49:42
  9. day3

    可变字符串 基本运算符 序列 列表列表元素的增加和删除 元素访问和计数 二维列表元组元组创建 元组元素访问和计数 生成器推导式创建元组可变字符串 在python中,字符串属于不可变对象,不支持原地修改,如果需要修改其中的值,智能创建新的字符对象。但是,经常我们确实需要原…...

    2024/4/16 13:25:56
  10. mapper中的方法访问不到

    参数我用的是int类型,而int默认值是0,换成integer就可以了...

    2024/5/2 0:44:34
  11. Prometheus部署(一)

    Prometheus是最初在SoundCloud上构建的开源系统监视和警报工具包。自2012年成立以来,许多公司和组织都采用了Prometheus,该项目拥有非常活跃的开发人员和用户社区。Prometheus 于2016年加入了 Cloud Native Computing Foundation,这是继Kubernetes之后的第二个托管项目。 官…...

    2024/4/19 13:34:41
  12. 上传项目到自己的仓库git,命令

    mkdir JCYJ cd JCYJ git init touch README.md git add README.md git commit -m “first commit” git remote add origin 这是你的仓库 SSH地址 git push -u origin master 先初始化 git init 然后 git add . 空格点 git commit -m “备注信息”...

    2024/5/2 1:51:01
  13. Vscode+python+flake8 安装 配置 使用

    Vscode+python+flake8 安装 配置 使用总述 Vscode+python环境下,配置flake8与yapf,以及使用方法1.1. Flake8——Python静态代码检查工具 Flake8 是由Python官方发布的一款辅助检测Python代码是否规范的工具,相对于目前热度比较高的Pylint来说,Flake8检查规则灵活,支持集成额…...

    2024/4/30 20:09:34
  14. 前端知识总结(新人)持续更新

    目录学习前端的第n天,总结一下学过的知识3.JavaScript 学习前端的第n天,总结一下学过的知识 3.JavaScript基本数据类型 Number、String、Boolean、Null、 Undefined、symbol(ES6)引用数据类型 Object(JS中除了基本数据类型以外都是对象,数组函数也是对象)typeof返回值: nu…...

    2024/4/20 17:01:00
  15. React阶段 - 生命周期函数

    React 生命周期函数 生命周期函数的存在,就是为了能够将页面加载的过程分割开来 便于开发和后期维护,提高效率 16.3版本前的 React 生命周期函数 挂载阶段componentWillMount 会有警告,该生命周期函数会被废弃 看他不顺眼可以写为UNSAFE_componentWillMount 组件挂载时触发t…...

    2024/4/16 13:26:16
  16. CentOS服务器下安装git

    本文环境CentOS6.8的虚拟机 **CentOS6.10的阿里云服务器 ** 1.下载git安装包 链接:https://pan.baidu.com/s/1lD42PhWAzW4kaS1QOg3FyQ 提取码:p3bi 2.将git安装包上传到服务器中 2.1 连接服务器在虚拟机命令行中输入ssh root@1.1.1.1这里的1.1.1.1就是你的服务器公网ip地址 输…...

    2024/4/27 10:51:21
  17. 设计模式-Java-单例模式

    一、应用场景一般会在以下两种情况下采用单例模式:资源共享的情况下,避免由于资源操作时导致的性能或损耗等。控制资源的情况下,方便资源之间的互相通信。 场景举例:为了方便线程池对池中的线程进行管理,一般线程池也会采用单例模式。操作系统的文件系统,也是大的单例模式…...

    2024/4/27 4:54:19
  18. JS 调用 麦克风 检测实时音量

    代码较多 看第二份调用代码 里面有注释 关键步骤 1、将成功调用麦克风后的 媒体轨道保存 (第二份代码) 2、 关闭的时候便利轨道数组 逐个关闭 (第三份代码)封装部分 直接调用 封装代码 、 /** Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.** U…...

    2024/5/2 2:31:12
  19. 一个苦逼游戏建模师的内心独白,请在经理的陪同下阅读。

    一、游戏建模的那些常用软件?高模:Maya、3Dmax、Zbrush中模:Maya、3Dmax低模:Maya、3Dmax、Topogun展UV:Maya、Zbrush、Unfold3D、Uvlayout烘焙:Maya、Zbrush、3Dmax、Xnormal、3DO、GrazyBump绘制贴图:Photoshop、Substance Painter 、Quixel SUITE、mari、Bodypaint、…...

    2024/5/1 23:37:00
  20. 图像处理之灰度转化

    灰度转化 目的:将三通道图像(彩色图)转化为单通道图像(灰度图) 公式: 3-->1: GRAY = B * 0.114 + G * 0.587 + R * 0.299 1-->3: R = G = B = GRAY; A = 0 函数:cv2.cvtColor(img,flag) 参数说明:参数1:待转化图像; 参数2:flag就是转换模式,cv2.COLOR_BGR2G…...

    2024/4/16 13:26:06

最新文章

  1. 15.Blender Eevee和Cycles渲染引擎对比

    初步介绍 Eevee是实时渲染的引擎&#xff0c;会省略一些解算方式&#xff0c;尤其对光线和阴影 Cycles会考虑这些因素&#xff0c;所以会对光线和阴影的表达更加真实&#xff0c;有一个实时光线追踪的功能 Cycles渲染完之后&#xff0c;每移动一次画面&#xff0c;都会重新渲染…...

    2024/5/2 2:41:32
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. PostCss:详尽指南之安装和使用

    引言 在现代前端开发中&#xff0c;CSS预处理器如Sass、Less等已经成为提升开发效率、增强代码可维护性的重要工具。然而&#xff0c;随着Web技术的发展&#xff0c;CSS的功能也在不断扩展&#xff0c;一些新的CSS语法&#xff08;如变量、自定义属性、CSS Grid等&#xff09;以…...

    2024/4/30 8:58:35
  4. 电脑上音频太多,播放速度又不一致,如何批量调节音频播放速度?

    批量调节音频速度是现代音频处理中的一个重要环节&#xff0c;尤其在音乐制作、电影剪辑、有声书制作等领域&#xff0c;它能够帮助制作者快速高效地调整音频的播放速度&#xff0c;从而满足特定的制作需求。本文将详细介绍批量调节音频速度的方法、技巧和注意事项&#xff0c;…...

    2024/5/1 9:49:36
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/1 17:30:59
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/30 18:14:14
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/30 18:21:48
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/30 9:43:22
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57