Довольно часто в практике работы с базами данных в MS-SQL сервер для повышения производительности и для уменьшения времени отклика системы стоит задача ускорить доступ к какой-то одной конкретно взятой таблице, либо группе таблиц.
Возможны различные методы решения данной задачи. Можно использовать для этого файловые группы, быстрые диски и т.д. Это зависит от того, какой доступ к таблице нужно сделать максимально быстрым – на запись или на чтение.
Данная статья поможет вам в том случае, если необходимо обеспечить быстрый доступ для чтения таблицы. MS-SQL сервер имеет возможность устанавливать для отдельно взятой таблицы флаг фиксации в памяти. Это означает, что при первом обращении к страницам таблицы, те загружаются в буфер MS-SQL сервера, и в дальнейшем не освобождаются для других данных. Таким образом, каждая из страниц таблицы, которую мы закрепляем в памяти, будет прочитана с диска только один раз. При этом, фиксация таблицы в памяти не повлияет на процесс записи страниц данной таблицы на диск при их изменении. То есть, запись в данную таблицу будет производиться в обычном режиме, то есть на общем основании. Но, при этом второе, и каждое последующее чтение страниц таблицы будет осуществляться не с диска, а из буфера в памяти MS-SQL сервера.
У метода закрепления таблиц в памяти есть как преимущества, так и недостатки. Главный недостаток – это возможность переполнения буфера. Так как память MS-SQL сервера используется для всех баз данных, находящихся на нем, то значит и закрепленные в памяти таблицы из разных баз, отнимают из общего доступного объема буфера. Независимо от количества таблиц, закрепляемых в памяти, общее количество памяти, выделенное под закрепленные страницы таблиц не должно превысить физически доступную для MS-SQL сервера память, во избежание нарушения работы MS-SQL сервера. Такое может случиться, если закрепленная в памяти таблица или общее количество таблиц займет всю память, доступную для MS-SQL сервера.
Если происходит переполнение, то придется делать останов и запуск сервера, и снимать фиксацию с больших таблиц, забравших всю память. Так что с данной функцией нужно обращаться с осторожностью. Например, использовать ее для закрепления небольших, но часто используемых таблиц, вроде «_1SJOURN » и др.
Какой-то статистики, или показателей, демонстрирующих получаемый прирост в производительности у меня нет, но, думаю, что при некотором умении из этой функции может получиться неплохой инструмент.
У меня есть готовая обработка, которая позволяет вывести свойства таблиц для текущей базы данных, закрепить нужные таблицы в памяти, либо наоборот, убрать закрепление.
Текст обработки представлен ниже:
Процедура ПрочитатьДанные () ТЗ .Очистить (); ТЗ .НоваяКолонка ("ИмяТаблицы" ,"Строка" ,,,"Имя таблицы" ); ТЗ .НоваяКолонка ("Закреплена" ,"Число" ,1 ,0 ,); ТЗ .НоваяКолонка ("ТекущийСтатус" ,"Строка" ,,,"Фиксирована" ); ТЗ .ВидимостьКолонки ("Закреплена" ,0 ); ЗапросРадуги =СоздатьОбъект("ODBCQuery" ); ТекстЗапроса ="SELECT RTRIM(CONVERT(char(30),TABLE_NAME)), OBJECTPROPERTY(OBJECT_ID(TABLE_NAME),'TableIsPinned') |FROM information_schema.tables |WHERE TABLE_TYPE='BASE TABLE' and TABLE_NAME<>'dtproperties'" ; Если ЗапросРадуги .Prepare (ТекстЗапроса ,0 ,0 )=1 Тогда Если ЗапросРадуги .Open ()=1 Тогда ЗапросРадуги .GotoNext (); Пока ЗапросРадуги .IsOK ()=1 Цикл ТЗ .НоваяСтрока (); ТЗ .ИмяТаблицы =СокрЛП(ЗапросРадуги .GetString (0 )); ТЗ .Закреплена =ЗапросРадуги .GetLong (1 ); ТЗ .ТекущийСтатус =?(ТЗ .Закреплена =1 ,"Да" ,"Нет" ); ЗапросРадуги .GotoNext (); КонецЦикла; ЗапросРадуги .Close (); Иначе Предупреждение("Ошибка открытия запроса!" ,10 ); КонецЕсли; ЗапросРадуги .Reset (); Иначе Предупреждение("Ошибка выполнения запроса!" ,10 ); КонецЕсли; ЗапросРадуги ="" ; ТЗ .Сортировать ("ТекущийСтатус, ИмяТаблицы" ); КонецПроцедуры
//________________________________________________________ Процедура ЗаписатьДанные () ЗапросРадуги =СоздатьОбъект("ODBCQuery" ); ТЗ .ВыбратьСтроки (); Пока ТЗ .ПолучитьСтроку ()=1 Цикл ТекНовСтатус =?(ТЗ .ТекущийСтатус ="Да" ,1 ,0 ); Если ТЗ .Закреплена <>ТекНовСтатус Тогда ТекВариант =?(ТекНовСтатус =0 ,"UN" ,"" ); ТекстЗапроса ="DECLARE @db_id int, @tbl_id int |SET @db_id = DB_ID() |SET @tbl_id = OBJECT_ID('" +ТЗ .ИмяТаблицы +"') |DBCC " +ТекВариант +"PINTABLE (@db_id, @tbl_id)" ; Если ЗапросРадуги .Prepare (ТекстЗапроса ,0 ,0 )=1 Тогда Если ЗапросРадуги .Open ()=1 Тогда Иначе Предупреждение("Ошибка открытия запроса!" ,10 ); КонецЕсли; ЗапросРадуги .Reset (); Иначе Предупреждение("Ошибка выполнения запроса!" ,10 ); КонецЕсли; КонецЕсли; КонецЦикла; ЗапросРадуги ="" ; КонецПроцедуры
//________________________________________________________ Процедура ОбновитьСтатусы () ЗаписатьДанные (); ПрочитатьДанные (); КонецПроцедуры
//________________________________________________________ Процедура ОбработкаТаблицы () Если (ТЗ .ТекущаяСтрока ()>0 ) И (ТЗ .ТекущаяКолонка ()="ТекущийСтатус" ) Тогда СЗ =СоздатьОбъект("СписокЗначений" ); СЗ .ДобавитьЗначение ("Да" ); СЗ .ДобавитьЗначение ("Нет" ); НомПоз =0 ; Если СЗ .ВыбратьЗначение (,,НомПоз ,,1 )=1 Тогда ТЗ .ТекущийСтатус =?(НомПоз =1 ,"Да" ,"Нет" ); КонецЕсли; КонецЕсли; КонецПроцедуры
//________________________________________________________ Процедура ПриОткрытии () Если ЗагрузитьВнешнююКомпоненту("rainbow.dll" )=0 Тогда Предупреждение("Не загружена внешняя компонента " "rainbow.dll" " !" ,10 ); СтатусВозврата(0 ); Иначе ПрочитатьДанные (); КонецЕсли; КонецПроцедуры
Эта обработка доступна в разделе "Скачать".
Перепечатка, воспроизведение в любой форме, распространение, в том числе в переводе, любых материалов с сайта www.softpoint.ru возможны только с письменного разрешения компании "СофтПоинт". Это правило действует для всех без исключения случаев, кроме тех, когда в материале прямо указано разрешение на копирование (основание: Закон Российской Федерации "Об авторском праве и смежных правах").
|