Скрипты для реиндексации, перестройки индексов в SQL 2005




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2025-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

22 Comments

  1. markers

    Подсказать не могу, но однозначно плюс за сборку всего в 1 месте!

    Reply
  2. zzz_natali

    Тебе сюда:

    http://www.sql.ru/forum

    Но там народ слишком манерный(профессиональный) — разжевывать не будут. Что-то на молекулярном уровне подскажут, а концептуально и академически прокачивайся сам.

    Reply
  3. rozer

    Начинающим можно посоветовать использовать Maintenance Plans…

    Reply
  4. anig99

    (3) Maintenance Plans — вещь в данном случае неподходящая

    Reply
  5. anig99

    (2) вот-вот….я в зависать ещё в одном форуме… мне пока хватает тут (:

    Reply
  6. idef
    Rebuild шести индексов каждые 3 часа с очисткой кэша чем чревата кроме устранения всех тормозов в проведении документов??

    Череват тормозами базы на время перестройки индекса

    Для какой-то оценки проделанной вами работы неплохо привести статистику: размер базы, размер соответствующих таблиц и индексов, время выполнения запроса до и после скрипта, скорость деградации производительности в течении 3 часов между запусками скриптов. Кроме того неплохо знать конфигурацию сервера и конфигурацию 1С.

    ПС. А какой смысл очистки кэша каждые 3 часа?

    Вы понимаете что этой операцией вы удаляете скомпилированные запросы?

    Reply
  7. anig99

    (6) Да… Понимаю, что очисткой кэша удаляю скомпилированные запросы. Но очистку кэша рекомендуют делать после обновления статистики. Практика показывает, что иногда достаточно только очистки кэша, чтобы скорость записи в регистр увеличилась.

    Размер базы 100 гБ.

    Деградация производительности… Снижение скорости оперативного проведения по регистру партии товаров на складах с 3-4 секунд до 60-90 секунд. Снижение скорости проведение по регистру партии товаров на складах в документах более 3-4 дней с 5-6 секунд до 500 и более секунд. При этом фрагментация индексов регистра партии товаров на складах не превышает 5 процентов…

    Платформа 1с 8.2.11.236 Конфа УПП 1.3 Win 2003 x64 SQL 2005 x64. 2 четырех ядерных XEON по 2ghz, 16 Гб оперативы на IBM серваке…. Но… Эти же самые затыки наблюдались на всех версиях 8.1 и УПП 1.2. На 32х битной оси и SQL 2000.

    Reply
  8. idef

    (7) ИМХО проблемы у вас не в фрагментации индексов, а в большом количестве приходов, в результате чего Скуль считает более эффективным сканирование таблиц, чем использование индексов. Тут надо смотреть план запроса и сам тормозной запрос, возможно его легче переделать, чем каждый раз «греметь винтами», кста, а дисковую систему почему сокрыли???

    Reply
  9. anig99

    (8) и как бы в 1с этого не учли? По-моему, тут больше проблема в том, что постоянно исправляют документы за прошлые числа (не будет развивать тему запрета изменений задним числом и т.д. — 1с тупо не учел специфику РЕАЛЬНОЙ работы и не сделал удобного механизма альтернативного неоперативному исправлению и перепроведения документов).

    Согласен, что нужно анализировать запросы на уровне SQL. Только опыта в этом никакого. Да и после этого не совсем понятно, что делать.

    Reply
  10. anig99

    (8) Пока я вижу практический результат от реиндексации, обновления статистики и очистки кэша — устранения провала в производительности. Может попробовать только обновление статистики?

    По дискам — tempdb, log и сама база данных разнесены на физически разные диски…

    Думаете проблема может быть во фрагментации? На диске с базой ничего другого нет.

    Reply
  11. idef

    (9) А вы считаете что в 1С всЁ учитывают 😉

    А когда через год база будет 200Гб — каждый час реиндексировать(дефрагментировать) базу???

    Проблема здесь в том что производительность в v8 надо рассматривать в рамках всей системы, т.е. аппаратная платформа+сервер БД+Сервер приложений+платформа 1С.

    Базы размером более 50Г уже можно считать большими и настройка таких баз должна выполнятся индивидуально. Возьмите к примеру файловые БД — у них очень хорошая производительность для объемов до 1-2Гб в однопользовательском режиме, а с некоторого объема уже начинаются приколы.

    Я не считаю что ваш путь не правильный. Но, может стоит начать разбираться с индексами и статистикой? Это даст гораздо больший выиграш в скорости и масштабируемости. При этом все те регламенты, которые предусмотрены в сервере БД никто не отменял.

    Если много INSERT/UPDATE/DELETE в базе, то статистика очень быстро устаревает(характерно для OLTP баз) ее нужно обновлять периодически.

    А вы знаете, что обновление статистики выполняется сервером автоматически для некоторых индексов, а для некоторых автообновление отключено. Проверьте включено-ли автообновление статистики примерно так:

    DBCC SHOW_STATISTICS (N’dbo._acc1′, _Acc1_ByCode_SR)

    или так:

    EXEC sp_autostats ‘dbo._acc1’

    Смысл параметров я думаю понятен.

    Еще есть синхронное и асинхронное обновление статистик.

    Статистика очень тонкий инструмент в сервере SQL. Теперь я думаю понятно почему большинство скриптов которые вы нашли не обновляет статистики.

    (10) Диски разные, но это могут быть RAID[0,1,5,6,10]? Нужное подчеркнуть.

    Монитор производительности — очередь записи на диск, например???

    объем оперативы = Объем базы/4, ИМХО конечно.

    Reply
  12. anig99

    (11) зачем всю? В том то и дело, что провал в производительности происходит только для 1 конкретного регистра…

    Reply
  13. anig99

    (11) а в остальном буду копать дальше

    Reply
  14. anig99

    (11) уточняю… automatically recompute statistics в параметрах индекса — это и есть автообновление статистики для конкретного индекса? Если да, то они были включены. Сейчас для пробы я их отключил и оставил только скрипт по перестройке этих конкретных индексов с цикличностью в час.

    Reply
  15. idef

    (14) Да. Но зачем отключать? Для экспериментов? И каковы результаты?

    Reply
  16. anig99

    (15) так как знания мои малы — прибегаю к шаманству (: Уже по результатам отключения можно сделать предположение. Автообновление статистики вещь хорошая, но при определенных условиях статистика может формироваться неверная, что приводит к резкому увеличению времени записи в регистр. А чем чаще обновлять статистику — тем больше вероятность, что это произойдет.

    Сейчас периодичность обновления статистики — 3 часа. Полет нормальный.

    Reply
  17. idef

    (16) А можно текст задания, который обновляет статистику на всеобщее рассмотрение?

    Reply
  18. anig99

    (17) если я правильно все понял, то после перестройки индексов статистики обновляется в любом случае. Поэтому использую скрипт, который идет последний в статье. На данный момент перешел на исполнение этого скрипта раз в сутки + 1-2 раза в день вручную, если начинаются затыки.

    Reply
  19. idef

    (18) Однозначно после ALTER INDEX статистика будет обновлена, но только если включено автообновление, а оно у вас похоже включено.

    А какие размеры имеют индексы и таблицы и сколько времени это занимает?

    Какая утилизация ресурсов?

    Я это к тому, что может допустимый вариант решения: ночью реиндексация, а в течении дня обновление статистики несколько раз.

    Reply
  20. MICK77

    уже проскакивало :

    «общее

    — Обновление статистики — каждые 2 часа

    — DBCC FREEPROCCACHE — каждые 2 часа»

    только вот общее — это для всех баз включая системные или только пользовательские?

    Reply
  21. anig99

    (20) всю статистику обновлять — это долго. очистку кэша — можно. Перестраивать несколько индексов и обновлять по ним статистику с очисткой кэша — вот всё, что нужно. У меня это происходит сейчас 3 раза в день. Занимает меньше 2 минут — результат поразительный.

    На другой базе иногда вручную делаю очистку кэша. Для чего? У меня есть проверка, которая делате много-много мелких запросов. Иногда один этот запрос начинает выполнятся больше секунды — запрос должен выполнится больше сотни тысяч раз. Такая производительность не устраивает. Очистка кэша (иногда не с первого раза) снижает время выполнения до приемлемых 0,08-0,04 сек в зависимости от близости к текущей дате по времени.

    Reply
  22. vis_tmp

    А для SQL 2008 можно применять без изменений?

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *