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




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2026-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 не будет опубликован. Обязательные поля помечены *