Система управления базами данных MySQL
База данных представляет собой организованную группу
данных. Реляционная база данных организует информацию в таблицы,
где строки соответствуют ЗАПИСЯМ базы данных, а столбцы -
ПОЛЯМ базы данных. Для чтения и записи в базе данных MySQL
используется структурированный язык запросов SQL (Structured
Query Language).
SQL представляет из себя компьютерный язык,
используемый для выражения операций с базой данных, организованной
в реляционной (от слова relation) форме, т.е. в виде таблиц. SQL
является принятым в отрасли стандартом языка, на котором говорит
большинство программистов баз данных и который используется большинством
пакетов РСУБД (RDBMS): Oracle, Sybase, Informix, DB2, MS SQL,
Postgree SQL и т.п. MySQL, однако, из-за своей простоты,
поддерживает лишь подмножество современного стандарта SQL
- SQL2.
SQL структурирован в том отношении, что он
следует определенному набору правил. Компьютерной программе легко
разобрать на части сформулированный запрос SQL. Запрос (query)
- это полностью заданная команда, посылаемая серверу баз данных,
который выполняет запрошенное действие. Ниже приведен пример SQL-запроса:
SELECT name FROM people WHERE name LIKE 'Stac%'
Как можно видеть, это предложение выглядит почти как
фраза на ломанном английском языке: "Выбрать имена из список
люди, где имена похожи на Stac". SQL в очень незначительной
мере использует форматирование и специальные символы, обычно ассоциируемые
с компьютерными языками. Сравните, к примеру,
$++;($*++/$|);$&$^,,;$!
на Perl и
SELECT value FROM table
в SQL. Комментарии, как говорится, излишни.
Проблема различных кодировок при использовании операторов выборки
и сортировки в MySQL
Кодировка koi-8r является основной кодировкой
русского языка в Internet и, как следствие, в операционных
системах семейства UNIX. Т.о. неудивительно, что MySQL
при сортировке полей базы данных руководствуется koi-8r.
Проблемы возникают при наличии виртуального сервера
с базовой кодировкой cp1251. Если Вы разрабатываете приложения
для работы с MySQL, то при помещении данных в базу в кодировке
cp1251 все работает нормально, за исключением сортировки.
Например, запрос вида
select * from some_table order by some_text_field;
(выбрать все поля из таблицы some_table сортируя
по полю some_text_field) будет отработан "неверно"
с точки зрения кодировки cp1251. Обратите внимание на команду
SET OPTION CHARACTER SET.
В оригинальной документации MySQL про нее
сказано следующее: "If you want to convert characters between
server and the client". Пока поддерживается только 'SET
OPTION CHARACTER SET cp1251_koi8'. На нашем сервере mysqld установлена
опция
--default-character-set=koi8_ru
Мы предлагаем следующее решение: Вы продолжаете держать
виртуальный сервер в кодировке cp1251, но перед каждым соединением
с MySQL-сервером исполняется SQL-команда:
set CHARACTER SET cp1251_koi8;
При этом все данные, которые поступают от клиента
в MySQL-сервер,
подвергаются принудительной перекодировке из cp1251 в koi-8r,
а данные от MySQL-сервера к клиенту перекодируются из koi-8r
в cp1251. Данные в MySQL-сервере хранятся и сортируются
в кодировке koi-8r. Сортировка работает корректно. Внимание!
Команду "set" приходится выдавать при каждом соединении
с MySQL-сервером. К сожалению, в конструкции "Create
table" в MySQL нельзя указывать CHARACTER SET.
"ORDERBY" VARCHAR(30) CHARACTER SET ISO8859_1
-
неправильно!
Правильность сортировки и выборки кириллицы
зависит от типа колонки в которой хранятся данные. Бинарные данные
дают зависимость сравнения и поиска от регистра букв. Кроме того,
бинарные данные сортируются не по алфавиту, а по их номерам в ASCII-таблице.
Какие данные нужно хранить в MySQL
Не старайтесь поместить в базы данных всю информацию,
которая у Вас есть. Например, не нужно хранить там картинки,
хотя MySQL это и позволяет. Помещая в базу данных двоичные
образы графических файлов, Вы только замедлите работу своего
сервера. Прочитать файл с картинкой с диска гораздо проще
и, с точки зрения потребляемых ресурсов, экономичнее, нежели
соединиться из скрипта к SQL, сделать запрос, получить
образ, обработать его и, выдав нужные http-заголовки,
показать посетителю веб-сервера.
Во втором случае операция выдачи картинки потребует
в несколько раз больше ресурсов процессора, памяти
и диска. Также стоит помнить о том, что существуют механизмы
кэширования веб-документов, которые позволяют пользователю
экономить на трафике, а при динамической генерации контента Вы фактически
лишаете своих посетителей этой удобной возможности.
Вместо картинок лучше хранить в MySQL информацию,
на основе которой можно генерировать ссылки на статические
картинки в динамически создаваемых скриптами документах.
Оптимизация запросов
В ситуациях, когда реально требуется получить только
определенную порцию данных из MySQL, можно использовать
ключ LIMIT для функции SELECT. Это полезно, когда,
например, нужно показать результаты поиска чего-либо в базе данных.
Допустим, в базе есть список товаров, которые
предлагает Ваш интернет-магазин. Выдавать весь список товаров в
нужной категории несколько негуманно по отношению
к пользователю - каналы связи с интернет не у всех быстрые и выдача
лишних ста килобайт информации зачастую заставляет пользователей
провести не одну минуту в ожидании результатов загрузки
страницы.
В таких ситуациях информацию выдают порциями,
например, по 10 позиций. Неправильно делать выборку из базы
всей информации и фильтрацию вывода скриптом. Гораздо
оптимальнее будет сделать запрос вида
select good, price from books limit 20,10
В результате, MySQL "отдаст" Вам
10 записей из базы начиная с 20-й позиции. Выдав результат
пользователю, сделайте ссылки "Следующие 10 товаров",
в качестве параметра передав скрипту следующую позицию, с которой
будет делаться вывод списка товаров, и используйте это число при
генерации запроса к MySQL.
Также следует помнить, что при составлении запросов
к базе данных (SQL queries) следует запрашивать только ту
информацию, которая Вам реально нужна. Например, если в базе
10 полей, а в данный момент реально требуется получить только
два из них, вместо запроса
select * from table_name
используйте конструкцию вида
select field1, field2 from table_name
Таким образом, Вы не будете нагружать MySQL ненужной
работой, занимать лишнюю память и совершать дополнительные
дисковые операции.
Также следует использовать ключ WHERE там,
где нужно получать информацию, попадающую под определенный шаблон.
Например, если нужно получить из базы поля с названиями книг,
автором которых является Иванов, следует использовать конструкцию
вида
select title from books where author='Иванов'
Также есть ключ LIKE, который позволяет искать
поля, значения которых "похожи" на заданный шаблон:
select title from books where author like 'Иванов%'
В данном случае MySQL выдаст названия книг,
значения поля author у которых начинаются с 'Иванов'.
Ресурсоемкие операции
Вместе с тем следует помнить, что существуют
операции, выполнение которых само по себе требует больших
ресурсов, чем для обычных запросов. Например, использование
операции DISTINCT к функции SELECT вызывает потребление
гораздо большего количества процессорного времени, чем обычный SELECT.
DISTINCT пытается искать уникальные
значения, зачастую производя множество сравнений, подстановок
и расчетов. Причем, чем больше становится объем данных,
к которому применяется DISTINCT (ведь Ваша база со временем
растет), тем медленнее будет выполняться такой запрос и рост
ресурсов, требуемых для выполнения такой функции, будет происходить
не прямо пропорционально объему хранимых и обрабатываемых данных,
а гораздо быстрее.
Индексы
Индексы используют для более быстрого поиска
по значению одного из полей. Если индекс не создается, то
MySQL осуществляет последовательный просмотр всех
полей с самой первой записи до самой последней, осуществляя сопоставление
выбранного значения с исходным. Чем больше таблица и чем
больше в ней полей, тем дольше осуществляется выборка.
Если же у данной таблицы существует индекс
для рассматриваемого столбца, то MySQL сможет сделать
быстрое позиционирование к физическому расположению данных
без необходимости осуществлять полный просмотр таблицы.
Например, если таблица состоит из 1000 строк, то скорость поиска
будет как минимум в 100 раз быстрее. Эта скорость будет еще
выше, если есть необходимость обратиться сразу ко всем 1000
столбцам, т.к. в этом случае не происходит затрат времени
на позиционирование жесткого диска. В каких ситуациях создание индекса
целесообразно:
- быстрый поиск строк при использовании конструкции WHERE,
- поиск строк из других таблиц при выполнении объединения,
- поиск значения MIN() или MAX() для проиндексированного
поля,
- сортировка или группировка таблицы в случае, если используется
проиндексированное поле.
В некоторых случаях полностью теряется необходимость
обращаться к файлу данных. Если все используемые поля
для некоторой таблицы цифровые и формируют левосторонний
индекс для некоторого ключа, то значения могут быть возвращены
полностью из индексного дерева с намного большей
скоростью. Если выполняются запросы вида
SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
и существует смешанный индекс для полей col1
и col2, то данные будут возвращены напрямую. Если же созданы
отдельные индексы для col1 и для col2, то оптимизатор попробует
найти наиболее ограниченный индекс путем определения того,
какой из индексов может найти меньше строк, и будет использовать
этот индекс для получения данных.
Если у таблицы есть смешанный индекс, то будет
использоваться любое левостороннее совпадение с существующим
индексом. Например, если есть смешанный индекс 3-х полей
(col1, col2, col3), то индексный поиск можно осуществлять по полям
(col1), (col1, col2) и (col1, col2, col3).
Поддержка соединения
Как Вы наверняка знаете, для работы с MySQL-сервером
необходимо предварительно установить с ним соединение,
предъявив логин и пароль. Процесс установки соединения
может продолжаться гораздо большее время, нежели непосредственная
обработка запроса к базе после установки соединения.
Следуя логике, надо избегать лишних соединений к базе, не отсоединяясь
от нее там, где это можно сделать, если в дальнейшем планируется
продолжить работу с SQL-сервером.
Например, если Ваш скрипт установил соединение к базе,
сделал выборку данных для анализа, не нужно закрывать соединение
к базе, если в процессе работы этого же скрипта Вы планируете
результаты анализа поместить в базу.
Также можно поддерживать так называемое persistent
(постоянное) соединение к базе, но это возможно в полном объеме
при использовании более сложных сред программирования, чем
php или perl в обычном CGI-режиме, когда интерпретатор соответствующего
языка разово запускается веб-сервером для выполнения пришедшего
запроса.
|