четверг, 7 февраля 2013 г.

Мобильный blogger

Установил себе мобильное гугловское приложение Blogger. Будем посмотреть, возможно начну писать чаще.
С понедельника начинаются курсы по безопасности персональных данных от софтлайна, так что можно сказать, что приложение я себе установил очень кстати.
Пока не знаю насколькоудобно будет писать большие тексты на телефоне, но пока всё устраивает.

Как работает DTA в SQL Server

В SQL Server, начиная с 2005-го, присутствует такой компонент как Database Tuning Advisor. Он может проанализировать рабочую нагрузку и предоставить свои рекомендации по созданию/удалению индексов для повышения производительности.
Не сказать, чтобы мне прям было очень интересно как он работает. Теоретически, глядя на условия соединения таблиц, выбираемые поля, сортировки и прочее - можно предоставить рекомендации по создаваемым индексам. Мой диплом, например, назывался "Инструментарий для оптимизации запросов в среде 1с 8.1", который этим и занимался. Смотрел какие индексы есть, какие поля остаются неиндексированными и, основываясь на этих данных, давал свои рекомендации. Надо признать, что спустя 4 года я понимаю какую ересь он предлагал, но сам подход, в принципе, можно, наверное считать приемлемым.
Ну так вот, возвращаясь к DTA. Я думал, что примерно такую же работу он и проводит. Но, оказалось, что это не совсем так. Точнее, возможно, именно этим он и занимается, но не в том виде, как я себе это представлял.
Итак, у SQL Server есть несколько интересных недокументированных возможностей.
1) При создании индекса есть возможность указать WITH STATISTICS_ONLY.
Это заставляет SQL Server создать гипотетический (hypothetical) индекс. Т.е. фактически создаётся такой индекс, который нельзя использовать в обычных запросах (и который никак не учитывается оптимизатором), но который, как бы существует. Ещё есть возможность указания  WITH STATISTICS_ONLY = -1 - тогда индекс будет гипотетическим, но, вот статистика, созданная по этому индексу, будет вполне себе реальной.
2) DBCC AUTOPILOT и SET AUTOPILOT.
Как я уже говорил - гипотетический индекс не может использоваться при выполнении запросов. Но, с помощью DBCC AUTOPILOT мы можем заставить оптимизатор создать такой план запроса, какой он создал бы при наличии этого индекса в "обычном", не гипотетическом, виде.
Итак, чтобы использовать DBCC AUTOPILOT, выполним:
DBCC TRACEON (2588)
DBCC HELP('AUTOPILOT')
 и увидим описание:
DBCC AUTOPILOT (typeid [, dbid [, {maxQueryCost | tabid [, indid [, pages [, flag [, rowcounts]]]]} ]])

Итак, чтобы выполнить запрос с учётом гипотетического индекса, в режиме "автопилота", нужно сделать следующее:
1. Создать индекс WITH STATISTICS_ONLY.
2. Узнать идентификатор БД: select db_id()
3. Узнать id таблицы и id индекса, например из sysindexes
4. Вместо остальных значений можно использовать нули, а можно попробовать поиграться и проанализировать результаты.
5. Выполнить  SET AUTOPILOT ON
6. Выполнить DBCC AUTOPILOT.
7. Выполнить запрос и посмотреть его план выполнения. Если гипотетический индекс будет являться оптимальным для этого запроса, он будет использоваться.
8. Выполнить SET AUTOPILOT OFF

В общем, штука крутая, но с ней надо быть осторожным. Недокументированные возможности всегда используются на свой страх и риск (и я никому не советовал бы использовать их на продакшене).

О DBCC AUTOPILOT я узнал отсюда (мой перевод на хабре). Примерно тоже самое, от того же автора, но с более удобным вариантом использования есть здесь. О гипотетических индексах можно почитать здесь.

пятница, 2 ноября 2012 г.

Доверяй, но проверяй

Вот уже четыре года и один день я официально администратор баз данных. И, естественно, в мою работу входит "забота" об индексах в базах данных SQL Server.
Согласно рекомендациям по обслуживанию индексов от самих Microsoft, индекс, степень фрагментации которого превышает 5%, должен быть дефрагментирован, а индекс, степень фрагментации которого превышает 30%, должен быть перестроен (т.е., фактически, удалён и построен заново). Reorganize and Rebuild Indexes
И вот, сегодня, читая книжку Troubleshooting SQL Server for Accidental DBA, натыкаюсь в ней на ссылку на пост Пола Рэндала Where do the Books Online index fragmentation thresholds come from?, в которой прямым текстом написано, что эти значения (5% и 30%) были им взяты от балды, поскольку в документации надо было указать хотя бы какие-то "пороговые" значения.
Грусть, печаль, тоска (на самом деле нет). Просто забавно, ведь эти значения я и ещё сотни (а то и тысячи людей) действительно считали важными (или, по крайней мере, обоснованными).

четверг, 22 марта 2012 г.

Установка Service Pack на SQL Server 2008 R2 в кластере

Очень давно хотел попробовать развернуть SQL Server Failover Cluster ("Кластер отработки отказа SQL Server" в русской редакции оного), но то не хватало времени, то желания. А на днях скачал "Introducing Microsoft SQL Server 2012", начал разбираться с Availability Groups (боюсь даже представить как их обзовут в руссифицированной версии) и понял, что нихрена не понимаю - надо ставить и разбираться.
С помощью чудесной серии статей SQL кластер на VMware Workstation (аж из 11-ти статей!), Windows-кластер был развернут буквально за три часа. Но, увы, после того как я попробовал установить SQL Server 2012, то понял, что в дальнейшем мне надо бы заранее читать требования к ПО. Для установки SQL Server 2012 требуется Windows Server 2008 R2 Service Pack 1, а я, умница такая, ставил просто Windows Server 2008 R2.
И, пока сервис-пак для операционки качался, подумал, что неплохо бы вообще поиграться с кластером. Кто его знает когда это пригодится. Во-первых, в кластере был установлен SQL Server 2008, которого вполне себе удовлетворяла операционка без сервис-пака, и было решено попробовать следующее:
1. Установить сервис-пак на SQL Server 2008 R2 в кластере и посмотреть - есть тут какие-нибудь хитрости или нет
2. Установить сервис-пак на Windows Server 2008 R2 и, соответственно, посмотреть какие хитрости есть тут.
В этом посте я буду писать только про установку сервис-пака на SQL Server, а про установку SP на ОС будет отдельный пост.
Итак, у нас есть отказоустойчивый кластер, состоящий из двух нод: ClustNodeA и ClustNodeB; есть "рабочая станция" с установленными клиентскими утилитами для SQL Server: ClustWork. Все это добро уютненько разместилось в сети 192.168.81.0/24. Так же есть контроллер домена ClustDC (домен называется ClustDom, доменный администратор ClustDom\adm) и "эмулятор" SAN ClustSAN. В общем, все как в статьях приведенных выше.
На обоих нодах была совершена "кластерная установка" и теперь у меня есть кластер SQL2008CLUST с ip-адресом 192.168.81.99 - полностью работоспособный.
Теоретически, установка SP не представляет сложности. Нам надо установить сервис пак на пассивной ноде (ClustNodeB), проверить правильность установки, сделать переезд на обновленную ноду и обновить ClustNodeA, ставшую теперь пассивной.
Стоит отметить, что такой механизм работает начиная с SQL Server 2008. В SQL Server 2005 все было по-другому. Сервис пак должен был устанавливаться ТОЛЬКО на активной ноде, на пассивные он устанавливался автоматически, соответственно и downtime в этой редакции был намного больше, чем в последующих.
У меня SQL Server 2008 R2 и, соответственно, downtime должен быть минимальным.
Подключаюсь к пассивной ноде ClustNodeB и запускаю установку:
Пока устанавливается сервис-пак, я проверяю доступность нашего кластера. С машины ClustWork подключаюсь к sql2008clust и выполняю запросы:
SELECT SERVERPROPERTY('IsClustered')
SELECT SERVERPROPERTY('ComputerNamePhysicalNetBIOS').
Результат представлен на рисунке:
Первый говорит о том, что этот экземпляр кластеризованный (IsClustered = 1), а второй о том, что физически SQL Server сейчас запущен на ноде ClusterNodeA, как и предполагалось.
Установка сервис-пака на пассивной ноде успешно завершилась и теперь нужно "перевести" SQL Server на нее и установить SP на второй ноде.
Итак, SQL Server переехал:
Обратите внимание, на предыдущем скриншоте, в окне обозревателя объектов стоит версия SQL Server: 10.50.1600 - версия без SP, а на последнем - 10.50.2500 - SQL Server 2008 R2 SP1. Так же обратите внимание - если вы решите вернуться на ClustNodeA до тех пор пока она не обновлена, вы увидите такую ошибку:
в то время как на второй, обновленной, ноде (ClustNodeB) подключение проходит нормально и можно выполнять запросы.
Установка обновления на уже пассивной ноде ClustNodeA проходит довольно быстро и успешно. Снова делаю failover, чтобы нода ClusterNodeA вновь стала активной и проверяю версию:
Версия: SQL Server 2008 R2 SP 1 (проверить можно вот здесь: SQL Server builds), активная нода: ClustNodeA.
Таким образом, установка SP на SQL Server Failover Cluster - это не просто, это очень и очень просто (и быстро, downtime равен времени failover'a с активной ноды на пассивную).

вторник, 7 февраля 2012 г.

SQL Server. Определение размера таблиц в БД

У меня иногда возникает необходимость найти наиболее "тяжелые" таблицы в той или иной базе данных, и их удалить. Нет, я не сошел с ума, просто иногда требуется создать "маленькую и шуструю" копию той или иной БД, в которой нет ничего лишнего. Можно, конечно, выбирать только нужные таблицы и переносить их в новую БД выборочно, но это получается дольше и требует больших усилий. Этот вариант я рассматривать не буду.
А вот для выбора тех таблиц, которые нужно удалить, есть чудо-процедура sp_spaceused, но этой заразе нужно передавать имя таблицы в качестве параметра. Можно, конечно, совместить ее с sp_msForEachTable и результат становится более или менее приемлимым, но остаются минусы - например, оно возвращает все "цифры" как varchar, из-за чего сортировка становится не очень удобной. В общем, я просто оставлю это здесь:

(раньше здесь была большая портянка, стыренная отсюда, но, благодаря Алексею Нестерову, всё стало намного лучше)

declare @t table (name varchar(255), row varchar(255), reserved varchar(255), data varchar(255), index_size varchar(255), unused varchar(255))

insert into @t
exec sp_msforeachtable N'exec sp_spaceused ''?'''

select * from @t
where CONVERT(bigint,REPLACE(data,' KB','')) > 10000
order by CONVERT(bigint,REPLACE(data,' KB','')) DESC

вторник, 31 января 2012 г.

Глупенький пост про установку 1С с помощью msiexec

Для того, чтобы установить 1С на все компьютеры в сети, 1С предлагает варианты установки через логон-скрипт, либо через групповые политики. В силу определенных причин, наш системный администратор не хочет использовать ни тот, ни другой. Обычно установка производится батником, с помощью программы RemoteExec, запускающей этот батник на всех машинах.
Ну и просто, чтоб я в следующий раз снова не вспомниал как это все делается, то вот содержимое такого батника:

msiexec /i "D:\soft\!1C 8.2 platform\8.2.14.540\x86\1CEnterprise 8.2.msi" /quiet THICKCLIENT=1 THINCLIENT=0 WEBSERVEREXT=0 SERVER=0 CONFREPOSSERVER=0 CONVERTER77=0 SERVERCLIENT=1 LANGUAGES=RU 

Путь, естественно, будет заменен на сетевой. Ключ /i показывает, что мы устанавливаем новую программу, а /quiet прячет от пользователя все окна. В результате, на машинах будут установлены толстые клиенты и компоненты для доступа к серверам.

четверг, 19 января 2012 г.

Запускаем 2 сервера 1С 8.2 на одной машине

В связи с предстоящим переходом на 8.2.14.540 с установленной сейчас 8.2.13.205, потребовалось протестировать новую платформу. У нас есть два сервера - рабочий, виртуальный, к которому ключи проброшены средствами VMWare ESXi и тестовый, физический, в котором ключи воткнуты "напрямую".
На тестовом сервере я и начал играться.
Первый блин вышел комом. При установке я не снял галку "запускать серверную часть как службу" и 14-я платформа благополучно установилась ВМЕСТО 13-й. К счастью, 8.2 устанавливается не затирая файлы предыдущей версии и все что мне потребовалось сделать - в реестре изменить путь к исполняемому файлу ragent (с "C:\Program Files (x86)\1Cv82\8.2.14.540\bin\ragent.exe" на  "C:\Program Files (x86)\1Cv82\8.2.13.205\bin\ragent.exe").
"Хорошо", - подумал я. И попытался запустить ragent.exe из командной строки (все порты были изменены так, чтобы не пересекаться с портами других серверов, как 1С 8.1, так и 8.2, плюс, дополнительно был изменен каталог с серверной информацией - temp_srvinfo):

"C:\Program Files (x86)\1cv82\8.2.14.540\bin\ragent.exe" -regport 2641 -port 2640 -range 2660:2691 -d "C:\Program Files (x86)\1cv82\temp_srvinfo" -debug

К моему удивлению, все запустилось:

После этого я успешно запустил консоль кластера, создал новый кластер и подсоединил к нему имеющуюся базу данных. Я всегда считал, что это показатель того, что ключ виден и успешно используется. Но, когда я попытался запустить клиента на своей машине и соединиться с созданной БД, меня ждало громадное разочарование - "На сервере нет ключа", - кричала 1С. Точнее, сообщение было таким:
На компьютере сервера не обнаружена лицензия для использования сервера 1С:Предприятия! Если Ваш комплект поставки включает информацию для получения лицензии из центра лицензирования (пинкоды), то Вы можете получить лицензию для использования программы на данном компьютере. Если Вы используете комплект с аппаратной лицензией (ключом защиты), то проверьте установку ключа. Получить лицензию из центра лицензирования? Да/ Нет
После этого я попробовал запустить клиента на другой машине - результат тот же самый. Потом, я попробовал запустить клиента на том же сервере (и из той же сессии), но результат остался точно таким же. В свойствах БД стоял запрет на раздачу лицензий, я попробовал включить его, но результат оставался тем же самым.

Поиск в интернетах показал, что есть люди у которых все работает, но, увы, никто из них не делился конкретным рецептом как это сделать.
Тогда я решил попробовать остановить службу 8.2.13.205 и запустить оба сервера "как приложения". Оба запустились замечательно, но в итоге, ни к одному из них не получилось подключиться, ошибка все та же.
Поиск в интернетах привел на мисту. В итоге, все оказалось очень и очень просто. Подключившись "напрямую" к тестовому серверу через IP-KVM, я запустил сервер, и БИНГО! Все заработало.
Жаль, что этот момент ("Все "однотипные" сервера должны запускаться как службы, либо НЕ из терминальной сессии") напрямую не прописан нигде.
Результат. 8.2.14.540
и 8.2.13.205

upd 20.08.2015

Понадобилось мне запустить два сервера 8.3, причём оба как службы, поскольку запускалось всё на виртуальной машине и KVM бы не помог. Всё оказалось не намного сложнее. Стояла и была запущена как служба 8.3.6.2041, установил как обычное приложение 8.3.6.2152. Запустил FAR от администратора, из него cmd и выполнил sc create 1CNewServer binPath= "C:\Program Files\1Cv8\8.3.6.2152\bin\ragent.exe". В "Службах" появилась новая служба, отредактировал через regedit параметр ImagePath и всё, на одном сервере запущены две службы 8.3.