Миграция на MS SQL Server 7.0

Рейтинг:   / 3
ПлохоОтлично 

Одно из важных условий успеха современного предприятия - его способность организовать эффективную обработку информации. Это можно отнести к любой области деятельности: производству, торговле, транспорту и т. д. Правильно организованные сбор данных, их хранение, обработка и анализ позволяют реально оценить текущее состояние дел предприятия, своевременно принять решение об изменении стратегии развития и обеспечить контроль за распределением ресурсов. Программное обеспечение для поиска, сбора и визуализации оперативно-доступной информации - ключ к созданию эффективных систем управления данными.

 

Современные системы управления данными хранят громадные объемы информации, отражающие историю развития той или иной компании. Размеры подобных баз данных постоянно растут. В этой ситуации основной проблемой оказывается выбор программного обеспечения для наиболее эффективною функционирования системы. Одной из наиболее распространенных СУБД уровня предприятия является Microsoft SQL Server компании Microsoft, некоторым особенностям работы с которой и посвящена данная статья.

Как и у любой системы, у SQL-сервера есть свои достоинства и недостатки. Очевидно, что параллельное выполнение транзакций, процедур индексации и загрузки данных, удобные графические средства администрирования сервера, сервис управления заданиями SQL Executive, поддержка стандартов языка ANSI SQL-92 и FIPS 127-2 и многое другое, подробно описанное в документации на SQL Server, относятся к достоинствам данной СУБД. Однако при работе с этой системой вы не застрахованы от неожиданностей, никак не отраженных в официальных источниках. С некоторыми из них я столкнулся при переходе от версии MS SQL Server 6.5 к версии 7.0 в рамках реального корпоративного проекта.

В базу данных проекта входят порядка ста таблиц, восьмидесяти триггеров, пятидесяти представлений и около ста хранимых процедур. К 80% таблиц создано по два-три индекса для ускорения выполнения SQL-запросов. Общий обьем БД составляет 1,5 Гбайт. До момента принятия решения о переходе от MS SQL Server 6.5 на Server 7.0 проект развивался около полугора лет. За этот период был разработан ряд клиентских приложений, уже сданных в промышленную эксплуатацию.

Обработка информации в БД осуществляется с использованием хранимых процедур и триггеров, а чтение - SQL-запросами клиентских приложений. Новые данные помещаются в БД в пакетном режиме посредством импорта из dBase-файлов. Процесс импорта автоматизирован и состоит из следующих этапов:

1. Импорт данных из dBase-файлов в БД на SQL-сервере. На сервере существуют таблицы, совпадающие по структуре с DBase-файлами, из которых импортируются данные.

2. Обработка данных для сокращения времени доступа к ним из клиентских приложений. На этом этапе в БД добавляется избыточная информация, позволяющая сократить количество таблиц в запросах к серверу из клиентских приложений. Это особенно актуально при работе с MS SQL Server версии 6.5, так как в ней действует ограничение на число таблиц в одном запросе - не более 16.

К системе предъявляются требования по минимально возможному времени отклика на запрос со стороны клиентских приложений, а также высокой скорости обработки и модификации данных. По сути, это означает необходимость поиска золотой середины между количеством индексов к таблицам и скоростью их построения при вставке/модификации информации. За полтора года работы были выявлены и оптимизированы наиболее часто используемые запросы, под которые были созданы необходимые для эффективной работы индексы. Однако недостатки SQL Server 6.5 еще на этапе проектирования системы уже оказывали влияние на ее дальнейшее развитие. Перечислим некоторые из них, наиболее существенные, по мнению автора.

Во-первых, наличие индексов для некоторых нолей отнюдь не означало высокую скорость работы при выполнении запросов к БД. В частности, иногда возникала необходимость добавить в SQL-запросы так называемые optimizer hints («подсказки оптимизатору»). Этот механизм применяется, в частности, для указания серверу того, какой индекс необходимо использовать при выполнении данного запроса. Поясню это на небольшом примере.

Существует некоторая таблица:

CREATE TABLE ExampleTable ( Id INT NOT NULL,

Day DATETIME NOT NULL,

SomeNum INT NOT NULL )

К ней создан индекс:

CREATE INDEX ExampleTablelNDl ON ExampleTable ( Id )

Предположим, вам необходимо получить данные обо всех записях, в которых Id > 30. Можно просто выполнить следующий запрос в надежде на то, что сервер сам определит оптимальный для работы индекс:

SELECT Day

FROM ExampleTable

WHERE Id > 30

Если окажется, что производительность сервера на данной операции окажется значительно ниже ожидаемой, можно попытаться указать серверу на необходимость использования определенного индекса:

SELECT Day

FROM ExampleTable ( INDEX = ExampleTablelNDl ) WHERE Id > 30

Текст в скобках и является одним из вариантов «подсказки оптимизатору». Подобное решение накладывает лишние ограничения на модернизацию системы, заставляя отслеживать не только корректность запроса базовым структурам БД -таблицам, но и выполнять аналогичную работу по отношению к индексам.

Во-вторых, SQL-сервер совершенно не может работать с индексами к полям типа DateTime, если в них хранится информация с точностью до минут (а не с точностью до суток). Это проявилось, в частности, при работе с таблицей, содержащей поле этого типа, объемом порядка 2,5 млн. записей. Скорости работы запросов к ней с использованием и без использования индекса к DateTime-полю были практически одинаковыми.

В-третьих, уже упомянутое выше ограничение на количество таблиц в одном запросе влияло и на количество внешних ключей, которые могут быть построены для полей одной таблицы. Их не могло быть более 16, что проявлялось не в процессе создания таблицы через предупреждение системы, а при попытках записи в нее данных.

Кроме того, иногда сервер начинал «жить собственной жизнью». Ни с того ни с сего ломались индексы, что проявлялось в замедлении в несколько раз времени выполнения запросов. Переставали корректно работать триггеры и хранимые процедуры, не позволяя корректно работать с информацией в таблицах. Важно не то, что такие явления имели место, а то, что их возникновение очень трудно было отследить и своевременно исправить. Особенно неприятно было узнавать о неработоспособности системы от пользователей. Иногда перечисленные эффекты исправлялись перекомпиляцией триггера или перестройкой индекса, а иногда не помогало даже восстановление архива базы данных, который был сделан заведомо до их проявления.

Я ни в коем случае не хочу утверждать, что данная СУБД состоит из одних недостатков, однако именно они в большой степени повлияли на решение о переходе на более современную версию сервера.

Прежде чем начать разговор собственно о миграции на седьмую версию сервера, хочу обратить внимание еще на один механизм, предоставляемый данной СУБД. Он заключается в возможности получить на основании существующей базы данных SQL-скрипт для ее генерации. По моему мнению, это полезно не только для написания технической документации, но и в тех случаях, когда вся информация, необходимая для инициализации системы, также существует в SQL-скриптах. Например, если ряд таблиц в БД предназначен для хранения списка стран и городов, являющихся практически константами, то имеет смысл создать SQL-запрос, который заполнит соответствующие таблицы необходимой информацией. Это может оказаться полезным в будущем, при создании однотипных систем. В этом случае совокупность SQL-скриптов с информацией для генерации таблиц и данных представляет собой решение, позволяющее на ранних этапах разработки обойтись без клиентских приложений для ввода инвариантной (для большинства систем) информации.

К сожалению, не обходится без накладок. При генерации SQL-скрипта расположение хранимых процедур не соответствует тому, как эти процедуры должны создаваться, то есть вызывающая процедура не всегда располагается после всех вызываемых в ней. Таким образом, данный механизм также не лишен недостатков, что значительно ограничивает его применение, в частности, при переходе на новые версии сервера.

Итак, что же необходимо для перехода на MS SQL Server 7.0? При рассказе об этом я воспользуюсь информацией, полученной в результате самостоятельного изучения вопроса. СУБД может работать под управлением любой из версий Windows, начиная с Windows'95. К сожалению, под управлением Windows'9x может работать только Desktop Edition, пригодный разве что для ознакомления с возможностями сервера. Разумеется, никто не собирается использовать в качестве операционной системы для сервера баз данных ОС Windows'9x. Целесообразность же практического применения Desktop Edition для сколько-нибудь значительных разработок представляется весьма сомнительной. Enterprise Edition требует, как минимум, Windows NT Server 4.0 с установленным Service Pack 4.0 (можно более позднюю версию). Кроме того, необходимо, чтобы на сервере был установлен Internet Explorer версии 4.1 с Service Pack 1 или более поздним выпуском. Оба этих пакета включены в поставку Microsoft SQL Server 7.0, так что нет необходимости беспокоиться об их наличии. Сервер был установлен на компьютере со следующей конфигурацией: Intel Pentium II 266, 64 Мбайт RAM, HDD Quantum 4,3 Мбайт. Также успешно был установлен Microsoft SQL Server 7.0 Desktop Edition на компьютер с конфигурацией Pentium 166, 32 Мбайт RAM, HDD Quantum 2,1 Мбайт. Однако если вы хотите мигрировать с более ранних версий SQL-сервера (в частности, с Microsoft SQL Server 6.5), учтите, что вам будут необходимы дополнительные аппаратные ресурсы. Во-первых, на жестком диске дополнительно должно быть примерно полтора объема переводимых вами на седьмой сервер баз данных. Во-вторых, миграция возможна только под управлением Microsoft Windows NT Server Enterprise Edition version 4.0 с установленным Service Pack 4.0. В-третьих, должен быть установлен, как минимум, Service Pack 3 для Microsoft SQL Server 6.5. Естественно, в рамках статьи будут упомянуты только те моменты, которые представляются мне наиболее существенными.

Для обновления версий 6.0 и 6.5 Microsoft SQL Server до седьмой удобно использовать так называемый SQL Server Upgrade Wizard - мастер обновления SQL-сервера. Мастер переводит на новую версию все ваши базы данных (или любую из них), информацию о пользователях системы, настройки сервиса SQL Executive и все остальные конфигурационные настройки SQL Server 6.5. Однако с помощью мастера нельзя произвести обновление с более ранних, чем 6.0, версий СУБД. Исходя из информации, предоставляемой Microsoft, обновление с версии 4.2 до версии 7.0 производится в два этапа. Первый - обновление до версии 6.5, второй - до седьмой. Мастер не работает с базами данных, расположенными на нескольких SQL-серверах. Для этого необходимо перевести все базы данных под управление одного SQL-сервера версии 6.5 и затем запустить Upgrade Wizard.

После завершения процесса обновления мастер не удаляет самостоятельно предыдущую версию SQL Server. Таким образом, у вас появляется два независимых сервера. Более ранняя версия сервера при необходимости удаляется отдельно.

Одним из неожиданных результатов миграции явилось то, что на компьютере разработчика, если он хотел продолжать работать как с SQL Server 6.5, так и с 7.0, необходимо было иметь оба пакета утилит -и версии 6.5, и версии 7.0. При попытке обратиться к БД, расположенной на сервере 6.5, из Enterprise Manager от седьмой версии автоматически запускалась версия Enterprise Manager для Microsoft SQL Server 6.5. Кроме того, в одно и то же время на одной машине может работать только одна версия SQL-сервера (6.5 или 7.0). Я не берусь отнести эту особенность к недостаткам или к достоинствам, но лишь упоминаю ее здесь как факт, достойный внимания.

В первую очередь меня интересовало то, насколько гладко прошла миграция. В зависимости от объема усилий, которые потребуются для восстановления работоспособности системы (если они вообще понадобятся), должно было быть принято решение об окончательном переходе на Microsoft SQL Server 7.0 или об отказе от него. Поскольку первая миграция была осуществлена не на рабочем сервере, у нас были возможности для экспериментов.

Результаты оказались неутешительными. Во-первых, резко увеличилось время выполнения запросов к БД, что сразу же отразилось на работе клиентских приложений. Это было бы неудивительно, если бы база данных создавалась «с нуля». Однако в процессе работы на SQL Server 6.5 сервером была набрана достаточная статистика для оптимизации запросов. Видимо, MS Server 7.0 не воспользовался ею. То, что проблема заключается именно в статистике выполнения запросов, стало ясно после того, как несколько SQL-выражений были выполнены многократно через средства SQL-сервера и скорость их выполнения увеличилась примерно после 50 запусков. Однако пользователей системы, коих к тому времени было немало, вряд ли обрадовал факт резкого замедления работы клиентских приложений. Данное явление, безусловно, относится к недостатку СУБД, поскольку на оптимизацию работы сервера и набор статистики потребовалось бы продолжительное время, а искусственная оптимизация путем повторения одних и тех же запросов была совершенно неэффективна вследствие большого числа клиентских приложений. К сожалению, не помогали даже перестройки индексов.

Во-вторых, изменились сами принципы работы с индексами (по сравнению с SQL Server 6.5). В нашем случае это проявилось в выполнении запросов, использующих функцию ISNULL. Напомним, что данная функция позволяет устанавливать для пустых нолей (null-значений) некоторые значения. Рассмотрим небольшой пример, из которого станут понятны и принципы использования этой функции, и проблемы, возникающие при ее использовании в SQL Server 7.0.

Существует таблица, состоящая из трех столбцов и предназначенная для хранения информации о значениях некоторых объектов в хронологическом порядке:

CREATE TABLE SomeTable (Id INT NOT NULL,

Day DATETIME NULL,

Value FLOAT NOT NULL)

Примером типового запроса к таблице может служить следующее выражение:

SELECT Value FROM SomeTable

WHERE ISNULL( Day, '01.01.2000' ) > '01.01.1999' AND Id - 15

Функция ISNULL используется для обеспечения возможности сравнения значения «01.01.1999» с пустым значением, хранящимся в поле Day.

Для сокращения времени выполнения запросов с ограничениями на значения Id и Day был создан индекс:

CREATE INDEX SomeTablelNDl ON SomeTable ( Day, Id )

При работе с Microsoft SQL Server 6.5 никаких сложностей не возникало. Однако после перехода на седьмую версию начались проблемы со скоростью выполнения таких запросов. После продолжительных экспериментов выяснилось, что к таблице необходимо построить еще один индекс, отдельно для поля Day:

CREATE INDEX SomeTableIND2 ON SomeTable ( Day )

В-третьих, начали неправильно работать некоторые триггеры и хранимые процедуры. Причем об этом стало известно косвенно, в результате анализа результатов работы клиентских приложений. И главное, триггеры начали ломаться на том коде, который абсолютно правильно работал на сервере версии 6.5. После непродолжительного поиска в закромах корпорации Microsoft мы обнаружили информацию о подобной ошибке. Речь идет об элементарном запросе на изменение данных в таблице. Ниже приведен поясняющий пример. Этот код работает в версии 6.5, но не работает в MS SQL Server 7.0:

USE pubs GO

UPDATE Titles

SET t.Price = t.Price + 100 -References alias FROM Titles t GO

Л этот код работоспособен вне зависимости от версии сервера:

USE pubs GO

UPDATE t

SET t.Price = t.Price + 100 -References alias FROM Titles t GO

Как видим, принципиальных различий нет. Удручает не то, что не работает некоторый запрос, а то, что он работал в предыдущей версии СУБД. Ведь теперь нам пришлось изменить около 80 триггеров. И нет никакой гарантии, что подобное не проявится в других запросах. Особенно неприятным может оказаться проявление такой ситуации при работе клиентского приложения, что потребует значительных усилий по их корректировке, перекомпиляции, отладке и тестированию. Кроме того, при большой продолжительности жизненного цикла системы информация о том, где именно использовался тот или иной стиль при составлении SQL-запроса, часто оказывается утраченной.

В-четвертых, некоторые встроенные функции SQL-сервера, которые применялись нами при написании триггеров, теперь возвращали значения других, в отличие от аналогов этих функций в SQL Server 6.5, типов данных. В частности, для контроля за действиями пользователя в каждую таблицу базы данных нами было введено поле, в которое записывался индивидуальный код пользователя, вносившего изменения в таблицу; Для определения имени пользователя использовалась функция USER_ NAME0, которая возвращала значение типа char. В SQL Server 7.0 данная функция существует, но возвращает значение не char, a nchar (тип данных, поддерживающий Unicode-кодировку). Соответственно, всю логику, использующую данную функцию, пришлось переписывать, тестировать и т. д.

И все же, повторяю, нельзя утверждать, будто в Microsoft SQL Server 7.0 нет достоинств. Если бы не необходимость восстановления работоспособности системы, перспективы работы с SQL 7.0 были бы весьма привлекательными. Я обнаружил удобные механизмы и возможности, отсутствовавшие в версии 6.5. И если бы не необходимость восстановления работоспособности системы, перспективы работы с SQL 7.0 были бы весьма привлекательными. Их можно разделить на особенности в Transact SQL (расширение стандарта SQL для Microsoft SQL Server) и новые инструменты администратора и разработчика. Перечислим те из них, отсутствие которых в SQL Server версии 6.5 было особенно чувствительно.

Итак. Появилась возможность объявлять локальные курсоры, чего нельзя было делать в предыдущей версии, где при объявлении имя курсора должно было быть уникальным в рамках БД в целом. Теперь можно получать курсор как параметр хранимой процедуры. Имена объектов БД теперь могут достигать 128 символов - против 30 в версии 6.5. К одной таблице можно создавать несколько триггеров одного типа. Например, за одной таблицей.могут быть закреплены три триггера на удаление данных, два на вставку и один на обновление.

Упомяну также и поддержку типов данных Unicode, что облегчает обработку данных, хранящихся в одной базе, но использующих различные наборы символов. Введены специальные типы данных, поддерживающие Unicode: ntext, nchar, nvar-char. Однако они не могут быть автоматически преобразованы в данные типа text, char и varchar соответственно.

Утилита ISQL/w теперь называется SQL Server Query Analyzer и предоставляет разработчику ряд дополнительных по сравнению с предыдущей версией возможностей. Наиболее полезной, на мой взгляд, является возможность просмотра в графической интерпретации плана запроса с указанием процента от всего времени выполнения SQL-запроса для каждого из его этапов. Во многом благодаря этому инструменту были выявлены причины замедления работы клиентских приложений.

Одним из любопытных механизмов является Microsoft English Query. Он разработан для предоставления пользователям возможности формировать запросы к базе данных на английском языке. По утверждениям Microsoft, аналогом представленного ниже SQL-запроса:

SELECT sum( Orders.Quantity ) from

Orders, Parts

WHERE Orders.State = 'WA' and Datepart(0rders.Purchase_Date,

Year' ) = '1996' and Parts.PartName 'widget' and Orders.Part_ID = Parts.Part_ID применительно к Microsoft English Query может служить фраза «How many widgets were sold in Washington last year?». К сожалению, для отечественных разработчиков и тем более для пользователей в практическом плане данный механизм вряд ли представляет интерес, поскольку здесь необходимо не только корректно сформулировать запрос, но и перевести его на английский язык.

В заключении попробую дать несколько рекомендаций по принятию решения о выборе между MS SQL Server 6.5 и MS SQL Server 7.0. Если вы начинаете разработку информационной системы «с нуля», то есть у вас не было до этого серьезных наработок с использованием других СУБД, то выбор Microsoft SQL Server 7.0 предпочтительнее по сравнению с более ранними его версиями.

Если говорить о переходе с версии 6.5 на 7.0, сперва необходимо определить целесообразность подобного перехода в конкретной ситуации. В качестве аргумента «за» могут служить нововведения в Transact-SQL, удобные механизмы администрирования и разработки. Однако после перехода может резко замедлиться работа запросов к базе данных, могут потребоваться изменения в триггерах и хранимых процедурах и т. д.

Если в базе данных немного информации, введенной пользователями системы, или же проект находится на этапе разработки, то переход на седьмую версию должен пройти безболезненно. Если нет доверия к мастеру обновления (Update Wizard), то можно установить SQL Server 7.0 без его использования, а затем создать новую БД с использованием SQL-скрипта, который можно получить средствами SQL Server 6.5.

Если же вы хотите перевести на SQL Server 7.0 крупный проект, то будьте готовы к разного рода эффектам, которые не упоминаются в официальной документации. Сразу после миграции необходимо протестировать наиболее часто выполняемые запросы на корректность их выполнения. После этого - перестроить существующие индексы. Если скорость работы запросов вас все еще не удовлетворяет, необходимо проанализировать составные индексы и разделить их на индексы по отдельным полям. Как показала практика, иногда это помогает. Также желательно перетранслировать все хранимые процедуры и триггеры. Естественно, это требует времени, но лучше самим обнаружить ошибки в работе системы, чем после выслушивать претензии пользователей.

Рекомендуем также проверить все используемые вами функции SQL-сервера на предмет изменения типов возвращаемых ими значений или изменения списков параметров по сравнению с предыдущей версией СУБД. Такая проверка будет полезна как мера по предотвращению некорректной работы триггеров и хранимых процедур, использующих эти функции.

Еще одно замечание, напрямую не относящееся к работе с SQL Server. Для упрощения контроля за обработкой данных и оптимальностью выполняемых запросов рекомендую максимум обработки информации вынести в хранимые процедуры, а запросы к данным - в представления. В клиентских же приложениях следует оставлять только сами вызовы процедур и обращения к представлениям. Таким образом вы получаете возможность изменять и оптимизировать логику работы запросов и процессов обработки информации с внесением минимальных изменений в клиентские приложения. Это особенно удобно в рассматриваемой нами ситуации по выявлению «слабых» мест в обработке данных.

В любом случае целесообразно будет выделить под задачу миграции отдельный сервер, на котором протестировать систему после перехода, при выявлении ошибок попытаться их устранить и только после этого подключать к серверу пользователей либо отказаться от миграции. Таким путем шел я. К сожалению, первый опыт перехода оказался неудачным: недостатков было выявлено намного больше, чем преимуществ, и из-за отсутствия времени было принято решение отложить миграцию на некоторое время. В ближайшем будущем будет осуществлена вторая попытка перехода на седьмую версию сервера. Хотя уже вот-вот появится MS SQL Server 2000, думаю, переход на эту СУБД еще менее целесообразен, чем на седьмую версию. Кроме того, переход на новый продукт от Microsoft вообще следует начинать только после того, как эта компания выпустит к нему хотя бы один Service Pack.

Комментарии   

0 #1 Игорь 20.06.2016 22:00
Спасибо,подробный мануал!
Цитировать

Добавить комментарий


Защитный код
Обновить