Какой индекс или запрос будет иметь лучшую производительность? - PullRequest
0 голосов
/ 30 июня 2019

У меня есть таблица с 600k строк:

CREATE TABLE `vector` (
  `word_id` int(11) NOT NULL,
  `а` tinyint(1) NOT NULL DEFAULT '0',
    [........]
  `ю` tinyint(1) NOT NULL DEFAULT '0',
  `я` tinyint(1) NOT NULL DEFAULT '0',
  `total` int(8) AS (а+б+в+г+д+e+ё+ж+з+и+й+к+л+м+н+о+п+
                     р+с+т+у+ф+х+ц+ч+ш+щ+ъ+ь+ы+э+ю+я) PERSISTENT
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


ALTER TABLE `vector`
  ADD PRIMARY KEY (`word_id`),
  ADD KEY `а` (`а`),
    [....]
  ADD KEY `ш` (`ш`),
  ADD KEY `ы` (`ы`),
  ADD KEY `ь` (`ь`),
  ADD KEY `ъ` (`ъ`),
  ADD KEY `total` (`total`),
  ADD KEY `а_2` 
    (`а`,`б`,`в`,`г`,`д`,`e`,`ж`,`з`,`и`,`й`,`к`,`л`,`м`,`н`,`о`,`п`,
     `р`,`с`,`т`,`у`,`ф`,`х`,`ц`,`ч`,`ш`,`щ`,`ъ`,`ь`,`ы`,`э`,`ю`,`я`);

Я использую запрос:

select sql_no_cache `word_id`
    from `vector` use index(а_2)
    where а<=2
      AND б=0 AND в=0 AND г=0 AND д=0 AND е=0 AND ё=0 AND ж=0 AND з=0
      AND и=0 AND й=0 AND к=0 AND л=0 AND м=0
      AND н<=1
      AND о=0 AND п=0 AND р=0 AND с=0 AND т=0 AND у=0 AND ф=0 AND х=0 AND ц=0
      AND ч=0 AND ш=0 AND щ=0 AND ъ=0 AND ь=0 AND ы=0 AND э=0 AND ю=0 AND я=0
      AND word_id != 804272 limit 500

это займет около 0,35 с при использовании комбинированного индекса a_2 - как я могу сделать это быстрее?

профилирование:

Sending Data    344.5 ms    99.85%  1   344.5 ms
Preparing   157 µs  0.05%   1   157 µs
Statistics  98 µs   0.03%   1   98 µs
Starting    82 µs   0.02%   1   82 µs
[--CUT--]

ОБЪЯСНЕНИЕ запроса:

id select_type table  type  possible_keys key key_len ref  rows   Extra
1  SIMPLE      vector range а_2           а_2 5       NULL 292073 Using index condition; Using where

без индекса использования (а_2)

1 SIMPLE vector ref PRIMARY,а,б,в,г,д,ё,ж,з,и,й,к,л,м,н,о,п,р,с,т,у,ф,...и 1 const 568037 Using index condition; Using where

Ответы [ 2 ]

0 голосов
/ 01 июля 2019

ё не охватывается указателем а_2 (я предполагаю, что вы хотите проиндексировать все столбцы, используемые в предложении where).Исправьте и попробуйте еще раз, чтобы увидеть, увеличилась ли скорость.

на второй ноте: важен порядок индексированных столбцов.Размещение столбцов с большим количеством элементов в начале индекса увеличит скорость, но делает индекс пригодным для использования только при определенных выборках.

0 голосов
/ 01 июля 2019
  • 35 индексов это много. И большинство никогда не будет использовано.
  • USE INDEX может помочь в некоторых случаях, но может причинить боль в других случаях.
  • Для схемы и таблицы, сформулированных таким образом, нет хорошего индекса.

Если вы ищете слова с определенными буквами, у меня есть несколько нестандартных идей. (Некоторые помогут больше, чем другие.)

всего

SELECT ...
    WHERE total <= 3
      AND ...

может работать намного быстрее.

REGEXP : если вы используете MySQL 8.0 (с улучшенной REGEXP) или MariaDB, то

... AND word REGEXP '^[ан]*$' ...

может привести к другому подходу.

бит : я также размышляю над 32-битным INT UNSIGNED, который указывает, какие символы имеют ненулевое число.

Сортировка : И еще одна мысль - иметь еще один столбец с отсортированными "отсортированными" буквами. Тогда это мгновенный тест, чтобы сказать

WHERE sorted_word IN  ('', 'а', 'аа', 'ан', 'аан', 'н')

Сортировка и REGEXP : (не так быстро, но проще):

WHERE sorted_word REGEXP '^а{0,2}н{0,1}$'

Некоторым может потребоваться наличие word в той же таблице и индексировании.

Однако я предполагаю, что вы ищете короткие слова, содержащие только а и н? Если это не то, что вы ищете, то, пожалуйста, уточните; может быть и другая нестандартная идея, которая поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...