Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Клуб профессиональных программистов :: Выпуск #141


Клуб профессиональных программистов «Весельчак У»
Информационная рассылка сайта и форума.  Выпуск 141.  1 сентября 2012 г.

Здравствуйте, уважаемые читатели!



Сегодня предлагаем вам прочесть фрагмент статьи «MySQL. Расширяем функционал работы со списками». Название говорит само за себя.


На «книжную полку» добавлено:



В «средства разработки» добавлено:




Приятного чтения! Прощаемся с вами до следующего выпуска.


С уважением, команда Клуба.



Вводная


В современных версиях MySQL (5.1, 5.5, 5.6) есть несколько функций работы со списками и специальный списочный тип SET. Под списком подразумевается строка текста, составленная из разделенных запятыми подстрок (естественно, не содержащих запятые). Некоторые функции поддерживают произвольный разделитель, что несколько расширяет их применение, но это выходит за рамки статьи, и об этом вы и сами можете прочитать в документации. Здесь я расскажу про тип SET, возможности его применения, опишу встроенные функции работы со списками и предложу варианты расширений.


Тип SET


Английское слово «set» в данном контексте можно перевести как «множество» или «набор». Набор строк. Учитывая, что набор представлен в форме списка, считаю, что и называть его нужно списком. Чтобы не путаться с другими списками, когда возможна неоднозначность понимания, буду называть его CSV-списком (comma separated values—значения, разделенные запятыми).

Хранится тип SET как число (1, 2, 3, 4 или 8 байт), а точнее—как битовая карта (до 64 бит), где порядковый номер бита соответствует порядковому номеру строки в описании столбца, а значение бита управляет вхождением ассоциированной строки в результирующий CSV-список. Работать с этим типом можно как с числом, как с битовой картой или как со строкой (списком). Приведу небольшой пример:


mysql> CREATE TABLE t (a SET ('aaa', 'bbb', 'ccc'));
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO t VALUES ('aaa'), ('aaa,bbb'), ('bbb'), ('ccc,aaa');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT a `string`, a + 0 `decimal`, LPAD(BIN(a + 0), 8, '0') `binary` FROM t;
+---------+---------+----------+
| string  | decimal | binary   |
+---------+---------+----------+
| aaa     |       1 | 00000001 |
| aaa,bbb |       3 | 00000011 |
| bbb     |       2 | 00000010 |
| aaa,ccc |       5 | 00000101 |
+---------+---------+----------+
4 rows in set (0.00 sec)

Наглядно видно соответствие бит и строк. К сожалению, битовых индексов MySQL не имеет и ниже приведенные операции приводят к полному просмотру всех строк таблицы (или полному сканированию индекса, если такое возможно).


mysql> SELECT a FROM t WHERE a & 1;
+---------+
| a       |
+---------+
| aaa     |
| aaa,bbb |
| aaa,ccc |
+---------+
3 rows in set (0.00 sec)

mysql> SELECT a FROM t WHERE FIND_IN_SET('aaa', a);
+---------+
| a       |
+---------+
| aaa     |
| aaa,bbb |
| aaa,ccc |
+---------+
3 rows in set (0.00 sec)

mysql> SELECT a FROM t WHERE a LIKE '%aaa%';
+---------+
| a       |
+---------+
| aaa     |
| aaa,bbb |
| aaa,ccc |
+---------+
3 rows in set (0.00 sec)

И только равенство позволяет использовать индекс. Индексировать столбец SET можно, но бессмысленно.


mysql> SELECT a FROM t WHERE a = 'aaa';
+-----+
| a   |
+-----+
| aaa |
+-----+
1 row in set (0.00 sec)

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


...



Полностью прочитать статью можно на нашем сайте, в разделе «Базы данных::MySQL».



В избранное