管理搜索索引

本文介绍管理搜索索引的操作方法。

前提条件

使用限制

数据类型限制

搜索索引仅支持以下数据类型:

  • 基础数据类型:BOOLEAN,BYTE,SHORT,INT,LONG,FLOAT,DOUBLE,STRING,CHAR,BINARY,TIMESTAMP。

  • JSON数据类型:JSON。

重要

JSONTIMESTAMP数据类型自宽表引擎2.6.5开始支持,若当前版本低于2.6.5,请升级小版本2.6.5及以上。

索引数量限制

每张表只能创建一个搜索索引。

数据准备

使用搜索索引前,需要先创建目标表并写入测试数据。

  1. 执行以下语句创建目标表,表名为search_table

    CREATE DATABASE searchindex_db;
    USE searchindex_db;
    CREATE TABLE IF NOT EXISTS search_table (user_id BIGINT, name VARCHAR, age SMALLINT, gender VARCHAR, address VARCHAR, email VARCHAR, city VARCHAR, PRIMARY KEY (user_id));
  2. 执行以下语句在目标表中写入四条数据。

    UPSERT INTO search_table (user_id,name,age,gender,address,email,city) VALUES (1, '张先生', 18, 'M', '北京市朝阳区', 'a***@example.net', '北京');
    UPSERT INTO search_table (user_id,name,age,gender,address,email,city) VALUES (6, '李先生', 32, 'M', '杭州市余杭区', 'a***@example.net', '杭州');
    UPSERT INTO search_table (user_id,name,age,gender,address,email,city) VALUES (20, '王先生', 28, 'M', '杭州市滨江区', 'a***@example.net', '杭州');
    UPSERT INTO search_table (user_id,name,age,gender,address,email,city) VALUES (28, '陈女士', 36, 'F', '深圳市南山区', 'a***@example.net', '深圳');
  3. 执行以下语句查询目标表中的数据。

    SELECT * FROM search_table LIMIT 10;

    查询结果如下:

    +---------+--------+-----+--------+--------------+------------------+------+
    | user_id |  name  | age | gender |   address    |      email       | city |
    +---------+--------+-----+--------+--------------+------------------+------+
    | 1       | 张先生  | 18  | M      | 北京市朝阳区 | a***@example.net  | 北京 |
    | 6       | 李先生  | 32  | M      | 杭州市余杭区 | a***@example.net  | 杭州 |
    | 20      | 王先生  | 28  | M      | 杭州市滨江区 | a***@example.net  | 杭州 |
    | 28      | 陈女士  | 36  | F      | 深圳市南山区 | a***@example.net  | 深圳 |
    +---------+--------+-----+--------+--------------+------------------+------+

管理搜索索引

以上述测试数据为例,创建搜索索引可以满足以下需求:

  • 对任意一列都可以进行快速检索。

  • address字段进行分词查询。

  • email字段进行模糊查询。

  1. 创建搜索索引

    CREATE INDEX IF NOT EXISTS idx USING SEARCH ON search_table (
      name,
      age,
      gender,
      address(type=text, analyzer=ik),
      email,
      city
    ) WITH (numShards=4);
    说明
    • 以上示例指定了numShards的值为4,表示创建的索引idx的分片数量为4。如果不指定numShards,则默认numShards的值为搜索引擎节点数的两倍。在创建用于生产环境的搜索索引前,建议您提前规划好分片数量,避免单分片数据量过大,进而影响系统稳定性。分片设计说明及索引使用建议,可参考numShards参数说明

    • 创建搜索索引语句中,address字段按照ik分词器进行分词。

    • 创建搜索索引时,系统默认在后台异步构建搜索索引,历史数据越多,构建所需的时间越长。如果您希望同步构建搜索索引,请在创建搜索索引语句后添加SYNC关键字。

    • 执行创建搜索索引语句时的报错和解决方法请参考常见问题

  2. 查询指定表的搜索索引信息。

    SHOW INDEX FROM search_table;

    查询结果如下:

    +---------------+--------------+------------+-------------+------------+---------------+------------------------------------+-----------+-------------------+
    | TABLE_SCHEMA  |  DATA_TABLE  | INDEX_NAME | INDEX_STATE | INDEX_TYPE | INDEX_COVERED |            INDEX_COLUMN            | INDEX_TTL | INDEX_DESCRIPTION |
    +---------------+--------------+------------+-------------+------------+---------------+------------------------------------+-----------+-------------------+
    | searchindex_db| search_table | idx        | BUILDING    | SEARCH     | NA            | address,city,age,gender,name,email | 0         |                   |
    +---------------+--------------+------------+-------------+------------+---------------+------------------------------------+-----------+-------------------+
    说明

    搜索索引尚未构建完成时,索引状态为BUILDING。搜索索引构建完成后,索引状态为ACTIVE。返回结果的详细说明,请参见SHOW INDEX

  3. 查询数据,更多查询场景的方法请参见通过搜索索引查询宽表数据

    SELECT * FROM search_table WHERE name='王先生' AND age > 18 AND city='杭州';

    查询结果如下:

    +---------+--------+-----+--------+--------------+------------------+------+
    | user_id |  name  | age | gender |   address    |      email       | city |
    +---------+--------+-----+--------+--------------+------------------+------+
    | 20      | 王先生 | 28   | M      | 杭州市滨江区  | a***@example.net | 杭州 |
    +---------+--------+-----+--------+--------------+------------------+------+
  4. 删除索引

    重要

    2.7.7以下版本的宽表引擎,在删除索引前,您需要先执行ALTER INDEX IF EXISTS idx ON search_table DISABLED;禁用索引。索引禁用后状态为DISABLED,如果想要再次启用,需执行ALTER INDEX IF EXISTS idx ON search_table REBUILD;语句重新构建。

    DROP INDEX IF EXISTS idx ON search_table;

使用动态列

  1. 开启动态列功能。

    ALTER TABLE search_table SET 'DYNAMIC_COLUMNS' = 'true';
  2. 添加动态列。动态列需要显式添加至搜索索引中。此处动态列的示例为password,且password未在建表时定义。

    • 新建搜索索引时指定动态列。

      CREATE INDEX idx USING SEARCH ON search_table(user_id,name,age,gender,password);
    • 已有搜索索引,通过ALTER INDEX命令添加动态列。

      ALTER INDEX idx ON search_table ADD COLUMNS(password);
  3. 写入动态列。动态列password只能写入HexString格式数据。

    UPSERT INTO search_table (user_id,name,age,gender,address,email,city,password) VALUES (30, '王女士', 38, 'F', '深圳市南山区', 'a***@example.net', '深圳', 'ef0011');
  4. 查询动态列。动态列password只能以HexString格式查询。

    SELECT * FROM search_table WHERE password='ef0011' LIMIT 1;

    返回结果如下:

    +---------+--------+-----+--------+--------------+------------------+------+----------+
    | user_id |  name  | age | gender |   address    |      email       | city | password |
    +---------+--------+-----+--------+--------------+------------------+------+----------+
    | 30      | 王女士 | 38   | F      | 深圳市南山区  | a***@example.net | 深圳 | 0xef0011 |
    +---------+--------+-----+--------+--------------+------------------+------+----------+

使用通配符列

通配符列是指列名带有通配符的特殊列。定义通配符列后,可以动态地写入任何满足通配符规则的列,而不需要预先定义每个具体的列。通配符列适用于写入列数量较多,且列名具有特定规则的场景,详细说明请参见通配符列

  1. 创建宽表并定义通配符列。示例中定义了通配符列info_*address_*

    CREATE TABLE search_table (user_id BIGINT, name VARCHAR, age SMALLINT, `info_*` VARCHAR, `address_*` VARCHAR, PRIMARY KEY (user_id)) WITH (wildcard_column='info_*,address_*');
  2. 将通配符列添加至搜索索引。通配符列address_*设定为分词列。

     CREATE INDEX idx USING SEARCH ON search_table (name,age,`info_*`,`address_*`(type=text, analyzer=ik));
  3. 向通配符列写入数据。info_genderinfo_emailinfo_city属于通配符列info_*address_detail属于通配符列address_*,这些列不需要预先定义,在写入时可以自动匹配到对应的通配符列,并继承相应的数据类型、分词等属性。

    UPSERT INTO search_table (user_id,name,age,info_gender,address_detail,info_email,info_city) VALUES (1, '张先生', 18, 'M', '北京市朝阳区', 'a***@example.net', '北京');
    UPSERT INTO search_table (user_id,name,age,info_gender,address_detail,info_email,info_city) VALUES (6, '李先生', 32, 'M', '杭州市余杭区', 'a***@example.net', '杭州');
    UPSERT INTO search_table (user_id,name,age,info_gender,address_detail,info_email,info_city) VALUES (20, '王先生', 28, 'M', '杭州市滨江区', 'a***@example.net', '杭州');
    UPSERT INTO search_table (user_id,name,age,info_gender,address_detail,info_email,info_city) VALUES (28, '陈女士', 36, 'F', '深圳市南山区', 'a***@example.net', '深圳');
  4. 查询通配符列。

    SELECT * FROM search_table WHERE name='王先生' AND age > 18 AND info_city='杭州' LIMIT 10;

    返回结果如下:

    +---------+--------+-----+----------------+-----------+------------------+-------------+
    | user_id | name   | age | address_detail | info_city | info_email       | info_gender |
    +---------+--------+-----+----------------+-----------+------------------+-------------+
    | 20      | 王先生  | 28  | 杭州市滨江区    | 杭州      | a***@example.net | M           |
    +---------+--------+-----+----------------+-----------+------------------+-------------+
    说明

    如需验证查询是否使用了搜索索引,可执行以下EXPLAIN命令EXPLAIN SELECT * FROM search_table WHERE name='王先生' AND age > 18 AND info_city='杭州' LIMIT 10;

常见问题

创建索引时报错The Lindorm Search cluster address is null是什么原因?

原因:未开通搜索索引。

解决方法:开通搜索索引后再次执行创建语句。

报错Only one search index is allowed to be created.怎么处理?

原因:每张表只能创建一个搜索索引,当前表已存在搜索索引。

解决方法:如果不再使用原索引,可以通过DROP INDEX语句将其删除,再重新创建新的索引。