Учебная страница курса биоинформатики,
год поступления 2010
Реляционные базы данных. MySQL.
Реляционные базы данных
Представим себе, что у нас есть большое хранилище геномных данных, основанное на текстовых файлах. И нам необходимо дать возможность десяти пользователям параллельно читать данные из разных мест файлов, вносить изменения в файлы и при этом следить, чтобы формат хранения данных соблюдался, а, кроме того, чтобы данные в разных файлах соответствовали друг другу. Если добавить сюда проверку паролей, ограничение на запись для некоторых пользователей и возможность обращения по локальной сети, то получится типичная система управления базами данных (СУБД). Наиболее распространенной архитектурой баз данных на данный момент являются реляционные базы данных. В этой архитектуре главным структурным элементов является таблица. Столбцы таблицы описывают свойства объектов определенного вида, а каждая строка содержит значения этих свойств, присущие одному объекту.
Пример. Гены и геномы.
Имя генома |
Длина генома |
Имя гена |
Старт |
Стоп |
Белковая последовательность |
Escherichia coli |
4639675 |
thrL |
190 |
255 |
MKRISTTITTTITITTGNG… |
Escherichia coli |
4639675 |
thrA |
337 |
2799 |
MRVLKFGGTSVANAER… |
Escherichia coli |
4639675 |
thrB |
2801 |
3733 |
MVKVYAPASSANMSVG… |
В этом примере можно заметить, что некоторые свойства повторяются. Они принадлежат не объекту ген, а объекту геном. Чтобы не тратить места на диске на повторение данных, мы можем завести еще одну таблицу. Она будет описывать свойства геномов, а чтобы связать гены с геномами, будем назначать объектам (т.е. строкам) уникальные номера, идентификаторы (id от identifier), которые будут эти объекты идентифицировать. А чтобы различать таблицы, дадим им имена. . Хорошо бы договориться называть имена таблиц и столбцов (или полей) в одном стиле, например, они будут содержать только латинские буквы или знак подчеркивания.
Таблица genome
genome_id |
name |
length |
1 |
Escherichia coli |
4639675 |
2 |
Bacillus subtilis |
4214630 |
3 |
Kineococcus radiotolerans |
4761183 |
Таблица gene
gene_id |
genome_id |
name |
start |
stop |
protseq |
1 |
1 |
thrL |
190 |
255 |
MKRISTTITTTITITTGNG… |
2 |
1 |
thrA |
337 |
2799 |
MRVLKFGGTSVANAER… |
3 |
1 |
thrB |
2801 |
3733 |
MVKVYAPASSANMSVG… |
В такой ситуации говорят, что таблица gene ссылается на таблицу genome по полю genome_id. Это поле является первичным ключом для таблицы genome. Т.е. ключом, по значению которого можно найти строку объекта. В таблице gene поле genome_id называют внешним ключом, а первичным ключом тут является поле gene_id.
Язык SQL
Для работы с данными, лежащими в базе данных, разработан язык SQL, Structural Query Language. Он содержит команды для просмотра данных, вставки, корректировки, удаления, создания и удаления таблиц и многого другого. В 1992 году был разработан стандарт этого языка, который в той или иной мере соблюдается различными системами управления базами данных. Для наших задач мы будем использовать СУБД MySQL. Язык для работы с этой СУБД немножко отличается от SQL, но при этом поддерживает все необходимые стандарты.
Простые запросы к базе данных
Команды SQL называют запросами. Запрос выборки имеет вид:
SELECT * FROM gene; SELECT * FROM gene LIMIT 100;
Данный запрос показывает все поля и все записи. Если хочется просмотреть не все свойства, то вместо * нужно перечислить через запятую имена нужных полей. Кроме полей, в блоке SELECT можно указывать математические выражения, содержащие имена полей и константы:
SELECT id, name,stop-start+1 AS len FROM gene;
Слово AS означает, что третья колонка в результирующей выдаче будет называться “len”. Если нам нужны не все строчки (частое желание, если в таблице тысячи записей), то нам нужно использовать фильтр. Он описывается блоком WHERE:
SELECT id, name,stop-start+1 AS len FROM gene WHERE stop-start+1>=1000; .. WHERE name = 'thrA'; #(в одинарных кавычках!) .. WHERE name LIKE 'thr%';
( _ - один любой символ, % - любое количество любых символов)
В данном примере выдача будет содержать только те строки, для которых верно утверждение в WHERE-блоке, т.е. гены thrA и thrB. Вообще запрос типа SELECT пишется в следующем порядке:
- определяемся с тем, из какой таблицы выбираем данные (блок FROM);
- задаем фильтр на строки, т.е. выражение в блоке WHERE;
- перечисляем поля и производные от них в блоке SELECT.
Строки в таблице располагаются неупорядоченно. Кроме того, запрос выборки позволяет задать способ сортировки возвращаемых записей. За это отвечает блок ORDER BY:
SELECT id,name,stop-start+1 AS len FROM gene WHERE stop-start+1>=1000 ORDER BY name;
Если мы хотим сортировать в обратном порядке, то нам необходимо добавить после выражения сортировки слово DESC (descending):
SELECT id,name,stop-start+1 AS len FROM gene WHERE stop-start+1>=1000 ORDER BY stop-start+1 DESC;
Помимо арифметических операций можно использовать различные дополнительные функции, предоставляемые СУБД MySQL.
Числовые функции
ABS(x), ROUND(x), SIGN(x) |
Абсолютное значение, окруление, знак. |
COS(x), SIN(x), PI(), … |
Тригонометрические (в радианах). |
EXP(x), LN(x), LOG(base,y) |
Экспонента, логарифм. |
POW(x,power), SQRT(x) |
Степень, корень. |
Строковые функции
SUBSTRING(t,from_1,count) |
Подстрока (нумерация с 1!) |
LENGTH(t) |
Длина строки |
CONCAT(t1,t2,t3,…) |
Соединение строк |
TRIM(t) |
Удаление пробелов по краям |
LOWER(t), UPPER(t) |
Изменение регистра букв |
LOCATE(word,t) |
Поиск вхождения слова в текст |
В выражениях WHERE кроме сравнений можно использовать другие логические функции:
t1 LIKE ‘%test_’ |
Проверка на соответствие паттерну |
x OR y, x AND y, NOT z |
Логические операции |
Группировка данных
Кроме простой выборки данных, можно разделить записи на группы так, чтобы в записях из каждой группы повторялись выбранные свойства (значения полей). В этом случае говорят, что группировка проводится по этим полям. При выдаче каждая группа репортируется как одна запись, в которой показываются только те поля, по которым производится группировка, а также поля, содержащие сводную информацию обо всей группе (например, количество записей в группе, минимальное или максимальное значение какого-нибудь поля, сумма значений поля и т.д.). Для описания свойств группировки используется слово GROUP BY. Приведем пример, в котором считается количество генов в каждом геноме:
SELECT genome_id,COUNT(*) AS qnt FROM gene GROUP BY genome_id;
В этом примере мы группируем строки по одинаковости поля genome_id:
gene_id |
genome_id |
name |
start |
stop |
protseq |
1 |
1 |
thrL |
190 |
255 |
MKRISTTITTTITITTGNG… |
2 |
1 |
thrA |
337 |
2799 |
MRVLKFGGTSVANAER… |
3 |
1 |
thrB |
2801 |
3733 |
MVKVYAPASSANMSVG… |
… |
… |
… |
… |
… |
… |
4133 |
1 |
yjtD |
4638965 |
4639651 |
MRITIILVAPARAENIGA… |
4134 |
2 |
dnaA |
410 |
1750 |
MENILDLWNQALAQIE… |
… |
… |
… |
… |
… |
… |
Далее к каждой группе мы применяем функцию COUNT(*), вычисляющую количество записей в группе. В результате для нашего примера, в котором три генома, получим:
genome_id |
qnt |
1 |
4133 |
2 |
4105 |
3 |
4681 |
Для подсчета минимального, максимального, среднего значения или суммы используются функции MIN, MAX, AVG или SUM соответственно.
Соединение таблиц
Часто бывает необходимо соединить несколько таблиц в одну большую таблицу по связывающим эти таблицы ключам. Это бывает нужно, когда хочется посмотреть одним взглядом на связанные между собой данные, разложенные по разным таблицам. В таких случаях используют конструкцию
<таблица1> INNER JOIN <таблица2> ON <условие_соединения>
Рассмотрим простой пример. Нам нужно посчитать количество генов, длина которых не менее 1000 нуклеотидов и в названии соответствующего генома встречается слово ‘coli’:
SELECT count(*) FROM gene INNER JOIN genome ON gene.genome_id=genome.genome_id WHERE stop-start+1>=1000 AND genome.name LIKE ‘%coli%’;
В этом примере мы несколько раз используем полные квалификаторы полей (но не везде), т.к. в обеих таблицах есть поля genome_id и name. Чтобы сократить запись, можно, как и для полей, делать подмену имени для таблиц:
SELECT count(*)FROM gene gn INNER JOIN genome gm ON gn.genome_id=gm.genome_id WHERE stop-start+1>=1000 AND gm.name LIKE '%coli%';
По сути, соединение таблиц – операция обратная той, которую мы делали вначале, когда разделяли данные на несколько таблиц во избежание многократного повторения значений. Мы как бы подстраиваем к записям из таблицы генов записи из таблицы геномов. Вообще запрос, состоящий из блоков SELECT, FROM, INNER JOIN, WHERE и GROUP BY выполняется в таком порядке:
- таблицы в блоке FROM присоединяются друг к другу в соответствии с условием, описанным в ON
- из объединенной таблице остаются только те записи, которые удовлетворяют условию в WHERE
- если есть блок GROUP BY, то записи объединяются в группы, и в результате каждая группа рождает одну запись
- из всех полей всех таблиц из блока FROM остаются только те (или из них вычисляются выражения), которые перечислены в блоке SELECT.
Подзапросы
Вместо использования в блоке FROM настоящих таблиц, лежащих в базе данных, мы можем подставить туда результат выполнения какого-нибудь запроса, собирающего данные из других таблиц (т.е. виртуальную таблицу). Например, нам надо посчитать, в скольких геномах количество генов не превосходит 4500 штук:
SELECT count(*)FROM (SELECT genome_id,count(*) AS qnt FROM gene GROUP BY genome_id )tbl WHERE tbl.qnt<=4500;
Как видно, при этом такой виртуальной таблице необходимо задать имя (например, tbl).
Полезные команды диалекта MySQL
Команда
SHOW TABLES;
перечисляет таблицы, лежащие в текущей базе данных. Команда
DESC[RIBE] <имя_таблицы>;
перечисляет поля в таблице и их типы. Типы данных, начинающиеся на int, float, double, tinyint являются числовыми. Типы данных со словами char, varchar, text являются текстовыми.
Мы будем работать с базой данных student2_db, которая содержит геномные данные по 10-ти штаммам E.coli. Подключаться к ней нужно через текстовую консоль mysql.exe, вызывая команду:
mysql -h db.bioinf.fbb.msu.ru -u student student2_db
Структура базы данных тут. Клиент MySQL командной строки для Windows тут.