Зачем таблице нужен ключ
Разработчики теоретической модели систем управления базами данных исходили из того простого предположения, что каждая строка таблицы, кроме конкретных данных, содержит еще и личный идентификатор, обычно это ее порядковый номер. Таким образом, какие бы данные ни находились далее, каким бы образом они ни пересекались между собой, в каждый конкретный момент времени можно абсолютно однозначно идентифицировать любой их фрагмент, назвав номер строки в таблице, следовательно этот номер можно использовать как индивидуальный ключ отдельной записи. Отсюда вытекают два следствия: каждая таблица обязательно должна иметь хотя бы один ключ и должен существовать специальный тип данных, значение которого автоматически увеличивается на единицу при добавлении к таблице еще одной строки. В СУБД Microsoft Access 97 эти следствия реализованы в виде одного обязательного правила и одного специального типа данных. Таким типом является СЧЕТЧИК, а правилом - невозможность сохранить новую таблицу до тех пор, пока в ней не будет создан хотя бы один ключ. На рис.1 изображена таблица из одного примера, использовавшегося ранее. Как вы помните, это таблица, в которой предполагается вести учет автомобилей, проданных сервисным центром. В ней упоминается марка проданного автомобиля, дата продажи, вид платежа и его сумма. Это, так сказать, переменная информация, а вот содержимое поля " Счетчик" является ключевым, так как ссылка на конкретное его содержимое равнозначна прямому указанию на конкретную продажу.
Так определяется ключ, называемый "первичным". Однако во многих случаях первичного ключа оказывается недостаточно для индексации содержимого таблицы, особенно в случаях больших таблиц со множеством полей почти наверняка в процессе работы придется отбирать из них данные и по другим критериям, отличным от простого номера строки в таблице: в таблице адресов это может быть наименование населенного пункта при выборке данных для определенных регионов; в таблице продаж это может быть категория или группа товара, например бакалея или молочные продукты, при выявления статистических показателей по этим категориям. Таким образом, в определенных случаях возникает потребность в создании так называемых "индексов". Индекс - это дополнительная внутренняя таблица Microsoft Access, состоящая всего из двух столбцов: в первом содержатся значения полей, включенных в индекс, а во втором - местоположение этих полей в индексируемой таблице. Сама таблица индексов нигде не отражается и вообще никоим образом для пользователя не видна, тем не менее, начиная с момента создания, она строго привязана к конкретной таблице с данными и всегда доступна для встроенных в СУБД механизмов поиска. Применение индексов значительно ускоряет просмотр и выборку данных, так как СУБД может сразу обратиться к внутренней таблице индексов, вместо того чтобы сначала сортировать огромный массив данных по заданным условиям, потом выделять из него необходимую информацию и лишь затем уже делать с ней то, что пожелал составитель запроса. Правда, имеют индексы и оборотную сторону - каждый из них занимает дополнительное место на жестком диске, а также в оперативной памяти. К тому же сама база данных начинает открываться медленнее, так как каждый раз при запуске СУБД, например Microsoft Access 97, заново проводит перерасчет всех индексов, что требует определенного времени. Таким образом, желательно еще на этапе проектирования общей архитектуры конкретной СУБД продумывать степень разбивки данных по отдельным таблицам исходя из возможных потребностей в них. Иногда самым лучшим бывает создать одну большую таблицу и назначить ей несколько индексов, что также возможно, а иногда проще сразу сделать несколько таблиц меньшего размера, но обойтись минимальным количеством индексов или вообще без них.
Сначала попробуем создать индекс по одному полю. Наверняка руководству нашего гипотетического предприятия будут нужны данные не только по общим цифрам продаж, но и с разбивкой по маркам автомобилей. Чтобы облегчить Microsoft Access задачу, я проиндексирую поле "Марка автомобиля". Для этого нужно открыть указанную таблицу в режиме конструктора и выделить указанную строку при помощи мыши. Далее в системном меню ВИД следует выбрать режим ИНДЕКСЫ. Это активизирует специальный мастер назначения индексов, с которым и предстоит немного повозиться (см. рис. 2). Мастер содержит простую таблицу из трех столбцов: "Индекс", "Имя поля" и "Порядок сортировки". По умолчанию сначала там присутствует только лишь "PrimaryKey", что в переводе означает "первичный ключ". Однако мы внесем сюда некоторые изменения. В первом поле следующей строки набираем с клавиатуры имя, под которым в дальнейшем будет фигурировать наш индекс. Я назвал его " Марка автомобиля" по аналогии. Во втором поле данной строки, как только вы его выделите мышью, появится поле со списком. Открыв список обычным для подобного случая образом, вы обнаружите, что в нем уже перечислены все поля таблицы ПРОДАЖИ, на основании которой создается данный индекс. Надлежит выбрать вариант " Марка автомобиля". В третьем поле указывается вариант сортировки данного поля внутри индексной таблицы. Обычно предполагается, что данные пойдут по возрастанию, исходя в данном случае из порядка чередования букв в алфавите, но вы вольны выбрать и другие варианты, например по убыванию. Изначальное упорядочивание какой бы то ни было информации является непременным условием значительного ускорения работы любых запросов любой СУБД. Вместо того чтобы проверять каждое поле на соответствие всем условиям отбора, программе останется лишь найти начало и конец нужной последовательности данных, что гораздо быстрее. Теперь остается лишь внести завершающие штрихи. В нижней части окна мастера индексирования расположены три общих поля, определяющих базовые свойства каждого конкретного индекса. Первое из них - " Ключевое поле" - определяет: является ли данный индекс уникальным, то есть возможны ли в нем повторения содержимого. К примеру, если вы проектируете СУБД для нужд службы охраны, а внутренняя политика предприятия предусматривает, что существует некоторая категория служебной информации, доступ к которой может быть разрешен только на уровне начальников региональных отделений, то, определяя индекс по полю " Должность", следует сразу указать, что два сотрудника из одного отделения не могут получить вышеуказанный доступ. Это удобнее и быстрее, так как за корректностью данных будет следить сам индекс, а не дополнительный, специально созданный запрос. В противном случае, как, например, в моем примере, индекс должен разрешать существование нескольких полей с одинаковым содержимым, так как множество клиентов могут пожелать приобрести автомобили одной марки. Microsoft Access может также создать индекс не по всем значениям конкретного поля, а только по уникальным, отражающим лишь редко встречающиеся для данной таблицы ситуации. Допустим, фирма крайне редко продает заказные автомобили ручной сборки, но все же время от времени такое происходит. Чтобы запросу не пришлось перебирать все строки нашей таблицы в поисках уникальных значений, можно создать специальный индекс, в свойстве " Уникальный индекс" которого будет значиться " Да". Отдельно стоит обратить внимание на свойство " Пропуск пустых полей". Как известно, раз в год и валенок стреляет, а значит - в сложном проекте может случиться так, что в важном поле окажется значение "ничто", вставляемое СУБД Microsoft Access 97 в том случае, когда в свойствах данного поля таблицы не указано, что поле обязательно должно быть чем-нибудь заполнено, а пользователь по ошибке его пропустил. С точки зрения СУБД "ничто" - это действительно "ничто" и ни к какому определенному типу не относится. Следовательно, на нем будут спотыкаться все функции и модули, для работы которых потребуется содержимое именно данного поля. Да и вообще, таблица с пустыми строками - вещь в хозяйстве крайне неудобная.
Даже чтобы точно указать число ее значащих величин, мало прочитать номер последней строки, нужно непременно писать специальный модуль, который будет проверять наличие пустых ячеек и подсчитывать их количество. Это и долго, и ресурсов требует, и времени. Так что, коль уж возникла нужда в отдельном индексировании каких-то полей таблицы, то пусть уж СУБД сразу избавит нас от лишней головной боли с этими пустыми ячейками. Хотя в некоторых случаях отсутствие информации даже само по себе может быть информацией. Допустим, отсутствие специальной галочки может, к примеру, означать, что клиент расплачивался наличными, а не кредитной карточкой.
Почти так же, как и по одному полю, индекс можно составить по двум и более полям. Вернемся к нашей автомобильной фирме. Предположим, что мы закупаем автомобили не от случая к случаю и не партиями, а официально представляем в данном регионе определенных производителей - таким образом, поставки происходят "под заказ". В то же время известно, что заводы поставляют машины сериями, что отражается в их ценах: там - на десять долларов дороже, тут - на пятерку дешевле и так далее. Технически, создавая собственную СУБД, программистам предстоит создать отдельную таблицу, в которой фиксировать каждую конкретную поставку. Однако может быть и другое решение, конкретная поставка однозначно идентифицируется также при помощи составного индекса. Зная марку машины и ее цену, можно совершенно однозначно сказать, из какой она партии. Это один из примеров составного индекса, объясняющий область их применения.
Чтобы создать составной индекс, например, состоящий из двух полей ("Марка автомобиля" и "Цена"), нужно проделать следующее: открыть нужную таблицу в режиме конструктора (в нашем случае - таблицу ПРОДАЖИ), в меню ВИД выбрать режим ИНДЕКСЫ (на экране должен появиться уже известный вам мастер (см. рис. 2)), в графе " Индекс" набрать с клавиатуры желаемое имя вновь создаваемого индекса. С этого момента процедура немного изменяется, вместо одного имени поля, нужно указать два (или более) - первое из них выбирается в поле " Имя поля" той же строки в поле " Индекс", которой вами только что было набрано имя этого составного индекса, а имя второго поля - строкой ниже. Далее по стандартной методике - когда все готово, окно мастера просто закрывается, как любое другое окно в Microsoft Windows 95, при помощи перечеркнутого квадратика, расположенного в правом верхнем углу. Отныне, продолжая разрабатывать базу данных, можно при создании запросов ссылаться не просто на те или иные поля таблицы, а исключительно на специально индексированные поля. В этом случае СУБД Microsoft Access 97 не станет перебирать саму базовую таблицу, а сразу же воспользуется таблицей соответствующего индекса. Компьютер весьма справедливо полагает, что с индексами придется возиться куда меньше, чем с самой таблицей данных. Причем следует помнить: составным индексом СУБД предпочитает пользоваться даже тогда, когда запрос касается не всех его полей, а лишь некоторых из них или даже вообще всего одним полем.
Вот и получается, что одним из самых важных дел, если вообще не важнейшим, является не конструирование схемы самих таблиц и их содержимого, а определение первичных ключей и всевозможных индексов. Вообще, ключи - дело полезное и удобное, а для СУБД так и вообще незаменимое.
Александр Запольскис
Так определяется ключ, называемый "первичным". Однако во многих случаях первичного ключа оказывается недостаточно для индексации содержимого таблицы, особенно в случаях больших таблиц со множеством полей почти наверняка в процессе работы придется отбирать из них данные и по другим критериям, отличным от простого номера строки в таблице: в таблице адресов это может быть наименование населенного пункта при выборке данных для определенных регионов; в таблице продаж это может быть категория или группа товара, например бакалея или молочные продукты, при выявления статистических показателей по этим категориям. Таким образом, в определенных случаях возникает потребность в создании так называемых "индексов". Индекс - это дополнительная внутренняя таблица Microsoft Access, состоящая всего из двух столбцов: в первом содержатся значения полей, включенных в индекс, а во втором - местоположение этих полей в индексируемой таблице. Сама таблица индексов нигде не отражается и вообще никоим образом для пользователя не видна, тем не менее, начиная с момента создания, она строго привязана к конкретной таблице с данными и всегда доступна для встроенных в СУБД механизмов поиска. Применение индексов значительно ускоряет просмотр и выборку данных, так как СУБД может сразу обратиться к внутренней таблице индексов, вместо того чтобы сначала сортировать огромный массив данных по заданным условиям, потом выделять из него необходимую информацию и лишь затем уже делать с ней то, что пожелал составитель запроса. Правда, имеют индексы и оборотную сторону - каждый из них занимает дополнительное место на жестком диске, а также в оперативной памяти. К тому же сама база данных начинает открываться медленнее, так как каждый раз при запуске СУБД, например Microsoft Access 97, заново проводит перерасчет всех индексов, что требует определенного времени. Таким образом, желательно еще на этапе проектирования общей архитектуры конкретной СУБД продумывать степень разбивки данных по отдельным таблицам исходя из возможных потребностей в них. Иногда самым лучшим бывает создать одну большую таблицу и назначить ей несколько индексов, что также возможно, а иногда проще сразу сделать несколько таблиц меньшего размера, но обойтись минимальным количеством индексов или вообще без них.
Сначала попробуем создать индекс по одному полю. Наверняка руководству нашего гипотетического предприятия будут нужны данные не только по общим цифрам продаж, но и с разбивкой по маркам автомобилей. Чтобы облегчить Microsoft Access задачу, я проиндексирую поле "Марка автомобиля". Для этого нужно открыть указанную таблицу в режиме конструктора и выделить указанную строку при помощи мыши. Далее в системном меню ВИД следует выбрать режим ИНДЕКСЫ. Это активизирует специальный мастер назначения индексов, с которым и предстоит немного повозиться (см. рис. 2). Мастер содержит простую таблицу из трех столбцов: "Индекс", "Имя поля" и "Порядок сортировки". По умолчанию сначала там присутствует только лишь "PrimaryKey", что в переводе означает "первичный ключ". Однако мы внесем сюда некоторые изменения. В первом поле следующей строки набираем с клавиатуры имя, под которым в дальнейшем будет фигурировать наш индекс. Я назвал его " Марка автомобиля" по аналогии. Во втором поле данной строки, как только вы его выделите мышью, появится поле со списком. Открыв список обычным для подобного случая образом, вы обнаружите, что в нем уже перечислены все поля таблицы ПРОДАЖИ, на основании которой создается данный индекс. Надлежит выбрать вариант " Марка автомобиля". В третьем поле указывается вариант сортировки данного поля внутри индексной таблицы. Обычно предполагается, что данные пойдут по возрастанию, исходя в данном случае из порядка чередования букв в алфавите, но вы вольны выбрать и другие варианты, например по убыванию. Изначальное упорядочивание какой бы то ни было информации является непременным условием значительного ускорения работы любых запросов любой СУБД. Вместо того чтобы проверять каждое поле на соответствие всем условиям отбора, программе останется лишь найти начало и конец нужной последовательности данных, что гораздо быстрее. Теперь остается лишь внести завершающие штрихи. В нижней части окна мастера индексирования расположены три общих поля, определяющих базовые свойства каждого конкретного индекса. Первое из них - " Ключевое поле" - определяет: является ли данный индекс уникальным, то есть возможны ли в нем повторения содержимого. К примеру, если вы проектируете СУБД для нужд службы охраны, а внутренняя политика предприятия предусматривает, что существует некоторая категория служебной информации, доступ к которой может быть разрешен только на уровне начальников региональных отделений, то, определяя индекс по полю " Должность", следует сразу указать, что два сотрудника из одного отделения не могут получить вышеуказанный доступ. Это удобнее и быстрее, так как за корректностью данных будет следить сам индекс, а не дополнительный, специально созданный запрос. В противном случае, как, например, в моем примере, индекс должен разрешать существование нескольких полей с одинаковым содержимым, так как множество клиентов могут пожелать приобрести автомобили одной марки. Microsoft Access может также создать индекс не по всем значениям конкретного поля, а только по уникальным, отражающим лишь редко встречающиеся для данной таблицы ситуации. Допустим, фирма крайне редко продает заказные автомобили ручной сборки, но все же время от времени такое происходит. Чтобы запросу не пришлось перебирать все строки нашей таблицы в поисках уникальных значений, можно создать специальный индекс, в свойстве " Уникальный индекс" которого будет значиться " Да". Отдельно стоит обратить внимание на свойство " Пропуск пустых полей". Как известно, раз в год и валенок стреляет, а значит - в сложном проекте может случиться так, что в важном поле окажется значение "ничто", вставляемое СУБД Microsoft Access 97 в том случае, когда в свойствах данного поля таблицы не указано, что поле обязательно должно быть чем-нибудь заполнено, а пользователь по ошибке его пропустил. С точки зрения СУБД "ничто" - это действительно "ничто" и ни к какому определенному типу не относится. Следовательно, на нем будут спотыкаться все функции и модули, для работы которых потребуется содержимое именно данного поля. Да и вообще, таблица с пустыми строками - вещь в хозяйстве крайне неудобная.
Даже чтобы точно указать число ее значащих величин, мало прочитать номер последней строки, нужно непременно писать специальный модуль, который будет проверять наличие пустых ячеек и подсчитывать их количество. Это и долго, и ресурсов требует, и времени. Так что, коль уж возникла нужда в отдельном индексировании каких-то полей таблицы, то пусть уж СУБД сразу избавит нас от лишней головной боли с этими пустыми ячейками. Хотя в некоторых случаях отсутствие информации даже само по себе может быть информацией. Допустим, отсутствие специальной галочки может, к примеру, означать, что клиент расплачивался наличными, а не кредитной карточкой.
Почти так же, как и по одному полю, индекс можно составить по двум и более полям. Вернемся к нашей автомобильной фирме. Предположим, что мы закупаем автомобили не от случая к случаю и не партиями, а официально представляем в данном регионе определенных производителей - таким образом, поставки происходят "под заказ". В то же время известно, что заводы поставляют машины сериями, что отражается в их ценах: там - на десять долларов дороже, тут - на пятерку дешевле и так далее. Технически, создавая собственную СУБД, программистам предстоит создать отдельную таблицу, в которой фиксировать каждую конкретную поставку. Однако может быть и другое решение, конкретная поставка однозначно идентифицируется также при помощи составного индекса. Зная марку машины и ее цену, можно совершенно однозначно сказать, из какой она партии. Это один из примеров составного индекса, объясняющий область их применения.
Чтобы создать составной индекс, например, состоящий из двух полей ("Марка автомобиля" и "Цена"), нужно проделать следующее: открыть нужную таблицу в режиме конструктора (в нашем случае - таблицу ПРОДАЖИ), в меню ВИД выбрать режим ИНДЕКСЫ (на экране должен появиться уже известный вам мастер (см. рис. 2)), в графе " Индекс" набрать с клавиатуры желаемое имя вновь создаваемого индекса. С этого момента процедура немного изменяется, вместо одного имени поля, нужно указать два (или более) - первое из них выбирается в поле " Имя поля" той же строки в поле " Индекс", которой вами только что было набрано имя этого составного индекса, а имя второго поля - строкой ниже. Далее по стандартной методике - когда все готово, окно мастера просто закрывается, как любое другое окно в Microsoft Windows 95, при помощи перечеркнутого квадратика, расположенного в правом верхнем углу. Отныне, продолжая разрабатывать базу данных, можно при создании запросов ссылаться не просто на те или иные поля таблицы, а исключительно на специально индексированные поля. В этом случае СУБД Microsoft Access 97 не станет перебирать саму базовую таблицу, а сразу же воспользуется таблицей соответствующего индекса. Компьютер весьма справедливо полагает, что с индексами придется возиться куда меньше, чем с самой таблицей данных. Причем следует помнить: составным индексом СУБД предпочитает пользоваться даже тогда, когда запрос касается не всех его полей, а лишь некоторых из них или даже вообще всего одним полем.
Вот и получается, что одним из самых важных дел, если вообще не важнейшим, является не конструирование схемы самих таблиц и их содержимого, а определение первичных ключей и всевозможных индексов. Вообще, ключи - дело полезное и удобное, а для СУБД так и вообще незаменимое.
Александр Запольскис
Компьютерная газета. Статья была опубликована в номере 06 за 1999 год в рубрике soft :: субд