используя индекс с таблицей mysql - PullRequest
2 голосов
/ 08 октября 2011

В моей базе данных MySQL есть таблица с 3 столбцами,

его структура:

CREATE TABLE `Table` (
    `value1` VARCHAR(50) NOT NULL DEFAULT '',
    `value2` VARCHAR(50) NOT NULL DEFAULT '',
    `value3` TEXT NULL,
    `value4` VARCHAR(50) NULL DEFAULT NULL,
      `value5` VARCHAR(50) NULL DEFAULT NULL,
       PRIMARY KEY (`value1`, `value2`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT

первый и второй столбцы: varchar(50)

и они оба объединяют первичный ключ третий столбец text,

таблица содержит около 1000000 записей. Я выполняю поиск по первому столбцу, который занимает минуты

для поиска определенного элемента.

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

Ответы [ 5 ]

5 голосов
/ 08 октября 2011

Первичный ключ из 50 + 50 символов? Что это содержит? Вам следует, чтобы таблица была в 3-й нормальной форме? Звучит так, что сам ключ может содержать некоторую информацию, звучит для меня как сигнал тревоги.

Если вы можете изменить свой первичный ключ с помощью чего-то более короткого и управляемого, есть несколько вещей, которые вы можете попробовать:

  • экспортировать текст3 в другую таблицу в соответствии с новым первичным ключом
  • проанализируйте вашу таблицу, чтобы определить более оптимизированную длину, а не 50 символов с SELECT FROM xcve_info PROCEDURE ANALYSE()
  • соответственно измените размер полей, и если вы можете позволить себе дополнительное пространство, измените VARCHAR на CHAR
  • добавить индекс к value1, который, вероятно, не должен быть частью первичного ключа

Всегда проверяйте эффективность изменений, чтобы узнать, стоили ли они этого или нет.

3 голосов
/ 08 октября 2011

Какой фактический запрос вы выполняете? Индекс поможет, только если вы ищете префикс (или точное) совпадения. Например:

SELECT * FROM Table WHERE value1='Foo%'

найдет все, что начинается с Foo, и должно использовать индекс и быть относительно быстрым. С другой стороны:

SELECT * FROM Table WHERE value1='%Foo%'

не будет использовать индекс, и вам придется выполнить полное сканирование таблицы. Если вам нужно сделать это, вы должны использовать полнотекстовый индекс и запрос: http://dev.mysql.com/doc/refman/5.5/en/fulltext-search.html

1 голос
/ 19 апреля 2013

Всегда плохая идея использовать такие длинные строки в качестве индексов, но в случае, если вам действительно нужно искать его таким образом, подумайте, как вы фильтруете запрос, потому что MySQL не может выполнять аналогичные операции с индексами, поэтому такие условия, как WHERE value1 LIKE "%mytext%" никогда не будет использовать индексы, вместо этого попробуйте поискать более короткую строку, чтобы MySQL мог преобразовать эту операцию в равенство.Например, используйте: value1 = "XXXXX", где "XXXXX" является частью строки.Чтобы определить наилучшую длину строки сравнения, проанализируйте селективность вашего поля value1 .

Также учтите, что несколько индексов полей, таких как (value1, value2), не будут использовать второе поле, если первое не совпадаетименно так.То, что это не плохой индекс, это просто, чтобы вы знали и понимали, как он работает.

Если это не сработает, другое решение может быть хранить value1 и value2 в новой таблице (например, table2) с автоматическим инкрементным полем id, затем добавьте внешний ключ от Table до table2 с использованием идентификаторов (например, my_long_id) и, наконец, создайте индекс дляТаблица 2, как: my_idx (value1, value2).Поиск будет выглядеть примерно так:

SELECT t1.*
FROM 
  table2 as t2
INNER JOIN Table as t1 ON (t1.my_long_id = t2.id)
WHERE
  t2.value1 = "your_string"

Убедитесь, что таблица2 имеет индекс типа (value1, value2), а таблица имеет основной индекс (my_long_id).

. В качестве окончательной рекомендации добавьтеПоле 'id' с AUTO_INCREMENT в качестве PRIMARY KEY и (value1, values2) в качестве уникального / обычного ключа.Это очень помогает, потому что B-Tree хранит отсортированные индексы, поэтому использование строки из 100 символов приводит к потере ввода-вывода при такой сортировке.InnoDB определяет наилучшую позицию для этого индекса при вставке, возможно, ему потребуется переместить некоторые индексы на другие страницы, чтобы освободить место для нового.С автоинкрементным значением это проще и дешевле, потому что никогда не нужно будет делать такие движения.

1 голос
/ 08 октября 2011

Единственное, что я могу увидеть, что может улучшить положение дел, - это добавить уникальный индекс в первый столбец. Это, очевидно, не работает, если первый столбец на самом деле не уникален, и сомнительно, будет ли он вообще более эффективным, чем уже существующий первичный ключ. Я подумал, что это может помочь, если уникальный индекс в первом столбце будет меньше первичного ключа (сканирование индекса будет быстрее).

Кроме того, вы можете создать индекс для частей вашего первого столбца, возможно, только для 5 или 10 первых символов, что может быть более эффективным.

Кроме того, после удаления и / или вставки большого количества значений не забудьте запустить ANALYZE TABLE для затронутой таблицы или даже OPTIMIZE TABLE. Таким образом, статистика для оптимизатора запросов MySQL обновляется.

0 голосов
/ 10 октября 2011

Но почему вы ищете уникальный элемент в неуникальном столбце? Почему вы не можете делать запросы на основе вашего первичного ключа? Если по какой-либо причине вы не можете это сделать, я бы проиндексировал значение1 в столбце, по которому вы ищите.

CREATE INDEX 'index_name' ON 'таблица' (имя столбца)

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