Быть или не быть значению переменной
К. Дж. Дейт
Перевод -
Оригинал: To Be Is to Be a Value of a Variable
Все три статьи этого цикла построены в виде полемики с двумя анонимными критиками Третьего Манифеста. Однако данная статья особенно полемична. Местами она напоминает мне одну из любимых книг моего детства – «Материализм и эмпириокритицизм» В.И.Ленина (хотя стиль Дейта является гораздо более интеллигентным). На самом деле, в статье обсуждаются вопросы, играющие важнейшую роль в реляционной модели данных, как она представляется Дарвеном и Дейтом в Третьем Манифесте: значения, проявления значений, переменные отношений, присваивания, равенство и т.д. Вся статья читается исключительно увлекательно, но основной сюрприз запрятан в самом конце. Самое смешное, что если вы сразу начнете читать статью с конца, то можете и не найти этот сюрприз. Вернее, вы может не понять всю каверзность этого сюрприза. Так что читайте уж с начала до конца. Обещаю, не пожалеете.
С.Д. Кузнецов
Автор просит прощения у Джорджа Булос и его книги «Логика, логика и логика» (я позаимствовал название этой статьи из одного из эссе, включенного в эту книгу)
Если мы хотим, чтобы мир оставался таким, как есть,
он должен изменяться
Джузеппе Томази ди Лампедуза
«Изменение» является научным понятием, а прогресс – понятием этическим,
наличие изменения несомненно, а наличие прогресса можно оспаривать
Бертран Рассел
Cache' Server Pages (CSP).
Основой концепции серверных страниц Cache' является автоматическое создание по запросу пользователя web-страниц, содержащих требуемую информацию из БД Cache'. Как видно из рис. 7., вся бизнес-логика CSP-приложений выполняется в непосредственной близости к хранилищу данных Cache', таким образом сокращается объем данных, которыми обмениваются web-сервер и сервер БД Cache', что приводит к выигрышу в производительности по сравнению с другими технологиями создания web-приложений. Для еще большего увеличения производительности CSP приложений при обмене данными между сервером Cache' и web-сервером используются высокоскоростные интерфейсы API.
Рис.7. Сравнение web-технологий.
Серверные страницы Cache' представляют собой текстовые HTML-файлы, расширяемые тегами приложений Cache' (Cache' Application Tags или CATs). Для создания CSP приложений можно воспользоваться стандартными средствами разработки HTML страниц (Cache' предоставляет add-in модуль для полной интеграции с Macromedia DreamWeaver) или, на крайний случай, обыкновенным текстовым редактором.
В Листинге 1 приведен пример небольшого CSP-приложения, которое выводит значения свойств объекта, хранящегося в БД Cache'.
Листинг 1.
<html> <head></head> <body> <script language="Cache'" runat="Server"> set obj=##class(Sample.Person).%OpenId(1) write obj.Name,"<br>" write obj.Age,"<br>" do obj.%Close() </script> </body> </html>
Стандартные теги приложений Cache' приведены в Таблице 1. Однако пользователь не ограничен только стандартными тегами. Cache' предоставляет также интерфейсы для создания пользовательских тегов приложений.
Таблица 1. Стандартные теги CSP.
#(а)# | Вывод значения переменной/функции/метода |
##(a)## | тоже, но во время компиляции |
<CSP:IF CONDITION='a=1'> <b>Unautorized!!!</b> </CSP:IF> | Условие |
<CSP:WHILE …> <CSP:LOOP …> | Циклы |
<SCRIPT Language="Cache'" RUNAT="Server/Compiler"> …. </SCRIPT> | Скрипт внутри страницы |
<SCRIPT Method=methodName Arguments=spec [ReturnType=dataType]>Inner Text</SCRIPT> | Метод CSP класса |
<CSP:QUERY …> <CSP:SEARCH …> <SCRIPT LANGUAGE="SQL" …> | Запрос класса Поисковая форма SQL-запрос |
<CSP:OBJECT …> <FORM CspBind="obj" …> <INPUT CspBind="obj.Name" …> | Открытие объекта Привязка объекта к форме Привязка свойства к полю |
<CSP:CLASS [Encoded=encodedType] [Private=accessType] [Super=classList] …> | Определение родительских классов, режима шифрования и пр. |
При открытии CSP-страницы в браузере Cache' автоматически преобразует CSP-страницу в класс Cache' (по умолчанию классом-предком для CSP-классов является системный класс %CSP.Page). CSP-класс - это не просто способ представления кода. Это отражение полноценной объектной модели CSP-приложения. Т.е. можно использовать все преимущества объектного подхода к разработке при работе с CSP, такие как наследование и полиморфизм.
После преобразования CSP-страницы в класс Cache' класс можно редактировать, используя возможности Object Architect, например, возможность контекстной подцветки кода методов.
Для изучения CSP можно воспользоваться примерами, поставляемыми в стандартной комплектации Cache'. Для этого необходимо установить Cache' и в браузере обратиться по адресу http://127.0.0.1:1972/csp/samples/menu.csp:
CASE
Область CASE обсуждалась с точки зрения требований таких систем к поддерживающим их базам данных. Отмечались такие потребности как версионность, поддержка сложных объектов, наследование и т.д.
Насколько мне известно, в последние десять лет производители CASE-средств в основном продолжали использовать чисто реляционные базы данных, хотя и стали обеспечивать в последнее время возможности проектирования информационных систем, основанных на объектно-ориентированных и объектно-реляционных базах данных.
Цели реляционного подхода
Позвольте начать с того, что думал Кодд относительно перспектив исследуемого им реляционного подхода. В ходе работы представления о перспективах изменялись. Не удивительно, что это отразилось в нескольких статьях Кодда. Например, в статье про RM/T [1] Кодд пишет: "Изначально ... реляционная модель ... рассматривалась как средство для освобождения пользователей от неприятностей, связанных с потребностью иметь дело с массой деталей представления хранимых данных". Более конкретно, а статье про Alpha [2] он обозначает следующие "принципиальные мотивы создания реляционной модели":
Независимость данных Простейшая из числа возможных структура, согласованная с семантическими соображениями Обеспечение унифицирующего принципа, упрощающего язык, требуемый для взаимодействия, и анализ операций, требуемый для авторизации доступа и оптимизации поиска Сравнительно легкий анализ согласованности [данных].
Позже в своей статье про "Великое Сражение" [3] Кодд пишет: "Реляционный подход разрабатывался как ответ на следующие требования, которые были сравнительно новыми в 1968 г.":
Независимость данных Интеграция файлов в базы данных Разнообразные типы пользователей Наличие многих терминальных пользователей с оперативным доступом к данным Возрастающий уровень совместного использования данных Сети удаленных баз данных.
В приглашенном докладе на конгрессе IFIP 1974 [4] (в том же году, когда была опубликована статья про Великое Сражение) Кодд перечисляет следующее как "цели [реляционного подхода]":
Обеспечить высокий уровень независимости данных Обеспечить спартанскую простоту представления данных, чтобы разнообразные пользователи (от новичков в области компьютеров до самых опытных) могли взаимодействовать с данными на основе общей модели (не запрещая добавлять пользовательские представления в специальных целях) Упростить потенциально огромную работу администратора базы данных Ввести теоретическую основу (хотя бы небольшую) в управление базами данных (область, в которой, к сожалению, отсутствуют надежные принципы и руководства) Объединить области выборки фактов и управления файлами, чтобы впоследствии можно было обеспечить соответствующие услуги в мире коммерции Переместить прикладное программирование с использованием баз данных на новый уровень - уровень, на котором множества (и, более конкретно, отношения) трактуются как операнды, а не обрабатываются поэлементно.
И он добавляет: "В связи со второй [ из перечисленных целей] важно помнить, что базы данных появились, чтобы приносить пользу конечным пользователям, а не для прикладных программистов, которые сегодня выступают в качестве посредников (middle-men [sic]) при удовлетворении потребностей обработки данных".
Кодд повторяет те же цели в статье про Великое Сражение и добавляет, что реляционный подход состоит из "четырех основных компонентов":
До предела упростить типы структур данных, используемых в принципиальной схеме (или общем представлении) Ввести мощные операции, обеспечивающие и программистов и непрограммистов возможностями хранения и выборки данных без потребности "навигации" [в оригинале подчеркнуто] Ввести диалоговую поддержку естественного языка (например, английского) для обеспечения эффективного взаимодействия с базой данных случайных (возможно, далеких от мира компьютеров) пользователей Выражать требования авторизации и ограничения целостности отдельно от структур данных (поскольку они подвержены изменениям).
"Обсуждения реляционного подхода часто замыкаются на первом [из этих компонентов] в ущерб остальным трем... Для обоснования этого подхода все четыре компонента должны рассматриваться в одном пакете." [3]
Наконец, в статье, написанной по поводу получения Тьюринговской премии (вполне заслуженной) в 1981 г. за работы Кодда в связи с реляционной моделью [5], он утверждает, что истинная реляционная система может:
Сделать многие приложения доступными для непрограммистов в тех случаях, когда ранее программисты бы необходимы Увеличить производительность программистов во многих (хотя и не всех) приложениях баз данных (немного перефразировано).
Мне кажется, что эти разные списки целей и связанных с ними предметов совместно составляют впечатляющее свидетельство огромных достижений Кодда. Я не думаю, что кто-либо может серьезно утверждать, что (a) какая-либо из этих целей нежелательна и (b) реляционная модель - за одним исключением - не может их достичь.Возможным исключением является "добавление впоследствии соответствующих услуг для мира коммерции". Обеспечение таких услуг все еще является (насколько мне известно) вопросом, адресуемым рынку СУБД. Тем не менее, имеются все основания считать, что реляционная модель действительно обеспечивает правильную основу для таких услуг по причине отмечавшейся в предыдущей заметке тесной связи с логикой предикатов.
Что было, то и теперь есть, и что будет, то уже было…
Сергей Кузнецов
Что было, то и будет, и что делалось, то и будет делаться, и нет ничего нового под солнцем. Бывает нечто, о чем говорят: "смотри, вот это новое"; но это было уже в веках, бывших прежде нас.
Книга Екклесиаста [9:10]
Объектно-ориентированные СУБД (ООСУБД) являются далеко не новым словом в технологии баз данных. Пятнадцать, и даже в некоторых случаях даже 20 лет тому назад это была одна из любимых тем университетских исследований. Общие идеи, лежащие в основе этого подхода, довольно просты и доступно изложены в опубликованном десять лет назад Манифесте объектно-ориентированных баз данных (русский вариант см. в "СУБД" N 4, 1995). Если прибегнуть к еще большему упрощению, то основная цель проектировщиков и разработчиков ООСУБД состояла в том, чтобы предоставить разработчикам информационных приложений механизм управления данными во внешней памяти, который полностью стыковался бы со средствами объектно-ориентированного программирования. Существует обширный класс программистов, для которых объектно-ориентированный подход является гораздо более естественным, чем более традиционное чисто процедурное программирование, а языки объектно-ориентированного программирования плохо сопрягаются со средствами реляционных СУБД (РСУБД).
Одним из основных дефектов технологии информационных приложений на основе реляционных баз данных является то, что логически связанный проект распадается на две реализационно различные части: проектирование и разработка схемы базы данных и проектирование и разработка программного кода приложения. Понятно, что, как правило, данные, хранящиеся во внешней памяти, никому не нужны без обрабатывающих их программ, а эти программы бессмысленны при отсутствии данных. Тем не менее, при реализации этих связанных частей используются абсолютно разные модели и инструменты: системы программирования, с одной стороны, и модели и языки баз данных - с другой.
Технология ООСУБД предполагает существование интегрированной языковой среды, которая одновременно позволяет конструировать объектную базу данных, содержащую не только данные, но и программный код (методы объектов), обеспечивающий доступ к этим данным, и код приложения.
Тем самым, исчезает разрыв между пассивными данными и активными программами, проект прикладной системы ведется в рамках единой технологии, что убыстряет его разработку и облегчает последующее сопровождение. Естественно, что при этом должны преследоваться цели сохранения всех преимуществ объектно-ориентированного программирования (уникальная идентификация объектов, инкапсуляция, наследование, полиморфизм и т.д.) и систем баз данных (многопользовательский режим доступа, восстановление после сбоев, управление транзакциями и т.д.). Казалось бы, блестящие перспективы, и я действительно считал их блестящими пятнадцать лет назад. Почему же эти ожидания не оправдались в полной мере, и почему теперь наблюдается некоторый всплеск активности на рынке ООСУБД? Я перечислю несколько причин негативного характера, возможно, не в порядке возрастания или убывания их важности и, скорее всего, не все.
До последнего времени отсутствовал объектно-ориентированный язык программирования, который был бы (1) "настоящим", т.е. строго соответствующим принципам объектно-ориентированного подхода и (AND!) (2) был бы достаточно распространенным В среде исследователей технологии ООСУБД так и не нашлось специалиста, который, подобно Теду Кодду по отношению к реляционным базам данных, смог бы создать простую и надежную теорию; более того, большинство участников этого сообщества уже давно склоняется к тому, что такую теорию создать невозможно Среди специалистов в области объектно-ориентированных языков программирования отсутствует общепринятое понятие объектной модели, причем все попытки выработать компромиссную эталонную модель до сих пор оканчивались неудачно Преследуя цели сохранить преимущества РСУБД, приходится, тем не менее, пересматривать смысл таких понятий, как единица блокировки для поддержки многопользовательского режима, транзакция, журнализация, ограничение целостности и т.д., причем общепринятой трактовки не существует Преследуя цели сохранить преимущества объектно-ориентированных языков программирования, приходится для обеспечения удовлетворительной эффективности ООСУБД приходится жертвовать полнотой инкапсуляции, вводить ограниченные средства наследования и т.д. При всех отмеченных недостатках (а реально их гораздо больше!) использования реляционных баз данных для разработки информационных приложений существуют надежные методологии и программные средства, позволяющие проектировать, реализовывать, сопровождать и распространять такие приложения; при ориентации на ООСУБД выбор гораздо меньше.
Другими словами, до последнего времени ООСУБД на рынке относились к области риска. С одной стороны, имеется много примеров удачного использования этих продуктов в реализованных приложениях. С другой стороны, сектор рынка ООСУБД очень узок и пока не может приносить больших доходов. Как следствие, сравнительно стабильно существует ряд продуктов ООСУБД. Например, на сегодня достаточно устойчивы следующие продукты: O2 (Ardent Software, Inc. www.ardentsoftware.com), Cashe (InterSystems Corporation, www.intersys.com), ObjectStore (Object Design, Inc., www.odi.com), Objectivity/DB (Objectivity, Inc., www.objectivity.com), POET (POET Software, Inc., www.poet.com, VERSANT (Versant Corporation, www.versant.com), GemStone/S (GemStone Systems, Inc., www.gemstone.com) и т.д. Все эти компании невелики, и годовой бюджет каждой из них находится в пределах десятков миллионов долларов. Крупные софтверные компании, такие как Oracle, Informix, Sybase, Microsoft и IBM, не собираются развивать свою линию продуктов ООСУБД. Вместо этого они предлагают свои подходы к расширению реляционных баз данных объектными свойствами. По этому поводу много писалось, и в любом случае это выходит за пределы объема этой заметки.
Что же сейчас происходит? Почему снова печатные издания часто возвращаются к теме ООСУБД? Неужели что-то радикально изменилось? Неужто появилось что-то новое под нашим с вами солнцем? И да, и нет.
Все проблемы (а я сказал далеко не обо всех) пока остаются актуальными. Технологическая поддержка объектно-ориентированных приложений имеется, но не является достаточно общепринято и признанной. Теоретического основания по-прежнему нет. И т.д.
Но!
a) Появился Internet, появилась технология intranet, появился язык программирования Java.
С точки зрения теории это почти ничего не значит. Internet - это перенос в практическую сферу (с соответствующим развитием) идей и принципов ОС UNIX (вспомните "Сеть - это компьютер" Билла Джоя), Web - это естественное внедрение в Internet принципов организации гипертекста, intranet - это методика использования средств Internet при разработке внутрикопоративных информационных систем; Java (это мое личное мнение, не отражающее какие-либо официальные источники) - это прагматический объектно-ориентированный язык, единственным преимуществом которого является возможность безопасной интерпретации (конечно, здесь я многое утрирую).
С точки зрения практики это значит очень много. Internet - это технология, перевернувшая человеческие представления о распространении информации, бизнесе на основе продажи информации, стремительно переходящая от предоставления обществу множества текстовых документов к графическим образам (необязательно двумерным), аудио- и видео-данным.
Web - компонент технологии Internet, возникший позже других. Здесь тоже нет ничего принципиально нового: естественная идея распространения идеи гепертекста на территориально распределенные информационные ресурсы. Но опять же Но! Технология Web открыла возможность публикации в Internet самых разнообразных источников, начиная от публично доступных и заканчивая сугубо коммерческими.
Язык Java вышел на мировой рынок, главным образом, в связи с потребностями сообщества Internet. Возникший вместе с Web язык HTML является языком гипертекстовой разметки документов, это не язык программирования. А какой-то язык программирования был нужен, чтобы расширить возможности Web - дать возможность Web-клиентам получать не только статические тексты и графику, но и динамические изменяемые картинки, видео- и аудио-данные. Созданный в компании Sun Microsystems интерпретируемый, безопасный, объектно-ориентированный язык Java быстро завоевал распространение именно в среде Web-разработчиков. Не обладая какими-либо принципиально новыми возможностями, Java прежде всего дает возможность создания мобильных в Internet объектов, методы которых могут выполняться в клиентских браузерах независимо от особенностей компьютера клиента (поскольку язык интерпретируемый). Естественно, что появление на мировой арене широко распространенного объектно-ориентированного языка вновь обострило интерес к ООСУБД и к возможностям Java быть языковой основой таких систем баз данных.
Возникновение и распространение информационных корпоративных Intranet-систем явилось естественной реакцией мира бизнеса на существование удобных для разработчиков и пользователей, сравнительно стандартных средств Internet (электронная почта, удаленный доступ к файлам, Web и т.д.) Эта технология, в частности, сделала особенно актуальными возможности сетевого доступа к существующим базам данных и повысила значимость языка Java.
Кроме того, разрабатываемые совершенно заново Intranet-системы стали новой областью повышенного интереса к ООСУБД.
b) На технологию объектно-ориентированных баз данных обратила внимание одна из крупнейших софтверных компаний Computer Associates
Это произошло немногим более двух лет тому назад. Тогда Чарльз Ванг, президент и основатель CA принял решение о стратегическом партнерстве с японской компанией Fujitsu и о фактическом приобретении ее продукта ООСУБД Jasmine. По моему мнению, в исходном продукте не было ничего принципиально нового, но новым было то, что ООСУБД заинтересовалась одна из лидирующих софтверных компаний. Это означало новый уровень доводки продукта до промышленного образца, новый уровень рекламы и маркетинга.
Так оно и произошло. Около полутора лет специалисты CA доводили продукт Fujitsu до промышленного уровня. Уже более полугода компания CA проводит агрессивную рекламную и маркетинговую компанию вокруг Jasmine. Г-н Ванг публично заявил о намерениях компании довести оборот продаж Jasmine до цифр, соизмеримых с оборотом ведущего продукта CA UniCenter.
В этой истории мало интересно техническое содержание (что было, то и будет!), но представляет интерес стратегия Чарльза Ванга, входящего, по моему мнению, в один ряд с Биллом Гейтсом и Ларри Эллисоном, которые никогда не проигрывают. Он рисковый игрок, но игрок, играющий не по азарту, а на выигрыш.
На самом деле, сегодня в Jasmine мы видим два новых для ООСУБД момента, которые оба связаны с масштабностью CA. Во-первых, используя свой практически неограниченный инженерный потенциал, CA смогла довести Jasmine до уровня коммерческого продукта, обеспечив необходимый набор средств разработки (но не проектирования объектно-ориентированных баз данных!). Если вы спросите, верю ли я в работоспособность этой системы, я, конечно, отвечу да. CA - это надежная компания.
Во-вторых, потенциал CA позволил перевести на новый уровень рекламу и маркетинг ООСУБД. Если полностью доверять рекламе CA, то можно вообразить, что эта компания первой создала промышленно доступную технологию объектно-ориентированных баз данных.
Конечно же, это не так, но остается фактом, что CA явилась первой компанией среди монстров софтверной индустрии, которая решилась потратить большие деньги на развитие этой технологии.
Итак, революции в нашем деле, слава Богу, нет. При планировании информационной системы имеется выбор между чисто реляционными, объектно-реляционными и объектно-ориентированными системами баз данных. Чисто реляционные системы слегка туповаты (обратная сторона простоты и эффективности), но зато спокойно справляются с терабайтами информации. Объектно-реляционные системы привлекают тем, что не заставляют полностью пересматривать свой способ мышления и обещают (но не обязательно гарантируют!) тот же уровень надежности, эффективности и масштабируемости, что чисто реляционные системы. Наконец, объектно-ориентированные СУБД предоставляют новый, привлекательный способ создания информационных систем, но пока не обладают коммерческими качествами реляционных систем.
Вряд ли что-нибудь изменится очень быстро. Поживем - увидим. А пока: не делайте резких движений и дышите глубже.
Что это такое?
Вот пример на XML, в котором описывается структура записи данных в документе:
<?XML version="1.0"?>
<!- *** Basket *** ->
<PRODUCT>
<product_id>98756</product_id>
<product_name>basket</product_name>
<unit_of_measure>each</unit_of-measure>
<specification>
<variable>color</variable>
<value>blue</value>
</specification>
<specification>
<variable>size</variable>
<value>large</value>
</specification>
<specification></specification>
<specification/>
</PRODUCT>
Отметим несколько интересных моментов.
Прежде всего, как и в HTML, каждый тег окружается угловыми скобками (<>), и за ним обычно следует текст. За текстом, в свою очередь, следует тег в форме </...>. Тег может не иметь содержания, и тогда за ним сразу следует концевой тег (как в <specification></specification>, или тег может сам заканчиваться прямым слешем (как в <specification/>). Однако, в отличие от HTML, концевой тег требуется всегда.
Во-вторых, заметим, что в данном случае за тегом продукта следует набор связанных тегов, описывающих характеристики (в данном случае столбцы) продукта. Тег <PRODUCT> определяется таким образом, что за ним должен следовать в точности один тег для <product_id> и один тег для <product_name>. Тег <unit_of_measure> является необязательным, хотя пример этого не показывает. Тег <specification> также является необязательным, но у него может существовать одно или большее число вхождений.
Все XML-документы должны начинаться с <?XML version="1.0"?> (или с указанием другой действующей версии). Комментарии задаются в форме
<!- ... ->. Заметим, что пара двойных дефисов должны быть часть содержимого. Также заметим, что, в отличие от HTML, XML позволяет использовать комментарий для окружения строк кода, которые желательно сделать недействующими.
Смысл тега определяется в том, что называется объявлением типа документа (document type declaration - DTD). Это тело кода, определяющее теги через набор элементов. DTD для предыдущего примера выглядит примерно так:
<!DOCTYPE product [
<!ELEMENT PRODUCT (product_id,
product_name, unit_of_measure?, specification*)>
<!ELEMENT product_id (#PCDATA)>
<!ELEMENT product_name (#PCDATA)>
<!ELEMENT unit_of-measure (#PCDATA)>
<!ELEMENT specification (variable, value>>
<!ELEMENT variable (#PCDATA)>
<!ELEMENT value (#PCDATA)>
]
DTD для XML-документа может быть либо частью документа, либо внешним файлом. Если это внешний файл, то все равно оператор DOCTYPE должен присутствовать в документе с аргументом SYSTEM -filename-, где -filename- является именем файлаЮ содержащего DTD. Например, если бы приведенное выше DTD содержалось во внешнем файле с именем xxx.dtd, то оператор DOCTYPE должен был бы иметь вид
<!DOCTYPE product SYSTEM xxx.dtd>
Такая же строка должна быть первой строкой файла xxx.dtd.
Определение элемента product включает список других элементов, в данном случае, product_id, product_name, unit_of_measure и specification. Знак после unit_of_measure означает, что может иметься или не иметься одно вхождение; это необязательный элемент. Знак "*" после specification означает, что элемент является необязательным, но допускается одно или большее число вхождений. Если после какого-то элемента списка присутствует знак "+", то это означает обязательность элемента, а также то, что допускатся более одного вхождения.
В свою очередь, каждый из элементов списка должен быть определен в одной из следующих строк. #PCDATA означает, что тег будет содержать тег, который может быть разобран браузером. Элемент specification уточняется через определения элементов variable и value.
Что такое подставляемость?
При объявлении иерархии типов, мы начинаем с корневого типа, из которого выводятся все другие подтипы. Например, в языке Java все классы (приблизительно аналогичные "объектным типам" Oracle) происходят от корневого класса Object. В Oracle, где объектная модель располагается на вершине реляционной базы данных, не существует встроенной глобальной иерархии. Поэтому, каждый раз, когда мы работаем с объектными типами, необходимо объявлять свой собственный корень.
В этой статье мы рассмотрим очень простую иерархию типов, показанную на Рисунке 1 (и объявленную в файле food.ot, который находится в прилагаемом Download файле).
В этой иерархии тип еда (food), food_t, является корнем. Тип десерт (dessert), dessert_t, является подтипом еды, а пирожное (cake), описанное как cake_t, является в свою очередь подтипом dessert_t. Ниже приведены объявления этих типов (показаны только атрибуты, без связанных с ними PL/SQL методов):
CREATE TYPE food_t AS OBJECT ( name VARCHAR2(100), food_group VARCHAR2 (100), grown_in VARCHAR2 (100) ) NOT FINAL ; / CREATE TYPE dessert_t UNDER food_t ( contains_chocolate CHAR(1), year_created NUMBER(4) ) NOT FINAL ; / CREATE TYPE cake_t UNDER dessert_t ( diameter NUMBER, inscription VARCHAR2(200) ) ; /
Каждый тип имеет свои собственные характерные для данного типа атрибуты. Каждый подтип, не забывайте, также наследует атрибуты своего супертипа(ов). Поэтому, если нужно присвоить значение объекту типа cake, то необходимо указать семь атрибутов, как показано ниже:
DECLARE my_favorite cake_t := cake_t ( 'Marzepan Delight', 'CARBOHYDRATE', 'Swedish Bakery', 'N', 1634, 8, 'Happy Birthday!' ); BEGIN DBMS_OUTPUT.put_line (my_favorite.NAME); DBMS_OUTPUT.put_line (my_favorite.inscription); END; /
Обратите внимание, что я отображаю и ссылаюсь на атрибуты как базового типа еда, так и подтипа пирожное. Они все одинаково доступны мне в объекте типа пирожное.
Эту иерархию нужно понимать следующим образом: пирожное является типом десерта, который, в свою очередь является типом еды.
Но не все десерты являются пирожными, и не всякая еда является десертом (отложим сейчас очевидные культурные сложности, например, что-нибудь, что не считается десертом в Соединенных Штатах, может являться таковым, скажем, в Эквадоре). Любые характеристики еды приложимы к пирожному, но не все характеристики пирожного обязательно имеют смысл для еды, к примеру, такой как огурец.
После того как иерархия объявлена, мы можем работать с ней и выполнять изменения типов в этой иерархии. В некоторых случаях, возможно, потребуется выбирать и просматривать все типы по всей иерархии. В других случаях - только обновлять определенный уровень иерархии, такой как пирожные. И, наконец, бывают ситуации, когда необходимо работать с, скажем, всеми десертами, которые не являются пирожными. И это приводит нас прямо к концепции подставляемости (substitutability)
Супертип является подставляемым, если один из его подтипов может заменить его в некоторых ситуациях, например, при присваивании столбцу или программной переменной, объявленной как супертип (а не как этот конкретный подтип).
Допустим, я создаю таблицу объектов типа food_t:
CREATE TABLE sustenance OF food_t;
Я могу теперь вставить строки в эту таблицу следующим образом:
BEGIN INSERT INTO sustenance VALUES (food_t ( 'Brussel Sprouts', 'VEGETABLE', 'farm' ) ); INSERT INTO sustenance VALUES (dessert_t ( 'Jello', 'PROTEIN', 'bowl', 'N', 1887 ) ); INSERT INTO sustenance VALUES (cake_t ( 'Marzepan Delight', 'CARBOHYDRATE', 'bakery', 'N', 1634, 8, 'Happy Birthday!' ) ); END; /
После запуска этого кода в моей таблице будет три строки: объект еда, объект десерт и объект пирожное. В этом блоке кода, я подставляю мои подтипы вместо супертипа в двух вставках. Это не вызывает ошибки, поскольку пирожные и десерты являются типами еды.
Я могу выполнить запрос к этой таблице в SQL*Plus и он покажет мне все атрибуты типа еда (и только) для трех строк.
SQL> SELECT * FROM sustenance; NAME FOOD_GROUP GROWN_IN ------------------------- ------------------ ------------- Brussel Sprouts VEGETABLE farm Jello PROTEIN bowl Marzepan Delight CARBOHYDRATE bakery
Я могу также использовать преимущества подставляемости в PL/SQL блоках. В следующем коде, я объявляю еду, но инициализирую ее десертом, более конкретным типом еды.
DECLARE mmm_good food_t := dessert_t ( 'Super Brownie', 'CARBOHYDRATE', 'my oven', 'Y', 1994); BEGIN DBMS_OUTPUT.PUT_LINE ( mmm_good.name); END; /
А вот пример подставляемости в PL/SQL коллекциях:
DECLARE TYPE foodstuffs_nt IS TABLE OF food_t; fridge_contents foodstuffs_nt := ( food_t ( 'Eggs benedict', 'PROTEIN', 'Farm'), dessert_t ( 'Strawberries and cream', 'FRUIT', 'Backyard', 'N', 2001), cake_t ( 'Chocolate Supreme', 'CARBOHYDRATE', 'Kitchen', 'Y', 2001, 8, 'Happy Birthday, Veva')); BEGIN FOR indx IN fridge_contents.FIRST .. fridge_contents.LAST LOOP DBMS_OUTPUT.PUT_LINE ( fridge_contents(indx).name); END LOOP; END; /
Теперь рассмотрим вставки, которые не работают. Допустим, я создал объектную таблицу десертов:
CREATE TABLE sweet_nothings OF dessert_t; /
Если теперь я попытаюсь вставить объект типа еда, Oracle выдаст ошибку, как показано ниже:
BEGIN INSERT INTO sweet_nothings VALUES (dessert_t ( 'Jello', 'PROTEIN', 'bowl', 'N', 1887 ) ); INSERT INTO sweet_nothings VALUES (food_t ( 'Brussel Sprouts', 'VEGETABLE', 'farm' ) ); END; / PL/SQL: ORA-00932: inconsistent datatypes
Я получил эту ошибку потому, что любой десерт является едой, но не любая еда является десертом. Я не могу вставить объект типа food_t в столбец типа dessert_t.
Теперь рассмотрим аналогичную ситуацию, в PL/SQL. Я объявляю в своей программе объект типа еда и инициализирую его десертом. Обратите внимание, что я указал Y или "Yes, it sure does!" ("Да, конечно, содержит!") для атрибута contains_chocolate (содержит_шоколад). Однако, если я попытаюсь в своем коде указать этот атрибут, характерный для десерта, PL/SQL выдаст мне ошибку.
SQL> DECLARE 2 -- Опять я подставляю, но на этот раз 3 -- я пытаюсь получить доступ к атрибуту десерта. 4 mmm_good food_t := 5 dessert_t ( 6 'Super Brownie', 7 'CARBOHYDRATE', 8 'my oven', 'Y', 1994); 9 BEGIN 10 DBMS_OUTPUT.PUT_LINE ( 11 mmm_good.contains_chocolate); 12 END; 13 / mmm_good.contains_chocolate); * ERROR at line 11: ORA-06550: line 11, column 16: PLS-00302: component 'CONTAINS_CHOCOLATE' must be declared
Как вы можете заметить, типы являются, как правило, подставляемыми (то есть, вы можете подставить подтип для его супертипа). Преимущества подставляемости можно использовать в объектных типах, объявленных как атрибуты объектных типов, столбцы таблицы или строки в таблицах и коллекциях.
В описании самого объектного типа Oracle не предоставляет никакого способа для отключения подставляемости; любой объектный тип является теоретически или потенциально подставляемым. С другой стороны, Oracle предлагает способ ограничить подставляемость и даже сделать ее невозможной при объявлении использования этого объектного типа.
CIM
Небольшая часть участников отмечала важность области Computer Integrated Manufacturing (CIM). Указывалась потребность таких приложений во встроенных в базу данных правилах и триггерах.
По-моему, прогноз оправдался.
CUBE
Мы обсудили полезность операции ROLLUP для группирования данных на разных уровнях детальности в одном измерении. (В примерах этим измерением была география.) При потребности анализировать данные путем их группировки в более, чем одном измерении, нужно использовать операцию CUBE.
Предположим, что нас интересует влияние пола и даты рождения на сумму дохода. Поскольку пол и дата рождения являются независимыми переменными, имеются четыре возможных способа группировки данных переписи:
Группировка по sex и birthdate (типичный пример: женщины, родившиеся в 1955 г.) Группировка только по sex (типичный пример: женщины всех возрастов) Группировка только по birthdate (типичный пример: люди обоих полов, родившиеся в 1955 г.) Обработка таблицы как одной группы, содержащей оба пола и все даты рождения
Операция CUBE заставляет систему производить группировку по списку выражений всеми возможными способами. Например, если указывается GROUP BY CUBE (sex, year(birthdate)), то система будет формировать группы всеми четырьмя перечисленными выше способами. В запросе с CUBE, как и в запросе с ROLLUP, содержимое сгруппированного столбца появляется как неопределенное значение.
При взгляде на строку результата запроса с CUBE может оказаться трудно сказать, какой вид группы представляет строка. Например, строка с неопределенным значением birth_year может представлять группу с неопределенными годами рождения или группу, содержащую все возможные годы рождения. Чтобы различить группы, можно использовать функцию grouping.
В запросе с CUBE можно применять функцию grouping к любым столбцам или выражениям, используемым внутри операции CUBE. Как и в запросах с ROLLUP, если неопределенное значение выражения группировки имеет специальный смысл "все значения", функция grouping возвращает "1". Например, если grouping(sex) = 1, неопределенное значение столбца sex означает "оба пола". (Такая ситуация могла бы встретиться в строке, для которой данные группировались по году рождения, а не по полу.) Можно использовать функцию grouping внутри выражений CASE, чтобы выдавать на экран некоторое слово или символ для представления специального смысла "все значения".
В следующем примере для этой цели используется "(-all-)". Нужно помнить, что в выражении CASE все возможные значения выражения должны иметь совместимые типы. В примере было необходимо использовать функцию char внутри CASE для преобразования year(birthdate) из целого типа в тип символьных строк, чтобы его тип был совместим со строкой "(-all-)".
SELECT CASE grouping(sex) WHEN 1 THEN '(-all-)' ELSE sex END AS sex, CASE grouping(year(birthdate)) WHEN 1 THEN '(-all)' ELSE char(year(birthdate)) END AS birth_year, max(income) AS max_income FROM census GROUP BY CUBE(sex, year(birthdate));
В таблице 5 показаны результаты этого запроса. Операция CUBE, примененная к n измерениям, будет генерировать 2n различных видов групп. Так, GROUP BY CUBE (sex, year(birthdate)) произвела бы трехмерный результат, содержащий восемь видов групп. К каждой группе можно обычным образом применить раздел HAVING.
F | 1955 | 46700 |
F | 1956 | 36300 |
F | 1957 | 26500 |
F | (null) | 44700 |
M | 1955 | 32100 |
M | 1956 | 42500 |
M | 1957 | 40200 |
F | (-all-) | 46700 |
M | (-all-) | 42500 |
(-all-) | 1955 | 46700 |
(-all-) | 1956 | 42500 |
(-all-) | 1957 | 40200 |
(-all-) | (null) | 44700 |
(-all-) | (-all-) | 46700 |
Действующий OLAP
Супергруппы в DB2 UDB являются мощным средством, позволяющим более просто выражать сложные аналитические запросы и дающим системе возможность более эффективно обрабатывать эти запросы. Используя супергруппы, можно выполнять многомерный анализ разного вида, который обычно связывается с отдельными продуктами хранилищ данных, напрямую над операционными данными базы данных DB2 UDB.
Эта статья основана на выдержках из последней книги Дона Чемберлина "A Complete Guide to DB2 Universal Database (Morgan Kaufmann, 1998), www.mkp.com.
Динамическая обработка запросов.
Также доступен интерфейс для динамической обработки поступающих запросов. В этом случае реализация объекта взаимодействует с заданным интерфейсом по аналогии с интерфейсом динамических вызовов.
Подпрограммы динамической отработки запросов могут вызываться как с помощью интерфейса динамических вызовов, так и с помощью процедур-заглушек, каждый метод дает одинаковый результат.
набор операторов SQL предназначен
Описанный в стандарте SQL/ 89 набор операторов SQL предназначен для встраивания в программу на обычном языке программирования. Поэтому в этом наборе перемешаны операторы "истинного " реляционного языка запросов (например оператор удаления из таблицы части строк, удовлетворяющих заданному условию) и операторы работы с курсорами, позволяющими обеспечить построчный доступ к таблице-результату запроса.
Понятно, что в диалоговом режиме набор операторов SQL и их синтаксис должен быть несколько другим. Весь вопрос состоит в том, как реализовывать такую диалоговую программу. Правила встраивания стандартного SQL в программу на обычном языке программирования предусматривают, что вся информация, касающаяся операторов SQL, известна в статике (за исключением значений переменных, используемых в качестве констант в операторах SQL). Не предусмотрены стандартные средства компиляции с последующим выполнением операторов, которые становятся известными только во время выполнения (например вводятся с терминала). Поэтому, опираясь только на стандарт, невозможно реализовать диалоговый монитор взаимодействия с БД на языке SQL или другую прикладную программу, в которой текст операторов SQL возникает во время выполнения, т. е. фактически так или иначе стандарт необходимо расширять.
Один из возможных путей расширения состоит в использовании специальной группы операторов, обеспечивающих динамическую компиляцию (во время выполнения прикладной программы) базового подмножества операторов SQL и поддерживающих их корректное выполнение. Некоторый набор таких операторов входил в диалект SQL, реализованный в System R, несколько отличный набор входит в реализацию Oracle V. 6, и, наконец, в новом стандарте SQL/92 появилась стандартная версия динамического SQL.
Поскольку в СУБД Oracle средства динамического SQL реализованы уже сравнительно давно, имеет смысл рассмотреть сначала их, чтобы иметь основу для сравнения с SQL/92.
Замечание: мы говорим здесь именно об Oracle V. 6, а не о последней, седьмой версии, поскольку в Oracle V. 7 имеется реализация динамического SQL, соответствующая стандарту SQL/92.
В дополнительный набор операторов, поддерживающих динамическую компиляцию базовых операторов SQL, входят операторы: PREPARE, DESCRIBE и EXECUTE.
Должностная инструкция
Администратор БД отвечает за целостность информационных ресурсов компании. На нем лежит ответственность по созданию, обновлению и сохранности связанных между собой резервных копий файлов, исходя из задач предприятия. Этот человек должен в мельчайших подробностях знать существующие механизмы восстановления программного обеспечения БД.
Возможны ситуации, при которых администратору БД потребуется на основе логических прикладных моделей создавать элементы физической схемы, а также поддерживать связь пользователей с системой и обеспечивать соответствующий уровень информационной безопасности, следя за тем, чтобы доступ к данным имели только те люди, которые в нем нуждаются.
Администратор БД должен уметь определять узкие места системы, ограничивающие ее производительность, настраивать SQL и программное обеспечение СУРБД и обладать знаниями, необходимыми для решения вопросов оптимизации быстродействия БД.
Достижения компьютерной аппаратуры
В следующем десятилетии будет действовать закон Мура: центральные процессоры будут быстрее, диски - больше, появятся крупные достижения в области повышения скорости коммуникаций. В течение десяти лет станет общераспространенным наличие терабайтной основной памяти, служащей буферным пулом для баз данных объемом в сотни терабайт. Все таблицы баз данных, кроме самых крупных, будут постоянно содержаться в основной памяти. Эта технология сделает недействительными фундаментальные предположения, лежащие в основе современных архитектур систем баз данных. В контексте этих новых компьютерных архитектур потребуется переоценка структур данных, алгоритмов и утилит.
Возможно, более важно то, что изменились относительная стоимость вычислений и человеческого фактора: человеческий ресурс - более дорогой. Эта новая экономика требует, чтобы компьютерные системы стали полностью автоматическими: автоинсталлируемыми, автоуправляемыми, авторемонтируемыми и автопрограммируемыми. Компьютеры могут усилить человеческий интеллект путем анализа и обобщения данных, их организации, путем интеллектуальных ответов на прямые вопросы и информирования людей о происшествии интересных событий. Взрывообразное развитие таких модульных приложений масштаба предприятия как SAP™, Baan™ и Peoplesoft™ оказывает огромное давление на системы баз данных. Пользователи достаточно часто желают иметь приложения систем баз данных с 50000 одновременно работающих пользователей. Вычислительные системы и системы баз данных, на которых работают такие приложения, должны обеспечивать на порядки лучшую масштабируемость и доступность.
Если тенденции развития технологии не изменятся, большие организации будут располагать петабайтами памяти, управляемой тысячами процессоров -- в сотни раз большим числом процессоров, чем возможно сегодня. Сообщество баз данных по праву гордится своими успехами в использовании параллельных компьютеров как для обработки транзакций, так и для анализа данных. Однако современные методы вряд ли допускают масштабирование на два порядка.
В течение следующих десяти лет Web будут использовать миллиарды людей, но к нему будут также подключены триллионы "мелочей". В следующем десятилетии будет возрастать мощность встроенных компьютеров в смарт-картах, телефонах и других информационных бытовых приборах. Появятся существенные компьютерные компоненты в переносимых органайзерах (например, Palm Pilots™) и сотовых телефонах. Более того, будут существенно компьютеризованы телевизоры и другие домашние устройства. В новых домах компьютеры будут устанавливаться в выключатели электричества, торговых автоматах и других бытовых приборах. Все товары будут помечаться с помощью идентификационного чипа. Все эти информационные приспособления содержат внутренние данные, которые сопрягаются с другими хранилищами данных. Каждая такая "мелочь" является кандидатом на использование технологии систем баз данных, поскольку большинство из них будет хранить некоторую информацию и управлять ею.
По причине распространения компьютеризованных бытовых приборов мы предсказываем рост размеров и масштабов использования клиентов и серверов данных -- для триллионов мелочей потребуются миллиарды серверов. Число, мобильность и прерывающаяся связность бытовых приборов со встроенными компьютерами делают современные клиент-серверные и трехзвенные архитектуры непригодными для поддержки таких устройств. У многих таких устройств будет отсутствовать пользовательский интерфейс и не будет возможности наличия администратора баз данных -- они должны быть самоуправляемыми, очень безопасными и очень надежными. Повсеместное распространение подобных приборов является основной движущей силой программы исследований, обсуждаемой в следующем разделе.
Древовидные запросы
В Oracle также реализованы так называемые древовидные запросы, предназначенные для работы с данными, организованными в виде дерева. Для реализации дерева в виде таблицы в ней должно быть дополнительных два поля: id узла и id родительского узла. Также должен быть корень (корни). Для реализации древовидных запросов имеются два дополнительных предложения:
START WITH - для идентификации коренных строк CONNECT BY - для связи строк-потомков и строк-предков
В предложении CONNECT BY реализован также оператор PRIOR который используется для обозначения выражения-родителя.
Оператор SELECT, осуществляющий древовидный запрос, может использовать псевдостолбец LEVEL, содержащий уровень вложенности для каждой строки. Для коренных записей LEVEL=1, для потомков коренных записей LEVEL=2 и и.д.
SELECT LPAD(' ',2*(LEVEL-1)) ename org_chart, empno, mgr, job FROM emp START WITH job = 'PRESIDENT' CONNECT BY PRIOR empno = mgr; ORG_CHART EMPNO MGR JOB ------------ ---------- ---------- --------- KING 7839 PRESIDENT JONES 7566 7839 MANAGER SCOTT 7788 7566 ANALYST ADAMS 7876 7788 CLERK FORD 7902 7566 ANALYST SMITH 7369 7902 CLERK BLAKE 7698 7839 MANAGER ALLEN 7499 7698 SALESMAN WARD 7521 7698 SALESMAN MARTIN 7654 7698 SALESMAN TURNER 7844 7698 SALESMAN JAMES 7900 7698 CLERK CLARK 7782 7839 MANAGER MILLER 7934 7782 CLERK
Дубликаты, неопределенные значения
Наверное, многим знатокам языка SQL содержимое этой заметки
покажется тривиальным. Особенно тем, кто читает колонку Криса
Дейта в журнале "Database Programming and Design" (www.dbpd.com).
Поверьте, что я не конкурирую с уважаемым господином (и моим
любимым автором) Дейтом, а лишь хочу высказать свои собственные
соображения, возникшие в ходе подготовки практического курса по
языку SQL. Я занимаюсь вопросами, связанными с организацией
доступа к базам данных, уже более 20 лет, и поэтому мне самому
было странно обнаружить в языке SQL некоторые неафишируемые, но
глубоко присущие ему свойства, отстраняющие язык от классической
реляционной теории.
Дубликаты
Будем придерживаться глубоко противной, но прижившейся в мире
популистской терминологии таблиц, строк и столбцов (вместо
классической терминологии отношений, кортежей и атрибутов).
Некуда деваться, поскольку классическая терминология не дает
возможности погрузиться в болезненные отклонения языка SQL.
Поверьте, что я не являюсь противником этого языка. Хотелось бы
лучшего, равно как хотелось бы иметь общественный строй, отличный
от коммунизма и капитализма, но мы не можем быстро изобрести
что-либо законченное и хорошее.
Язык SQL подобно языку Си (покажите мне того, кто его искренне
любит) возник вовремя. Людям нравятся компромиссы. Компромиссы
любят и создаваемые ими предметы. SQL - это классический пример
языка баз данных, с самого начала основанный на компромиссах.
Господа, Вы хотите иметь реляционный язык? OK, вот он, реляционно
полный (доказано!) язык. Господа, Вы хотите сохранить житейскую
правду жизни при ее моделировании в базах данных? OK, вот он -
язык SQL, близкий и полезный неортодоксальным пользователям баз
данных. За что боролись, то и имеем... Примером бескомпромиссного
языка был Quel. Чистый, понятный, основанный исключительно на
реляционном исчислении кортежей. Его не приняли.
Да, язык SQL действительно реляционно полон. То есть, на нем
можно выразить любое выражение классической реляционной алгебры
или любую формулу реляционного исчисления. Но, к сожалению, на
языке SQL можно сказать гораздо больше, и к какой языковой группе
относятся расширения - остается непонятным...
Прежде всего это касается возможности таблиц (в модели SQL)
содержать строки-дубликаты. На первый взгляд это кажется мелочью.
На самом деле это принципиально. Вся реляционная теория основана
на теории множеств. Математические множества не допускают наличия
дублирующих элементов. Поэтому в теории реляционных баз данных
отношения, которые определяются как множества кортежей, не могут
содержать кортежи-дубликаты. И дальше все получается прекрасно.
Строится алгебра или исчисление, которые замкнуты относительно
понятия отношения: результат вычисления алгебраического выражения
или интерпретации логической формулы является отношением,
следовательно, везде, где можно использовать хранимое отношение,
можно использовать выражение или формулу. Именно из
фундаментального свойства отсутствия дубликата следует наличие
возможного (а следовательно, и первичного) ключа отношения (быть
может, нескольких возможных ключей).
С другой стороны, требование отсутствия дубликатов в некоторых
случаях приводит к утрате части информации при выполнении
алгебраических операций. Прежде всего это связано с операцией
проецирования отношения. Поскольку не требуется, чтобы в число
атрибутов проекции входили атрибуты, составляющие возможный ключ,
при выполнении этой операции могут возникать кортежи-дубликаты, а
поскольку в результате должно получиться отношение, то они должны
устраняться. Тем самым, при выполнении операции проекции мы,
вообще говоря, теряем информацию о количестве кортежей,
содержащих одни и те же значения в атрибутах проекции.
Поскольку язык SQL является компромиссом между требованиями
теории и практики, в нем отсутствие в таблицах дублирующих строк
не является абсолютным требованием. То есть хорошим тоном
является отказ от использования таких таблиц, но язык этого не
требует.
На самом деле, отказ от полного запрета дублирующих
строк вызывает очень далеко идущие последствия.
Например, по этой причине пришлось переопределить семантику
теоретико-множественных операций над таблицами. В SQL имеются
операции UNION ALL (расширенное объединение), INTERSECT ALL
(расширенное пересечение) и EXCEPT ALL (расширенное вычитание),
выполнение которых не уничтожает строки-дубликаты в результате.
Если такая операция выполняется над таблицами T1 и T2, и
некоторый кортеж C входит в обе таблицы, причем содержит n
дубликатов в таблице T1 и m дубликатов в таблице T2, то в
результате операции T1 UNION ALL T2 будет содержаться n+m
дубликатов C, в результате операции T1 INTERSECT ALL T2 -
min(n, m) дубликатов С, а в результате T1 EXCEPT ALL T2 - max((n-m), 0)
дубликатов C. Похоже, что такая трактовка
"теоретико-мультимножественных" операций введена исключительно
для определенности и не подкрепляется какими-либо здравыми
доводами.
Но это, конечно, далеко не все последствия, которые вызвал отказ
от запрета дубликатов.
Возможные и первичные ключи
Когда читаешь описание языка SQL (например, стандарт SQL/92),
как-то не сразу обращаешь внимание, что при определении схемы
таблицы (оператор CREATE TABLE) разделы PRIMARY KEY и UNIQUE
являются необязательными. Зато сразу бросается в глаза
определение таблицы, в которой не задан первичный ключ. Лично я
впервые в своей практике столкнулся с такими таблицами в
демонстрационной базе данных pubs, поставляемой вместе с
Microsoft SQL Server. В этих таблицах, естественно, нет
дубликатов, и немного позже мы обсудим реальные причины того, что
в них не существует ни одного возможного ключа. Но сам факт
наличия подобных таблиц заставил меня по-новому оценить
необязательность разделов PRIMARY KEY и UNIQUE в определении
таблицы.
На самом деле, как мы увидим ниже, компания Microsoft могла
немного по-другому спроектировать схему базы данных pubs,
добившись того, чтобы у каждой таблицы существовал хотя бы один
возможный ключ. Более того, можно было бы потребовать
использовать только такие базовые таблицы, у которых возможный
ключ существует. Но все дело в том, что это противоречило бы
принципам ортогональности компонентов языка SQL. В описании языка
утверждается, что базовые таблицы, динамически создаваемые
таблицы (хранимые таблицы, порождаемые при выполнении оператора
выборки) и представляемые таблицы (таблицы, материализуемые
только при выполнении адресованного к ним оператора языка SQL)
могут использоваться равноправно. Даже если мы потребуем, чтобы в
таблицах, входящих в основную схему базы данных, отсутствовали
дубликаты, а тем самым существовал хотя бы один возможный ключ,
мы никогда не сможем гарантировать отсутствие дубликатов (а
следовательно, наличие возможного ключа) в порождаемых (хранимых
и представляемых) таблицах. Поскольку все виды таблиц
равноправны, неразумно требовать наличия возможного ключа у
базовых таблиц. Все это звучит логично, и в некоторой степени
оправдывает необязательность разделов PRIMARY KEY и UNIQUE.
Но с другой стороны, возможность существования таблицы без
первичного ключа в достаточной степени противоречит здравому
смыслу. Базы данных существуют для хранения информации о реально
существующих или воображаемых объектах окружающей
действительности. В классическом реляционном подходе принято
считать, что каждый кортеж каждого отношения описывает свойства,
присущие некоторой сущности реального мира. В реальном мире не
бывает двух полностью одинаковых объектов, поэтому и любые два
кортежа любого отношения должны различаться. Как мы уже видели,
из этого следует существование возможного (и первичного) ключа.
Можно взглянуть на это и с другой точки зрения. Первичный ключ
является своего рода адресом кортежа отношения. Используя
соответствующее значение (может быть, составное) мы можем сказать
системе управления базами данных, информация о каком объекте нас
интересует. Конечно, все эти здравые соображения становятся
бессмысленными, когда речь идет о таблицах со
строками-дубликатами. Самое интересное состоит в том, что если
реляционная теория наводит на мысль о том, как правильно,
корректно и полезно использовать базы данных, то язык SQL, якобы
давая пользователям большую свободу, ничего не предлагает
относительно способов полезного использования этой свободы.
Первичные ключи и неопределенные значения
Как мы обещали выше, рассмотрим реальные причины того, что в двух
таблицах базы данных pubs отсутствует первичный ключ. Для
определенности выберем одну из этих таблиц - discounts (скидки).
Схема таблицы выглядит следующим образом:
CREATE TABLE discounts
(discounttype varchar(40) NO NULL, stor_id char(4),
lowqty smallint, highqty smallint, discount float NO NULL,
FOREIGN KEY stor_id REFERENCES stores)
Как видно, строка таблицы описывает скидку, назначенную для
указанного магазина. Однако в то же время строки таблицы могут
описывать и потенциально возможные скидки, даже если они не
назначены никакому магазину (поэтому столбцы stor_id, lowqty и
highqty могут содержать неопределенные значения). С другой
стороны, тип и размер скидки могут быть одни и те же для разных
магазинов. Тем самым, пара столбцов (discounttype и discount),
которые могли бы служить первичным ключом, на самом деле таковыми
не являются (остальные столбцы не могут входить в первичный ключ,
потому что потенциально содержать неопределенные значения). Тем
самым, мы имеем таблицу, принципиально не содержащую первичного
ключа и потому (опять же потенциально) включающую
строки-дубликаты (смысла в них нет, но ничто не запрещает их
появление).
Как мы уже говорили, компания Microsoft могла бы сделать схему
базы данных pubs более соответствующей рецептам реляционной
теории. Например, можно было бы вместо таблицы discount сделать
две таблицы:
CREATE TABLE discounts
(discount_id int NO NULL, discounttype varchar(40) NO NULL,
discount float NO NULL,
PRIMARY KEY (discount_id))
CREATE TABLE discountsstores
( discount_id int NO NULL, stor_id char(4) NO NULL,
lowqty smallint NO NULL, highqty smallint NO NULL,
PRIMARY KEY (discount_id, stor_id),
FOREIGN KEY (discount_id) REFERENCES discounts,
FOREIGN KEY (stor_id) REFERENCES stores)
В обеих новых таблицах с первичным ключом полный порядок. Но ведь
SQL никаким образом не стимулирует такое более правильное
проектирование баз данных. И именно потому, что в таблицах могут
содержаться дубликаты. Раз все равно могут существовать таблицы
без первичного ключа, то зачем навязывать первичные ключи при
определении таблицы. Компромиссы...
Первичные, возможные, внешние ключи, функциональные зависимости и
операция группирования
Я снова воспользуюсь примером из базы данных pubs. В базе данных
имеются таблицы sales и stores, определяемые следующим образом:
CREATE TABLE sales (stor_id char(4) NO NULL,
ord_num varchar(20) NO NULL, ord_date datetime NO NULL,
qty smallint NO NULL, payments varchar(12) NO NULL,
title_id tid NO NULL,
PRIMARY KEY (stor_id, ord_num, title_id),
FOREIGN KEY (stor_id) REFERENCES stores,
FOREIGN KEY (title_id) REFERENCES titles)
CREATE TABLE stores (stor_id char(4) NO NULL,
stor_name varchar(40), stor_address varchar(40),
city varchar(20), state char(2), zip char(5),
PRIMARY KEY (stor_id))
Возникает естественное желание выполнять запросы с
эквисоединением этих двух таблиц, получая некоторую агрегатную
информацию о заказах, выполняемых некоторыми магазинами. Примером
такого запроса может быть следующий: "Выдать названия, адреса и
общий объем заказов для магазинов, расположенных в штате
Калифорния". На языке SQL хочется написать такой запрос:
SELECT stor_name, stor_address, sum(qty)
FROM stores A, sales B
WHERE state = 'CA' AND A.stor_id = B.stor_id
GROUP BY A.stor_id
Мы-то понимаем, что хотим сказать: результат соединения
группируется по значениям столбца stor_id, но мы знаем, что
идентификатору магазина в таблице stores однозначно соответствует
его название и адрес (более точно, существуют функциональные
зависимости stor_id -> stor_name и stor_id -> stor_address,
потому что stor_id - первичный ключ таблицы stores). Эти
зависимости сохраняются и в соединенной таблице (stores INNER
JOIN sales ON (stores.store_id = sales.stor_id)). Тем самым,
значения полей stor_name и stor_address являются общими
характеристиками группы c одинаковыми значениями stor_id
соединенной таблицы. Однако при попытке выполнить запрос мы
получим диагностику о недопустимости включения в список выборки
имен столбцов, не входящих в список группирования. И формально
это совершенно правильно, поскольку язык SQL не обязывает
реализацию выводить зависимости для порождаемых таблиц, и система
не имеет информации о существующих функциональных зависимостях.
Более того, язык SQL не предоставляет средств для выражения таких
функциональных зависимостей.
Мне казалось, что ситуация изменится, если мы огрубим ситуацию и
объявим столбцы stor_name и stor_address возможными ключами. Для
этого в языке SQL используется раздел UNIQUE определения таблицы.
В частности, в определении таблицы stores добавились бы строчки
UNIQUE (stor_name),
UNIQUE (stor_address)
Теперь уже система имеет полную информацию об однозначном
соответствии значений столбцов stor_id, stor_name и stor_address.
Однако запрос по-прежнему не выполняется, и диагностика
сохраняется той же самой. И опять-таки это формально правильно,
поскольку в спецификациях языка четко сказано, что если в запросе
используется раздел GROUP BY, то в списке выборки могут
участвовать только имена столбцов, входящих в список
группирования, и агрегатные функции, применяемые к другим
столбцам таблиц, которые перечислены в разделе FROM. Но
пользователям от этого не легче. Похожие таблицы очень вероятно
используются в практических базах данных, и запросы, подобные
приведенному выше, вполне естественны. Для того, чтобы получить
запрос, правильно воспринимаемый системой, его придется
переформулировать следующим образом:
SELECT stor_name, stor_address, sum(qty)
FROM stores A, sales B
WHERE state = 'CA' AND A.stor_id = B.stor_id
GROUP BY A.stor_id, A.stor_name, A.stor_address
В общем- то ничего страшного, можно написать и так. Но, во-первых,
это неестественно: мы вторично сообщаем системе то, что уже было
сказано при создании таблицы stores. Во-вторых, если совершенно
очевиден способ выполнения операции группирования по столбцу
stores.stor_id (поскольку это первичный ключ, то в любой СУБД для
столбца stor_id будет создан уникальный индекс), то не очень
понятно, как будет выполняться модифицированный запрос
(оптимизатор сможет выбирать стратегии сортировки соединенной
таблицы по значениям всех трех полей группирования, а также
использования одного из трех индексов; поскольку мы объявили
stor_name и stor_address возможными ключами, то для этих столбцов
тоже вполне вероятно будут созданы уникальные индексы).
И последнее в этой заметке наблюдение. Если классики реляционной
теории говорят, что в любом отношении должен существовать хотя бы
один возможный ключ, а первичный ключ выбирается неформализуемым
образом из набора возможных ключей, то в языке SQL это не так. В
соответствии со стандартом, первичный ключ не может содержать
неопределенных значений, а ключи, объявляемые с использованием
спецификации UNIQUE, - могут содержать неопределенные значения.
Следовательно, вообще говоря в таблице SQL-ориентированной базы
данных может существовать возможный ключ и одновременно не
существовать первичного ключа. Кстати, именно так обстоит дело в
исходным вариантом таблицы discounts (если еще раз внимательно
посмотреть на ее определение, то можно убедиться, что возможный
ключ в смысле языка SQL в этой таблице существует).
Вывод, который мне хотелось бы сделать, совпадает с призывом
одного из прогрессивных деятелей: "Люди, будьте бдительны!" (даже
если вы пользуетесь стандартным языком баз данных SQL).
ДВА ПОДХОДА К ВЗАИМОДЕЙСТВИЮ
Существует
два основных способа построения продуктов межсетевого взаимодействия, которые во многом
определяют их потребительские характеристики.
Первый способ согласования
разнородных сетей состоит в установке нескольких дополнительных стеков протоколов на
одной из конечных машин, участвующих во взаимодействии. Такой подход называется
мультиплексированием стеков протоколов. Компьютер с несколькими стеками протоколов
использует для взаимодействия с другим компьютером тот стек или тот протокол, который
понимает этот компьютер, то есть выбирает язык, понятный его собеседнику. При
мультиплексировании протоколов реализуется отношение "один-ко-многим", то есть
один клиент с дополнительным стеком может обращаться ко всем серверам, поддерживающим
этот стек, или один сервер с дополнительным стеком может предоставлять услуги многим
клиентам.
Стеки мультиплексируются как целиком, так и по частям - протоколами
отдельных уровней. Хотя в стандартной модели взаимодействия открытых систем OSI
определено семь уровней, коммуникационные средства реальных систем обычно
подразделяются на три уровня. Нижний уровень составляют драйверы сетевых адаптеров,
реализующие функции канального уровня модели OSI, на среднем уровне работают так
называемые транспортные средства, выполняющие функции сетевого и транспортного уровней.
Верхний уровень образуют серверы и редиректоры, выполняющие функции сеансового,
представительного и прикладного уровней модели OSI.
Если в системе
предусматривается мультиплексирование средств каждого из трех уровней, то диалог между
компьютерами может поддерживаться, например, протоколом SMB на верхнем уровне,
протоколами TCP и IP на среднем уровне и протоколом Ethernet на нижнем уровне. Для
организации связей между различными протоколами на каждом уровне вводится
дополнительный компонент, называемый мультиплексором или менеджером протоколов.
Мультиплексор осуществляет стыковку пар протоколов двух соседних уровней в зависимости от
потребностей приложений (заметим, что на верхнем уровне мультиплексор соединяет
приложение с различными редиректорами).
Для того чтобы тот или иной компонент
мог быть использован в режиме мультиплексирования, он должен быть написан в соответствии с
определенными соглашениями, то есть поддерживать требуемый интерфейс с мультиплексором.
Сам мультиплексор должен поддерживать два, в общем случае, разных интерфейса- с
нижележащими и вышележащими компонентами.
Второй способ организации
совместной работы двух разных сетей состоит в выделении специального элемента сети - шлюза,
в котором установлены оба согласуемых стека протоколов. Шлюз транслирует один стек
протоколов в другой для всех нуждающихся в этом приложений, то есть выступает
переводчиком для компьютеров, использующих разные языки общения. Как и обычный перевод,
трансляция протоколов - это сложная эвристическая процедура, так как явное соответствие
между типами сообщений разных протоколов имеется не всегда. Ключевым моментом
трансляции является согласование разных систем адресации ресурсов, принятых в различных
сетях. Шлюз обычно решает эту проблему, привлекая символьные имена ресурсов,
используемых протоколом прикладного уровня при установке соединения клиента с
сервером.
Шлюз реализует взаимодействие "многие-ко-многим", то есть все
клиенты сервера, на котором установлен шлюз, могут обращаться с запросами ко всем серверам
в другой сети.
Движущие силы
Три основных силы определяют предлагаемый ориентацию исследований систем баз данных:
Web и Internet делают легким и привлекательным размещение всей информации в киберпространстве и обеспечивают ее доступность почти для каждого. Все более сложные прикладные среды испытывают возрастающую потребность в интеграции программ и данных. Достижения в области компьютерной аппаратуры делают недействительными предположения и проектные решения, лежащие в основе современной технологии СУБД.
Конечно, читатели знакомы с этими направлениями, но мы обсудим их, чтобы обосновать свое утверждение, что программа исследований нуждается в переопределении в терминах этих новых предположений.
Единая среда разработки XML-приложений. Заключение
В настоящее время среди разработчиков XML-приложений сложился стереотип того, что язык XQuery обладает преимуществами перед языком XSLT при обработки XML-данных, ориентированных на данные, в то время как язык XSLT предпочтителен при работе с XML-данными, ориентированными на документы.
Предложенные в статье функциональные update-выражениями значительно улучшают трансформационные возможности языка XQuery, расширяя его применимость для широкого класса задач обработки XML-данных независимо от их ориентированности. Мы полагаем, что введение функциональных update-выражений позволит избежать существующей на сегодняшний день практики комбинтрования многих языков в XML-приложениях (например, языков XSLT и XQuery).
Функциональные update-выражения - это естественный подход к реализации тесной интеграции языка XQuery и языка модификации XML-данных. Такая интеграция необходима для эффективной разработки XML-приложений на одном языке в пределах одной модели данных языка XQuery.
Идеи, изложенные в работе, требует более детальной проработки и представляют собой предмет дальнейших исследований авторов.
ER-модель поискового механизма
Существует такая хорошая характеристика реляционных баз данных, как очень маленькое время выборки конкретной записи из миллионов других. Это достигается созданием так называемого индекса к таблице на какое-то из полей этой таблицы. Обычно индексы реализуются с применением алгоритма сбалансированного двоичного дерева. Предположим, у нас есть таблица, в которой всего один столбец и в каждой записи таблицы хранится фамилия человека. Предположим, мы загнали в такую таблицу 1 миллион фамилий. Нам необходимо проверить существует ли в этой таблице фамилия ИГУМНОВ. Предположим, что мы еще никаких индексов на эту таблицу не сделали, так же фамилия ИГУМНОВ стоит посередине таблице. Когда мы пошлем вот такой запрос: select surname from ourtable where surname='ИГУМНОВ' база данных переберет пол миллиона записей пока не дойдет до фамилии ИГУМНОВ и не выдаст результат. Получается слишком медленно. Но как только мы сделаем индекс на поле нашей таблицы, как сразу все наши запросы будут обрабатываться за миллисекунды, чего мы и добиваемся. Естественно, одной таблицы будет мало для решения нашей проблемы. Классическая структура базы данных, которая позволит решить нашу проблему, изображена на рис.2.
Рис.2
Начнем с таблицы document. В этой таблице хранятся имена файлов или URL'ы страниц и каждой такой записи сопоставлен уникальный ключ id. В таблице dictionary хранятся все слова, которые могут встретиться в наших документах, и каждому слову сопоставлен уникальный id. Естественно, создаются индексы на поле word в таблице dictionary и на поле id в таблице document. В нашем примере существует отношение многие ко многим. Это необходимо, так как в таблице match мы храним соответствие слова и документа. Другими словами, в таблице match хранится информация о том, какие слова есть в каждом документе. На таблицу match создают индекс, на поле dict_id.
Еще о триггерах
Триггеры реляционной БД должны выполнять код реализующий R- и O- правила. Однако эти триггеры могут контролировать не только данные объекта. Структура класса описывающего данный объект также налагает ограничения на возможные манипуляции с записями, из которых он состоит. Эти ограничения могут быть названы
S-правила (Structure)
Рассмотрим процесс создания объекта. Существование объекта любого класса определяется существованием кортежа отношения OIDs. Таким образом в процессе создание объекта в таблице OIDs должна появится запись, содержащая идентификатор вновь созданного объекта. Все остальные действия по созданию объекта могут выполняться триггером реляционной БД, определенным как триггер на добавление записей таблицы OIDs. В процессе выполнения этот триггер, на основании записей таблиц классов описывающих структуру класса создаваемого объекта производит добавление записей в таблицы сохраняющие данные этого объекта. Для каждой добавленной записи значение поля OID устанавливается равным значению поля OID создаваемого объекта. После этого триггер вызывает конструктор данного класса, производящий инициализацию созданного объекта. Схожим образом может быть реализован процесс уничтожения объекта. Также S-триггеры должны отвечать за поддержку стуктурной целостности объекта в процессе его существования.
Следует отметить, что именно каталог классов фактически является набором S-правил, а код содержащийся в триггере любой таблицы, служит лишь для проверки того, насколько выполняемое в текущий момент действие соответствует данному описанию. Поэтому этот код не зависит от таблицы и может генерироваться по умолчанию.
Физическое проектирование баз данных
Участники пришли к согласию, что требуется построения средств автоматического проектирования физической схемы баз данных, включая добавление и уничтожение индексов, балансировку загрузки дисков и т.д.
Как мы видим, предсказание частично сбылось только к концу 1998 г., когда в Microsoft SQL Server 7.0 появились средства автоматизированной поддержки набора индексов. Автоматизированная балансировка загрузки дисков пока остается на будущее.
Формализм (1).
Придадим сказанному более точный смысл.
Пусть существует конечное множество D доменов {D1,D2...,Dn}, и множество Q определенных на D отношений
Пусть существует домен DS (DS
D), содержащий значения, которые можно рассматривать как уникальные имена DS = {S1, S2, .... Sm}. Каждому имени Si ставиться в соответствие подмножество si отношение Qj, которое можно назвать доменом Qj = dom(si) ,1<=i <=m, QjQ.Замечание : мы не случайно назвали отношение Qi доменом si. Конечно это не соответствует классическому пониманию домена, которое подразумевает, что домен - это множество, а значение домена - это скаляр. В нашем случае значением так же является множество - т.е. значение отношения. Однако, речь все же идет о паре "тип" - "значение типа". Кроме того, такой подход позволяет рассматривать скалярное значение качества (типа) Q и значение отношения этого же типа Q, являющееся атрибутом объекта, как значения, определенные на одном и том же домене Q.
Схемой класса С называется конечное подмножество DS, C = {Si | Si
DS} (будем называть такое Si именем атрибута класса С). Тогда класс c со схемой C - это конечное множество отображений {o1, o2, ..., ok} из C в Q, причем каждое отображение oс должно удовлетворять следующему ограничению: o(si) Qi. Такие отображения o будем называть объектами. Другими словами , объектом о класса c называется множество {si:Si | si является именованным (имеющим имя Si) подмножеством соответсвуещего Qj , si Qj }.Поскольку DS можно рассматривать как объединение всех схем классов C (Ds = C1
C2 .... Cm, где m - число классов существующих в системе), то множество всех объектов всех классов O=c1 c2 .... cm можно рассматривать как множество отображений из домена DS в то же самое множество Q.Формализм (2). Отображение "объекты" "отношения"
Пусть существует домен DOID (DOID
D), содержащий значения, являющиеся уникальными идентификаторами, и каждому объекту о существующему в системе ставиться в соответствие одно и только одно значение из этого домена т.е. O DOID. Поскольку любое o (o O) мы рассматриваем как отображение из DS в Q, и каждому такому отображение соответствует определенное значение OID (OID DOID), то O можно рассматривать как подмножество прямого произведения DOID, DS и QO
DOID DS Q (2)Исходя из того, что
предыдущее выражение можно переписать какЗамечание. Поскольку каждому Q ставиться в соответсвие множество dom-1(Q) именованных атрибутов s, для которых это Q является доменом Q=dom(s), s
dom-1(Q) , dom-1(Q) DS то более точным будет выражениеВыражение (3) можно переписать как
Видно, что множество O является реляционной системой. Каждому значению <d1,...,dn>качества Qi со схемой [D1,...,Dn ], входящему в атрибут sj, объекта ok соответствует кортеж <OIDk, Sj, d1,...,dn> отношения Ri со схемой [DOID:OID, S, D1,...,Dn ]. Каждому качеству Qi ставиться в соответствие отношений Ri, содержащее значения всех атрибутов этого качества, принадлежащих всем существующим в системе объектам. Любой набор данных представленный в виде О (множество объектов) может быть сохранен в виде R (множество отнощений). Другими словами модель "объект-качество" определяет однозначный переход от объектного представления данных (объектный уровень или уровень представления данных) к их реляционному хранению (реляционный уровень или уровень хранения данных). Именно этот переход и должна осуществить система, построенная на основании модели "объект-качество".
Наиболее интересным является то, что уровень хранения является полностью реляционным и описывается в терминах доменов и отношении. Таким образом, модель "объект-качество" не меняет реляционную модель - но она позволяет представить информацию хранящуюся реляцонно, в виде сложных идентифицируемых объектов. Архитектура систем хранения и обработки информации, основанных на таком подходе, может быть проиллюстрирована следующим образом:
Формат сообщений протокола GIOP.
Перед тем, как описывать сообщения протокола GIOP, необходимо определить понятие клиента и сервера. Под клиентом далее понимается агент, который открыл соединение и инициировал запрос. Сервер - это агент, который принял соединение и этот запрос получил. Протокол GIOP определяет семь сообщений, список которых приведен далее в таблице вместе с указанием того, какая сторона какие сообщения может посылать.
Значение, соответствующее типу сообщения | Тип сообщения | Кто может посылать сообщение | |
Клиент | Сервер | ||
0 | Request | Да | - |
1 | Reply | - | Да |
2 | CancelRequest | Да | - |
3 | LocateRequest | Да | - |
4 | LocateReply | - | Да |
5 | CloseConnection | - | Да |
6 | MessageError | Да | Да |
Заголовок сообщения однозначно определяет его тип. Заголовок определен таким образом, чтобы не зависеть от порядка байт в представлении базовых типов данных. Элементами заголовка являются:
Поле magic, которое состоит из четырех символов "GIOP", идентифицирующих все сообщения протокола GIOP. Поле GIOP_version, которое состоит из двух полей major
и minor, идентифицирующих старший и младший номера версии используемого протокола. Текущая спецификация определяет версию 1.0. Приложение должно поддерживать взаимодействие в рамках протокола только если номер, содержащийся в поле major равен, а в поле minor - больше или равен номерам версии, используемой при разработке приложения. Поле byte_order. Значение 0 в этом поле определяет, что в сообщении принято кодирование данных с лидирующим наиболее значащим байтом, 1 - наименее значащим. В настоящее время подавляющее большинство процессоров, в том числе и серия Intel x86 используется представление с лидирующим наименее значащим байтом. Поле message_type
содержит значение от 0 до 6, определяющее тип сообщения. Поле message_size
содержит длину оставшейся части сообщения (0 если больше ничего нет).
За общим заголовком каждого сообщения в зависимости от его типа может идти заголовок и тело конкретного сообщения. Структура каждого заголовка специфична для каждого типа сообщения и представляет особенного интереса для рассмотрения.
Форматы таблиц в MySQL
MySQL для хранения данных использует три типа таблиц: с фиксированной длиной строки, с динамической длиной строки и сжатые таблицы.
Таблицы с фиксированной длиной строки.
Этот формат применяется по умолчанию, если в таблице нет полей с типом VARCHAR,
BLOB или TEXT.
Все поля типа CHAR, NUMERIC и DECIMAL дополняются в конце пробелами.
Высокая скорость работы.
Легко кэшируются.
Легко восстановить после краха, так как все строки имеют постоянную длину.
Не требуют реорганизации ( помощью isamchk), до тех пор, пока не будет удалено очень много записей, и вы захотите освободить место на диске.
Обычно такие таблицы занимают больше места, чем таблицы с динамической длиной строки.
Таблицы с динамической длиной строки.
Этот формат применяется, если в таблице есть поля с типом VARCHAR, BLOB или TEXT.
Все строки динамические (CHAR хранятся как VARCHAR, кроме тех у которых длина меньше 4).
Каждое поле имеет дополнительный бит, который устанавливается, если строковое поле равно "" ( строка ), или если числовое поле равно 0 ( не то же самое, когда поле может иметь значение NULL).
Непустые строки хранятся в виде {_} {_}
Обычно такие таблицы занимают намного меньше места, чем таблицы с фиксированной длиной.
Ожидаемая длина строки вычисляется по формуле: 3+(количество полей + 7)/8+(количество полей типа CHAR)+(размер числовых типов в бинарном виде )+(длина всех строк )+(количество NULL-полей + 7)/8.
Сжатые таблицы.
Таблицы "только для чтения", их можно получить с помощью утилиты pack_isam. Эту утилиту получают все покупатели, которые приобрели расширенную поддержку MySQL.
Основная характеристика - занимают мало места.
Функциональные update-выражения
Для преодоления указанных проблем мы предлагаем расширить язык XQuery функциональными update-выражениями. Функциональные update-выражения составляют язык модификации XML-данных с функциональной семантикой. Основная идея функциональных update-выражений состоит в том, что в них используется синтаксис, близкий к синтаксису традиционных update-выраженияй, но они выполняются без побочных эффектов. В отличие от обычных update-выражений, функциональные update-выражения не изменяют состояние данных, а возвращают копию данных с измененным состоянием.
Компактность и выразительность функциональных update-выражений достигается благодаря использованию синтаксиса, близкого к традиционным update-выражениям. Результатом вычисления функциональных update-выражений являются XML-данные, то есть такие выражения не расширяют модель данных языка XQuery и, следовательно, могут быть естественным образом включены в состав выражений языка XQuery.
Рассмотрим синтаксис и семантику функциональных update-выражений на примерах, описанных во введении. В первом примере требовалось вернуть XHTML-представления обзоров кинофильмов в жанре fiction, заменив все вхождения элемента director соответствующей гиперссылкой. Такой запрос, записанный при помощи функциональных update-выражений, выглядит следующим образом:
for $r in doc("db.xml")/db/movie[gender="fiction"]/review transform replace $d in $r//director with
<a href="{doc("b")//person[name=$d/@name]/homepage/text()}"> {$d/text()} </a>
Запрос 3. Получение HTML-представления обзоров кинофильмов в жанре fiction с использованием функциональных update-выражений
Данное функциональное update-выражение следует интерпретировать следующим образом. Конструкция for связывает XQuery-переменную $r с последовательностью XML-узлов, возвращаемой XPath-выражением, которое следует за ключевым словом in. В функциональном update-выражении ветка for, помимо связывания переменной с последовательностью XML-узлов, определяет результат выражения, то есть новые узлы, которые будут являться результатом вычисления всего выражения.
В данном примере результатом вычисления выражения будет последовательность узлов review. Возвращаемые элементы review представляют собой копию узлов review оригинального документа с модификациями, описанными в конструкции transform replace функционального update-выражения. В данном примере запрос описывает трансформацию данных из класса "найти и заменить". Переменная $d связывается с узлами, расположенными внутри возвращаемого элемента review. Каждое из таких связываний в возвращаемом элементе заменяется на новый элемент, описываемый XQuery-конструктором. Таким образом, в примере функциональное update-выражение возвращает последовательность узлов review, в которых все вхождения элемента director заменены элементом a. Выражение вычисляется без побочных эффектов, т.е. узлы review документа db.xml не изменяются.
Рассмотрим второй пример из предыдущей главы. Нам требуется выполнить запрос над XML-данными с известной схемой данных, ориентированными на хранение данных. Логика запроса заключается в выборке всех заказов с ценой, конвертированной в другую валюту. Ниже представлена запись такого запроса с использованием функциональных update-выражений.
let $euro-rate:=doc("rates")/rates/rate[@name="euro"]/text() for $orders in doc("orders.xml")/orders transform replace $p in $orders/order/orderLine/price with <price>{$p/text()*$euro-rate}</price>
Запрос 4. Получение списка заказов с конвертированной ценой с использованием функциональных update-выражений
По синтаксису и семантике запрос аналогичен предыдущему запросу. Отличия заключаются в двух аспектах. Во-первых, вследствие известной схемы данных, все XPath-выражения прописаны без использования оси descendant-or-self []. Второе, более принципиальное отличие состоит в том, что запрос возвращает один элемент orders, в котором все вложенные элементы order изменены требуемым образом. Так происходит вследствие того, что XPath выражение doc("orders.xml")/orders возвращает только один элемент orders.
Как уже отмечалось выше, функциональное update-выражение может возвращать любые данные из модели данных языка XQuery. В предыдущих примерах результатом вычисления выражений были последовательности узлов элементов XML-документа. Необходимо подчеркнуть, что функциональное update-выражение может возвращать и узел документа. Предыдущий пример (Запрос 4), модифицированный соответствующим образом, представлен ниже (Запрос 5).
let $euro-rate:=doc("rates")/rates/rate[@name="euro"]/text() for $orders in doc("orders.xml") transform replace $p in $orders/orders/order/orderLine/price with <price>{$p/text()*$euro-rate}</price>
Запрос 5. Получение узла XML-документа orders.xml с конвертированной ценой с использованием функциональных update-выражений
Функциональные update-выражения естественным образом расширяют язык XQuery и не нарушают его замкнутости. В сложных XQuery-запросах, update-выражения с функциональной семантикой могут участвовать равноправно по отношению к выражениями языка XQuery. Благодаря этому принципиальной особенностью расширения языка XQuery функциональными update-выражениями является доступность в одном XQuery-выражении как исходного, так и модифицированного состояния XML-данных.
Последняя возможность может требоваться в целом ряде случаев . Например, такая потребность возникает при необходимости произвести некоторую аналитику над возможным изменением данных, то есть проанализировать изменения по отношению к текущему состоянию данных относительно некоторого модифицированного состояния.
В примере Запрос 6 выражение на расширенном языке конструирует сводные XML-данные над исходным и модифицированным состояниями данных. Несмотря на то, что этот запрос может быть относительно просто выражен средствами языка XQuery, в практических приложениях его запись в представленном виде может быть более приемлемой.
let $euro-rate:=document("stock")/rates/euro/text() let $orders:=document("orders")/orders/order let $new-orders:=for $o in document("orders")/orders/order transform replace $p in $o//price with <price> {$p/@euro-price/text() * $euro-rate} </price>
return <price-change> <initial>{sum($orders/price/text()}</initial> <new>{sum($new-orders/price/text()}</new> </price-change>
Запрос 6. Использование в одном запросе исходного и модифицированного состояний данных
Функциональные update-выражения, возвращающие текстовое значение
Для эффективной реализации функциональных update-выражений можно ограничить их семантику таким образом, чтобы такие выражение возвращали сразу сериализованное представление XML-данных, то есть значения текстового типа данных. Такая семантика допускает эффективную реализацию, так как при вычислении не требуется реконструировать узлы документа.
Основное ограничение такого подхода - невозможность композиции выражений. Сериализованное представление не имеет смысла обрабатывать на языке XQuery, так как к нему не применимы XPath-выражения []. Из этого следует, что реализация сложной логики обработки данных на расширенном таким образом языке XQuery затруднена, так как не допускает декомпозиции. Типичный пример - невозможность отделить логику обработки данных от логики их представления, т.е невозможность следовать одному из лозунгов современных технологий разработки Web-приложений. Логично представить, что бизнес-логика обработки XML-данных и построение HTML-представления XML-данных могут реализовываться различными XQuery-функциями, которые разрабатывают разные специалисты. В таком сценарии текстовые update-выражения нельзя использовать для описания логики работы с данными, так как текстовый результат не имеет смысл передавать функции, строящей HTML-код.
Таким образом, возвращение XML-данных в сериализованном виде не вносит ограничений на доступность исходного состояния данных, но ограничивает возможности работы с модифицированной копией данных, не допуская композиции выражений.
Тем не менее, выделенное ограничение не делает такой подход неприменимым. Например, популярный язык трансформации XML-данных XSLT [] обладает схожей семантикой. Результатом вычисления выражений XSLT также является сериализованное представление XML-данных. Мы считаем, что для большого класса трансформационных задач такой подход является достаточным и планируем более детально исследовать присущие ему ограничения.
ГДЕ ВСЕ ЭТО РАЗМЕЩАТЬ?
Если в
качестве средства межсетевого взаимодействия выбран шлюз, то вопрос о месте его размещения
вообще не возникает: шлюз должен быть расположен на сервере той сети, в которой находятся
его клиенты. Например, шлюз SNA Server, позволяющий клиентам Windows NT обращаться к
мэйнфреймам IBM, должен быть установлен на сервере Windows NT
Server.
При установке редиректора NetWare Compatible
Service рабочая станция Windows NT Workstation может непосредственно обращаться к серверам
NetWare 3.x.
При использовании мультиплексоров протоколов
существует два варианта размещения дополнительного стека протоколов - на одном или на
другом взаимодействующем компьютере. Для протоколов типа "клиент-сервер"
важно учитывать функциональные различия между клиентскими и серверными частями. Если
дополнительный стек устанавливается на сервере, то этот сервер становится доступным для всех
клиентов с этим стеком. Однако нужно тщательно оценивать влияние установки
дополнительного продукта на производительность сервера.
При размещении
дополнительного стека на клиентах вопросы производительности не столь существенны. Здесь
более важно ограничить ресурсы клиентских машин, а также облегчить работу администратора
по установке и поддержке дополнительных стеков в работоспособном состоянии на большом
числе компьютеров.
Редиректор NetWare Client for
Windows NT компании Novell позволяет рабочей станции Windows NT стать полноценным
клиентом сервера NetWare 4.xс поддержкой средств NDS.
При
выборе места размещения часто возникает и другой, чисто практический вопрос: можно ли
изменять программное обеспечение обеих взаимодействующих сетей или одна из них
недоступна? В принципе задача взаимодействия двух сетей решается в полном объеме за счет
установки согласующих продуктов только в одной сети - если для нее есть соответствующие
продукты. Например, Windows NT позволяет обеспечить двустороннее взаимодействие с сетями
NetWare, устанавливая дополнительные продукты только на своей стороне и оставляя в
неизменном виде программное обеспечение клиентов и серверов NetWare. Клиенты на базе
Windows NT Workstation получают доступ к сети NetWare с помощью установленных в них
продуктов NWLink и NWCS, а серверы Windows NT Server предоставляют свои ресурсы
клиентам сети NetWare с помощью продукта File and Print Services for NetWare. (Однако нужно
учитывать, что редиректор NWCS не поддерживает службу каталогов NDS компании Novell,
поэтому если мы хотим работать с серверами NetWare 4.x как полноценные клиенты или тем
более как администраторы, то вместо NWCS и NWLink следует использовать продукт компании
Novell - NetWare Client for Windows NT. Сервер File and Print Services for NetWare также не
поддерживает NDS и выполняет функции сервера NetWare 3.12.)
Мы рассмотрели
далеко не все имеющиеся на рынке продукты межсетевого взаимодействия для Windows NT. Их
богатый выбор говорит о постоянно растущем интересе к средствам построения неоднородных
корпоративных сетей "без головной боли". Сегодня каждая операционная система
стремится проявлять максимум дружественности к своим потенциальным партнерам по
объединенной сети, и Windows NT, только еще завоевывающая свое место под корпоративным
солнцем, подает в этом отношении пример своим более зрелым и поэтому более эгоистичным
собратьям.
#4/96
Гедель, Рассел, Кодд: Рекурсивная золотая чехарда
К. Дж. Дейт
Перевод -
Оригинал:
В этой небольшой и изящной статье Дейт обсуждает возможности формулировки неразрешимых выражений средствами языков баз данных. Скорее всего, статья покажется тривиальной математическим логикам, но многие программисты смогут узнать о неожиданных потенциальных трудностях, с которыми можно столкнуться при работе с базами данных.
Статья является первой из трех статей цикла "Обсуждение некоторых критических замечаний в адрес Третьего Манифеста"
С.Д. Кузнецов
Автор просит прощения у Дугласа Хофстадтера и его книги
«Гёдель, Эшер, Бах: Бесконечная золотая нить»
Графические образы
Два участника указывали на потребности приложений, связанных с обработкой графических образов. Для этого требовалась возможность СУБД хранить потенциально неограниченные в объеме битовые строки.
Естественно, такая возможность появилась.
Грандиозный вызов
Мы полагаем, что должна существовать грандиозная мечта, к достижению которой должно стремиться исследовательское сообщество в следующем десятилетии. Грандиозный вызов должен охватывать большую часть проблем, обсуждавшихся в разделе 3, но ориентировать их на достижение некоторой важной цели. Эта цель должна быть простой для понимания и впечатляющей для людей за пределами области исследований баз данных. Другие области будут использовать эти грандиозные задачи для ориентации и мотивации своей собственной деятельности.
В качестве цели на следующие десять лет для исследовательского сообщества баз данных мы рекомендуем:
Полезность информации: Облегчить для каждого хранение, организацию, доступ и анализ большей части человеческой информации в оперативном режиме.
Большая часть человеческой информации в течение десяти лет будет располагаться во Всемирной Паутине. Во многих форматах по всей планете будет распределен экзабайт данных. Без новых средств находить и понимать ответы на наши вопросы будет еще труднее, чем сегодня. Идеальная система должна кратко отвечать на вопросы и предвосхищать их путем оповещения нас об интересных событиях.
Другими словами, целью является превращение Web в следующем десятилетии в более полезную информационную утилиту.
GROUPING SETS
В предыдущих разделах обсуждалось, каким образом можно использовать операции ROLLUP и CUBE в разделе GROUP BY для выполнения детального анализа данных в одном или нескольких измерениях. DB2 UDB поддерживает также некоторые другие виды специальной группировки. Например, может понадобиться анализировать данные в одном измерении без выполнения полного ROLLUP, анализировать несколько измерений без формирования полного CUBE или просто выполнять определенные виды группировки, которые приходят в голову. DB2 UDB позволяет точно специфицировать желаемые виды групп с помощью операции GROUPING SET.
Для использования GROUPING SETS нужно просто указать список видов групп, которые должна сформировать система. Если некоторые критерии группировки включают более одного столбца или выражения, эти критерии заключаются в скобки. Можно использовать пустые скобки для обозначения единственной группы, которая охватывает всю таблицу. Запрос следующего примера разбивает данные переписи на группы по state и sex, затем формирует другие группы по году рождения и в завершение формирует одну большую группу, состоящую из всей таблицы Census. Для каждой группы отображается число человек в группе и средняя сумма дохода группы. Как и раньше, в этом запросе используется функция grouping для отображения специальной строки, когда неопределенное значение имеет специальный смысл "все значения".
SELECT CASE grouping(state) WHEN 1 THEN '(-all-)' ELSE state END AS state, CASE grouping(sex) WHEN 1 THEN '(-all') ELSE sex END AS sex, CASE grouping(year(birthdate)) WHEN 1 THEN '(-all)' ELSE char(year(birthdate)) END AS birth_year, count(*) as count, avg(income) AS avg_income FROM census GROUP BY GROUPING SETS ((state, sex), year(birthdate), ());
В таблице 6 приведены результаты этого запроса. Общее число групп в этом результате есть сумма числа групп, произведенных по каждому из трех наборов группировки: (state, sex) производит четыре группы, year(birthdate) производит четыре группы и пустой набор группировки () производит одну группу, представляющую всю таблицу; всего образуется девять групп.
FL | F | (-all-) | 4 | 38350 |
FL | M | (-all-) | 6 | 34333 |
TX | F | (-all-) | 3 | 39750 |
TX | M | (-all-) | 5 | 34620 |
(-all-) | (-all-) | 1955 | 6 | 37200 |
(-all-) | (-all-) | 1956 | 5 | 35920 |
(-all-) | (-all-) | 1957 | 6 | 33616 |
(-all-) | (-all-) | (null) | 1 | 44700 |
(-all-) | (-all-) | (-all-) | 18 | 36000 |
Группы повторения
Более общим является случай когда отношение, входящие в R*O-систему, содержит произвольное количество кортежей имеющих одинаковые значения полей OID и значения полей SID. Эти записи представляют из себя множество полей идентифицируемого этим OID объекта, имеющими одинаковое семантическое значение SID в контексте класса данного объекта и, таким образом, являются группой повторения.[1]
class Client { ... ADDR [] otheraddresses; ... };
В данном случае в каждом объекте класса Client может содержаться любое количество записей ранее созданной таблицы ADDR имеющих семантическое значение otheraddress. Отметим, что R*O не определяет какие-либо конструктивы позволяющие упорядочить элементы группы повторения - возможный порядок может определяться лишь информацией содержащейся в них:
ADDR [ORDER BY .../*имена атрибутов отношения ADDR*/...] otheraddresses
Характерные вопросы
Пользуясь такой таблицей, легко можно найти родителя или детей у определенного элемента. Но обычно с иерархическими объектами возникают более сложные задачи.
Вероятно, мы захотим узнать, является ли данный элемент терминальным, то есть, отсутствуют ли другие элементы, входящие в него. Это нужно, например, для того, чтобы отличать такие элементы от нетерминальных при выводе иерархического справочника пользователю.
Также может потребоваться узнать, на каком уровне иерархии находится заданный элемент.
Может оказаться необходимым получить всех предков данного элемента, начиная сверху или снизу.
Часто бывает нужно получить всех потомков какого-нибудь элемента, при этом с разными условиями: например, только терминальных, или, находящихся только на определенном уровне и т. д.
Из приведенной выше схемы совсем не очевидны ответы на все эти вопросы. Конечно, если сервер базы данных специально поддерживает иерархию или допускает рекурсию в запросах, то большинство ответов можно получить одним запросом. В противном случае получение результатов будет крайне неэффективным. Как же организовать хранение иерархических объектов, чтобы легко и быстро получать ответы на перечисленные вопросы?
Хранилище данных
Хранилище данных - методология и технология, позволяющая решить проблемы, возникающие при интеграции распределенных и гетерогенных баз учетной системы при внедрении методов OLAP.
Информация в Хранилище является предметно-ориентированной, интегрированной, она хранится долговременно, а ее управление осуществляется независимо от исходных операционных баз данных. В отличие от OLTP-баз, где хранятся детальные данные в виде отдельных записей, в Хранилище содержится сводная и консолидированная информация (часто из нескольких операционных источников), в том числе и историческая.
Объем данных в Хранилище намного больше, чем в базе учетной системы (в тысячи раз). Здесь данные организованы в пре-агрегированной форме в виде многомерных кубов (гиперкубов), удобных для выполнения аналитических операций. Архитектура Хранилища представлена набором компонентов, среди них: источники данных, репозиторий метаданных (здесь описывается, какая информация доступна и где), один или несколько серверов Хранилища или центральный репозиторий (который управляет исходными базами и поддерживает многомерные представления данных), а также интерфейсные средства (например, для создания запросов, отчетов и выполнения анализа).
При обновлении все изменения в исходных данных отражаются в Хранилище. За счет оперативных средств обратной связи Хранилище данных позволяет интегрировать процесс поддержки принятия решений с учетными системами и внешними источниками данных.
Хранилище описаний.
Хранилище описаний представляет из себя сервис, который обеспечивается постоянным объектом, доступном из программы. Во время выполнения программы он дает доступ к информации, аналогичной той, что сохраняется в IDL описании объекта. Эта информация может быть использована для выполнения запроса - таким образом программа, которая не предусматривала использование объекта какого-либо типа, определить доступные у этого типа методы, типы его параметров и осуществить вызов.
Имеет ли все это значение?
Еще одна выдержка из [1]:
Если язык Tutorial D является неразрешимым, то рано или поздно пользователь или система попытаются вычислить неразрешимый оператор, и это приведет к отказу реализации. Вы может возразить, указав, что этого не происходит в вычислительно полных языках, таких как Ada, Pascal, Fortran или Java. Но вы будет не правы. В действительности, нетрудно закодировать бесконечный процедурный цикл, который не распознает никакой компилятор.
Более точно, как мы видим, в [1] утверждается, что с реляционным языком должна быть ассоциирована процедура разрешения («должна существовать процедура разрешения для вычисления любого логического выражения»). Но корректно ли это утверждение? В исчислении предикатов отсутствует процедура разрешения, но, по крайней мере, можно придумать некоторую процедуру, являющуюся полной и совершенной (sound and complete). В моем пересказе в [10] говорится следующее:
Для заданной правильно построенной формулы исчисления предикатов такая процедура будет корректно возвращать TRUE в том и только в том случае, когда формула вычисляется в TRUE; однако, если формула вычисляется в FALSE, то процедура либо выдаст FALSE, либо будет выполняться бесконечно. (Другими словами, если формула истинна, то она является доказательно истинной; однако если она ложна, то не является доказательно ложной.)
Поэтому на практике мы можем включить такую процедуру в реализацию системы. Более того, мы можем включить в процедуру механизм тайм-аутов, так что, если вычисление некоторого заданного выражения не завершается в течение некоторого предопределенного периода времени, систем прекращает вычисление и возвращает пользователю сообщение типа Слишком сложное выражение. (Конечно, она не должна возвращать TRUE или FALSE! Иначе мы вернулись бы к тому, что Кодд – совсем в другом контексте – называл «строго некорректным» результатом [5].)
Следовательно, резюмирую:
Очевидно, нам хотелось бы иметь систему, в которой все возможные выражения могли бы вычисляться за конечное время. Этой цели невозможно достичь, если мы настаиваем на вычислительной полноте. Однако мы хотя бы знаем об этом, и можем к этому подготовиться. В частности, мы можем встроить в систему код, который позволит выдавать в ответ на некоторые запросы сообщения типа «Я не могут ответить на этот запрос, потому что он слишком сложен».
В заключение я хотел бы отметить следующее:
При общении на естественном языке часто бывает невозможно точно ответить на некоторые вопросы. С такими ситуациями мы сталкиваемся постоянно. Поэтому система, которая иногда выдает сообщение Слишком сложное выражение, не является полностью бесполезной. В любом случает, даже при отсутствии вычислительной полноты, вполне вероятно существование запросов, на которые в принципе можно ответить за конечное время, но это время является настолько большим, что ответа дождаться практически невозможно. Другими словами, проблема неразрешимости существует и при отсутствии вычислительной полноты. И поэтому наше прагматическое решение этой проблемы (реализация механизма тайм-аутов), по-видимому, требуется в любом случае. Наконец, если вычислительная полнота ведет к отсутствию разрешимости, то, следовательно, неразрешимы традиционные языки программирования. Но мы благополучно уживаемся с этой проблемой на протяжении многих лет, и я не думаю, что она вызывает непреодолимые трудности. Чем в этом отношении отличаются языки баз данных?
Индексный механизм
Прежде чем ваши документы будут доступны для поиска, их необходимо проиндексировать. Объем индексной информации, полученной из текста, может быть в два раза больше чем сам тексте. А может еще больше, в случае если вы будете не оптимально использовать память. Алгоритм выглядит следующим образом.
1. Получаем документ для индексирования
2. Регистрируем его в таблице document, запоминаем полученный его уникальный id и будем его называть doc_id
3. Разбиваем документ на отдельные слова
4. Узнаем уникальные id этих слов из таблицы dictionary и будем их называть dict_id
5. Потом заносим записи с нашим одним doc_id и разными dict_id (для каждого слова в документе) в таблицу match.
Информационная система: как ее сделать?
Сергей Кузнецов
Вопросительный знак стоит не даром. Это действительно проблема,
которую приходится решать в большинстве современных предприятий,
независимо от того, какого рода бизнесом они занимаются. Термин
"информационная система" относится к классу программных
продуктов, облегчающих, или "автоматизирующих" ведение бизнеса.
Система называется "информационной", если она поддерживает
информационную поддержку бизнеса (любой деловой человек знает,
сколько сил и средств уходит на поддержание необходимой
информации). Соответствующая программа называется "системой",
если она (в некоторых случаях последовательно, а иногда
параллельно) выполняет более одной функции (одним из
распространенных примеров являются информационные системы,
поддерживающие ведение складского хозяйства: они отслеживают
поступление товаров на склад, отпуск товаров покупателю, а также
контролируют наличие на складе необходимого количества каждого
продукта).
В большинстве случаев для создания собственной информационной
системы невозможно обойтись без использования баз данных. Чем
отличается "база данных" от какого бы то ни было склада данных,
поддерживаемого в файлах операционной системы? Основное отличие
состоит в том, что набором данных, входящих в состав базы данных
управляет специальная системная программа, обычно называемая
"системой управления базами данных (СУБД)", которая обладает
знаниями по поводу связи между разнородными данными. Например, в
случае складской системы, СУБД, управляющая соответствующей базой
данных, должна знать, что для всех единиц любого товара,
перечисленных в общей складской ведомости, должно быть
проставлено правильное число в документе, регулирующем
поступление товаров на склад. Такого типа свойства называются
целостностью базы данных. При создании базы данных информационной
системы разработчик сообщает СУБД, какого рода ограничения
целостности система должна поддерживать в базе данных, а далее
ответственность берет на себя СУБД, без требования вмешательства
прикладной программы. Обычно механизм обеспечения целостности баз
данных интегрируется с механизмом управления транзакциями -
последовательностью операций модификации базы данных,
воспринимаемыми СУБД как одна атомарная операция.
Второй важной особенностью СУБД является обеспечение выполнения
так называемых "незапланированных (ad hoc)" запросов к базе
данных. Представим себе, что при проектировании информационной
системы, предназначенной для автоматизации управления складом,
было запланировано выполнение запросов о наличии на складе
товаров, операций модификации данных при отпуске товаров со
склада и их получении, а впоследствии понадобилась информация об
общем объеме поставок от данного поставщика. При отсутствии СУБД
понадобилась бы переделка информационной системы. Однако СУБД,
обладая достаточными знаниями о предметной области (например, о
структуре и смысле данных складской информационной системы),
может обеспечить (и реально обеспечивает) универсальный язык
запросов (обычно, язык SQL), позволяющий сформулировать
произвольный запрос на выборку информации из соответствующей базы
данных. Такой запрос может быть в любой момент подан с терминала
(без участия информационной системы) или встроен в одну из
прикладных программ, входящих в информационную систему.
Наконец, еще одной важной особенностью большинства современных
СУБД является обеспечение так называемого "режима мультидоступа".
Сегодня развитые компьютерные архитектуры обычно относятся к
одной из двух категорий (или к их комбинации):
информационно-вычислительный сервер (mainfraim) с более чем одним
подключенным к нему терминалом или локальная или распределенная
информационно-вычислительная сеть серверов и клиентских рабочих
станций, обеспечивающая совместное использование ресурсов. В
любом случае каждый из потенциальных пользователей может
захотеть (и иметь на это право) в любой момент времени
воспользоваться услугами информационной системы. Соответственно,
информационная система должна иметь возможность параллельно (или
квази-параллельно - главное, чтобы у конечного пользователя не
возникали ощущения чувствительной задержки ответа) выполнить
операции, задаваемые несколькими пользователями одновременно (или
очень близко во времени). При этом такое "параллельное"
выполнение является корректным, т.е. результат получается таким,
как если бы несколько параллельных транзакций выполнялось
последовательно (в литературе по базам данных используется термин
"сериализованное выполнение пользовательских транзакций").
Подавляющее большинство современных развитых СУБД поддерживает
эту возможность, избавляя разработчиков информационных систем от
необходимости заботиться об обеспечении режима мультидоступа.
Базовые знания в области систем управления базами данных кажутся
необходимыми для проектировщиков и разработчиков информационных
систем (независимо от того, какая конкретная СУБД будет
использоваться).
Итак, современные СУБД предназначены именно для разработчиков и
последующих пользователей информационных систем. Однако
достаточно ли этих базовых программных средств? Достаточно часто
проблемой является проектирование и разработка информационной
системы даже в том случае, если система опирается на какую-либо
современную СУБД. Приходится решать задачи трех видов:
проектирование и разработка логической структуры самой
информационной системы как набора программ; проектирование
лежащей в основе общего проекта информационной системы базы
данных; проектирование и разработка интерфейсных подсистем, как
тех, которые относятся к взаимодействиям информационной системы с
конечным пользователем, так и тех, которые связывают прикладные
программы с СУБД. Если проектируемая информационная система
достаточно сложна (а это обычное явление), то решение этих задач
"вручную", без привлечения программных инструментальных средств,
как правило, превышает человеческие возможности.
К нашему с вами счастью о нас (по крайней мере, частично)
позаботились софтверные компании, которые производят средства,
служащие инструментом при проектировании и разработке
информационных систем. Конечно, прежде всего это системы класса
CASE (Computer Added Software Enginering), ориентированные на
поддержку разработки информационных систем. Наиболее развитые
CASE-системы позволяют автоматизировать процесс проектирования и
разработки прикладной системы, поддерживая полную документацию
(возможно, с разными версиями) обо всем этом процессе. Может
быть, наиболее важно то, что такие системы существенно помогают
создавать схему базы данных, лежащей в основе проекта
информационной системы. CASE-системы позволяют естественно (и
достаточно просто) пройти путь от интуитивного представления
структуры и поведения нужной предметной области до
формализованного представления в терминах языка SQL. Такие
возможности CASE-систем может оценить каждый, кому приходилось
вручную проектировать схему достаточно сложной базы данных.
Другой класс программных средств (часто интегрированных с
CASE-системами) составляют программные системы языков четвертого
поколения (4GL). Это, может быть, чересчур громкое название
означает лишь то, что такие, как правило, интерпретируемые языки
предоставляют пользователю более или менее удобные средства для
формирования интерфейса с конечным пользователем (например, в
виде меню или форм), обеспечивают сравнительно простые
возможности для взаимодействия с системой управления базами
данных, а также предоставляют (обычно, достаточно примитивные)
средства программирования. Основным достоинством языков
четвертого поколения является то, что они обеспечивают
возможность так называемого "быстрого прототипирования приложений
(rapid prototyping)".
Это означает то, что при использовании 4GL можно действительно
быстро соорудить работающий прототип будущей системы,
обеспечивающий требуемый интерфейс с конечным пользователем и
взаимодействующий с макетом базы данных (а возможно, и с реальной
базой данных, если она к этому времени подготовлена). Приходится
говорить про "прототип", поскольку большинство современных систем
4GL не обеспечивают той эффективности прикладных систем, какую
дают обычные языки программирования (как теперь принято
выражаться, 2GL или 3GL). Вместе с тем, стоит заметить, что уже
существует масса реально используемых информационных систем,
разработанных исключительно на том или ином 4GL. Кто знает, что
будет завтра, но тенденция к увеличению использования 4GL
очевидна.
Наконец, некоторое количество замечаний по поводу методологии
проектирования и разработки информационных систем. Для
профессиональных программистов постоянной проблемой являлся
разрыв между данными и программой. При наличии сложно
структурированной информации проектирование схемы базы данных
является не менее сложной задачей, чем написание собственно
прикладной системы. Очевидно, что всегда хуже иметь две сложные
задачи, чем одна, даже если в совокупности ее сложность
превосходит сложность каждой их первых задач в отдельности.
Решение этой проблемы предлагает объектно-ориентированный подход.
Если говорить совсем коротко, суть этого подхода состоит в том,
что проектируются не данные и программы в отдельности, а объекты,
сочетающие в себе и данные, и программы, информационно и
функционально характеризующие соответствующие сущности предметной
области. Подход полезен как с методологической точки зрения
(исчезают две разнородные характеристики предметной области -
данные и программы объединяются в объекты), так и с точки зрения
техники проектирования и разработки программных систем (вместо
двух технически не связанных, но логически переплетенных веток
образуется один надежный ствол).
Заметим, что в последнее время подавляющее большинство
CASE-систем и 4GL если не ориентируется, то обращает внимание на
объектно-ориентированный подход. Более того, стали появляться
методики по объектно-ориентированному использованию средств
автоматизированного проектирования и разработки информационных
систем, которые (средства) исходно для этого не предназначались.
Коротко отвечая на вопрос, заданный в заглавии, скажем, что
сегодня создателю информационной системы, как минимум, нужно
иметь базовые знания о современных СУБД, ориентироваться в мире
инструментальных средств разработки программных систем и иметь
представления об объектно-ориентированном подходе к
проектированию и разработке программ. Конечно, при этом неплохо
еще уметь программировать :-).
Инструментальные средства разработки приложений в СУБД Cache'.
В СУБД Cache' реализован собственный язык программирования Cache' Object Script (COS). COS - это расширенная и переработанная версия языка программирования M (ANSI MUMPS).
В первую очередь, COS предназначен для написания исходного кода методов класса. Кроме этого, в Cache' вводится понятие Cache'-программы. Cache'-программа не является составной частью классов и предназначена для написания прикладного программного обеспечения для текстовых терминальных систем.
Для создания Cache'-программ и классов Cache' предназначены утилиты Cache' Studio и Cache' Architect.
Рис.4. Cache' Studio.
С помощью утилиты Cache' Studio можно создавать Cache'-программы. Внешний вид утилиты приведен на рис.4. Для удобства пользователя в Cache' Studio реализована контекстная подцветка команд, функций и операторов COS.
Рис.5. Cache' Architect.
Утилита Cache' Architect предназначена для работы с классами Cache'. Разработчику предоставляется ряд мастеров (wizard), для создания новых и редактирования параметров существующих классов, методов, свойств и др. компонент классов Cache'. Внешний вид утилиты Cache' Architect приведен на рис.5.
Для доступа к многомерным структурам ядра СУБД Cache' можно воспользоваться утилитой Cache' Explorer. Утилита Cache' Explorer предоставляет ряд интерфейсов для просмотра, импорта/экспорта, печати на принтер и др. глобалей, классов Cache', программ Cache'. Внешний вид утилиты приведен на рис. 6.
Рис.6. Cache' Explorer.
Интеграция языковых средств выборки
Расширение языка XQuery выражениями с побочными эффектами порождает ряд проблем, связанных с нарушением целостности данных и необходимостью вносить изменения в модель данных языка XQuery. Эти проблемы являются следствием введения в функциональный язык выражений, выполняющихся с побочными эффектами.
Мы предлагаем подход к интеграции языковых средств выборки XML-данных и изменения XML-данных на основе идеи функциональных update-выражений. Такой выбор обусловлен двумя соображениями:
функциональные update-выражения вычисляются без побочных эффектов, и, следовательно, могут быть естественным образом интегрированы в язык Xquery; функциональные update-выражения по выразительности эквиваленты языкам модификации XML-данных.
Это позволяет описывать логику обработки XML-данных на расширенном языке XQuery, используя функциональные update-выражения для получения модифицированных версий данных. Логика приложения описывается, таким образом, с доступностью начального состояния данных и всех модификаций. Единственное необходимое расширение при таком подходе заключается в возможности отражать модификации данных в базе данных. То есть требуется возможность указывать, какая именно версия данных должна стать актуальной после завершения вычислений.
Ниже приведен пример выражения на языке XQuery, расширенном функциональными update-выражениями, с возможностью сохранения состояния XML-данных в базе данных.
Интеграция структурированных и полуструктурированных данных
Похоже, что приход XML приведет к созданию бесчисленного количества данных, форма которых будет скорее иерархическая, а не реляционная или объектно-ориентированная. Более того, эти данные являются "полуструктурированными" в том смысле, что многие различные формы Web-страниц могут соответствовать одной схеме. Несмотря на энергичные действия сообщества баз данных в областях языков запросов и сред таких данных, эта область все еще находится в младенческом состоянии.
Исследователи баз данных предлагают для XML декларативные языки запросов. Однако, при наличии имеющихся индустриальных подходов, мы полагаем, что XML и его развивающиеся языки манипулирования данными будут напоминать традиционную иерархическую систему баз данных с процедурным языком доступа к данным. Исследовательскому сообществу баз данных следует принять на себя существенную работу по унификации технологий Web и баз данных, включая задачу превращения Web-сред в семантически привлекательные. В число характерных вопросов входят управление несопоставимыми множествами, самоописательность, потенциально глубоко вложенные объекты, разработка пригодных декларативных языков, модели транзакций с неточной согласованностью, автоматический анализ, версионность, взаимодействия обновлений и кэширования.
Interface'ом об table, или компонентный подход в базах данных
Примерно в это же время, а может быть, несколько раньше, разработчики СУБД столкнулись с необходимостью поддержки неструктурированных типов данных: мультимедиа, геопространственная информация, папки электронной почты и т.д. С идейной точки зрения, не принимая в расчет вопросов технической реализации, решение, казалось бы, лежит на поверхности: переписать заново или переработать ядро своего сервера баз данных, сделав его объектно-реляционным и включив туда поддержку новых типов наравне с традиционной информацией. Выигрыш очевиден: мы снова получаем единый API и полный контроль над данными и их изменениями. К сожалению, минусов при таком подходе оказывается больше, чем плюсов. Во-первых, требуется перекачка информации из исходных мест ее хранения в базу данных, где она будет обрабатываться, преобразовываться и возвращаться обратно. Естественно, это не лучшим образом сказывается на производительности и надежности. Во-вторых, выполнение запросов очень трудно поддается оптимизации, так как правила их обработки сильно зависят от типов данных. В-третьих, схема носит закрытый характер и оттого не является привлекательной в глазах разработчиков независимых приложений. Наконец, не вполне понятно, что делать, когда возникнет нужда в поддержке новых типов данных,- снова переписывать ядро? Поэтому следующим этапом стало проектирование универсальных серверов баз данных, где процедуры обработки неструктурированной информации обладали возможностью гибко встраиваться в технологию работы исполнительного механизма СУБД. В одном случае такие процедуры были оформлены как динамические библиотеки и работали в том же процессе, что и ядро универсального сервера, в другом- как самостоятельные процессы. При этом часть процедур отвечала за поддержку дополнительных типов данных, которые наряду с традиционными хранились в базе, а часть (во взаимодействии с сетевым сервером приложений) - за их обработку. В скором времени между приверженцами этих двух направлений разгорелась война не на шутку, которая вышла за пределы соревнования технологий и переместилась на придорожные рекламные щиты и в отделы по найму персонала.
Первый подход критиковался с точки зрения надежности, так как чисто теоретически можно допустить, что случайная ошибка в процедуре способна вывести из строя весь процесс, т.е. ядро СУБД, тем более, что право на написание встраиваемых модулей было также даровано независимым фирмам. Второй подход в силу изоляции процессов друг от друга выглядел более надежным, но по той же причине подвергался критике с точки зрения производительности. В последнее время достаточной популярностью пользуется идея компонентного подхода, когда данные не переносятся в базу, а используются по месту их непосредственного хранения. Для каждого типа данных существует компонент, который мы назовем, скажем, провайдером OLE DB и который по своему принципу работы напоминает хорошо известные ODBC-драйверы, с той лишь разницей, что он умеет обращаться к данным не обязательно реляционной природы. Каждый такой компонент "знает", как обеспечить доступ к своему типу и представляет для этого необходимые (стандартные) интерфейсы. В результате способы представления информации оказываются прозрачными для потребителя, и он сможет в одном операторе select запрашивать, например, информацию из различных баз данных, электронных таблиц, документов, электронной почты, файловой системы и т.п.
Проникновение компонентных технологий в область баз данных было даже в какой-то степени обусловлено исторически. Перенесемся буквально на несколько лет назад, и мы попадем в эпоху расцвета персональных настольных СУБД a la xBase, где пользовательский интерфейс, средства программирования бизнес-логики, обеспечение целостности схемы хранения данных- все было заключено внутри одного продукта. За относительно недолгое время необходимость корпоративной работы над проектом, рост объемов хранимой и перерабатываемой информации и многое другое привели к внедрению клиент-серверных систем, где на сервер базы данных возлагалась ответственность за безопасность хранения и доступа к данным, поддержку их транзакционной целостности, обеспечение пользовательских соединений и многое другое.
На клиенте, соответственно, остались пользовательский интерфейс и какая-то часть бизнес-логики. Вообще, бизнес-логика на сервере начинается с момента проектирования базы данных, и потому лично для меня вполне разумным представляется стремление сосредоточить как можно большую ее часть в триггерах, хранимых процедурах и т.п. Клиент-серверные системы получили широкое признание и распространение вплоть до уровня масштабных корпоративных и общегосударственных проектов. Невероятно разрослась и усложнилась бизнес-логика, она перестала умещаться внутри сервера базы данных. Плюс к тому продолжали оказывать влияние те самые тенденции, которые обусловили переход от персональных баз к клиент-серверным системам: увеличение объемов данных, транзакционной нагрузки, числа одновременных пользовательских коннектов и т.д. В итоге на клиенте остался интерфейс, на сервере баз данных- его типичные функции типа поддержки целостности схемы, резервное копирование, тиражирование, а все, что относилось к бизнес-логике, выделилось в самостоятельное промежуточное звено (middlware). Не успели утихнуть восторги по поводу того, как классно стало жить теперь нам всем, как выяснилось, что новое- это хорошо забытое старое, за все приходится платить, и вместе с бизнес-логикой на хрупкие плечи разработчиков среднего звена ложится обязанность программирования безопасности доступа, управления потоками, обработки транзакций, обеспечения необходимого быстродействия и масштабируемости и много чего еще, с чем раньше благополучно справлялся сервер баз данных. Более того, столь тесное переплетение системного и прикладного программирования не только удлинило сроки разработки и подняло примерно вполовину стоимость такого проекта, но, что еще более печально, увеличило зависимость результатов от конкретного проекта и сделало практически невозможным повторное использование наработок в этой области. В этом месте оставалось бы вздохнуть, развести руками и поставить точку, но я с детства не люблю сказок с несчастливым концом, поэтому в нашем повествовании появляется новое действующее лицо- Microsoft Transaction Server.
Интерфейс динамического выполнения вызовов.
Этот интерфейс допускает динамическое создание запросов к объекту вместо вызова процедуры, декорирующей такое создание. При динамическом создании запроса клиент должен указать всю информацию. Необходимую выполнения операции. Например, информация о типах параметров может быть получена с помощью хранилища описаний объектов. Клиентская часть - заглушки.
Для объектно-неориентированных языков программирования задается программный интерфейс для доступа к методам объекта-заглушки, имеющегося у клиента. Эта заглушка осуществляет передачу запроса и обычно оптимизирована для выполнения под управлением конкретного ORB-а. Если доступно более одного ORB-а, то у них может быть различное внутреннее представление заглушек.
Объектно-ориентированные языки программирования, такие как C++ и Smalltalk такого интерфейса не требуют.
Интерфейс ORB-а.
Интерфейс ORB-а является функциям, вызываемым непосредственно у Брокера Объектных Запросов и идентичным для всех ORB-ов, не зависящим от конкретного объекта либо адаптера объектов. Но так как большинство действий с объектами выполняется посредством адаптеров объектов, существует всего несколько общих операций, которые могут быть выполнены над каждым объектом. Эти операции могут вызываться как клиентом, так и реализацией объекта.
Интерфейсы.
Интерфейс - это описание множества возможных операций, которые клиент может выполнять над объектом. Объект удовлетворяет интерфейсу, если он может быть указан как конечным объектом для каждого потенциального запроса, описанного в интерфейсе.
Типу интерфейса удовлетворяют только объектные типы.
Интерфейсы языков программирования
Некоторые участники считали важным улучшить существующий ужасный интерфейс SQL для встроенных и динамических запросов.
Похоже, что этот ужасный интерфейс будет существовать до смерти SQL.
В течение многих лет не появится стандарт интерфейса 4GL.
Пока не видно даже движений в этом направлении.
Интерфейсы конечного пользователя
Отмечалось, что в исследовательском сообществе баз данных уделялось слишком мало внимания пользовательским интерфейсам. Некоторые участники говорили, что лучшим интерфейсом является такой, для использования которого не требуется руководства.
Мне кажется, что за прошедшие десять лет ситуация радикально не изменилась. Конечно, прочно вошли в практику оконные системы, появились развитые интерфейсы OLAP и администраторов баз данных, но революции не произошло.
IR (Information Retrieval)
Один участник думал, что важно поддерживать приложения, связанные c информационным поиском (то, что сейчас принято называть приложениями полнотекстовых баз данных).
И действительно, универсальные расширяемые СУБД теперь имеют средства, поддерживающие информационно-поисковые системы, хотя о качестве этих средств можно спорить.
Использование для описания данных
Одной из особенностей XML, привлекающей внимание промышленности, является возможность описания структур данных и хранимых данных. Предыдущий пример показывает, что с использованием XML можно определить новые теги специально для описания эквивалента таблиц и столбцов (или сущностей и атрибутов) в структуре реляционной базы данных. Еще более существенно то, что теги для набора столбцов или атрибутов могут связываться с тегами для их родительской таблицы или сущности. Хотя теговая структура кажется хорошим механизмом для описания и понимания структуры базы данных, способ организации данных требует как никогда ранее строгой дисциплины. XML не запрещает иметь повторяющиеся группы, чудовищные структуры данных и т.д. При желании использовать XML для выражения структуры данных нужно проделать настолько хорошую работу, нсколько это позволяет используемый инструмент.
Следуя традиции химиков и астрономов OMG сформировала набор тегов, названный XML Metadata Interchange (XMI), с целью предоставления возможности описания в стандартных терминах структуры данных о данных ("метаданных"). Этот стандарт будет полезен для обмена метаданными между CASE-средствами и для описания "репозитория метаданных" в проектах хранилищ данных. Двигаясь в том же направлении, группа компаний (включающая, в частности, IBM и Oracle) находится в процессе определения Common Warehouse Metadata Interchange (CWMI), подмножества XMI для поддержки хранилищ данных.
Это означает, что имеются два подхода к описанию структуры базы данных на XML:
Во-первых, прикладную базу данных может описывать DTD XML-документа. В этом случае операционные данные базы данных могут быть размещены между наборами описанных тегов. Такое DTD может, например, генерироваться одним CASE-средством, а читаться другим, обеспечивая способ передачи структуры данных. Во-вторых, можно разместить сами определения таблицы и столбцов между тегами XMI, определенными на более высоком уровне абстракции. Этот подход немного более хитрый, поскольку метамодель XMI очень абстрактна, но использование метамодели XMI позволяет описывать намного больше, чем таблицы и столбцы.
Однако заметим, что проблема определения репозитория метаданных или обмена метаданными между CASE-средствами не связана с использованием XML или какого-либо другого языка. Проблемой является структура и семантика базы данных. Важный вопрос состоит не в том, как будет представляться универсальный репозиторий метаданных. (Можно легко представить репозиторий в виде набора реляционных таблиц или диаграмм сущность/связь.) Вопросы состоят в том, что находится в репозитории и что это означает? Какие объекты являются существенными и должны быть описаны? Это гораздо более сложная тема, и она все еще находится в стадии обсуждения. Наличие нового языка не вносит существенный вклад в это обсуждение.
На самом деле при наличии понимания, что XML является хорошим средством для описания структуры базы данных, наиболее очевидным выводом является то, что испоьзование этого языка накладывает большую ответственность на администраторов данных по поводу корректности определения данных. XML не обеспечивает такую корректность; XML всего лишь регистрирует любой проект данных, поступающий от разработчика.
Как говорит Клайв Финкельштейн (Clive Finkelstein), появление XML повышает важность моделирования и проектирования данных: "После 15 лет безвестности люди, занимающиеся моделированием данных, могут в конце концов добиться мгновенного успеха".
Автор статьи приносит благодарность Клайву Финкельштейну, познакомившему его с XML и потратившему много времени на чтение и исправление этой статьи.
Использование индексов.
Все индексы (PRIMARY, UNIQUE и INDEX) хранятся в B-дереве. В строковых типах автоматически происходит сжатие начальных и конечных пробелов.
Индексы используются для:
Быстрого поиска записей по условию WHERE;
Для объединения таблиц с посредством JOIN;
Поиска MAX() и MIN() значений для ключевых полей ;
Для сортировки и группировки таблиц (......ORDER BY и GROUP BY);
Для извлечения данных не из таблицы с данными, а из индексного файла. Это возможно только в некоторых случаях, например, когда все извлекаемые поля проиндексированы.
Рассмотрим следующий запрос SELECT: SELECT * FROM tbl_name WHERE col =val AND col2=val2;
Если таблица имеет множественный индекс (col,col2), то соответствующие записи будут выбраны напрямую. Если существуют только одиночные индексы для col и col2, то оптимизатор сначала решит, при использовании какого индекса, количество возвращаемых записей будет меньше, а затем из этих записей будет произведена выборка по другому условию.
Если таблица имеет множественный индекс, то любой " префикс " этого индекса может использоваться для оптимизации запроса. Например, если есть индекс (col, col2, col3), то можно считать, что существуют индексы (col ); (col,col2); (col,col2,col3).
Любая другая часть индекса не может быть использована для оптимизации. Рассмотрим для примера такие запросы: mysql> SELECT * FROM tbl_name WHERE col =val ; mysql> SELECT * FROM tbl_name WHERE col2=val2; mysql> SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
Если есть индекс (col,col2,col3), то только в первом запросе будет использоваться индекс. Хотя второй и третий запросы содержат столбцы, которые присутствуют в индексе, но (col2) и (col2,col3) не являются левыми частями множественного индекса, и поэтому при выполнении этих запросов индекс применятся не будет.
MySQL также использует индексы для LIKE операций, если аргумент LIKE является строковой константой и при этом не начинается с символа шаблона (% или _). Например, следующие SELECT запросы используют индекс для key_col: mysql> select * from tbl_name where key_col LIKE "Patrick%"; mysql> select * from tbl_name where key_col LIKE "Pat%_ck%";
А следующие два запроса выполняются без использования индекса: mysql> select * from tbl_name where key_col LIKE "%Patrick%"; mysql> select * from tbl_name where key_col LIKE other_col;
В первом из этих запросов аргумент после LIKE начинается c символа шаблона, а во втором аргумент не является константой.