InnoDB support for hlindexes and mhnsw
* mhnsw: * use primary key, innodb loves and (and the index cannot have dupes anyway) * MyISAM is ok with that, performance-wise * must be ha_rnd_init(0) because we aren't going to scan * MyISAM resets the position on ha_rnd_init(0) so query it before * oh, and use the correct handler, just in case * HA_ERR_RECORD_IS_THE_SAME is no error * innodb: * return ref_length on create * don't assume table->pos_in_table_list is set * ok, assume away, but only for system versioned tables * set alter_info on create (InnoDB needs to check for FKs) * pair external_lock/external_unlock correctly
This commit is contained in:
parent
2efd9b17ba
commit
25b4000290
6
mysql-test/main/vector.combinations
Normal file
6
mysql-test/main/vector.combinations
Normal file
@ -0,0 +1,6 @@
|
||||
[innodb]
|
||||
innodb
|
||||
default-storage-engine=innodb
|
||||
|
||||
[myisam]
|
||||
default-storage-engine=myisam
|
@ -1,3 +1,4 @@
|
||||
replace_result InnoDB MyISAM;
|
||||
error ER_NO_INDEX_ON_TEMPORARY;
|
||||
create temporary table t1 (id int auto_increment primary key, v blob not null, vector index (v));
|
||||
|
||||
@ -7,6 +8,7 @@ create table t1 (id int auto_increment primary key,
|
||||
v blob not null, vector index (v));
|
||||
|
||||
create table t1 (id int auto_increment primary key, v blob not null, vector index (v));
|
||||
replace_result InnoDB MyISAM;
|
||||
show create table t1;
|
||||
show keys from t1;
|
||||
query_vertical select * from information_schema.statistics where table_name='t1';
|
||||
|
@ -6416,9 +6416,12 @@ int ha_create_table(THD *thd, const char *path, const char *db,
|
||||
DBUG_ASSERT(share.key_info[share.keys].algorithm == HA_KEY_ALG_VECTOR);
|
||||
TABLE_SHARE index_share;
|
||||
char file_name[FN_REFLEN+1];
|
||||
Alter_info index_ainfo;
|
||||
HA_CREATE_INFO index_cinfo;
|
||||
char *path_end= strmov(file_name, path);
|
||||
|
||||
index_cinfo.alter_info= &index_ainfo;
|
||||
|
||||
if ((error= share.path.length > sizeof(file_name) - HLINDEX_BUF_LEN))
|
||||
goto err;
|
||||
|
||||
|
@ -9900,8 +9900,6 @@ int TABLE::open_hlindexes_for_write()
|
||||
for (uint i= s->keys; i < s->total_keys; i++)
|
||||
{
|
||||
KEY *key= s->key_info + i;
|
||||
if (hlindex)
|
||||
hlindex->in_use= 0;
|
||||
for (uint j=0; j < key->usable_key_parts; j++)
|
||||
if (bitmap_is_set(write_set, key->key_part[j].fieldnr - 1))
|
||||
{
|
||||
@ -9915,8 +9913,11 @@ int TABLE::open_hlindexes_for_write()
|
||||
|
||||
int TABLE::reset_hlindexes()
|
||||
{
|
||||
if (hlindex)
|
||||
if (hlindex && hlindex->in_use)
|
||||
{
|
||||
hlindex->file->ha_external_unlock(in_use);
|
||||
hlindex->in_use= 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -283,8 +283,11 @@ static int write_neighbors(MHNSW_Context *ctx, size_t layer,
|
||||
err= graph->file->ha_index_read_map(graph->record[1], key,
|
||||
HA_WHOLE_KEY, HA_READ_KEY_EXACT);
|
||||
if (!err)
|
||||
{
|
||||
err= graph->file->ha_update_row(graph->record[1], graph->record[0]);
|
||||
|
||||
if (err == HA_ERR_RECORD_IS_THE_SAME)
|
||||
err= 0;
|
||||
}
|
||||
}
|
||||
my_safe_afree(neighbor_array_bytes, total_size);
|
||||
return err;
|
||||
@ -426,7 +429,9 @@ int mhnsw_insert(TABLE *table, KEY *keyinfo)
|
||||
|
||||
const double NORMALIZATION_FACTOR= 1 / std::log(thd->variables.hnsw_max_connection_per_layer);
|
||||
|
||||
if (int err= h->ha_rnd_init(1))
|
||||
table->file->position(table->record[0]);
|
||||
|
||||
if (int err= h->ha_rnd_init(0))
|
||||
return err;
|
||||
|
||||
SCOPE_EXIT([h](){ h->ha_rnd_end(); });
|
||||
@ -436,15 +441,13 @@ int mhnsw_insert(TABLE *table, KEY *keyinfo)
|
||||
|
||||
SCOPE_EXIT([graph](){ graph->file->ha_index_end(); });
|
||||
|
||||
h->position(table->record[0]);
|
||||
|
||||
if (int err= graph->file->ha_index_last(graph->record[0]))
|
||||
{
|
||||
if (err != HA_ERR_END_OF_FILE)
|
||||
return err;
|
||||
|
||||
// First insert!
|
||||
FVectorNode target(&ctx, h->ref);
|
||||
FVectorNode target(&ctx, table->file->ref);
|
||||
ctx.target= ⌖
|
||||
return write_neighbors(&ctx, 0, target);
|
||||
}
|
||||
@ -465,7 +468,7 @@ int mhnsw_insert(TABLE *table, KEY *keyinfo)
|
||||
if (ctx.vec_len * sizeof(float) != res->length())
|
||||
return bad_value_on_insert(vec_field);
|
||||
|
||||
FVectorNode target(&ctx, h->ref, res->ptr());
|
||||
FVectorNode target(&ctx, table->file->ref, res->ptr());
|
||||
ctx.target= ⌖
|
||||
|
||||
double new_num= my_rnd(&thd->rand);
|
||||
@ -612,7 +615,7 @@ const LEX_CSTRING mhnsw_hlindex_table_def(THD *thd, uint ref_length)
|
||||
" layer int not null, "
|
||||
" src varbinary(%u) not null, "
|
||||
" neighbors varbinary(%u) not null,"
|
||||
" index (layer, src)) ";
|
||||
" primary key (layer, src)) ";
|
||||
size_t len= sizeof(templ) + 32;
|
||||
char *s= thd->alloc(len);
|
||||
len= my_snprintf(s, len, templ, ref_length, 2 * ref_length *
|
||||
|
@ -8291,13 +8291,15 @@ calc_row_difference(
|
||||
|
||||
ut_a(buf <= (byte*) original_upd_buff + buff_len);
|
||||
|
||||
const TABLE_LIST *tl= table->pos_in_table_list;
|
||||
const uint8 op_map= tl->trg_event_map | tl->slave_fk_event_map;
|
||||
/* Used to avoid reading history in FK check on DELETE (see MDEV-16210). */
|
||||
prebuilt->upd_node->is_delete =
|
||||
(op_map & trg2bit(TRG_EVENT_DELETE)
|
||||
&& table->versioned(VERS_TIMESTAMP))
|
||||
? VERSIONED_DELETE : NO_DELETE;
|
||||
if (const TABLE_LIST *tl= table->pos_in_table_list)
|
||||
{
|
||||
const uint8 op_map= tl->trg_event_map | tl->slave_fk_event_map;
|
||||
/* Used to avoid reading history in FK check on DELETE (see MDEV-16210). */
|
||||
prebuilt->upd_node->is_delete =
|
||||
(op_map & trg2bit(TRG_EVENT_DELETE)
|
||||
&& table->versioned(VERS_TIMESTAMP))
|
||||
? VERSIONED_DELETE : NO_DELETE;
|
||||
}
|
||||
|
||||
if (prebuilt->versioned_write) {
|
||||
/* Guaranteed by CREATE TABLE, but anyway we make sure we
|
||||
@ -13170,6 +13172,11 @@ ha_innobase::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info,
|
||||
else if (!error && m_prebuilt)
|
||||
m_prebuilt->table= info.table();
|
||||
|
||||
if (form->s->primary_key >= MAX_KEY)
|
||||
ref_length = DATA_ROW_ID_LEN;
|
||||
else
|
||||
ref_length = form->key_info[form->s->primary_key].key_length;
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user