Индексирование столбца с повторяющимися значениями

Рассмотрим эти таблицы:

seed (seedid, seedname) # PK-(seedid) 
stock (seedid, stk, storeid)  # PK-(seedid,storeid), FK-(storeid)
#InnoDB

stock: 
      seedid, stk, storeid
         1    12     81
         2    13     81
         3    14     81

         1    12     82
         2    11     82
         3    13     82
         4    12     82

Query -> select stk from stock where seedid = 'aaa' and storeid = 'yyy'.

Таблица stock представляет запасы нескольких магазинов, поэтому storeid будет повторяться.

Как проиндексировать таблицу stock, учитывая, что она будет часто запрашиваться с использованием storeid?

Первичные ключи индексируются автоматически, и поскольку (seedid,storeid) уже является первичным ключом, нет ли необходимости его дополнительно индексировать?


person lmao    schedule 20.02.2019    source источник
comment
Вы либо знаете, что вам нужен индекс. Или ты ждешь, пока не узнаешь. Однако storeid является внешним ключом и должен быть проиндексирован.   -  person Paul Spiegel    schedule 20.02.2019
comment
обновите свой вопрос и добавьте схему таблиц ... основной запрос, который, по вашему мнению, задействован,   -  person scaisEdge    schedule 20.02.2019
comment
@PaulSpiegel: Спасибо за ответ! Я забыл упомянуть, что seedid на магазин будет около 65000, поэтому storeid будет повторяться столько раз. storeid будет около 12000. Должен ли я продолжить и проиндексировать его?   -  person lmao    schedule 20.02.2019
comment
@scaisEdge: обновил вопрос.   -  person lmao    schedule 20.02.2019
comment
@PaulSpiegel: Сегодня я сам прочитал ваш пост -php-larave]" title="какой подход быстрее для получения всех pois из mysql mariadb с помощью php larave%5d">stackoverflow.com/questions/51429997/. Спасибо за этот замечательный пост. Но, я не мог ничего спросить у вас там, так как у меня недостаточно репутации. К счастью, вы здесь! Только один вопрос Какая единица измерения расстояния возвращена, я думаю, это были метры...   -  person lmao    schedule 20.02.2019
comment
Аргх, мои глаза - ты можешь потерять нули?   -  person Strawberry    schedule 20.02.2019
comment
@lmao см. мой комментарий здесь   -  person Paul Spiegel    schedule 21.02.2019
comment
@Strawberry: Для ваших глаз ... см. Правку. Богу ZEROES может не понравиться эта дискриминация 0 :)   -  person lmao    schedule 21.02.2019
comment
@PaulSpiegel - Спасибо, сэр, огромное спасибо за разъяснения.   -  person lmao    schedule 21.02.2019


Ответы (2)


Основываясь на неполной спецификации, я бы сделал это:

   CREATE UNIQUE INDEX stock_UX1 ON stock (storeid,seedid,stk)

Этот индекс удовлетворил бы требованию индекса с storeid в качестве ведущего столбца. (И мы знаем, что это требование будет иметь место, если это InnoDB, а storeid является внешним ключом.)

С такой короткой строкой таблицы я бы сделал ее покрывающим индексом и включил все столбцы. Затем запросы могут выполняться непосредственно со страниц индекса без поиска страниц данных в базовой таблице.

Поскольку мы знаем, что (seedid,storeid) уникален (указанный как ПЕРВИЧНЫЙ КЛЮЧ), мы знаем, что (storeid,seedid) также уникален, поэтому мы могли бы также объявить индекс УНИКАЛЬНЫМ.


Есть и другие варианты; нам не нужно создавать этот индекс выше. Мы могли бы просто сделать это вместо этого:

   CREATE INDEX stock_IX2 ON stock (storeid)

Но это будет использовать почти такой же объем пространства и не будет так полезно для максимально возможного количества запросов.


Вторичный индекс будет содержать первичный ключ таблицы; так что второй индекс будет включать столбец seedid, учитывая ПЕРВИЧНЫЙ КЛЮЧ таблицы. То есть индекс эквивалентен этому:

   CREATE INDEX stock_IX3 ON stock (storeid,seedid)

И мы знаем, что комбинация этих двух столбцов уникальна, поэтому мы можем включить ключевое слово UNIQUE.

   CREATE UNIQUE INDEX stock_UX4 ON stock (storeid,seedid)

Если мы выполним EXPLAIN для запроса формы

  EXPLAIN
  SELECT t.storeid
       , t.seedid
       , t.stk 
    FROM stock t 
   WHERE t.storeid = 'foo'

мы, вероятно, увидим операцию сканирования диапазона на вторичном индексе; но для получения значения столбца stk потребуется поиск страниц данных в базовой таблице. Включение столбца stk во вторичный индекс сделает этот индекс покрывающим индексом для запроса. Поскольку в ответе впервые рекомендуется индекс, мы ожидаем, что вывод EXPLAIN покажет «Использование индекса».

person spencer7593    schedule 20.02.2019
comment
Я выберу ваш второй вариант, так как у меня уже есть индекс, поскольку первичный ключ(seedid,storeid) и внешний ключ(storeid) также будут проиндексированы. - person lmao; 20.02.2019
comment
Второй будет использовать почти столько же места, сколько и первый; поскольку вторичный индекс должен хранить значения столбцов PRIMARY KEY; все вторичные индексы включают значение столбца seedid. Исключение столбца seedid из определения индекса не экономит места, не делает индекс меньше или быстрее. Порядок ведущих столбцов в индексе важен. Второе определение индекса допустимо. Но это указывает на то, что создатель индекса не понимает деталей индексов InnoDB или нюансов стратегии индексирования. - person spencer7593; 21.02.2019
comment
Спасибо за объяснение, на этот раз все понял! - person lmao; 21.02.2019

Если seedid,storeid задан как первичный ключ, то он уже имеет уникальный индекс. Однако запросы могут использовать только один индекс за раз. Поэтому, если вы делаете регулярные запросы, чтобы сказать что-то вроде «где seedid = 3 и storeid = 5», будет использоваться этот индекс. Но если вы просто используете «where storeid = 5», он может не использовать индекс. (Вы можете использовать «объяснить» перед своим запросом, чтобы увидеть, какие индексы будет использовать mysql.)

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

person SilicaGel    schedule 20.02.2019
comment
Я предполагаю, что первичный ключ, поскольку индекс является единственным вариантом, учитывая запрос, который у меня есть здесь. - person lmao; 20.02.2019
comment
Спасибо за совет, сэр. - person lmao; 21.02.2019