1. 14 Sep, 2024 4 commits
  2. 13 Sep, 2024 2 commits
  3. 12 Sep, 2024 34 commits
    • Sergey Vojtovich's avatar
      Simplified quick_rm_table() and mysql_rename_table() · a0a34e5e
      Sergey Vojtovich authored
      Replaced obscure FRM_ONLY, NO_FRM_RENAME, NO_HA_TABLE, NO_PAR_TABLE with
      straightforward explicit flags:
      
      QRMT_FRM - [re]moves .frm
      QRMT_PAR - [re]moves .par
      QRMT_HANDLER - calls ha_delete_table()/ha_rename_table() and [re]moves
                     high-level indexes
      QRMT_DEFAULT - same as QRMT_FRM | QRMT_HANDLER, which is regular table
                     drop/rename.
      a0a34e5e
    • Sergey Vojtovich's avatar
      ALTER TABLE fixes for high-level indexes · 996e6c6d
      Sergey Vojtovich authored
      quick_rm_table() expects .frm to exist when it removes high-level indexes.
      For cases like ALTER TABLE t1 RENAME TO t2, ENGINE=other_engine .frm was
      removed earlier.
      
      Another option would be removing high-level indexes explicitly before the
      first quick_rm_table() and skipping high-level indexes for subsequent
      quick_rm_table(NO_FRM_RENAME).
      
      But this suggested order may also help with ddl log recovery. That is
      if we crash before high-level indexes are removed, .frm is going to
      exist.
      996e6c6d
    • Sergey Vojtovich's avatar
      ALTER TABLE fixes for high-level indexes · da053420
      Sergey Vojtovich authored
      Disable non-copy ALTER algorithms when VECTOR index is affected. Engines
      are not supposed to handle high-level indexes anyway.
      
      Also fixed misbehaving IF [NOT] EXISTS variants.
      da053420
    • Sergey Vojtovich's avatar
      ALTER TABLE fixes for high-level indexes · 2df6efe3
      Sergey Vojtovich authored
      Fixes for ALTER TABLE ... ADD/DROP COLUMN, ALGORITHM=COPY.
      
      Let quick_rm_table() remove high-level indexes along with original table.
      
      Avoid locking uninitialized LOCK_share for INTERNAL_TMP_TABLEs.
      
      Don't enable bulk insert when altering a table containing vector index.
      InnoDB can't handle situation when bulk insert is enabled for one table
      but disabled for another. We can't do bulk insert on vector index as it
      does table updates currently.
      2df6efe3
    • Sergei Golubchik's avatar
      if we require Eigen, we can as well use it everywhere · d8f3532a
      Sergei Golubchik authored
      it's measurably faster even in items
      d8f3532a
    • Sergei Golubchik's avatar
      VEC_Distance_Cosine() · 1f0e4e51
      Sergei Golubchik authored
      1f0e4e51
    • Sergei Golubchik's avatar
      rename VEC_Distance to VEC_Distance_Euclidean · d9b88394
      Sergei Golubchik authored
      and create a parent Item_func_vec_distance_common class
      d9b88394
    • Sergei Golubchik's avatar
    • Sergei Golubchik's avatar
      0d7d572e
    • Sergei Golubchik's avatar
      cleanup: extract transaction-related part of handlerton · fdaed228
      Sergei Golubchik authored
      into a separate transaction_participant structure
      
      handlerton inherits it, so handlerton itself doesn't change.
      but entities that only need to participate in a transaction,
      like binlog or online alter log, use a transaction_participant
      and no longer need to pretend to be a full-blown but invisible
      storage engine which doesn't support create table.
      fdaed228
    • Sergei Golubchik's avatar
      cleanup: handlerton · 7d4e9aef
      Sergei Golubchik authored
      remove unused methods, reorder methods, add comments
      7d4e9aef
    • Sergei Golubchik's avatar
      AVX-512 support · 149db02c
      Sergei Golubchik authored
      149db02c
    • Sergei Golubchik's avatar
      subdist optimization · 6e6b735b
      Sergei Golubchik authored
      1. randomize all vectors via multiplication by a random orthogonal
         matrix
         * to generate the matrix fill the square matrix with normally
           distributed random values and create an orthogonal matrix with
           the QR decomposition
         * the rnd generator is seeded with the number of dimensions,
           so the matrix will be always the same for a given table
         * multiplication by an orthogonal matrix is a "rotation", so
           does not change distances or angles
      2. when calculating the distance, first calculate a "subdistance",
         the distance between projections to the first subdist_part
         coordinates (=192, best by test, if it's larger it's less efficient,
         if it's smaller the error rate is too high)
      3. calculate the full distance only if "subdistance" isn't confidently
         higher (above subdist_margin) than the distance we're comparing with
         * it might look like it would make sense to do a second projection
           at, say, subdist_part*2, and so on - but in practice one check
           is enough, the projected distance converges quickly and if it
           isn't confidently higher at subdist_part, it won't be later either
      
      This optimization introduces a constant overhead per insert/search
      operation - an input/query vector has to be multiplied by the matrix.
      And the optimization saves on every distance calculation. Thus it is only
      beneficial when a number of distance calculations (which grows with M
      and with the table size) is high enough to outweigh the constant
      overhead. Let's use MIN_ROWS table option to estimate the number of rows
      in the table. use_subdist_heuristic() is optimal for mnist and
      fashion-mnist (784 dimensions, 60k rows) and variations of gist (960
      dimensions, 200k, 400k, 600k, 800k, 1000k rows)
      6e6b735b
    • Sergei Golubchik's avatar
      4bbcc0e3
    • Sergei Golubchik's avatar
      fix for rename · 5251aa97
      Sergei Golubchik authored
      5251aa97
    • Sergey Vojtovich's avatar
      VECTOR indexes support for RENAME TABLE · 6004803c
      Sergey Vojtovich authored
      Rename high-level indexes along with a table.
      6004803c
    • Sergei Golubchik's avatar
    • Sergey Vojtovich's avatar
      Fixed TRUNCATE TABLE against VECTOR indexes · faa9eb6d
      Sergey Vojtovich authored
      This patch fixes only TRUNCATE by recreate variant, there seem to be no
      reasonable engine that uses TRUNCATE by handler method for testing.
      
      Reset index_cinfo so that mi_create is not confused by garbage passed via
      index_file_name and sets MY_DELETE_OLD flag.
      
      Review question: can we add a test case to make sure VECTOR index is empty
      indeed?
      faa9eb6d
    • Sergey Vojtovich's avatar
      e8ca1c1f
    • Sergey Vojtovich's avatar
      c910b45b
    • Sergey Vojtovich's avatar
      36e3a37c
    • Vicențiu Ciorbaru's avatar
      MDEV-32886 Vec_FromText and Vec_ToText · 7444b3a7
      Vicențiu Ciorbaru authored
      This commit introduces two utility functions meant to make working with
      vectors simpler.
      
      Vec_ToText converts a binary vector into a json array of numbers
      (floats).
      Vec_FromText takes in a json array of numbers and converts it into a
      little-endian IEEE float sequence of bytes (4 bytes per float).
      7444b3a7
    • Vicențiu Ciorbaru's avatar
      Introduce String::append_float · 12313ed0
      Vicențiu Ciorbaru authored
      This method will write out a float to a String object, keeping the
      charset of the original string.
      
      Also have Float::to_string make use of String::append_float
      12313ed0
    • Sergei Golubchik's avatar
      mhnsw: make the search less greedy · 04a81ddc
      Sergei Golubchik authored
      introduced a generosity factor that makes the search less greedy.
      it dramatically improves the recall by making the search a bit slower
      (for the same recall one can use half the M and smaller ef).
      
      had to add Queue::safe_push() method that removes one of the
      furthest elements (not necessarily the furthest) in the queue
      to keep it from overflowing.
      04a81ddc
    • Sergei Golubchik's avatar
      cleanup search_layer() · 739035b4
      Sergei Golubchik authored
      to return only as many elements as needed, the caller no longer needs to
      overallocate result arrays for throwaway nodes
      739035b4
    • Sergei Golubchik's avatar
      mhnsw: store coordinates in 16 bits, not 32 · 48f4e9f9
      Sergei Golubchik authored
      use int16_t instead of floats, they're faster and smaller.
      but perform intermediate SIMD calculations with floats to avoid overflows.
      recall drop with such scheme is below 0.002, often none.
      
      int8_t would've been better but the precision loss is too big
      and recall degrades too much.
      48f4e9f9
    • Sergei Golubchik's avatar
      UPDATE/DELETE post-fixes · 96210d23
      Sergei Golubchik authored
      96210d23
    • Sergei Golubchik's avatar
      cleanup: prepare_for_insert() -> prepare_for_modify() · 4f947aee
      Sergei Golubchik authored
      make handler::prepare_for_insert() to be called to prepare
      the handler for writes, INSERT/UPDATE/DELETE.
      4f947aee
    • Hugo Wen's avatar
      MDEV-33408 Initial support for vector DELETE and UPDATE · 046bbad5
      Hugo Wen authored
      When the source row is deleted, mark the corresponding node in HNSW
      index by setting `tref` to null. An index is added for the `tref` in
      secondary table for faster searching of the to-be-marked nodes.
      
      The nodes marked as deleted will still be used for search, but will not
      be included in the final query results.
      
      As skipping deleted nodes and not adding deleted nodes for new-inserted
      nodes' neighbor list could impact the performance, we now only skip
      these nodes in search results.
      
      - for some reason the bitmap is not set for hlindex during the delete so
        I had to temporarily comment out one line
      
      All new code of the whole pull request, including one or several files
      that are either new files or modified ones, are contributed under the
      BSD-new license. I am contributing on behalf of my employer Amazon Web
      Services, Inc.
      046bbad5
    • Sergei Golubchik's avatar
      non-SIMD fallback · 7c892359
      Sergei Golubchik authored
      7c892359
    • Sergei Golubchik's avatar
      mhnsw: inter-statement shared cache · 0c8baa2f
      Sergei Golubchik authored
      * preserve the graph in memory between statements
      * keep it in a TABLE_SHARE, available for concurrent searches
      * nodes are generally read-only, walking the graph doesn't change them
      * distance to target is cached, calculated only once
      * SIMD-optimized bloom filter detects visited nodes
      * nodes are stored in an array, not List, to better utilize bloom filter
      * auto-adjusting heuristic to estimate the number of visited nodes
        (to configure the bloom filter)
      * many threads can concurrently walk the graph. MEM_ROOT and Hash_set
        are protected with a mutex, but walking doesn't need them
      * up to 8 threads can concurrently load nodes into the cache,
        nodes are partitioned into 8 mutexes (8 is chosen arbitrarily, might
        need tuning)
      * concurrent editing is not supported though
      * this is fine for MyISAM, TL_WRITE protects the TABLE_SHARE and the
        graph (note that TL_WRITE_CONCURRENT_INSERT is not allowed, because an
        INSERT into the main table means multiple UPDATEs in the graph)
      * InnoDB uses secondary transaction-level caches linked in a list in
        in thd->ha_data via a fake handlerton
      * on rollback the secondary cache is discarded, on commit nodes
        from the secondary cache are invalidated in the shared cache
        while it is exclusively locked
      * on savepoint rollback both caches are flushed. this can be improved
        in the future with a row visibility callback
      * graph size is controlled by @@mhnsw_cache_size, the cache is flushed
        when it reaches the threshold
      0c8baa2f
    • Sergei Golubchik's avatar
      mhnsw: change storage format · be021b86
      Sergei Golubchik authored
      instead of one row per node per layer, have one row per node.
      store all neighbors for all layers in that row, and the vector itself too
      
      it completely avoids searches in the graph table and
      will allow to implement deletions in the future
      be021b86
    • Sergei Golubchik's avatar
      33d79a44
    • Sergei Golubchik's avatar
      mhnsw: SIMD for euclidean distance · b3a639f1
      Sergei Golubchik authored
      b3a639f1