<?php // Полная загрузка сервисных книжек, создан 2024-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='\
То я так и не понял «OR» — плохо или нет?
Благодарю за статью, тем не менее, читабельность упала вдвое (вам ехать или шашечки?)
(1) вообще, по своему опыту могу сказать, что почти без разницы. С OR — один запрос, UNION — 2 запроса с объединением выборок. Поэтому в целом быстрее будет именно OR. Нужны специфические условия, чтобы с UNION юбыл план с index seek, а с OR — index scan и при том выборка была достаточно большой, чтобы UNION был значительно быстрее. Но, в любом случае, нужно смотреть планы конкретных запросов и их анализировать
В любом случае, если 1сник в запросе напишет
ИЛИ, то платформа 1с не превратит этот запрос в UNION.
(2) в данном случае да. Но когда человек пишет 10 условий OR, тогда читабельность выше наверно у UNION. В таких случаях лучше использовать IN. Так как IN работает эквивалентно OR, при этом воспринимается намного удобнее
(1)
«OR» — плохо для индексов.
Поэтому лучше писать через UNION запросы.
До сих пор полагал, что СУБД для каждой записи вычислит WHERE, причем за один проход?
Судя по оригиналу, речь о Microsoft SQL Server …
А то, что любое СКД основано на условиях в отборах компоновки в списке, в иерархии или не в списке, не в иерархии, это тоже плохо для индексов или там используется какой-то другой механизм ?
(3)
В статье написано, что с OR один скан 121000 строк, а с UNION «Одна ветвь затрагивает 358 строк, а другая — 346 строк».
Так что надо использовать UNION, так будет быстрее в случае автора. Да и 1С дает точно такую же рекомендацию в системе стандартов и методик разработки (см скриншот).
Источник:Глава «Использование логического ИЛИ в условиях»
Спасибо за перевод (если свой). Хорошее объяснение, почему конкретно UNION как правило эффективней.
Так-то это давно известный способ оптимизации тяжелых запросов.
(1) OR — хорошо. Но UNION зачастую лучше, если нужна оптимизация.
(9) так получилось, потому что в плане в первом случае index scan, во второму index seek
(12) Я про то, что в (3) вы пишите:
А это не верное утверждение. OR в целом будет не быстрее.
(11) не всегда. Например реальный случай, если выборка одного из условий очень большая. Тогда план запроса одной из веток при Union все-равно будет построен с использованием index scan, то есть будет просканирован весь индекс. А это нивелирует вторую ветку с поиском по индексу (index seek). Можете проверить, если хотите
(13) не быстрее будет только в одном случае — если при OR план будет использовать index scan, а при Union — index seek во всех ветках. Если хотя бы в одной ветке Union будет использоваться index scan, то OR будет даже немного быстрее. Кстати, если записей в целом выбирается немного план выполнения OR тоже использует поиск по индексу. Тем более clustered index scan сам по себе довольно быстрый
(15)
А как так может получиться, что при OR будет index scan, а при Union — index seek? Если учитывать, что условия по одним и тем же полям?
Мне кажется, то о чем вы говорите быть даже теоретически не может.
На сайте 1С классный пример на эту тему:
Через ИЛИ
Через ОБЪЕДИНИТЬ ВСЕ
Обратите внимание, речь идет в данном случае о том, что есть ОДИНАКОВОЕ поле для отбора.
(14)
Дык «зачастую» <> «всегда». «Зачастую» = «часто»
А еще чаще UNION рулит, когда избавляешься от OR в условии соединения.
(15)
Смотря с чем сравнивать. Если есть покрывающий обычный индекс, или объем извлекаемых данных не из индекса невелик, то по обычному индексу будет быстрее чем по кластерному.
Как показывает практика использование OR лучше отказываться в пользу UNION. Даже если на первый взгляд разницы нет, если количество выборки будет увеличиваться, а со временем обычно так и происходит, то UNION начнет в скорости превосходить.
(19) Такое… Я бы назвал это преждевременной оптимизацией. Читабельность и простоту кода уже ухудшили, а пригодится ли эта оптимизация — неизвестно. Ессно, когда известно заранее — тогда стоит сразу заложиться. Тут без вопросов.
(19) проверял на таблице в несколько миллионов строк OR vs Union. OR немного быстрее, так как в плане, из-за большого количества записей по отборам, и там и там использовалось полное сканирование индекса (index scan)
(16) вы невнимательно читали статью. Селективность при OR объединяется, и когда она достигает большого значения, сервер вместо поиска по индексу (index seek) выбирает полное сканирование индекса (index scan). При Union селекивность не объединяется, так как по сути это несколько выборок, объединённых в общий набор записей
(22)
Вы написали, что OR в целом будет быстрее чем UNION в подобных запросах. Я ответил, что нет и привел ссылку на сайт 1С и на систему стандартов и методик.
Так какой ответ верный по вашему мнению?
(23) проблема в том, что и при Union может быть большая селективность или в OR очень маленькая. И так чаще всего и происходит. Проверял это на реальных данных — анализировал планы запроса
(24)
Вы так и не ответили на вопрос.
Рекомендации 1С использовать всегда UNION в подобных запросах ошибочна или нет?
(17) не согласен. По моим наблюдениям все наоборот. В условиях соединений — может быть, нужно смотреть опять же план запроса
(25) вы опять невнимательно читали свою же ссылку. Там написано, что ИЛИ не рекомендуется использовать в условиях соединения запросов, то есть при СОЕДИНЕНИЕ…ПО (JOIN…ON), а не в ГДЕ (WHERE)
(27)
В смысле не внимательно? Это вы не внимательны.
Цитата из статьи 1С:
И статья про это же самое, даже примеры совпадающие на сайте 1С и в переводе.
(28) извиняюсь сейчас не с компьютера и статья открылась не полностью ваша. По поводу этой выдержки из вашей ссылки
Во первых, переведённая статья совсем не о том. Посмотрите в планы запроса на скриншотах. Индексы там везде используются, только идёт или поиск по индексу или сканирование индекса. Во вторых, рекомендации возможно устарели. И так было лет 20 назад чтобы индексы не использовались при условии OR в запросах SQL Server
Методика давно известна, холивар давно наскучил, а вот за труды по переводу, если сами переводили, плюсую.
(30) тут и не может быть в принципе холивара. Холивары разводят как раз любители разных методик. Каждый отдельный запрос должен анализироваться, исходя из конкретной ситуации, и выдаваться рекомендации
(25) Не всегда, а лишь рекомендация. В большинстве случаев OR работает быстрее.
(25) поэтому и говорю, что каждый конкретный случай нужно рассматривать и анализировать план запроса
(32) Аще-то или работает медленнее, но оно понятнее человекам. Так как большинство запросов для людей, то нужно писать ИЛИ, а в нагруженных местах ставить Объединить.
(34) Спасибо за глупый комментарий «человеков-архитекторов».