Новости сайта "Упражнения по SQL (http://www.sql-ex.ru)" Выпуск 44 (16 июля 2005 г.)
Новым посетителям сайта
Сайт посвящен изучению языка, с помощью которого осуществляется взаимодействие с реляционными (и не только) СУБД. Суть обучения состоит в выполнении заданий на написание запросов к учебным базам данных; при этом система контролирует правильность выполнения заданий. В настоящее время реализованы все операторы подъязыка манипуляции данными (DML), которые включают в себя оператор извлечения данных SELECT, а также операторы модификации данных - INSERT, DELETE и UPDATE.
Мы надеемся, что справочного материала сайта окажется достаточно для самостоятельного обучения. Кроме того, свои решения вы можете обсудить на форуме сайта. Опытных же специалистов приглашаем проверить (продемонстрировать) свое мастерство и принять участие в соревновании, обеспечиваемом рейтинговой системой учета времени выполнения заданий. Фактически, рейтинг ведется на втором этапе тестирования, который начинается сейчас после решения 59-ти задач первого этапа. При подсчете рейтинга каждого участника отбрасывается
один самый худший показатель среди всех решенных им упражнений.
Имеется возможность получить сертификат по SQL DML при выполнении определенного количества заданий.
Новости сайта
§ Добавил данных под 128 задачу. Спасибо, VIG.
§ burakov58 обратил внимание на то, что можно подогнать решение задачи 136. Меры приняты.
§ По сообщениям Verner и Jeha усилил проверку задач 18 и 64 соответственно.
На этом сайте (www.sqlservercentral.com) и не только Вы найдете статьи, рекомендующие избегать использования временных таблиц, чтобы повысить эффективность запросов. Я согласен с этим, но хотел бы добавить, что не всегда это удается сделать. Я работаю с несколькими очень большими базами данных на SQL Server (размер самой большой из них превышает 2.2 терабайта) и пришел к выводу, что в большинстве случаев могу обойтись без временных таблиц, хотя иногда они бывают
полезны. В данной статье обсуждаются альтернативы временным таблицам с точки зрения производительности и обслуживания запросов.
Большинство литературных источников, которые рекомендуют воздерживаться от использования временных таблиц, справедливо утверждают, что это может вызывать проблемы производительности из-за блокировки tempdb во время создания временной таблицы, увеличения числа операций ввода/вывода при использовании временной таблицы и потенциальной возможности блокировки tempdb, если создание и последующие операции с временной таблицей происходят в рамках одной транзакции. И это не говоря уже о многочисленных
проблемах, которые SQL Server испытывает при операциях с временными таблицами - см. список статей Knowledge Base ниже. Не подвергая вышесказанное сомнениям, я собираюсь привести некоторые доводы в пользу временных таблиц. Я признаю, что не использую или нашел причин для использования глобальной временной таблицы, поэтому Вы не найдете здесь обсуждения этих таблиц.
Для чего мы могли бы использовать временную таблицу?
Вот некоторые причины, по которым я использую временные таблицы в своей работе: сохранение результатов вызванной хранимой процедуры; уменьшение числа строк, используемых в соединениях; объединение данных из различных источников; и замена курсорам.
По мере того как ваш запрос становился все более сложным, Вы будете обнаруживать повторяющиеся блоки кода в пределах одного запроса или в разных запросах. Такое повторное использование кода стимулирует создание хранимой процедуры, содержащей повторяющийся код, с ее вызовом в соответствующих местах. Это может привести к появлению большого количества хранимых процедур в вашей базе данных, однако в значительной мере уменьшает обслуживание, т.к. при изменении функциональности Вам потребуется изменить код только
одного запроса, а не многочисленных запросов, которые еще нужно отыскать. Я используют эту технику весьма часто, и это часто вынуждает меня использовать временную таблицу для сохранения результатов таких хранимых процедур, поскольку Transact-SQL не позволяет использовать результаты хранимой процедуры в качестве таблицы. Это, вероятно, главная причина использования временных таблиц в моем коде.
Мне весьма часто приходится соединять в запросе таблицы, содержащие порядка 10, 100 и 20 миллионов строк с последующей сортировкой для вывода последних изменений в первых строках результата. Даже с надлежащими индексами и использованием предложения WHERE для фильтрации и принуждению к использованию индекса производительность запроса оказывается недопустимой (поскольку приложение, с которым я работаю, используется таким образом, что приемлемым временем отклика на запрос считаются секунды), и часто
сортировка вызывает огромные потери производительности, так же как и огромную загрузку tempdb. Весьма часто оказывалось, что использование соответствующих временных таблиц для каждой из постоянных таблиц для размещения в них отфильтрованных с помощью предложения WHERE данных, прежде чем выполнять соединение и сортировку, настолько увеличивало производительность запроса, что я могу фактически внедрять это, не беспокоясь о производительности или воздействии на базу данных tempdb. Ниже приведен
очень простой запрос, демонстрирующий сказанное.
Оригинальный запрос нахождения подробной информации по звонку с телефона некоего клиента:
SELECT table1.numCustID, table2.strPhoneNumber, table3.strPhoneNumberCalled FROM dbo.table1 table1 INNER JOIN dbo.table2 table2 ON table1.numBillID = table2.numBillID INNER JOIN dbo.table3 table3 ON table2.numBillDtlID = table3.numBillDtlID WHERE table1.numCustID = '5555' AND table2.strPhoneNumber = '5555555555' AND table3.strPhoneNumberCalled = '1234561234' ORDER
BY table3.dtmCalled DESC
(Этот запрос не соответствует ни схеме, ни существующему запросу в компании Verizon. Он был создан для демонстрации конкретной проблемы на гипотетической базе данных, связанной с телекоммуникациями.)
Новый Запрос:
(Я обычно называю временную таблицу по имени хранимой процедуры, которая ее создает; поэтому я могу быстрее разобраться в любых проблемах в tempdb, связанных с использованием временных таблиц.)
INSERT INTO #tquery2a SELECT columns FROM dbo.table2 WHERE table2.strPhoneNumber = '5555555555'
INSERT INTO #tquery2b SELECT columns FROM dbo.table3
WHERE table3.strPhoneNumberCalled = '1234561234'
SELECT table1.numCustID, #tquery2a.strPhoneNumber, #tquery2b.strPhoneNumberCalled FROM dbo.table1 table1 INNER JOIN #tquery2a #tquery2a ON table1.numBillID = #tquery2a.numBillID INNER JOIN #tquery2b #tquery2b ON #tquery2a.numBillDtlID = #tquery2b.numBillDtlID WHERE table1.numCustID = '5555' ORDER BY #tquery2b.dtmCalled DESC
Хотите - верьте, хотите - нет, но этот метод работает значительно быстрее, чем оригинальный запрос, особенно при наличии предложения ORDER BY.
Получение отчетов из базы данных OLTP - не всегда самая легкая вещь. База данных для того и строится, чтобы максимально удовлетворить потребности должностных лиц в получении отчетов. Использование временных таблиц для сбора результатов большого числа операторов SELECT, агрегирования этих результатов перед выдачей, - иногда является единственным способом получить отчеты из базы данных OLTP. При работе с приложением телефонной станции вас обычно просят выдавать отчеты, которые суммируют
то, что представители телефонной станции делают на основе фильтрации по времени. Собрать данные из всех таблиц и агрегировать их затем различными способами можно только с помощью временных таблиц. Предупреждаю напрашивающийся аргумент. Я знаю, что работаю в компании с многомиллиардным оборотом, но это не означает, что должностные лица желают выслушивать ваши аргументы о том, что им необходимо хранилище данных или простая база данных для генерации отчетов, если это означает, что они должны потратить деньги на
то, что они могут просто получить из базы данных OLTP, при этом обвиняя меня, если запросы выполняются слишком медленно и вызывают проблемы с производительностью серверов. Извиняюсь перед теми теоретиками, которые по мановению волшебной палочки получают все, что им требуется независимо от стоимости или размера компании, на которую они работают.
(окончание следует...)
Полезная информация
Конкурс
§ Мы выставили наш сайт на конкурс Интернить 2005. Победитель определяется числом поданых голосов. Просьба проголосовать. (рекомендуемая оценка 3 :-)).
Контакты
По всем вопросам, связанным с функционированием сайта, проблемами при решении упражнений, идеями вы можете обращаться к Сергею И.Моисеенко msi77@yandex.ru. Вы также можете предложить свои задачи для публикации на сайте.