
Бази даних-20210115T104840Z-001 / Реферат на тему _Современные СУБД_ / Using_MySql,_MS_SQL_Server_and_Oracle(1)
.pdf
Пример 39: оптимизация производительности с помощью хранимых процедур
MS SQL Решение 5.2.2.a (код процедуры)
1CREATE PROCEDURE UPDATE_BOOKS_STATISTICS
2AS
3IF (NOT EXISTS(SELECT *
4 |
|
FROM [information_schema].[tables] |
|
5 |
|
WHERE |
[table_catalog] = DB_NAME() |
6 |
|
AND |
[table_name] = 'books_statistics')) |
7BEGIN
8RAISERROR ('The [books_statistics] table is missing.', 16, 1);
9RETURN;
10END;
11
12UPDATE [books_statistics]
13SET
14[books_statistics].[total] = [src].[total],
15[books_statistics].[given] = [src].[given],
16[books_statistics].[rest] = [src].[rest]
17FROM [books_statistics]
18JOIN
19(SELECT ISNULL([total], 0) AS [total],
20ISNULL([given], 0) AS [given],
21ISNULL([total] - [given], 0) AS [rest]
22 |
|
FROM |
(SELECT (SELECT |
SUM([b_quantity]) |
|
|
23 |
|
|
FROM |
[books]) |
AS |
[total], |
24 |
|
|
(SELECT |
COUNT([sb_book]) |
|
|
25 |
|
|
FROM |
[subscriptions] |
|
|
26 |
|
|
WHERE |
[sb_is_active] = 'Y') AS |
[given]) |
27AS [prepared_data]
28) AS [src]
29ON 1=1;
30GO
Проверим работоспособность (предварительно можно выполнить отдельный запрос на обновление данных в таблице books_statistics и установить все значения в ноль).
MS SQL Решение 5.2.2.a (запуск и проверка работоспособности)
1 EXECUTE UPDATE_BOOKS_STATISTICS
Установка запуска полученной хранимой процедуры по расписанию в MS SQL Server не только выглядит куда более сложно, но и не даст эффекта, если вы используете Express Edition этой СУБД: в этой версии отсутствует компонент SQL Server Agent, который и отвечает за выполнение запланированных задач.
По каждой приведённой далее команде в официальной документации написано очень много (перед каждой командой специально приведены ссылка на соответствующий раздел документации), но если выразить простыми словами алгоритм, получится следующее. Необходимо:
•Создать задачу.
•Создать шаг задачи, описывающий запуск нашей хранимой процедуры.
•Создать расписание, в котором указать требуемую периодичность выполнения.
•Прикрепить ранее созданную задачу к только что созданному расписанию.
•Передать созданную задачу на обработку в SQL Server Agent.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 390/545

Пример 39: оптимизация производительности с помощью хранимых процедур
MS SQL |
Решение 5.2.2.a (установка запуска по расписанию) |
1USE msdb ;
2GO
3-- https://msdn.microsoft.com/en-us/library/ms182079.aspx
4EXEC dbo.sp_add_job
5@job_name = N'Hourly [books_statistics] update';
6GO
7-- https://msdn.microsoft.com/en-us/library/ms187358.aspx
8EXEC sp_add_jobstep
9@job_name = N'Hourly [books_statistics] update',
10@step_name = N'Execute UPDATE_BOOKS_STATISTICS stored procedure',
11@subsystem = N'TSQL',
12@command = N'EXECUTE UPDATE_BOOKS_STATISTICS',
13@database_name = N'library_ex_2015_mod';
14GO
15-- https://msdn.microsoft.com/en-us/library/ms187320.aspx
16EXEC dbo.sp_add_schedule
17@schedule_name = N'UpdateBooksStatistics',
18@freq_type = 4,
19@freq_interval = 4,
20@freq_subday_type = 8,
21@freq_subday_interval = 1,
22@active_start_time = 000100 ;
23USE msdb ;
24GO
25-- https://msdn.microsoft.com/en-us/library/ms186766.aspx
26EXEC sp_attach_schedule
27@job_name = N'Hourly [books_statistics] update',
28@schedule_name = N'UpdateBooksStatistics';
29GO
30-- https://msdn.microsoft.com/en-us/library/ms178625.aspx
31EXEC dbo.sp_add_jobserver
32@job_name = N'Hourly [books_statistics] update';
33GO
Убедиться, что соответствующая задача добавлена в планировщик, можно выполнив следующий запрос (он покажет список задач даже в MS SQL Server Express Edition):
MS SQL Решение 5.2.2.a (просмотр расписания)
1 SELECT * FROM msdb.dbo.sysschedules
В данном обсуждении24 представлен очень хороший готовый SQL-скрипт для получения в удобной форме информации обо всех запланированных в MS SQL Server задачах.
На этом решение для MS SQL Server завершено.
Переходим к Oracle. Логика работы хранимой процедуры здесь полностью эквивалентна решениям для MySQL и MS SQL Server: мы проверяем наличие таблицы books_statistics в строках 5-15 (и завершаем работу хранимой процедуры, если таблицы нет), а в строках 17-27 выполняем запрос, обновляющий данные.
24 http://www.sqlservercentral.com/Forums/Topic410557-116-1.aspx
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 391/545

Пример 39: оптимизация производительности с помощью хранимых процедур
Oracle Решение 5.2.2.a (код процедуры)
1CREATE OR REPLACE PROCEDURE UPDATE_BOOKS_STATISTICS
2AS
3rows_count NUMBER;
4BEGIN
5SELECT COUNT(1) INTO rows_count
6FROM ALL_TABLES
7WHERE OWNER = USER
8AND TABLE_NAME = 'books_statistics';
9
10IF (rows_count = 0)
11THEN
12RAISE_APPLICATION_ERROR(-20001,
13 |
|
'The "books_statistics" table is missing.'); |
14RETURN;
15END IF;
16
17UPDATE "books_statistics"
18SET ("total", "given", "rest") =
19(SELECT NVL("total", 0) AS "total",
20 |
|
|
NVL("given", 0) |
AS "given", |
|
21 |
|
|
NVL("total" - "given", 0) AS "rest" |
|
|
22 |
|
FROM |
(SELECT (SELECT |
SUM("b_quantity") |
|
23 |
|
|
FROM |
"books") |
AS "total", |
24 |
|
|
(SELECT |
COUNT("sb_book") |
|
25 |
|
|
FROM |
"subscriptions" |
|
26 |
|
|
WHERE |
"sb_is_active" = 'Y') AS "given" |
|
27 |
|
|
FROM dual) "prepared_data"); |
|
28END;
29/
Проверим работоспособность (предварительно можно выполнить отдельный запрос на обновление данных в таблице books_statistics и установить все значения в ноль).
Oracle |
Решение 5.2.2.a (запуск и проверка работоспособности) |
1 EXECUTE UPDATE_BOOKS_STATISTICS
Установка запуска полученной хранимой процедуры по расписанию выглядит следующим образом.
Oracle |
|
Решение 5.2.2.a (установка запуска по расписанию) |
||
1 |
BEGIN |
|
|
|
2 |
|
DBMS_SCHEDULER.CREATE_JOB ( |
||
3 |
|
job_name |
=> 'hourly_update_books_statistics', |
|
4 |
|
job_type |
=> 'STORED_PROCEDURE', |
|
5 |
|
job_action |
=> 'UPDATE_BOOKS_STATISTICS', |
|
6 |
|
start_date |
=> |
'01-APR-16 1.00.00 AM', |
7 |
|
repeat_interval |
=> |
'FREQ=HOURLY;INTERVAL=1', |
8 |
|
auto_drop |
=> |
FALSE, |
9 |
|
enabled |
=> |
TRUE); |
10 |
END; |
|
|
Убедиться, что соответствующая задача добавлена в планировщик, можно выполнив следующий запрос:
Oracle Решение 5.2.2.a (просмотр расписания)
1 SELECT * FROM ALL_SCHEDULER_JOBS WHERE OWNER=USER
На этом решение данной задачи завершено.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 392/545

Пример 39: оптимизация производительности с помощью хранимых процедур
Решение 5.2.2.b{388}.
Решение этой задачи одновременно является очень простым и очень сложным, т.к. нам нужно получить список таблиц базы данных и… что-то с ними сделать.
Вопрос оптимизации производительности баз данных и СУБД заслуживает отдельной книги, потому здесь мы пойдём по пути наименьшего сопротивления и будем считать, что:
•Для MySQL будет достаточно выполнить OPTIMIZE для всех таблиц.
•Для MS SQL Server достаточно выполнить REORGANIZE или REBUILD для всех кластерных индексов (что приводит к оптимизации соответствующей таблицы, на которых построен индекс).
•Для Oracle будет достаточно выполнить SHRINK SPACE COMPACT CASCADE для всех таблиц.
Ещё раз особо подчеркнём: решение данной задачи носит исключительно демонстрационный характер и не должно рассматриваться как рекомендация по универсальной оптимизации производительности. В некоторых случаях выполнение показанных ниже действий может снизить производительность базы данных, потому обязательно внимательно изучите официальную документацию по соответствующей СУБД и профессиональные рекомендации по оптимизации производительности в той или иной реальной ситуации.
Традиционно начинаем с MySQL.
MySQL Решение 5.2.2.b (код процедуры)
1DELIMITER $$
2CREATE PROCEDURE OPTIMIZE_ALL_TABLES()
3BEGIN
4DECLARE done INT DEFAULT 0;
5DECLARE tbl_name VARCHAR(200) DEFAULT '';
6DECLARE all_tables_cursor CURSOR FOR
7SELECT `table_name`
8 |
|
FROM |
`information_schema`.`tables` |
9 |
|
WHERE |
`table_schema` = DATABASE() |
10 |
|
AND |
`table_type` = 'BASE TABLE'; |
11 |
|
DECLARE |
CONTINUE HANDLER FOR NOT FOUND SET done = 1; |
12 |
|
|
|
13 |
|
OPEN all_tables_cursor; |
|
14 |
|
|
|
15tables_loop: LOOP
16FETCH all_tables_cursor INTO tbl_name;
17IF done THEN
18LEAVE tables_loop;
19END IF;
20
21SET @table_opt_query = CONCAT('OPTIMIZE TABLE `', tbl_name, '`');
22PREPARE table_opt_stmt FROM @table_opt_query;
23EXECUTE table_opt_stmt;
24DEALLOCATE PREPARE table_opt_stmt;
25
26 END LOOP tables_loop;
27
28CLOSE all_tables_cursor;
29END;
30$$
31
32 DELIMITER ;
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 393/545

Пример 39: оптимизация производительности с помощью хранимых процедур
Запрос в строках 7-10 позволяет получить список таблиц текущей базы данных (часть условия в строке 10 позволяет отличить таблицы от представлений), после чего:
•для полученного списка таблиц открывается курсор (строка 13);
•для всех строк курсора выполняется цикл (строки 15-26);
•в теле цикла формируется (строка 21) и выполняется (строки 22-23) запрос, реализующий оптимизацию таблицы.
Запустить полученную хранимую процедуру можно следующим образом.
MySQL |
Решение 5.2.2.b (запуск и проверка работоспособности) |
1 CALL OPTIMIZE_ALL_TABLES
Теперь остаётся создать событие, запускаемое планировщиком задач MySQL по определённому расписанию. Это реализуется следующим кодом.
MySQL |
Решение 5.2.2.b (установка запуска по расписанию) |
1 SET GLOBAL event_scheduler = ON;
2
3CREATE EVENT `optimize_all_tables_daily`
4ON SCHEDULE
5EVERY 1 DAY
6STARTS DATE(NOW()) + INTERVAL 1 HOUR
7ON COMPLETION PRESERVE
8DO
9CALL OPTIMIZE_ALL_TABLES;
Убедиться, что событие добавлено, можно следующим запросом.
MySQL Решение 5.2.2.b (просмотр расписания)
1 SELECT * FROM `information_schema`.`events`
Если рассмотреть избранные поля результата такого запроса, получается следующая картина. Здесь также представлено событие, активирующее раз в час хранимую процедуру, созданную в процессе решения{388} задачи 5.2.2.a{388}.
EVENT_NAME |
EVENT_TYPE |
INTER- |
INTER- |
STARTS |
ENDS |
STA- |
ON_COM- |
|
|
VAL_VALUE |
VAL_FIELD |
|
|
TUS |
PLETION |
update_books_statis- |
RECURRING |
1 |
HOUR |
2016-04-27 |
NULL |
ENA- |
PRESERVE |
tics_hourly |
|
|
|
14:01:00 |
|
BLED |
|
optimize_all_ta- |
RECURRING |
1 |
DAY |
2016-04-27 |
NULL |
ENA- |
PRESERVE |
bles_daily |
|
|
|
01:00:00 |
|
BLED |
|
На этом решение для MySQL завершено.
Переходим к MS SQL Server. Концепция представленного ниже решения основана на этой рекомендации25.
Итак, мы должны будем получить список кластерных индексов текущей базы данных, выяснить степень их фрагментации (avg_fragmentation_in_percent)
и, в зависимости от этого значения, выполнить реорганизацию (REORGANIZE) или
перестроение (REBUILD) индекса.
Для начала напишем запрос, предоставляющий информацию по всем индексам, соответствующим таблицам, полям и т.д. К сожалению, готового решения MS SQL Server не предоставляет, потому придётся всё делать «вручную».
25 http://blog.sqlauthority.com/2010/01/12/sql-server-fragmentation-detect-fragmentation-and-eliminate-fragmentation/
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 394/545

Пример 39: оптимизация производительности с помощью хранимых процедур
MS SQL Решение 5.2.2.b (получение данных по всем индексам)
1 |
|
SELECT |
[tables].[name] |
AS [table_name], |
|
2 |
|
|
[indexes].[name] |
AS [index_name], |
|
3 |
|
|
[indexes].[type] |
AS [index_type], |
|
4 |
|
|
[stats].[index_type_desc] |
AS [index_type_desc], |
|
5 |
|
|
[indexes].[object_id] |
AS [index_object_id], |
|
6 |
|
|
[columns].[name] |
AS [column_name], |
|
7 |
|
|
[stats].[avg_fragmentation_in_percent] |
AS [avg_fragm_perc], |
|
8 |
|
|
[stats].[avg_page_space_used_in_percent] |
AS [avg_space_perc] |
|
9 |
|
FROM |
sys.indexes AS [indexes] |
|
|
10 |
|
|
INNER JOIN |
sys.index_columns AS [index_columns] |
|
11 |
|
|
ON |
[indexes].[object_id] = [index_columns].[object_id] |
|
12 |
|
|
|
AND [indexes].[index_id] = [index_columns].[index_id] |
|
13 |
|
|
INNER JOIN |
sys.columns AS [columns] |
|
14 |
|
|
ON |
[index_columns].[object_id] = |
[columns].[object_id] |
15 |
|
|
|
AND [index_columns].[column_id] = [columns].[column_id] |
|
16 |
|
|
INNER JOIN |
sys.tables AS [tables] |
|
17 |
|
|
ON |
[indexes].[object_id] = [tables].[object_id] |
|
18 |
|
|
INNER JOIN |
sys.dm_db_index_physical_stats(DB_ID(DB_NAME()), |
|
19 |
|
|
|
|
NULL, NULL, NULL, |
20 |
|
|
|
|
'SAMPLED') AS [stats] |
21 |
|
|
ON |
[indexes].[object_id] = [stats].[object_id] |
|
22 |
|
|
|
AND [indexes].[index_id] = [stats].[index_id] |
|
|
|
|
|
|
|
23ORDER BY [tables].[name],
24[indexes].[name],
25[indexes].[index_id],
26[index_columns].[index_column_id]
Врезультате выполнение такого запроса мы получим следующие данные.
table_name |
index_name |
in- |
index_type_desc |
index_ob- |
col- |
avg_fragm_ |
avg_space_perc |
|
|
|
dex_type |
|
ject_id |
umn_name |
|
perc |
|
authors |
PK_authors |
1 |
CLUSTERED |
245575913 |
a_id |
0 |
|
3.22461082283173 |
|
|
|
INDEX |
|
|
|
|
|
books |
PK_books |
1 |
CLUSTERED |
277576027 |
b_id |
0 |
|
5.72028663207314 |
|
|
|
INDEX |
|
|
|
|
|
genres |
PK_genres |
1 |
CLUSTERED |
309576141 |
g_id |
0 |
|
2.59451445515196 |
|
|
|
INDEX |
|
|
|
|
|
genres |
UQ_gen- |
2 |
NONCLUS- |
309576141 |
g_name |
0 |
|
2.37212750185322 |
|
res_g_name |
|
TERED INDEX |
|
|
|
|
|
m2m_books |
PK_m2m_boo |
1 |
CLUSTERED |
341576255 |
b_id |
0 |
|
1.86557944156165 |
_authors |
ks_authors |
|
INDEX |
|
|
|
|
|
m2m_books |
PK_m2m_boo |
1 |
CLUSTERED |
341576255 |
a_id |
0 |
|
1.86557944156165 |
_authors |
ks_authors |
|
INDEX |
|
|
|
|
|
m2m_books |
PK_m2m_boo |
1 |
CLUSTERED |
373576369 |
b_id |
0 |
|
2.28564368668149 |
_genres |
ks_genres |
|
INDEX |
|
|
|
|
|
m2m_books |
PK_m2m_boo |
1 |
CLUSTERED |
373576369 |
g_id |
0 |
|
2.28564368668149 |
_genres |
ks_genres |
|
INDEX |
|
|
|
|
|
subscribers |
PK_subscrib- |
1 |
CLUSTERED |
405576483 |
s_id |
0 |
|
1.95206325673338 |
|
ers |
|
INDEX |
|
|
|
|
|
subscrip- |
PK_subscrip- |
1 |
CLUSTERED |
437576597 |
sb_id |
0 |
|
5.16431924882629 |
tions |
tions |
|
INDEX |
|
|
|
|
|
Этот результат хорош тем, что удобен для просмотра человеком, но внутри хранимой процедуры нам будут нужны только три поля: имя таблицы, имя индекса, процент фрагментации. К тому же составные кластерные индексы (например, PK_m2m_books_authors) должны быть представлены только один раз (а не по разу на каждое из входящих в состав индекса полей, как это есть сейчас).
Упростим запрос так, чтобы оставить только необходимые данные.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 395/545

Пример 39: оптимизация производительности с помощью хранимых процедур
|
MS SQL |
|
Решение 5.2.2.b (получение краткого набора данных по всем индексам) |
|||
|
1 |
|
SELECT |
DISTINCT |
|
|
|
2 |
|
|
|
[tables].[name] |
AS [table_name], |
|
3 |
|
|
|
[indexes].[name] |
AS [index_name], |
|
4 |
|
|
|
[stats].[avg_fragmentation_in_percent] |
AS [avg_fragm_perc] |
|
5 |
|
FROM |
sys.indexes AS [indexes] |
|
|
|
6 |
|
|
|
INNER JOIN sys.tables AS [tables] |
|
|
7 |
|
|
|
ON [indexes].[object_id] = [tables].[object_id] |
|
|
8 |
|
|
|
INNER JOIN sys.dm_db_index_physical_stats(DB_ID(DB_NAME()), |
|
|
9 |
|
|
|
|
NULL, NULL, NULL, |
|
10 |
|
|
|
|
'SAMPLED') AS [stats] |
|
11 |
|
|
|
ON [indexes].[object_id] = [stats].[object_id] |
|
12 |
|
|
|
AND [indexes].[index_id] = [stats].[index_id] |
13WHERE [indexes].[type] = 1
14ORDER BY [tables].[name],
15[indexes].[name]
Врезультате выполнение такого запроса мы получим следующие данные.
table_name |
index_name |
avg_fragm_perc |
authors |
PK_authors |
0 |
books |
PK_books |
0 |
genres |
PK_genres |
0 |
m2m_books_authors |
PK_m2m_books_authors |
0 |
m2m_books_genres |
PK_m2m_books_genres |
0 |
subscribers |
PK_subscribers |
0 |
subscriptions |
PK_subscriptions |
0 |
Теперь используем полученный запрос в теле хранимой процедуры. Проходя по всем рядам, возвращаемым курсором (цикл в строках 29-56), мы будем анализировать значение avg_fragm_perc и либо выполнять одно из двух действий по оптимизации, либо не выполнять никаких действий.
MS SQL Решение 5.2.2.b (код процедуры)
1CREATE PROCEDURE OPTIMIZE_ALL_TABLES
2AS
3BEGIN
4DECLARE @table_name NVARCHAR(200);
5DECLARE @index_name NVARCHAR(200);
6DECLARE @avg_fragm_perc DOUBLE PRECISION;
7DECLARE @query_text NVARCHAR(2000);
8DECLARE indexes_cursor CURSOR LOCAL FAST_FORWARD FOR
9SELECT DISTINCT
10 |
|
|
[tables].[name] |
AS [table_name], |
|
11 |
|
|
[indexes].[name] |
AS [index_name], |
|
12 |
|
|
[stats].[avg_fragmentation_in_percent] |
AS [avg_fragm_perc] |
|
13 |
|
FROM |
sys.indexes AS [indexes] |
|
|
14 |
|
|
INNER JOIN |
sys.tables AS [tables] |
|
15 |
|
|
ON |
[indexes].[object_id] = [tables].[object_id] |
|
16 |
|
|
INNER JOIN |
sys.dm_db_index_physical_stats(DB_ID(DB_NAME()), |
|
17 |
|
|
|
|
NULL, NULL, NULL, |
18 |
|
|
|
|
'SAMPLED') AS [stats] |
19 |
|
|
ON |
[indexes].[object_id] = [stats].[object_id] |
|
20 |
|
|
|
AND [indexes].[index_id] = [stats].[index_id] |
|
|
|
|
|
|
|
21WHERE [indexes].[type] = 1
22ORDER BY [tables].[name],
23 |
|
[indexes].[name]; |
24 |
|
|
25OPEN indexes_cursor;
26FETCH NEXT FROM indexes_cursor INTO @table_name,
|
27 |
|
|
@index_name, |
|
|
28 |
|
|
@avg_fragm_perc; |
|
|
|
|
|
|
|
Работа с MySQL, MS SQL Server и Oracle в примерах |
© EPAM Systems, RD Dep, 2016–2018 Стр: 396/545 |

Пример 39: оптимизация производительности с помощью хранимых процедур
MS SQL Решение 5.2.2.b (код процедуры) (продолжение)
29WHILE @@FETCH_STATUS = 0
30BEGIN
31IF (@avg_fragm_perc >= 5.0) AND (@avg_fragm_perc <= 30.0)
32BEGIN
33SET @query_text = CONCAT('ALTER INDEX [', @index_name,
34 |
|
|
'] ON [', @table_name, '] REORGANIZE'); |
|
35 |
|
PRINT CONCAT('Index [', |
@index_name,'] on |
[', @table_name, |
36 |
|
'] will be |
REORGANIZED...'); |
|
|
|
|
|
|
37EXECUTE sp_executesql @query_text;
38END;
39IF (@avg_fragm_perc > 30.0)
40BEGIN
41SET @query_text = CONCAT('ALTER INDEX [', @index_name,'] ON [',
42 |
|
|
@table_name, |
'] REBUILD'); |
43 |
|
PRINT CONCAT('Index [', |
@index_name,'] on [', @table_name, |
|
44 |
|
'] will be |
REBUILT...'); |
|
45EXECUTE sp_executesql @query_text;
46END;
47IF (@avg_fragm_perc < 5.0)
48BEGIN
49PRINT CONCAT('Index [', @index_name,'] on [', @table_name,
50 |
|
'] needs no optimization...'); |
51 |
|
END; |
52 |
|
|
53 |
|
FETCH NEXT FROM indexes_cursor INTO @table_name, |
54 |
|
@index_name, |
55 |
|
@avg_fragm_perc; |
56END;
57CLOSE indexes_cursor;
58DEALLOCATE indexes_cursor;
59END;
60GO
Запустить полученную хранимую процедуру можно следующим образом.
MS SQL Решение 5.2.2.b (запуск и проверка работоспособности)
1 EXECUTE OPTIMIZE_ALL_TABLES
Логика установки запуска задачи по расписанию была рассмотрена в решении{388} задачи 5.2.2.a{388}, потому здесь просто приведём код, с помощью которого выполняется эта операция.
MS SQL |
Решение 5.2.2.b (установка запуска по расписанию) |
1USE msdb ;
2GO
3-- https://msdn.microsoft.com/en-us/library/ms182079.aspx
4EXEC dbo.sp_add_job
5@job_name = N'Hourly [books_statistics] update';
6GO
7-- https://msdn.microsoft.com/en-us/library/ms187358.aspx
8EXEC sp_add_jobstep
9@job_name = N'Hourly [books_statistics] update',
10@step_name = N'Execute UPDATE_BOOKS_STATISTICS stored procedure',
11@subsystem = N'TSQL',
12@command = N'EXECUTE UPDATE_BOOKS_STATISTICS',
13@database_name = N'library_ex_2015_mod';
14GO
15-- https://msdn.microsoft.com/en-us/library/ms187320.aspx
16EXEC dbo.sp_add_schedule
17@schedule_name = N'UpdateBooksStatistics',
18@freq_type = 4,
19@freq_interval = 4,
20@freq_subday_type = 8,
21@freq_subday_interval = 1,
22@active_start_time = 000105 ;
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 397/545

Пример 39: оптимизация производительности с помощью хранимых процедур
MS SQL |
Решение 5.2.2.b (установка запуска по расписанию) |
23USE msdb ;
24GO
25-- https://msdn.microsoft.com/en-us/library/ms186766.aspx
26EXEC sp_attach_schedule
27@job_name = N'Hourly [books_statistics] update',
28@schedule_name = N'UpdateBooksStatistics';
29GO
30-- https://msdn.microsoft.com/en-us/library/ms178625.aspx
31EXEC dbo.sp_add_jobserver
32@job_name = N'Hourly [books_statistics] update';
33GO
Убедиться, что событие добавлено, можно следующим запросом.
MS SQL Решение 5.2.2.b (просмотр расписания)
1 SELECT * FROM msdb.dbo.sysschedules
Если рассмотреть избранные поля результата такого запроса, получается следующая картина. Здесь также представлено событие, активирующее раз в час хранимую процедуру, созданную в процессе решения{388} задачи 5.2.2.a{388}.
Name |
enabled |
freq_type |
freq_inter- |
freq_sub- |
freq_subday_in- |
ac- |
ac- |
|
|
|
val |
day_type |
terval |
tive_start_date |
tive_start_time |
UpdateBooksStatistics |
1 |
4 |
4 |
8 |
1 |
20160427 |
000105 |
DailyOptimizeAllTables |
1 |
4 |
4 |
1 |
1 |
20160427 |
000100 |
На этом решение для MS SQL Server завершено.
Переходим к Oracle. Код создания нужной нам хранимой процедуры выглядит следующим образом.
Oracle Решение 5.2.2.b (код процедуры)
1CREATE OR REPLACE PROCEDURE OPTIMIZE_ALL_TABLES
2AS
3table_name VARCHAR(150) := '';
4query_text VARCHAR(1000) := '';
5CURSOR tables_cursor IS
6SELECT TABLE_NAME AS "table_name"
7 FROM ALL_TABLES
8WHERE OWNER=USER;
9BEGIN
10FOR one_row IN tables_cursor
11LOOP
12query_text := 'ALTER TABLE "' || one_row."table_name" ||
13 |
|
'" ENABLE ROW MOVEMENT'; |
14 |
|
DBMS_OUTPUT.PUT_LINE('Enabling row movement for "' || |
15 |
|
one_row."table_name" || '"...'); |
16 |
|
EXECUTE IMMEDIATE query_text; |
17 |
|
|
18 |
|
query_text := 'ALTER TABLE "' || one_row."table_name" || |
19 |
|
'" SHRINK SPACE COMPACT CASCADE'; |
|
|
|
20 |
|
DBMS_OUTPUT.PUT_LINE('Performing SHRINK SPACE COMPACT CASCADE on "' || |
21 |
|
one_row."table_name" || '"...'); |
22 |
|
EXECUTE IMMEDIATE query_text; |
23 |
|
|
24 |
|
query_text := 'ALTER TABLE "' || one_row."table_name" || |
25 |
|
'" DISABLE ROW MOVEMENT'; |
26 |
|
DBMS_OUTPUT.PUT_LINE('Disabling row movement for "' || |
27 |
|
one_row."table_name" || '"...'); |
28EXECUTE IMMEDIATE query_text;
29END LOOP;
30END;
31/
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 398/545

Пример 39: оптимизация производительности с помощью хранимых процедур
Концепция представленного решения основана на этой рекомендации26. Итак, мы должны будем получить список всех таблиц, а затем для каждой из них сначала разрешить перемещение рядов, потом выполнить компактификацию и, наконец, снова запретить перемещение рядов. В отличие от MS SQL Server все запросы здесь совершенно тривиальны.
Запустить полученную хранимую процедуру можно следующим образом.
Oracle |
Решение 5.2.2.b (запуск и проверка работоспособности) |
1SET SERVEROUTPUT ON;
2EXECUTE OPTIMIZE_ALL_TABLES;
Теперь остаётся создать событие, запускаемое планировщиком задач Oracle по определённому расписанию. Это реализуется следующим кодом.
Oracle |
|
Решение 5.2.2.b (установка запуска по расписанию) |
||
1 |
BEGIN |
|
|
|
2 |
|
DBMS_SCHEDULER.CREATE_JOB ( |
||
3 |
|
job_name |
=> 'daily_optimize_all_tables', |
|
4 |
|
job_type |
=> 'STORED_PROCEDURE', |
|
5 |
|
job_action |
=> 'OPTIMIZE_ALL_TABLES', |
|
6 |
|
start_date |
=> |
'25-APR-16 4.00.00 PM', |
7 |
|
repeat_interval |
=> |
'FREQ=DAILY;INTERVAL=1', |
8 |
|
auto_drop |
=> |
FALSE, |
9 |
|
enabled |
=> |
TRUE); |
10 |
END; |
|
|
|
|
|
|
|
|
Убедиться, что событие добавлено, можно следующим запросом.
Oracle Решение 5.2.2.b (просмотр расписания)
1 SELECT * FROM ALL_SCHEDULER_JOBS WHERE OWNER=USER
Если рассмотреть избранные поля результата такого запроса, получается следующая картина. Здесь также представлено событие, активирующее раз в час хранимую процедуру, созданную в процессе решения{388} задачи 5.2.2.a{388}.
JOB_NAME |
JOB_STY |
JOB_TYPE |
JOB_ACTION |
START_DATE |
REPEAT_INTER- |
ENA- |
STATE |
|
LE |
|
|
|
VAL |
BLED |
|
DAILY_OPTI- |
REGU- |
STORED_PR |
OPTI- |
25-APR-27 |
FREQ=DAILY;IN |
TRU |
SCHE |
MIZE_ALL_TA- |
LAR |
OCEDURE |
MIZE_ALL_TA- |
04.00.00.000000 |
TERVAL=1 |
E |
DULE |
BLES |
|
|
BLES |
000 PM -03:00 |
|
|
D |
HOURLY_UP- |
REGU- |
STORED_PR |
UP- |
22-APR-27 |
FREQ=HOURLY |
TRU |
SCHE |
DATE_BOOKS_S |
LAR |
OCEDURE |
DATE_BOOKS_S |
04.00.00.000000 |
;INTERVAL=1 |
E |
DULE |
TATISTICS |
|
|
TATISTICS |
000 PM -03:00 |
|
|
D |
На этом решение данной задачи завершено.
Задание 5.2.2.TSK.A: создать хранимую процедуру, запускаемую по расписанию каждые 12 часов и обновляющую данные в агрегирующей таб-
лице subscriptions_ready (см. задачу 3.1.2.b{215}).
Задание 5.2.2.TSK.B: создать хранимую процедуру, запускаемую по расписанию раз в неделю и оптимизирующую (дефрагментирующую, компактифицирующую) все таблицы базы данных, в которых находится не менее одного миллиона записей.
26 https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:17312316112393#1765387500346472492
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 399/545