Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Новости сайта "Упражнения по SQL" (http://www.sql-ex.ru) 183


Новости сайта "Упражнения по SQL (http://www.sql-ex.ru)" Выпуск 183 (29 марта 2008 г.)

Новым посетителям сайта

SQL Exercises Сайт посвящен изучению языка, с помощью которого осуществляется взаимодействие с реляционными (и не только) СУБД. Суть обучения состоит в выполнении заданий на написание запросов к учебным базам данных; при этом система контролирует правильность выполнения заданий. В настоящее время реализованы все операторы подъязыка манипуляции данными (DML), которые включают в себя оператор извлечения данных SELECT, а также операторы модификации данных - INSERT, DELETE и UPDATE.

Мы надеемся, что справочного материала сайта окажется достаточно для самостоятельного обучения. Кроме того, свои решения вы можете обсудить на форуме сайта. Опытных же специалистов приглашаем проверить (продемонстрировать) свое мастерство и принять участие в соревновании, обеспечиваемом рейтинговой системой учета времени выполнения заданий. Фактически, рейтинг ведется на втором этапе тестирования, который начинается сейчас после решения 57-ти задач первого этапа. При подсчете рейтинга каждого участника отбрасывается один самый худший показатель среди всех решенных им упражнений.

Демонстрация плана выполнения запроса и сравнительная оценка эффективности решений поможет вам освоить принципы оптимизации запросов, которые пригодятся на третьем рейтинговом этапе, который начинается после 138 задачи.

Имеется возможность получить сертификат по SQL DML при выполнении определенного количества заданий.


Новости сайта

§ Исправил баг, который заметила vlksm на странице статистики.
Баг проявлялся в том, что в ряде случаев выводился список специалистов из другого региона.

§ Обновилась страница отзывов: два новых отзыва от Дмитрия Борисенкова и Bhav Tailor.

§ Опять улучшего время второго этапа. Лидером по итогам второго этапа стал $erges (задач 138, время 1.521)
Одна задача до третьего этапа осталась iglbeat (задач 137, время 19.532) и Gendalf (137, 112.086).

§ Изменения среди лидеров (решенные за неделю задачи третьего этапа):
7. lepton (144, 146)

§ Новые лица в ТОР 100 и вернувшиеся туда:
65. PandNsk (133, 2.122)
91. Eka (126, 10.369)

§ Продвинулись в рейтинге:
48. Fencer (135, 200.349)
51. nebiros (135, 84.057)
78. Чумазик (129, 94.823)
86. antihero (127, 13.697)

§ Продвижение ближайших претендентов на попадание в ТОР 100:
111. nadush (123, 161.81)
115. Cергей L (122, 36.710)
116. aprog (121, 32.505)
121. FanOfBeer (121, 121.510)
131. AKudrakov (118, 14.584)
160. Чих (111, 31.565)
161. DeadLock5 (111, 80.625)

§ На этой неделе сертифицированы:
Gendalf (B08022231) [AR] - г. Кострома, Россия
Eka (B08020375) [AR] - г. Москва, Россия
oo7 (A08015708) [BK] - г.Мозырь, Беларусь
DelphiN_ (A08022933) [BK] - г.Калуга, Россия
angolmya (A08028618) [BK] - г.Калининград, Россия
DiffMan (A08026717) [BK] - г.Москва, Россия
neel (A08025099) [BK] - г.Колпино, Санкт-Петербург, Россия

§ Число подписчиков - 3754

Число участников рейтинга - 15164

Число участников второго этапа - 1307

Число участников третьего этапа - 27

Сертифицировано на сайте - 255

Лучшие результаты (ТОР 20)

No Person Number of
Sel_ex
Last_Sel Number of
DML_ex
Scores Days Days_2 Days_3 S_3 LastSolved LastVisit
1 Печатнов В.В. (pvv) 146 146 21 357 127 19.165 6.326 28 23 Feb 2008 28 Mar 2008
2 Креславский О.М. (Arcan) 146 146 21 357 389 22.436 12.553 28 23 Feb 2008 28 Mar 2008
3 Карасёва Н.В. (vlksm) 146 146 21 357 667 64.764 38.288 28 03 Mar 2008 28 Mar 2008
4 Любченко В.А. (IAS56) 146 146 21 357 552 403.414 373.617 28 09 Mar 2008 27 Mar 2008
5 Держальцев В.А. (MadVet) 145 145 21 354 1064 57.441 25.129 25 15 Mar 2008 26 Mar 2008
6 Голубин Р.С. (Roman S. Golubin) 145 145 21 354 919 92.541 58.822 25 23 Feb 2008 28 Mar 2008
7 Мурашкин И.В. (lepton) 144 144 21 350 734 37.129 26.815 21 26 Mar 2008 27 Mar 2008
8 Белогурова К. (Katy_Ekb) 143 11 21 347 287 10.733 4.673 18 07 Mar 2008 19 Mar 2008
9 Войнов П.Е. (pаparome) 143 146 21 346 916 3.013 .213 17 26 Feb 2008 28 Mar 2008
10 Северюхин Ю.А. (Venser) 140 142 21 339 335 4.930 .655 14 01 Feb 2008 04 Feb 2008
11 Тарасов Д.Б. (Gavrila) 141 142 21 340 914 23.390 2.501 14 26 Feb 2008 28 Mar 2008
12 Солдатенков Ю.С. (SolYUtor) 139 142 21 338 490 17.852 2.695 14 20 Sep 2007 28 Mar 2008
13 Кувалкин К.С. (Cyrilus) 141 142 21 340 1207 13.042 2.782 14 15 Mar 2008 28 Mar 2008
14 Шептунов П.П. (Dzen) 139 142 21 338 279 8.130 3.499 14 02 Oct 2007 15 Nov 2007
15 Селезнёв А.С. (Артём С.) 142 141 21 343 127 15.597 4.279 14 14 Mar 2008 28 Mar 2008
16 Мальцев А.В. (Палкин) 139 142 21 338 422 48.788 7.690 14 13 Oct 2007 20 Jan 2008
17 Васьков Е.В. (Johan) 141 12 21 340 611 14.323 12.767 14 21 Mar 2008 22 Mar 2008
18 Бураков С.Г. (burakov58) 139 142 21 338 974 51.701 19.814 14 30 Sep 2007 09 Nov 2007
19 Валуев Д.И. (Fiolent) 142 142 21 343 1638 188.425 131.545 14 28 Feb 2008 28 Mar 2008
20 Агапов В. (KERBEROS) 132 141 20 322 89 6.140 1.262 11 20 Nov 2006 19 Mar 2008

Лучшие результаты за неделю

No surname n_sel sel_all sel_scores dml_scores scores rating last_visit
1 >Romanov A.V. (LexusSaD) 65 71 132 34 166 445 28 Mar 2008
2 Panfilov (Smerdyakoff) 43 56 91 28 119 883 27 Mar 2008
3 Батарейкин Е. (cray3000-) 46 55 95 3 98 1387 28 Mar 2008
4 >fatihov A.V. (a!rat) 48 48 87 0 87 2024 28 Mar 2008
5 >kkk K.K. (kkk777) 24 59 45 34 79 725 28 Mar 2008
6 Moreno (deckard) 36 48 76 0 76 1973 27 Mar 2008
7 Шовчко Д.А. (dimka.sh) 25 58 48 23 71 904 28 Mar 2008
8 Соколов Г.В. (Falcon300) 33 43 70 0 70 2218 27 Mar 2008
9 Ivanov I. (Gauleiter) 31 76 66 0 66 691 28 Mar 2008
10 >Нургалеев Р.И. (PzVenom) 36 36 62 3 65 2944 28 Mar 2008
11 Истомин Е.А. (Istomin) 16 67 30 34 64 548 28 Mar 2008
12 >Осипович А.Э. (}i{MyRik) 20 48 44 17 61 1341 28 Mar 2008
13 Богомолов А.С. (elsy_BALSICH) 27 47 60 0 60 1971 28 Mar 2008
14 123 1.1. (123456547) 22 22 32 28 60 3279 28 Mar 2008
15 >Osbourne O.W. (Ozzy) 31 31 59 0 59 3343 28 Mar 2008
16 >Белкин С.Н. (SIR) 21 57 38 19 57 1011 28 Mar 2008
17 Fedorov A.N. (Ho}{0l) 11 66 20 34 54 577 28 Mar 2008
18 Пестерев А. (PandNsk) 23 133 52 0 52 65 28 Mar 2008
19 Baranov (myth) 7 51 16 34 50 935 27 Mar 2008
20 >Петров А.И. (StAndrew) 23 47 49 0 49 1915 28 Mar 2008
21 >Freschi G.O. (Tordek) 21 21 31 17 48 4348 28 Mar 2008
22 temp (GB2) 22 22 38 9 47 4425 23 Mar 2008
23 Воронцов Д.С. (mitya_v) 18 58 34 11 45 1153 27 Mar 2008
24 Сакович И.В. (Rage Steel) 18 38 45 0 45 2512 27 Mar 2008
25 Nemo (Al-XuMuK) 24 24 43 1 44 4765 25 Mar 2008
26 Дровняшин В.П. (Витек) 26 26 44 0 44 4774 26 Mar 2008
27 Давыдов М.В. (marcell.88) 25 25 43 0 43 4839 26 Mar 2008
28 >Rodionov R.O. (Chupa) 24 63 42 0 42 692 28 Mar 2008
29 Антипина С.А. (SAnt) 27 27 42 0 42 4956 25 Mar 2008
30 Дементьев (Dimies) 13 29 28 13 41 2855 27 Mar 2008
31 >Дмитриев А.А. (BumbleBee) 18 30 41 0 41 3789 28 Mar 2008

Изучаем SQL

Хинт запроса OPTIMIZE FOR в SQL Server 2005

decipherinfosys (оригинал: OPTIMIZE FOR query hint in SQL Server 2005 )
Перевод Моисеенко С.И.

В одной из публикаций нашего блога мы рассмотрели поведение считывания значений связанной переменной (bind variable peeking - Oracle) и parameter sniffing (SQL Server), которое имеет место, когда в SQL запросах используются связанные переменные на наборах данных, значения в которых распределены неравномерно. Для таких запросов или конкретных сценариев можно предписать выполнение конкретного плана запроса (plan guides - SQL Server или stored outlines - Oracle) или же предпочесть использование постоянных/литеральных значений вместо связанных переменных. Это один из сценариев, когда в типичной транзакционной системе использование связанных переменных может не дать желаемых результатов.

В этой статье мы обсудим новый хинт запроса, который появился в SQL Server 2005 и называется "OPTIMIZE FOR". Это еще один способ решить проблему parameter sniffing в SQL Server. Эта опция связана с использованием plan guides (гидов плана) или может использоваться независимо для изменения построения плана выполнения оптимизатором. Этот хинт запроса дает указание оптимизатору использовать конкретное значение для локальной переменной, когда запрос проходит фазу оптимизации.

Давайте рассмотрим пример его использования:

 

CREATE TABLE DECIPHER_TEST (COL1 INT IDENTITY NOT NULL, STAT_CODE INT NOT NULL)
GO
CREATE INDEX DECIPHER_TEST_IND_1 ON DECIPHER_TEST (STAT_CODE)
GO
SET NOCOUNT ON
GO
DECLARE @I INT
SET @I = 1
WHILE (@I <= 1000000)
BEGIN
IF @I <=10
INSERT INTO DECIPHER_TEST (STAT_CODE) VALUES (0)
IF (@I > 10 AND @I <= 10000)
INSERT INTO DECIPHER_TEST (STAT_CODE) VALUES (30)
IF (@I > 10000 AND @I <= 1000000)
INSERT INTO DECIPHER_TEST (STAT_CODE) VALUES (90)
SET @I = @I + 1
END

 

Мы использовали вышеприведенный скрипт, чтобы создать тестовую таблицу и наполнить ее 1 миллионом строк. Вот распределение данных:

 

SELECT STAT_CODE, COUNT(*) CNT_DISTR FROM DECIPHER_TEST GROUP BY STAT_CODE

 

STAT_CODE   CNT_DISTR
 ----------- -----------
 0           10
 30          9990
 90          990000

Статистика тоже была собрана:

 

UPDATE STATISTICS DECIPHER_TEST WITH SAMPLE 100 PERCENT, ALL

 

Теперь давайте возьмем параметризованный запрос со значением параметра 90:

 

SET SHOWPLAN_TEXT ON
GO
DECLARE @STAT_CODE INT
SET @STAT_CODE = 90
SELECT * FROM DECIPHER_TEST WHERE STAT_CODE = @STAT_CODE

 

StmtText
-------------------------------------
|-Table Scan(OBJECT:([AdventureWorks].[dbo].[DECIPHER_TEST]),
  WHERE:([AdventureWorks].[dbo].[DECIPHER_TEST].[STAT_CODE]=[@STAT_CODE]))

Оптимизатор выполняет полное сканирование таблицы, что и должно делать, поскольку значение 90 достигается для большинства данных, в результате чего проход по индексу не даст никаких преимуществ. Теперь давайте заменим значение STAT_CODE на 0 и посмотрим, изменит ли теперь оптимизатор план выполнения на обход индекса, поскольку это значение используется лишь для 0.001% записей в таблице.

 

DECLARE @STAT_CODE INT
SET @STAT_CODE = 0
SELECT * FROM DECIPHER_TEST WHERE STAT_CODE = @STAT_CODE

 

StmtText
----------------------------------------------
|-Table Scan(OBJECT:([AdventureWorks].[dbo].[DECIPHER_TEST]),
  WHERE:([AdventureWorks].[dbo].[DECIPHER_TEST].[STAT_CODE]=[@STAT_CODE]))

Как Вы можете видеть, план выполнения остается таким же, как прежде; это происходит потому, что план выполнения параметризованного запроса был кэширован во время предыдущего выполнения. Теперь давайте используем хинт "OPTIMIZE FOR", и посмотрим, сможем ли мы заставить оптимизатор оптимизировать запрос для значения STAT_CODE равного 0:

 

DECLARE @STAT_CODE INT
SET @STAT_CODE = 0
SELECT * FROM DECIPHER_TEST WHERE STAT_CODE = @STAT_CODE OPTION (OPTIMIZE FOR (@STAT_CODE = 0))

 

StmtText
-------------------------------------
|-Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000]))
|-Index Seek(OBJECT:([AdventureWorks].[dbo].[DECIPHER_TEST].[DECIPHER_TEST_IND_1]),
   SEEK:([AdventureWorks].[dbo].[DECIPHER_TEST].[STAT_CODE]=[@STAT_CODE]) ORDERED FORWARD)
|-RID Lookup(OBJECT:([AdventureWorks].[dbo].[DECIPHER_TEST]),
   SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD)

Как показывает приведенный выше план выполнения запроса, оптимизатор на этот раз выбрал индекс и выполнил RID look-up (поиск идентификатора записи), чтобы получить данные, которые не были представлены в индексе. Это имеет смысл, поскольку селективность значения данных такова, что поиск в индексе должен дать преимущество. Итак, что же случится теперь, если мы выполним запрос со значением 90? Так как мы вынудили оптимизатор всегда формировать оптимизированный план выполнения для заданного значения кода состояния 0, то когда мы используем значение 90, по-прежнему будет использоваться план с индексом, который показан выше. Так, насколько это хорошо? В нашем конкретном сценарии, скажем, значения STAT_CODE представлены следующим образом:

0: Запись готова для обработки
30: Промежуточный код состояния для обработки
90: Обработка была успешной
99: Отказ/Ошибка

В большинстве случаев код, который взаимодействует с данной таблицей, будет выполнять поиск, на основании значения кода состояния либо 0, либо 30. Ситуации, где будут использоваться 90 или 99, типично представляются только запросами, которые проверяют данных или формируют отчеты, при этом они будут выполняться меньшее число раз по сравнению с запросами в транзакционных системах. Поэтому в действительно транзакционной системе, где требуется один раз парсить запрос и много раз его выполнить, можно все еще использовать связанные переменные (параметризованные запросы) и иметь план выполнения, который лучше всего представляет распределение данных и является оптимальным. В системе же генерации отчетов можно использовать запрос, основанный либо на константах/литералах, либо на запросе без хинта "OPTIMIZE FOR". Ниже представлен тот же самый запрос, использующий постоянное значение (константу/литерал), и его план выполнения, демонстрируемый оптимизатором:

 

SELECT * FROM DECIPHER_TEST WHERE STAT_CODE = 90

 

StmtText
--------------------------------------
|-Table Scan(OBJECT:([AdventureWorks].[dbo].[DECIPHER_TEST]),
  WHERE:([AdventureWorks].[dbo].[DECIPHER_TEST].[STAT_CODE]=(90)))

23-10-2007

Полезная информация

§ Все статьи, публикуемые в рассылке, затем выкладываются на сайте Книги и статьи по SQL.

§ Желающих поспособствовать популяризации сайта прошу проголосовать/поставить закладку в социальных сетях:
del.icio.us
dzone.com
Digg.com
stumbleupon.com

Контакты

По всем вопросам, связанным с функционированием сайта, проблемами при решении упражнений, идеями вы можете обращаться к Сергею И.Моисеенко msi77[@]yandex.ru. Вы также можете предложить свои задачи для публикации на сайте.

Подписка Subscribe.Ru
Новости сайта "Упражнения по SQL"

В избранное