Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » MySQL уникальный индеск

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки

Открыть новую тему     Написать ответ в эту тему

SergGur

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Доброго времени суток. Сегодня в процессе работы с большим изумлением обнаружил, что уникальный индекс в принципе не используется при поиске по этому полю. Возможно, я что-то прозевал в свое время, когда изучал MySQL, но возникло 2 вопроса. Во-первых - это нормальная ситуация, или там что-то не так? И, если все правильно, то всплывает второй вопрос: если мне нужно иметь уникальное поле, по которому, к тому же, ведется частый поиск (например, номер удостоверения личности, логин или что-то подобное), как это правильно реализовывать? Делать на одно поле два разных индекса - обычный и уникальный - или существуют более современные решения?

Всего записей: 41 | Зарегистр. 05-05-2006 | Отправлено: 17:33 21-09-2023 | Исправлено: SergGur, 17:34 21-09-2023
Mavrikii

Platinum Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
SergGur
а запрос показать? и результат добавления команды EXPLAIN перед ним?
 

Цитата:
Делать на одно поле два разных индекса - обычный и уникальный

нет, но сначала - запрос, все от него зависит.

Всего записей: 15121 | Зарегистр. 20-09-2014 | Отправлено: 20:00 21-09-2023 | Исправлено: Mavrikii, 20:15 21-09-2023
SergGur

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Начальное состояние таблицы :
 
Create Table If Not Exists `tbClients`
(`biID` BigInt UnSigned Not Null Primary Key Auto_Increment Comment 'Уникальный идентификатор',
 ...
 `vcLogin` VarChar(20) Default '…' Not Null Comment 'Логин',
 ...
) ENGINE=InnoDB Default CharSet=utf8 Auto_Increment=0 Comment='Клиенты';
 
Create Unique Index
  UK_Clients_Login
On
  `tbClients` (`vcLogin`);
------------------------------------------------------------------------------
До создания обычного индекса :
 
"Explain Select * From `tbClients` Where `vcLogin` = '1711214139'"
[SQL execution time: 00:00:00.027 / Total time: 00:00:00.041]
id    select_type  table      partitions  type  possible_keys  key   key_len  ref   rows   filtered  Extra        
----- ------------ ---------- ----------- ----- -------------- ----- -------- ----- ------ --------- ------------
1     SIMPLE       tbClients  NULL        ALL   NULL           NULL  NULL     NULL  12283  10        Using where  
------------------------------------------------------------------------------
Создание обычного индекса :
 
Create Index
  K_Clients_Login
On
  `tbClients` (`vcLogin`);
------------------------------------------------------------------------------
После создания обычного индекса :
 
"Explain Select * From `tbClients` Where `vcLogin` = '1711214139'"
[SQL execution time: 00:00:00.016 / Total time: 00:00:00.027]
id    select_type  table      partitions  type  possible_keys    key              key_len  ref    rows  filtered  Extra  
----- ------------ ---------- ----------- ----- ---------------- ---------------- -------- ------ ----- --------- ------
1     SIMPLE       tbClients  NULL        ref   K_Clients_Login  K_Clients_Login  62       const  1     100       NULL  
 
 
Что-то типа этого...

Всего записей: 41 | Зарегистр. 05-05-2006 | Отправлено: 21:10 21-09-2023 | Исправлено: SergGur, 21:11 21-09-2023
Mavrikii

Platinum Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
SergGur
индекс используется, почему решили, что нет?

Всего записей: 15121 | Зарегистр. 20-09-2014 | Отправлено: 21:15 21-09-2023
SergGur

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
До создания обычного индекса :
 
id    select_type  table      partitions  type  possible_keys  key   key_len  ref   rows   filtered  Extra        
----- ------------ ---------- ----------- ----- -------------- ----- -------- ----- ------ --------- ------------
1     SIMPLE       tbClients  NULL        ALL   NULL           NULL  NULL     NULL  12283  10        Using where  
 
После создания обычного индекса :
 
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
----- ------------ ---------- ----------- ----- ---------------- ---------------- -------- ------ ----- --------- ------
1 SIMPLE tbClients NULL ref K_Clients_Login K_Clients_Login 62 const 1 100 NULL
 
Действительно разницы нет?

Всего записей: 41 | Зарегистр. 05-05-2006 | Отправлено: 21:53 21-09-2023
Mavrikii

Platinum Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
SergGur

Цитата:
Действительно разницы нет?

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

Цитата:
уникальный индекс в принципе не используется при поиске по этому полю

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

Всего записей: 15121 | Зарегистр. 20-09-2014 | Отправлено: 21:58 21-09-2023 | Исправлено: Mavrikii, 22:01 21-09-2023
SergGur

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Вы, пожалуйста, повнимательнее прочтите мой пост с полными скриптами. Да, в таблице есть первичный ключ biID, но поиск идет по полю vcLogin. В первом случае идет, как вы выразились, перебор, во втором - используется новый созданный индекс. Я решил, что в первом случае не используется уникальный индекс UK_Login, потому, что его не было в результате Explain. Во втором случае используется новый созданный индекс K_Login

Всего записей: 41 | Зарегистр. 05-05-2006 | Отправлено: 22:07 21-09-2023
Mavrikii

Platinum Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
SergGur

Цитата:
Да, в таблице есть первичный ключ biID, но поиск идет по полю vcLogin.

ну так при поиске по vcLogin индекс от bID не используется. как создали индекс для этого поля - он (индекс этого поля) стал использоваться. что тут непонятного, в чем вопрос?

Всего записей: 15121 | Зарегистр. 20-09-2014 | Отправлено: 22:09 21-09-2023 | Исправлено: Mavrikii, 22:11 21-09-2023
SergGur

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Вопрос только в том, что условие поиска - не по biID, а по vcLogin. Еще вопрос в том, что во втором случае - после создания индекса - время выполнения запроса уменьшилось почти в 2 раза. Других вопросов больше нет

Всего записей: 41 | Зарегистр. 05-05-2006 | Отправлено: 22:18 21-09-2023
Mavrikii

Platinum Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
SergGur

Цитата:
Еще вопрос в том, что во втором случае - после создания индекса - время выполнения запроса уменьшилось почти в 2 раза

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

Всего записей: 15121 | Зарегистр. 20-09-2014 | Отправлено: 22:20 21-09-2023
SergGur

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Именно в этом и состоял вопрос. Мне нужно, чтобы в таблице было уникальное поле, по которому можно было осуществлять наиболее быстрый поиск. Я хочу знать, есть ли более правильный и современный способ это сделать, вместо того, чтобы создавать два индекса на одно и то же поле - один уникальный, другой обычный. Навскидку я такого способа пока не нашел. Других вопросов у меня не было

Всего записей: 41 | Зарегистр. 05-05-2006 | Отправлено: 22:40 21-09-2023 | Исправлено: SergGur, 22:42 21-09-2023
Mavrikii

Platinum Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
SergGur

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

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

Всего записей: 15121 | Зарегистр. 20-09-2014 | Отправлено: 22:48 21-09-2023 | Исправлено: Mavrikii, 22:48 21-09-2023
SergGur

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Create Index
  K_Clients_Login
On
  `tbClients` (`vcLogin`);
 
Create Unique Index
UK_Clients_Login
On
`tbClients` (`vcLogin`);
 
Это два индекса на два разных поля?

Всего записей: 41 | Зарегистр. 05-05-2006 | Отправлено: 22:58 21-09-2023
Mavrikii

Platinum Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
SergGur
сорри, только сейчас понял в чем вопрос, так и  нужно было показать.. я не смотрел на запросы создания индексов. думал, что идет речь именно об biID
 

Цитата:
Это два индекса на два разных поля?

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

Цитата:
Scanning the table is faster
Paradoxically, an index is only sometimes the fastest way to access data! The MySQL optimizer will always try to pick the quickest way to get the data it needs, which sometimes means choosing a slightly counter-intuitive method. For small tables or queries that select a large portion of a table, it can be faster for MySQL to skip the index scan and scan the table directly. Sometimes the dreaded table scan is the best access method possible!
 
An index is a secondary data structure (a B+ tree) apart from the table that must be traversed to find the matching row IDs. Once the IDs have been found, those rows must be found and read from disk. In situations where most of the rows will be fetched, reading all of the rows in order off of the disk is faster than going to the index first.
 
Usually, a table scan is bad news, but sometimes, even if rarely, it's the best possible outcome.

можно попробовать заставить использовать индекс - ... FROM tablename FORCE INDEX (имя_индекса)
https://stackoverflow.com/questions/20797475/mysql-force-index-vs-use-index
 
общая информация - https://dev.mysql.com/doc/refman/8.0/en/mysql-indexes.html
 
в любом случае, тогда не нужен и biID вообще.
 
ps: я воспроизвел первую ситуацию, все ок
 

Всего записей: 15121 | Зарегистр. 20-09-2014 | Отправлено: 23:11 21-09-2023 | Исправлено: Mavrikii, 23:18 21-09-2023
SergGur

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
biID нужен, как первичный ключ. А подобных уникальных, по которым может производиться поиск, у меня там еще штуки 3, как минимум. И перебор в данном случае гарантированно не может быть быстрее, чем использование индекса. Есть факт - уникальные ключи не участвуют в операциях поиска. При большой необходимости можно воспользоваться описанным мной методом, но по-моему, это не очень красиво. Не верится, что нет другого, более правильного метода

Всего записей: 41 | Зарегистр. 05-05-2006 | Отправлено: 23:19 21-09-2023
Mavrikii

Platinum Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
SergGur

Цитата:
Есть факт - уникальные ключи не участвуют в операциях поиска.

участвуют, смотрите выше скриншот. решение использовать индекс или нет - сугубо оптимизатора.
если хотите заставить - я написал выше как.

Всего записей: 15121 | Зарегистр. 20-09-2014 | Отправлено: 23:23 21-09-2023
SergGur

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Прошу прощения за введение присутствующих в заблуждение, проблема была в другом месте. Тема закрыта, всем спасибо

Всего записей: 41 | Зарегистр. 05-05-2006 | Отправлено: 05:43 22-09-2023
Открыть новую тему     Написать ответ в эту тему

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » MySQL уникальный индеск


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru