1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

initial support for vector indexes

MDEV-33407 Parser support for vector indexes

The syntax is

  create table t1 (... vector index (v) ...);

limitation:
* v is a binary string and NOT NULL
* only one vector index per table
* temporary tables are not supported

MDEV-33404 Engine-independent indexes: subtable method

added support for so-called "high level indexes", they are not visible
to the storage engine, implemented on the sql level. For every such
an index in a table, say, t1, the server implicitly creates a second
table named, like, t1#i#05 (where "05" is the index number in t1).
This table has a fixed structure, no frm, not accessible directly,
doesn't go into the table cache, needs no MDLs.

MDEV-33406 basic optimizer support for k-NN searches

for a query like SELECT ... ORDER BY func() optimizer will use
item_func->part_of_sortkey() to decide what keys can be used
to resolve ORDER BY.
This commit is contained in:
Sergei Golubchik
2024-01-17 15:32:45 +01:00
parent 9ccf02a9a7
commit d6add9a03d
28 changed files with 888 additions and 89 deletions

View File

@@ -1314,7 +1314,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
TABLE_LIST *table;
char path[FN_REFLEN + 1];
LEX_CSTRING alias= null_clex_str;
LEX_CUSTRING version;
LEX_CUSTRING version= {0, 0};
LEX_CSTRING partition_engine_name= null_clex_str;
StringBuffer<160> unknown_tables(system_charset_info);
DDL_LOG_STATE local_ddl_log_state;
@@ -1404,6 +1404,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
Table_type table_type;
size_t path_length= 0;
char *path_end= 0;
uint drop_index_from= 0, drop_index_to=0;
error= 0;
DBUG_PRINT("table", ("table_l: '%s'.'%s' table: %p s: %p",
@@ -1545,6 +1547,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
version= thd->strmake_lex_custring(share->tabledef_version);
if (plugin_ref pp= IF_PARTITIONING(share->default_part_plugin, NULL))
partition_engine_name= thd->strmake_lex_cstring(*plugin_name(pp));
drop_index_from= share->keys;
drop_index_to= share->total_keys;
tdc_release_share(share);
}
else
@@ -1620,14 +1624,12 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
}
#endif
error= -1;
if (thd->locked_tables_mode == LTM_LOCK_TABLES ||
thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)
{
if (wait_while_table_is_used(thd, table->table, HA_EXTRA_NOT_USED))
{
error= -1;
goto err;
}
close_all_tables_for_name(thd, table->table->s,
HA_EXTRA_PREPARE_FOR_DROP, NULL);
table->table= 0;
@@ -1652,13 +1654,24 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables,
else
res= ddl_log_drop_table(ddl_log_state, hton, &cpath, &db, &table_name);
if (res)
{
error= -1;
goto err;
if (path + sizeof(path) > path_end + HLINDEX_BUF_LEN)
{
for (uint i= drop_index_from; i < drop_index_to; i++)
{
my_snprintf(path_end, HLINDEX_BUF_LEN, HLINDEX_TEMPLATE, i);
int err= ha_delete_table(thd, hton, path, &db, &table_name, enoent_warning);
set_if_bigger(error, err);
}
*path_end= 0;
}
debug_crash_here("ddl_log_drop_before_delete_table");
error= ha_delete_table(thd, hton, path, &db, &table_name, enoent_warning);
{
int err= ha_delete_table(thd, hton, path, &db, &table_name, enoent_warning);
set_if_bigger(error, err);
}
debug_crash_here("ddl_log_drop_after_delete_table");
if (!error)
@@ -2131,6 +2144,7 @@ bool quick_rm_table(THD *thd, handlerton *base, const LEX_CSTRING *db,
- LONG UNIQUE keys
- Normal keys
- Fulltext keys
- Vector keys
This will make checking for duplicated keys faster and ensure that
PRIMARY keys are prioritized.
@@ -2167,6 +2181,10 @@ static int sort_keys(KEY *a, KEY *b)
(b_flags & HA_KEY_HAS_PART_KEY_SEG));
}
/* must be very last */
return_if_nonzero((a->algorithm == HA_KEY_ALG_VECTOR) -
(b->algorithm == HA_KEY_ALG_VECTOR));
return_if_nonzero((a->algorithm == HA_KEY_ALG_FULLTEXT) -
(b->algorithm == HA_KEY_ALG_FULLTEXT));
@@ -2697,6 +2715,34 @@ Type_handler_blob_common::Key_part_spec_init_ft(Key_part_spec *part,
}
bool Type_handler_string::Key_part_spec_init_vector(Key_part_spec *part,
const Column_definition &def)
const
{
part->length= 0;
return def.charset != &my_charset_bin;
}
bool Type_handler_varchar::Key_part_spec_init_vector(Key_part_spec *part,
const Column_definition &def)
const
{
part->length= 0;
return def.charset != &my_charset_bin;
}
bool
Type_handler_blob_common::Key_part_spec_init_vector(Key_part_spec *part,
const Column_definition &def)
const
{
part->length= 1;
return def.charset != &my_charset_bin;
}
static bool
key_add_part_check_null(const handler *file, KEY *key_info,
const Column_definition *sql_field,
@@ -3196,6 +3242,10 @@ mysql_prepare_create_table_finalize(THD *thd, HA_CREATE_INFO *create_info,
case Key::FOREIGN_KEY:
key_number--; // Skip this key
continue;
case Key::VECTOR:
if (key->key_create_info.algorithm == HA_KEY_ALG_UNDEF)
key->key_create_info.algorithm= HA_KEY_ALG_VECTOR;
break;
case Key::IGNORE_KEY:
DBUG_ASSERT(0);
break;
@@ -3318,6 +3368,27 @@ mysql_prepare_create_table_finalize(THD *thd, HA_CREATE_INFO *create_info,
const Type_handler *field_type= sql_field->type_handler();
switch(key->type) {
case Key::VECTOR:
if (field_type->Key_part_spec_init_vector(column, *sql_field))
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "VECTOR INDEX");
DBUG_RETURN(TRUE);
}
if (sql_field->check_vcol_for_key(thd))
DBUG_RETURN(TRUE);
if (!(sql_field->flags & NOT_NULL_FLAG))
{
my_error(ER_INDEX_CANNOT_HAVE_NULL, MYF(0), "VECTOR");
DBUG_RETURN(TRUE);
}
if (create_info->tmp_table())
{
my_error(ER_NO_INDEX_ON_TEMPORARY, MYF(0), "VECTOR",
file->table_type());
DBUG_RETURN(TRUE);
}
break;
case Key::FULLTEXT:
if (field_type->Key_part_spec_init_ft(column, *sql_field) ||
(ft_key_charset && sql_field->charset != ft_key_charset))
@@ -3649,6 +3720,13 @@ without_overlaps_err:
}
create_info->null_bits= null_fields;
if (*key_count >= 2 &&
(*key_info_buffer)[*key_count-2].algorithm == HA_KEY_ALG_VECTOR)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "multiple VECTOR indexes");
DBUG_RETURN(TRUE);
}
/* Check fields. */
it.rewind();
while ((sql_field=it++))
@@ -8912,6 +8990,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
else if (key_info->algorithm == HA_KEY_ALG_FULLTEXT)
key_type= Key::FULLTEXT;
else if (key_info->algorithm == HA_KEY_ALG_VECTOR)
key_type= Key::VECTOR;
else
key_type= Key::MULTIPLE;