SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 21.10.2013 20:19:07

_Igor_
Участник
Зарегистрирован: 19.08.2011
Сообщений: 7

Поля для хранение телефонных номеров в mysql

Добрый день!

Некогда давно создавалась база для хранения некой информации, в том числе и номеров телефонов.
Формат хранение следующий:
1. Таблица стран с полями id, name, phone_code
2. Таблица данных, где телефоны хранятся в следующем виде country_id(int), phone_code(int), phone_number(int).

Таблица данных порядка ~200000 записей, и используется активно, в том числе добавление и удаление записей.
В данный момент столкнулись с проблемой, что номера телефонов начинаются с нуля, и при добавлении в базу эти нули "съедаются", в результате записывается и отображается при выводе неправильный номер.

Как вариант, для лечения данной проблемы, можно поле для кода и номера изменить на char или varchar, но есть проблема.
При добавлении записи в таблицу идёт проверка сколько записей с данным телефонным номером существует, и если поля будут типа char или varchar, то такие запросы оказываются тяжелее по сравнению с полями типа int.

Подскажите, как можно решить проблему "съедания" нулей, без проседания производительности при поиске ?

Неактивен

 

#2 21.10.2013 20:45:30

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5847

Re: Поля для хранение телефонных номеров в mysql

Если длинна номера телефона фиксирована, то проще при отображении дописывать нужное кол-во нулей.

MariaDB [test]> create table test (id int(7) unsigned zerofill);
Query OK, 0 rows affected (0.19 sec)

MariaDB [test]> insert into test values(433);
Query OK, 1 row affected (0.06 sec)

MariaDB [test]> select * from test;
+---------+
| id      |
+---------+
| 0000433 |
+---------+

Неактивен

 

#3 22.10.2013 11:59:39

_Igor_
Участник
Зарегистрирован: 19.08.2011
Сообщений: 7

Re: Поля для хранение телефонных номеров в mysql

Вариант с zerofill не подойдёт, длина номера не фиксированная.

Неактивен

 

#4 22.10.2013 15:20:15

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5847

Re: Поля для хранение телефонных номеров в mysql

Тогда или varchar (но это большие расходы на индекс), или втрое поле,в котором хранить длину номера, а при выводе отображать нужное кол-во нулей.

Неактивен

 

#5 23.10.2013 18:25:38

_Igor_
Участник
Зарегистрирован: 19.08.2011
Сообщений: 7

Re: Поля для хранение телефонных номеров в mysql

vasya написал:

Тогда или varchar (но это большие расходы на индекс), или втрое поле,в котором хранить длину номера, а при выводе отображать нужное кол-во нулей.

добавлять новое поле тоже не очень приемлимый вариант, потому что нужно будет дорабатывать софт под такое поле, ну и ещё нужно тестировать, не будет ли это более ресурсоемко добавление ещё одного поля в where, чем перевести поля код и номер в varchar. Разве что, если только найти в mysql или самому написать функцию, которая в однозначном порядке будет конвертировать весь телефонный номер в число и использовать это поле для поиска, что-то вроде функций ATON и NTOA для ip-адресов.

С индексом этих полей тоже немного непонятно, проводил тестирование на таблице в которой больше миллиона записей, таблица с разными данными и в ней поля как писал выше country_id, phone_code, phone_number.
Поля phone_code и phone_number делаю varchar, пробую делать индекс из трёх полей country_id, phone_code и phone_number, и три отдельных индекса по каждому полю, и делаю запрос:
SELECT COUNT(*) FROM table WHERE country_id = 'x' && concat(phone_code,phone_number) = 'zzzyyyyyyy'
В таком запросе mysql отказывается использовать данные индексы. Может есть ещё вариант как сделать индексы чтоб поиск шёл по индексам, а не по всей таблице?

И ещё небольшой вопрос, если под поля phone_code и phone_number предусмотреть размер не более 6 и 8 символов соответственно, теоритически, должен ли быть выйгрыш при поиске если сделать данные поля char(6) и char(8) вместо varchar(6) и varchar(8) ?
На своей тестовой базе пробовал так и так, разницы не заметно.

Неактивен

 

#6 23.10.2013 19:19:08

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5847

Re: Поля для хранение телефонных номеров в mysql

_Igor_ написал:

С индексом этих полей тоже немного непонятно, проводил тестирование на таблице в которой больше миллиона записей, таблица с разными данными и в ней поля как писал выше country_id, phone_code, phone_number.
Поля phone_code и phone_number делаю varchar, пробую делать индекс из трёх полей country_id, phone_code и phone_number, и три отдельных индекса по каждому полю, и делаю запрос:
SELECT COUNT(*) FROM table WHERE country_id = 'x' && concat(phone_code,phone_number) = 'zzzyyyyyyy'
В таком запросе mysql отказывается использовать данные индексы. Может есть ещё вариант как сделать индексы чтоб поиск шёл по индексам, а не по всей таблице?

Bндекс не будет использоваться, если в части where поле входит в состав какого-нибудь выражения.
В вашем случае нужно убрать concat:
SELECT COUNT(*) FROM table WHERE country_id = 'x' && phone_code = 'zzz' && phone_number = 'yyyyyyy'; -- тогда составной индекс будет использоваться.

_Igor_ написал:

И ещё небольшой вопрос, если под поля phone_code и phone_number предусмотреть размер не более 6 и 8 символов соответственно, теоритически, должен ли быть выйгрыш при поиске если сделать данные поля char(6) и char(8) вместо varchar(6) и varchar(8) ?

А за счет чего вы ожидаете прибавку?

Неактивен

 

#7 31.10.2013 15:55:01

_Igor_
Участник
Зарегистрирован: 19.08.2011
Сообщений: 7

Re: Поля для хранение телефонных номеров в mysql

vasya написал:

Bндекс не будет использоваться, если в части where поле входит в состав какого-нибудь выражения.
В вашем случае нужно убрать concat:
SELECT COUNT(*) FROM table WHERE country_id = 'x' && phone_code = 'zzz' && phone_number = 'yyyyyyy'; -- тогда составной индекс будет использоваться.

спасибо за подсказку, такого ньюанса не знал.


vasya написал:

А за счет чего вы ожидаете прибавку?

Была мысль, что если сделать поле varchar, то в данном случае размер памяти для хранения данных будет меньшим, ну и поиск будет работать быстрее. Как показали мои результаты тестов на базе с ~1 млн. записей, никакой прибавки не наблюдалось, скорости выполнения запросов были одинаковы.

P.S. Может кому будет полезно, изначальная проблема была решена следующим образом. Поле кода и номера телефона сделано типом varchar(6) и varchar(8), а для поиска было создано поле bigint, в которое записывается код и номер (в международном формате записи телефонный код не может начинаться с 0, поэтому тип bigint вполне подходит). Создан индекс из двух полей country_id и нового поля типа bigint (название поля phone_search).
Для поиска используется запрос: SELECT COUNT(*) FROM table WHERE country_id = 'x' && phone_search = 'zzzyyyyyyy';
С использованием индексов всё просто летает, быстрее даже чем было до этого.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson