获取 PartiQL 语句统计信息 - Amazon Quantum Ledger Database (Amazon QLDB)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

获取 PartiQL 语句统计信息

Amazon QLDB 提供语句执行统计信息,可帮助您通过运行更高效的 PartiQL 语句来优化 QLDB 的使用。QLDB 将这些统计信息与语句结果一起返回。它们包含量化消耗的 I/O 使用情况和服务器端处理时间的指标,您可以使用这些指标来识别低效的语句。

此功能当前用于QLDB 控制台QLDB Shell以及最新版 QLDB 驱动程序(所有语言)的PartiQL 编辑器。您还可在控制台上查看查询历史的语句统计信息。

I/O 使用率

I/O 使用率指标介绍了读取 I/O 请求的数量。如果读取 I/O 请求的数量高于预期,则表示语句未经优化,例如缺少索引。我们建议您在上一主题 优化查询性能 中复习最优查询模式

注意

在非空表上运行CREATE INDEX语句时,I/O 使用率指标仅包含同步索引创建调用的读取请求。

QLDB 异步为表中的任何现有文档创建索引。这些异步读取请求不包括在语句结果的 I/O 使用率指标中。异步读取请求单独收费,且在索引构建完成后计入您的读取 I/O 总数。

使用 QLDB 控制台

若要使用 QLDB 控制台获取语句的读取 I/O 使用情况,请执行以下步骤:

  1. 通过以下网址打开 Amazon QLDB 控制台:https://console.aws.amazon.com/qldb

  2. 在导航窗格中,选择 ‬PartiQL 编辑器

  3. 从分类账下拉列表中选择分类帐。

  4. 在查询编辑器窗口中,输入您选择的任何语句,然后选择 运行。以下是查询示例。

    SELECT * FROM testTable WHERE firstName = 'Jim'

    要运行语句,你可对 Windows 使用快捷键Ctrl+Enter,对 macOS 使用Cmd+Return。有关更多键盘快捷键的信息,请参阅 ‭PartiQL 编辑器键盘快捷键

  5. 在查询编辑器窗口下方,您的查询结果包括读取 I/O,此语句发出的读取请求数。

您还可通过执行以下步骤来查看查询历史记录的读取 I/O:

  1. 在导航窗格中,选择PartiQL 编辑器下的最新查询

  2. 读取 I/O 列显示每条语句发出的读取请求数。

使用 QLDB 驱动程序

要使用 QLDB 驱动程序获取语句 I/O 使用情况,请调用结果的流指针或缓冲指针的getConsumedIOs操作。

以下代码示例显示如何从语句结果的流指针 中读取 I/O。

Java
import com.amazon.ion.IonSystem; import com.amazon.ion.IonValue; import com.amazon.ion.system.IonSystemBuilder; import software.amazon.qldb.IOUsage; import software.amazon.qldb.Result; IonSystem ionSystem = IonSystemBuilder.standard().build(); IonValue ionFirstName = ionSystem.newString("Jim"); driver.execute(txn -> { Result result = txn.execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName); for (IonValue ionValue : result) { // User code here to handle results } IOUsage ioUsage = result.getConsumedIOs(); long readIOs = ioUsage.getReadIOs(); });
.NET
using Amazon.IonDotnet.Builders; using Amazon.IonDotnet.Tree; using Amazon.QLDB.Driver; using IAsyncResult = Amazon.QLDB.Driver.IAsyncResult; // This is one way of creating Ion values. We can also use a ValueFactory. // For more details, see: https://docs.aws.amazon.com/qldb/latest/developerguide/driver-cookbook-dotnet.html#cookbook-dotnet.ion IIonValue ionFirstName = IonLoader.Default.Load("Jim"); await driver.Execute(async txn => { IAsyncResult result = await txn.Execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName); // Iterate through stream cursor to accumulate read IOs. await foreach (IIonValue ionValue in result) { // User code here to handle results. // Warning: It is bad practice to rely on results within a lambda block, unless // it is to check the state of a result. This is because lambdas are retryable. } var ioUsage = result.GetConsumedIOs(); var readIOs = ioUsage?.ReadIOs; });
注意

要转换为同步代码,请移除awaitasync关键字,然后将 IAsyncResult类型更改为IResult

Go
import ( "context" "fmt" "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver" ) driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { result, err := txn.Execute("SELECT * FROM testTable WHERE firstName = ?", "Jim") if err != nil { panic(err) } for result.Next(txn) { // User code here to handle results } ioUsage := result.GetConsumedIOs() readIOs := *ioUsage.GetReadIOs() fmt.Println(readIOs) return nil,nil })
Node.js
import { IOUsage, ResultReadable, TransactionExecutor } from "amazon-qldb-driver-nodejs"; await driver.executeLambda(async (txn: TransactionExecutor) => { const result: ResultReadable = await txn.executeAndStreamResults("SELECT * FROM testTable WHERE firstName = ?", "Jim"); for await (const chunk of result) { // User code here to handle results } const ioUsage: IOUsage = result.getConsumedIOs(); const readIOs: number = ioUsage.getReadIOs(); });
Python
def get_read_ios(transaction_executor): cursor = transaction_executor.execute_statement("SELECT * FROM testTable WHERE firstName = ?", "Jim") for row in cursor: # User code here to handle results pass consumed_ios = cursor.get_consumed_ios() read_ios = consumed_ios.get('ReadIOs') qldb_driver.execute_lambda(lambda txn: get_read_ios(txn))

以下代码示例显示如何从语句结果的缓冲指针中读取 I/O。这将返回来自 ExecuteStatementFetchPage 请求的读取 I/O 总数。

Java
import com.amazon.ion.IonSystem; import com.amazon.ion.IonValue; import com.amazon.ion.system.IonSystemBuilder; import software.amazon.qldb.IOUsage; import software.amazon.qldb.Result; IonSystem ionSystem = IonSystemBuilder.standard().build(); IonValue ionFirstName = ionSystem.newString("Jim"); Result result = driver.execute(txn -> { return txn.execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName); }); IOUsage ioUsage = result.getConsumedIOs(); long readIOs = ioUsage.getReadIOs();
.NET
using Amazon.IonDotnet.Builders; using Amazon.IonDotnet.Tree; using Amazon.QLDB.Driver; using IAsyncResult = Amazon.QLDB.Driver.IAsyncResult; IIonValue ionFirstName = IonLoader.Default.Load("Jim"); IAsyncResult result = await driver.Execute(async txn => { return await txn.Execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName); }); var ioUsage = result.GetConsumedIOs(); var readIOs = ioUsage?.ReadIOs;
注意

要转换为同步代码,请移除awaitasync关键字,然后将 IAsyncResult类型更改为IResult

Go
import ( "context" "fmt" "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver" ) result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { result, err := txn.Execute("SELECT * FROM testTable WHERE firstName = ?", "Jim") if err != nil { return nil, err } return txn.BufferResult(result) }) if err != nil { panic(err) } qldbResult := result.(*qldbdriver.BufferedResult) ioUsage := qldbResult.GetConsumedIOs() readIOs := *ioUsage.GetReadIOs() fmt.Println(readIOs)
Node.js
import { IOUsage, Result, TransactionExecutor } from "amazon-qldb-driver-nodejs"; const result: Result = await driver.executeLambda(async (txn: TransactionExecutor) => { return await txn.execute("SELECT * FROM testTable WHERE firstName = ?", "Jim"); }); const ioUsage: IOUsage = result.getConsumedIOs(); const readIOs: number = ioUsage.getReadIOs();
Python
cursor = qldb_driver.execute_lambda( lambda txn: txn.execute_statement("SELECT * FROM testTable WHERE firstName = ?", "Jim")) consumed_ios = cursor.get_consumed_ios() read_ios = consumed_ios.get('ReadIOs')
注意

流指针是有状态的,因为它会对结果集分页。因此,getConsumedIOsgetTimingInformation操作会返回您调用这些指标时的累积指标。

缓冲后的指针将结果集缓存至内存中,并返回累积的指标总数。

计时信息

计时信息指标描述了服务器端处理时间(以毫秒为单位)。服务器端处理时间定义为 QLDB 在处理语句上所需时间。这不包括网络通话或暂停时间。该指标将 QLDB 服务端的处理时间与客户端处理时间区分开来。

使用 QLDB 控制台

要使用 QLDB 控制台获取语句时序信息,请执行以下步骤:

  1. 通过以下网址打开 Amazon QLDB 控制台:https://console.aws.amazon.com/qldb

  2. 在导航窗格中,选择 ‬PartiQL 编辑器

  3. 从分类账下拉列表中选择分类帐。

  4. 在查询编辑器窗口中,输入您选择的任何语句,然后选择 运行。以下是查询示例。

    SELECT * FROM testTable WHERE firstName = 'Jim'

    要运行语句,你可对 Windows 使用快捷键Ctrl+Enter,对 macOS 使用Cmd+Return。有关更多键盘快捷键的信息,请参阅 ‭PartiQL 编辑器键盘快捷键

  5. 在查询编辑器窗口下方,您的查询结果包括服务器端延迟,即 QLDB 收到语句请求与发送响应之间的时间长度。这是总查询时长子集。

您还可通过执行以下步骤来查看查询历史记录的计时信息:

  1. 在导航窗格中,选择PartiQL 编辑器下的最新查询

  2. 执行时间 (ms)列将会显示每条语句的计时信息。

使用 QLDB 驱动程序

要使用 QLDB 驱动程序获取语句的计时信息,请调用结果的流指针或缓冲指针的getTimingInformation操作。

以下代码示例显示如何从语句结果的流指针 中获取处理时间。

Java
import com.amazon.ion.IonSystem; import com.amazon.ion.IonValue; import com.amazon.ion.system.IonSystemBuilder; import software.amazon.qldb.Result; import software.amazon.qldb.TimingInformation; IonSystem ionSystem = IonSystemBuilder.standard().build(); IonValue ionFirstName = ionSystem.newString("Jim"); driver.execute(txn -> { Result result = txn.execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName); for (IonValue ionValue : result) { // User code here to handle results } TimingInformation timingInformation = result.getTimingInformation(); long processingTimeMilliseconds = timingInformation.getProcessingTimeMilliseconds(); });
.NET
using Amazon.IonDotnet.Builders; using Amazon.IonDotnet.Tree; using Amazon.QLDB.Driver; using IAsyncResult = Amazon.QLDB.Driver.IAsyncResult; IIonValue ionFirstName = IonLoader.Default.Load("Jim"); await driver.Execute(async txn => { IAsyncResult result = await txn.Execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName); // Iterate through stream cursor to accumulate processing time. await foreach(IIonValue ionValue in result) { // User code here to handle results. // Warning: It is bad practice to rely on results within a lambda block, unless // it is to check the state of a result. This is because lambdas are retryable. } var timingInformation = result.GetTimingInformation(); var processingTimeMilliseconds = timingInformation?.ProcessingTimeMilliseconds; });
注意

要转换为同步代码,请移除awaitasync关键字,然后将 IAsyncResult类型更改为IResult

Go
import ( "context" "fmt" "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver" ) driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { result, err := txn.Execute("SELECT * FROM testTable WHERE firstName = ?", "Jim") if err != nil { panic(err) } for result.Next(txn) { // User code here to handle results } timingInformation := result.GetTimingInformation() processingTimeMilliseconds := *timingInformation.GetProcessingTimeMilliseconds() fmt.Println(processingTimeMilliseconds) return nil, nil })
Node.js
import { ResultReadable, TimingInformation, TransactionExecutor } from "amazon-qldb-driver-nodejs"; await driver.executeLambda(async (txn: TransactionExecutor) => { const result: ResultReadable = await txn.executeAndStreamResults("SELECT * FROM testTable WHERE firstName = ?", "Jim"); for await (const chunk of result) { // User code here to handle results } const timingInformation: TimingInformation = result.getTimingInformation(); const processingTimeMilliseconds: number = timingInformation.getProcessingTimeMilliseconds(); });
Python
def get_processing_time_milliseconds(transaction_executor): cursor = transaction_executor.execute_statement("SELECT * FROM testTable WHERE firstName = ?", "Jim") for row in cursor: # User code here to handle results pass timing_information = cursor.get_timing_information() processing_time_milliseconds = timing_information.get('ProcessingTimeMilliseconds') qldb_driver.execute_lambda(lambda txn: get_processing_time_milliseconds(txn))

以下代码示例显示如何从语句结果的 缓冲指针 中获取处理时间。这将返回来自 ExecuteStatementFetchPage 请求的总处理时间。

Java
import com.amazon.ion.IonSystem; import com.amazon.ion.IonValue; import com.amazon.ion.system.IonSystemBuilder; import software.amazon.qldb.Result; import software.amazon.qldb.TimingInformation; IonSystem ionSystem = IonSystemBuilder.standard().build(); IonValue ionFirstName = ionSystem.newString("Jim"); Result result = driver.execute(txn -> { return txn.execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName); }); TimingInformation timingInformation = result.getTimingInformation(); long processingTimeMilliseconds = timingInformation.getProcessingTimeMilliseconds();
.NET
using Amazon.IonDotnet.Builders; using Amazon.IonDotnet.Tree; using Amazon.QLDB.Driver; using IAsyncResult = Amazon.QLDB.Driver.IAsyncResult; IIonValue ionFirstName = IonLoader.Default.Load("Jim"); IAsyncResult result = await driver.Execute(async txn => { return await txn.Execute("SELECT * FROM testTable WHERE firstName = ?", ionFirstName); }); var timingInformation = result.GetTimingInformation(); var processingTimeMilliseconds = timingInformation?.ProcessingTimeMilliseconds;
注意

要转换为同步代码,请移除awaitasync关键字,然后将 IAsyncResult类型更改为IResult

Go
import ( "context" "fmt" "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver" ) result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { result, err := txn.Execute("SELECT * FROM testTable WHERE firstName = ?", "Jim") if err != nil { return nil, err } return txn.BufferResult(result) }) if err != nil { panic(err) } qldbResult := result.(*qldbdriver.BufferedResult) timingInformation := qldbResult.GetTimingInformation() processingTimeMilliseconds := *timingInformation.GetProcessingTimeMilliseconds() fmt.Println(processingTimeMilliseconds)
Node.js
import { Result, TimingInformation, TransactionExecutor } from "amazon-qldb-driver-nodejs"; const result: Result = await driver.executeLambda(async (txn: TransactionExecutor) => { return await txn.execute("SELECT * FROM testTable WHERE firstName = ?", "Jim"); }); const timingInformation: TimingInformation = result.getTimingInformation(); const processingTimeMilliseconds: number = timingInformation.getProcessingTimeMilliseconds();
Python
cursor = qldb_driver.execute_lambda( lambda txn: txn.execute_statement("SELECT * FROM testTable WHERE firstName = ?", "Jim")) timing_information = cursor.get_timing_information() processing_time_milliseconds = timing_information.get('ProcessingTimeMilliseconds')
注意

流指针是有状态的,因为它会对结果集分页。因此,getConsumedIOsgetTimingInformation操作会返回您调用这些指标时的累积指标。

缓冲后的指针将结果集缓存至内存中,并返回累积的指标总数。

要了解如何查询系统目录,请继续 查询系统目录