SELECT

本文介绍查询时空数据表的语法。

语法

SELECT [hint_clause] ( select_clause | '*' )
    FROM table_name
    [force index(index_name)]
    [ WHERE where_clause ]
    [ ORDER BY ordering_clause ]
    [ LIMIT integer ] | [LIMIT integer, integer]
select_clause    ::=  selector [ AS identifier ] ( ',' selector [ AS identifier ] )
selector         ::=  column_name
                      | term
                      | function_name '(' [ selector ( ',' selector )* ] ')'
                      | COUNT '(' '*' ')'
where_clause     ::=  relation ( AND|OR relation )*
                      | [st_contains] '(' [ selector ( ',' selector )* ] ')'    
relation         ::=  column_name operator term
                      '(' column_name ( ',' column_name )* ')' operator tuple_literal
operator         ::=  '=' | '<' | '>' | '<=' | '>=' | '!=' | IN | IS NOT? NULL
ordering_clause  ::=  column_name [ ASC | DESC ] ( ',' column_name [ ASC | DESC ] )*

hint_clause::=/*+hint_items*/
hint_items::=hint_item(','hint_item)*
hint_item::=identifier('('hint_option(','hint_option)*')')
hint_option::=expression

参数说明

SELECT语法中部分参数说明如下:

  • 执行SELECT语句时如果您需要强制选择某条索引,请在查询语句后使用force index(index_name)

  • LIMIT后只跟一个数字,表示LIMIT限制。如果跟两个由英文逗号(,)分隔的数字,表示OFFSET和LIMIT条数。

  • 在SELECT语句中添加/*+ _l_allow_filtering_ */,可以强制执行低效查询操作。当执行SELECT语句被Lindorm宽表引擎识别为低效查询时,为了避免这类查询语句给Lindorm带来性能稳定性风险,Lindorm宽表引擎默认不允许执行该类查询,同时会抛出异常。例如Lindorm数据库中存在一张表dt,执行SELECT * FROM dt WHERE nonPK=100;查询语句,会返回以下异常报错。如果查询语句为低效查询语句,解决方法请参见常见问题

    DoNotRetryIOException: Detect inefficient query: SELECT * FROM dt WHERE nonPK=100 supportEmptyResult true. This query may be a full table scan and thus may have unpredictable performance.
  • HINT的使用请参见HINT简介

示例

  • 调用时空函数进行简单查询。时空函数的分类及介绍,请参见函数概览

    SELECT id, ST_AsText(g) FROM gps_data;
    SELECT id, ST_Buffer(g, 1.0) AS buffer FROM gps_data;
  • 调用时空函数进行条件查询,目前支持ST_ContainsST_DWithinST_DWithinSphere三种空间条件的高效执行。

    • 使用ST_Contains函数查询给定空间范围内的点对应的数据。

      SELECT id FROM gps_data WHERE ST_Contains(ST_GeomFromText('POLYGON((...))'), g);
    • 使用ST_DWithin函数查询与中心点在给定平面距离以内的点对应的数据。距离单位:degree。

      SELECT id FROM gps_data WHERE ST_DWithin(ST_GeomFromText('POINT(0 0)'), g, 100);
    • 使用ST_DWithinSphere函数查询与中心点在给定球面距离以内的点对应的数据。距离单位:米。

      SELECT id FROM gps_data WHERE ST_DWithinSphere(ST_GeomFromText('POINT(0 0)'), g, 100);
  • 如果查询语句为低效查询语句,在查询语句中增加/*+ _l_allow_filtering_ */,表示跳过该检查,强制执行低效查询操作。

    SELECT /*+ _l_allow_filtering_ */ * FROM gps_data WHERE ST_Within(g,ST_GeomFromText('POLYGON((...))'));
    说明

    如果SELECT查询的条件同时满足以下三个条件,则该查询语句被认为是低效查询语句。

    • WHERE语句中没有指定表的第一个主键的上下界。

    • WHERE语句中没有指定索引表中第一个索引列的上下界。

    • WHERE语句中存在非第一个主键(或非第一个索引列)的条件。

开启并行查询

开启Lindorm并行查询功能可以将时空查询的性能提升至原来的两倍以上。一般情况下,Lindorm并行查询能力默认为关闭状态,请提交工单开启并行查询功能。开启并行查询功能后,需要通过HINT设置_l_enable_parallel_参数,为每条SQL语句指定并行度。如果不指定并行度,则该条SQL语句无法使用并行查询能力。更多信息,请参见HINT简介

使用限制

如果查询使用索引回查主表功能,那么将无法使用并行查询能力。通常建议在创建索引时将查询所需列冗余,避免回查主表。

示例

  • 采用默认最大并行度

    说明

    并行查询能力默认为关闭状态,请提交工单开启并行查询功能。

    不指定并行度时,系统会根据查询复杂度,自动采用最优的并行度。

    SELECT /*+_l_enable_parallel_*/ id FROM gps_data WHERE ST_Contains(ST_GeomFromText('POLYGON((...))'), g);
  • 自定义并行度

    如下示例设置自定义并行度为8时,那么最大的并行度为8。

    SELECT /*+_l_enable_parallel_(8)*/ id FROM gps_data WHERE ST_Contains(ST_GeomFromText('POLYGON((...))'), g);
    说明
    • 自定义并行度必须为大于等于1的整数,如果自定义并行度超过默认最大并行度,则采用默认最大并行度。

    • 当您不知道并行度设置成多少合适时,建议不指定并行度,系统将自动采用最优的并行度。

常见问题

  • Q:什么情况下,查询语句被认为是低效查询语句?

    A:如果SELECT查询的条件同时满足下列三个条件,则该查询被认为是低效查询。

    • WHERE语句中没有指定表的第一个主键的上下界。

    • WHERE语句中没有指定索引表中第一个索引列的上下界。

    • WHERE语句中存在非第一个主键(或非第一个索引列)的条件。

  • Q:如果查询语句为低效查询语句,应该怎么解决?

    A:解决方法有以下四种。

    • 在查询语句中增加/*+ _l_allow_filtering_ */,如下语句,表示跳过该检查,强制执行低效查询操作。

      SELECT /*+ _l_allow_filtering_ */ * FROM dt WHERE nonPK=100;
    • WHERE语句中增加表的主键条件。

    • 修改表的主键设计,避免大查询,具体详情请参见如何设计宽表主键

    • 使用高性能原生二级索引,具体详情请参见二级索引