Анти-оптимизация: как мы ускорили запрос в 4 раза, сделав его неоптимальным




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

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

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

<?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='\

97 Comments

  1. SlavaKron

    А сколько элементов было в справочнике?

    Reply
  2. hlop11

    Избавиться от «ИЛИ» в секции «ГДЕ» не пробовали?

    Reply
  3. acanta

    Или это внутренние соединения таблицы сама с собой несколько раз?

    Reply
  4. Sashares

    Поддерживаю, приведите варианты оптимизации, которые получились «по всем правилам» и которые не сработали.

    Reply
  5. Diversus

    Вообще 1С рекомендует уходить от «ИЛИ» в секции «ГДЕ» и заменить на конструкцию вида «ОБЪЕДИНИТЬ ВСЕ».

    В вашем случае можно было бы попробовать:

    «ВЫБРАТЬ
    |  Номенклатура.Ссылка
    |ИЗ
    |  Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |  Номенклатура.Наименование ПОДОБНО &Наименование
    |
    |ОБЪЕДИНИТЬ ВСЕ
    |
    |ВЫБРАТЬ
    |  Номенклатура.Ссылка
    |ИЗ
    |  Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |  Номенклатура.Код ПОДОБНО &Наименование
    |
    |ОБЪЕДИНИТЬ ВСЕ
    |
    |ВЫБРАТЬ
    |  Номенклатура.Ссылка
    |ИЗ
    |  Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |  Номенклатура.ПолнАртикул ПОДОБНО &Наименование
    |
    |ОБЪЕДИНИТЬ ВСЕ
    |
    |ВЫБРАТЬ
    |  Номенклатура.Ссылка
    |ИЗ
    |  Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |  Номенклатура.КодРозницы ПОДОБНО &Наименование;»

    Показать

    Пруф: Использование логического ИЛИ в условиях

    Не понятно правда на сколько это будет быстрее в вашем случае, но официальная рекомендация такая.

    Reply
  6. SlavaKron

    (5) По идее, оптимизация через «ОБЪЕДИНИТЬ ВСЕ» — это первое, что приходит в голову. Но автор пишет: «Любые попытки оптимизации этого запроса по стандартным методикам не привели к нужному результату». Вот и гадай, что он имел в виду под «стандартными методиками».

    Reply
  7. vasilev2015

    (5) я бы добавил: нужно писать максимально простой запрос, отдельный для каждого варианта поиска.

    Reply
  8. igordynets

    (2) пробовали) это первое что сделали — не помогло, стоимость плана маленькая — запрос выполняется долго)

    Reply
  9. igordynets

    (5) да, этот вариант был первым, который использовали) не помогло

    Reply
  10. igordynets

    (1) несколько сотен тысяч

    Reply
  11. igordynets

    (6) согласен, следовало уточнить) через ОБЪЕДИНИТЬ ВСЕ переписали сразу когда увидели запрос. Результата это не дало)

    Reply
  12. igordynets

    (4) сходу все не вспомню, из того что делали:

    — переписывали через ОБЪЕДИНИТЬ ВСЕ

    — в параметр наименование передавали строку с фиксированным началом (например, вместо «%строкапоиска%» использовали «строкапоиска%».

    Reply
  13. trntv

    (5) вы написали тоже самое, что делал план долгого запроса на скриншоте, за исключением того, что вы забыли сгруппировать результат. То есть 4 раза будут перебираться все элементы одной и той же таблицы. Вы как бы таким образом пишите, что вам надо его перебирать именно 4 раза.

    Понятно что LIKE в индексе будет заниматься тем же самым перебором, что и без индекса. У него (у LIKE) другого варианта и нет.

    Быстрее конечно перебрать все элементы 1 раз, сравнивая их на 4 различных условия.

    А может кто-то все же добавил индекс на один из реквизитов при повышении совместимости? Например, до измениний были индексы только на реквизитах «Код», «Артикул», «КодРозницы». А после добавили индекс на «Наименование».

    Reply
  14. igordynets

    (12) проверяли, по всем полям поиска («Код», «Артикул», «КодРозницы», «Наименование») индексы были

    Reply
  15. spacecraft

    (13)

    в параметр наименование передавали строку с фиксированным началом (например, вместо «%строкапоиска%» использовали «строкапоиска%».

    Вот с этого и нужно было начинать. При Like и подстановочных символах не может использоваться именно поиск по индексу. Был полный перебор индексов, причем 4 разных. Во втором был просто перебор таблицы один раз.

    Для таких случаев придумали Полнотекстовый поиск.

    Reply
  16. Diversus

    На одной из конференций Инфостарт Event, по-моему, выступал представитель компании Софтпоинт и он предложил решение задачи поиска номенклатуры, которое будет отрабатывать очень быстро.

    Добавил регистр сведений с измерениями:

    — Подстрока (индекс)

    — Номенклатура

    и регламентное задание, которое бы перезаполняло этот регистр:

    А именно: разбивало бы исходную строку на подстроки:

    Пример:

    Туфли женские (наименование)

    3-х буквенные:

    туф

    уфл

    фли

    жен

    енс

    нск

    кие

    4-х буквенные:

    туфл

    уфли

    женс

    енск

    нски

    ские

    5-ти буквенные

    и т.д.

    Каждой такой подстроке соответствует номенклатура «Туфли женские». А дальше разбиваем исходную строку поиска на слова и делаем запрос к регистру, который работает без ПОДОБНО, через равно.

    Да получается много данных сохраняем и огромный регистр, который строится долго, но поиск работает очень быстро.

    Вот такой вариант по поиску был предложен.

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

    Все это имеет смысл только для баз где ОЧЕНЬ много номенклатуры. И люди пользуются такими извращениями потому, что деваться в общем-то некуда…

    Reply
  17. Diversus

    (16)

    Для таких случаев придумали Полнотекстовый поиск.

    Хехе… Знаем проходили… Поищите ошибки при полнотекстовом поиске в интернете.

    Да, этот механизм предназначен именно для этого, но оно же не работает как надо.

    Для реально больших баз, были ошибка с дампами (отключаешь полнотекстовый поиск — все ок, выполняешь поиск дамп и вылет из программы) и место заканчивалось в папке с файлами индекса, а его же на другой диск не перенесешь в отличие от файлов того же сиквела…

    Поэтому полнотекстовый поиск как бы есть, но для больших данных нужны свои велосипеды.

    Reply
  18. psih12

    (5) Проверяли мы на своей базе рекомендации 1С. Из справочника «Номенклатура» нужно было отобрать данные по 8-ми условиям артикула. Отбор составлял 270 000 позиций номенклатуры с 43 реквизитами. Так вот, обычным отбором с помощью «ИЛИ» замер показал 23 секунды, а запросами с помощью «ОБЪЕДИНИТЬ ВСЕ» 25 секунд, плюс текст запроса становится совершенно громоздким. Так что не всё так просто с этими рекомендациями.

    Reply
  19. Diversus

    (18) На то это и рекомендации 🙂 Применять их или нет зависит от ситуации.

    Reply
  20. Dorosh

    (15)

    Все это имеет смысл только для баз где ОЧЕНЬ много номенклатуры.

    И когда ОЧЕНЬ МНОГО свободного места на дисках.

    Reply
  21. Dorosh

    В тему анти-оптимизации: никогда не забуду одного случая из своего опыта. Доставшийся мне запрос собирал данные по таб. части документа. Как весь из себя правильный прог, я возмутился и переписал на «канонический» способ — получения из регистра накопления. В результате время выполнения увеличилось в разы. Пришлось вернуть обратно.

    Reply
  22. PerlAmutor

    В защиту рекомендаций 1С по оптимизации запросов могу сказать, что там есть упоминание того, что запросы могут работать быстрее до оптимизации чем после, но проводить оптимизацию все равно рекомендуется по той причине, что один и тот же запрос может быстро выполняться на одном сервере и недопустимо долго на другом. А оптимизированный запрос может работать медленнее, но время его выполнения будет стабильным/предсказуемым в большинстве случаев.

    Насчет скриншота итогового плана запроса есть сомнения. До этого было сканирование 4 разных не кластерных индекса, а в итоге идет сканирование по кластерному индексу, который еще и Primary Key похоже… Что-то тут не так. Он обрезанный?

    Reply
  23. acanta

    (21) имхо, это рекомендации времен дбф.

    Reply
  24. asved.ru

    (17)

    Дамп — ситуация расследуемая и устранимая.

    Индекс ППД, а точнее каталог кластера, легко и непринужденно переносится куда угодно симлинком или в командной строке запуска службы.

    Reply
  25. asved.ru

    (15) Т.е. накостылили свой ППД несмотря на существование такового как в платформе, так и в СУБД.

    Reply
  26. nvv1970

    Очень поверхностная статья без знания СУБД. Мы стукнули по телевизору и он стал показывать лучше… (С сожалению именно такие ощущения)

    Нет, конечно это не оптимизация. Даже для частного случая. Это ещё выстрелит вам в ногу. Вы заставили свалиться запрос в один скан и параллелизм, почему сам поиск работает долго по каждому индексу — не разобрались. При такой оптимизации можно уже и индексы отключать. О записи то вы почему-то не стали беспокоиться.

    Так можно поступить только «пока не разберемся’.

    Давайте детали:

    Версия СУБД. Совместимость базы. Maxdop=0? Или сколько? Почему при наличии maxdop разница в 4 раза? Очень странно. Нужны цифры…

    Сколько записей в таблице, сколько записей в выборке по каждому индексу.

    Прогрет ли кэш? Покажите чтения и время для каждого случая по всем (пяти) индексам отдельно.

    План запроса свежий или из кэша? закэширован для какого параметра?

    ПС: 5 сек — это тоже не результат. Что делает этот запрос? Если это список, то где ПЕРВЫЕ?

    Reply
  27. stepan96

    (15) Cвой вариант Elasticsearch?

    Reply
  28. nicxxx

    (2) MSSLQ сам неявно избавился от «ИЛИ». Посмотрите на план запроса 8.2. Оптимизатор параллельно читает таблицу 4 раза, а затем объединяет результат операцией Concatenation. То же самое происходит при использовании UNION ALL. Пруф https://sqlperformance.com/2017/05/sql-plan/union-all-optimization.

    Reply
  29. nicxxx

    (5) см. (29)

    Reply
  30. nicxxx

    (6) Первое, что должно прийти в голову — посмотреть план запроса. В данном случае UNION ALL ничего не даст, см. (29).

    Reply
  31. HAMMER_59

    Из личного опыта — никаких гарантий нет, что по одному и тому же запросу будет построен один и тот же план выполнения. То что разово сработало ни о чем не говорит, и даже не разово сработало. Может месяцами работать, а потом хоп и сюрприз.

    Ну его нафиг такую оптимизацию.

    Reply
  32. myxins1989

    (21) на уровне субд все это таблицы. Плюс регистров в том, что там могут быть собраны данные из нескольких типов документов. Ну и различные итоги и агрегаты. Если точно знать, что запросом будем получать каждую запись и по одному типу документов, то можно и таблицу документа взять.

    Reply
  33. pbazeliuk

    Используйте для поиска более подходящие инструменты, например, Elasticsearch.

    Reply
  34. SeiOkami

    (10) перепишите статью и заново на модерацию. А то вам теперь только про это и будут говорить.

    Reply
  35. hlop11

    (29) Конечно избавился и потратил на это (на оптимизацию) своё время.

    Reply
  36. insurgut

    Как-то не однозначно все. Если даже взять первоначальные данные — 5 секунд на поиск подобных в справочнике из несколько сотен тысяч элементов. Не многовато? Для примера аналогичный запрос по справочнику с 900 тысяч элементов отрабатывает менее секунды (если быть точнее, около 300-400 миллисекунд). Самое интересное, что конструкция ВЫРАЗИТЬ никак не влияет на производительность — +/- время одинаковое.

    Reply
  37. A_Max

    (17)

    а его же на другой диск не перенесешь

    Очень даже можно перенести. Windows уже давно умеет хард/софт линки.

    Reply
  38. Diversus

    (25) Повторю — это не моя реализация. Это было на одном из докладов IE, сотрудник Софтпоинта рассказывал о таком способе.

    С другой стороны, если это будет работать быстро, то почему нет?

    Reply
  39. DarkUser

    А почему во втором плане запроса есть сортировка?

    Reply
  40. lobonosov@mail.ru

    (5)

    анчивалось в папк

    В данном случае если вместо ПОДОБНО было строгое равенство, тогда было бы оптимальнее: было бы 4 поиска по индексам и объединение.

    Reply
  41. igordynets

    (26)

    Версия СУБД. Совместимость базы. Maxdop=0? Или сколько?

    Версия СУБД: Microsoft SQL Server 2008 R2 10.50.6000.34

    maxdop = 8

    compatibility level = 100

    Почему при наличии maxdop разница в 4 раза? Очень странно. Нужны цифры…

    Проверялась работа с разными значениями maxdop, в том числе и с выключенным (=1), результат значительно не изменялся.

    Прогрет ли кэш?

    План запроса свежий или из кэша? закэширован для какого параметра?

    Кэш прогревался. Тестирование выполнялось с предварительной очисткой кэша и его прогревом.

    Что делает этот запрос? Если это список, то где ПЕРВЫЕ?

    запрос выполняет поиск номенклатуры по части строки, поиск выполняется по разным реквизитам (это не динамический список)

    Сколько записей в таблице, сколько записей в выборке по каждому индексу.

    Покажите чтения и время для каждого случая по всем (пяти) индексам отдельно.

    Эту информацию, к сожалению, сейчас нет возможности предоставить — доступа к базе уже нет.

    Reply
  42. igordynets

    (34)

    Elasticsearch

    Напишите, пожалуйста, где можно прочитать про этот инструмент и как с ним работать в связке с 1С

    Reply
  43. igordynets

    (41) Да, согласен, поиск на равенство работал бы максимально быстро. Но поиск на строгое равенство не всегда устраивает клиента.

    Reply
  44. capitan

    Отличная статья как не надо оптимизировать запросы я считаю

    Решение задачи методом подселения козла.

    Подозреваю юзеры жаловались и на 5 сек поиск номенклатуры, им сделали 20 сек, а потом вернули 5 сек и наступило счастье )

    На самом деле не хватает информации по задаче.

    Самое главное — сколько секунд ищется такой конструкцией

    «ВЫБРАТЬ
    |  Номенклатура.Ссылка
    |ИЗ
    |  Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |  Номенклатура.Наименование ПОДОБНО &Наименование
    
    
    сколько секунд ищется такой конструкцией
    «ВЫБРАТЬ
    |  Номенклатура.Ссылка
    |ИЗ
    |  Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |  Номенклатура.Наименование = &Наименование

    Показать

    и по какому полю чаще всего пользователи ищут

    и если они в большинстве случаев правильно вводят начало слова а я думаю 100% они не ищут по середине — то можно искать по равенству, а не по подобию — это будет 0.5 сек к примеру вместо 5 сек

    Reply
  45. AntonNV

    (10)Т.Е. это уже не актуально писать через объединить ?

    Reply
  46. insurgut

    (45) там вероятнее всего проблема в железе, потому что даже подобие отрабатывает на сотнях тысяч элементов менее секунды на нормальном сервере.

    Reply
  47. nvv1970

    (42) Спасибо за детали.

    Очень жаль, что уже нет доступа к данным и больших подробностей. Можно было хотя бы отдельно таблицу выдрать/сохранить.

    Я такие вещи тестирую прямо в SSMS. Можно рекомпиляцию делать (для избежания снифинга), хоть как-то контролировать кэши, можно чтения видеть, замеры и т.п. Из 1С проводить тесты — так себе…

    Очень важный момент: как бы повел себя оптимизатор на 2012-2017 версиях. Теперь мы этого не узнаем. ((

    Проверялась работа с разными значениями maxdop, в том числе и с выключенным (=1), результат значительно не изменялся.

    Время скана кластерного то точно должно было меняться. Интересно сколько оно занимало при =1.

    Во всех подобных случаях не стоит рассматривать примеры запросов как что-то универсальное (а-ля вот такая таблица с таким-то количеством строк). Подобные странности проявляются на определенных данных, с определенным статистическим распределением значений.

    PS: прошу прощения за лишнюю резкость в предыдущем посте.

    Reply
  48. A_Max
  49. ogidni

    (15)На мой взгляд безсмысленная оптимизация, СУБД самостоятельно это делает. И вообще Полнотекстовый поиск для чего вам?

    Reply
  50. Sybr

    Я бы попробовал вручную создать индекс состоящий из ссылки и всех полей поиска. Скорее всего запрос стал бы работать быстрее 5 секунд.

    Reply
  51. for_sale

    (15)

    Бред, а не решение. Автор этого решения, видимо, даже не подумал о том, что 99% этих буквосочетаний не будут нужны никогда. Потому что в 99.99% случаев пользователи ищут по началу слова, а не по середине, если нужны «туфли», то никто не будет писать «уфл».

    Затем автор этого бредового решения не подумал о том, что даже если номенклатуры в справочнике миллион, то даже группировка по двум первым буквам уже даёт выборку всего в пару тысяч элементов, что вполне уже подъёмно даже для 1С.

    Соответственно, если уж хочется решать это всё через регистр, то можно весь миллион номенклатуры разбить по словам, у каждого слова взять две-три первые буквы, а дальше уже составлять индекс — «туф» как начало любого из слов в номенклатуре присутствует в этих двух тысячах номенклатур. А во время поиска, когда пользователь набрал «туфли ж», выбирается вся номенклатура, у которой индекс = «туф» (равно, не подобно), дальше уже из этих пары тысяч строк по Имя Подобно «%туфли ж%» за несколько мс выбирается всё нужное.

    Нет террабайтов бесполезных индексов, нет часов ожидания перестроения бесполезных индексов, нет ожидания пользователей.

    Reply
  52. capitan

    (46)Это не обязательно в железе, может быть фрагментация индексов или БД, судя по переходу с 8.1 там все не новенькое

    Reply
  53. FreeArcher

    (45) Вот как раз по середине и ищут, например такая фраза «цем иск 50», означает «Цемент (ОАО «Искитимцемент») 50кг /25″.

    У нас примерно так же сделан поиск и простых альтернатив этому я не вижу.

    Reply
  54. acanta

    У нас было искать в найденном.

    Reply
  55. pbazeliuk

    (43) Вот ссылка на материалы мастер-класса https://github.com/FoxyLinkIO/FoxyLink/tree/develop/samples/is-this-design-2019

    Reply
  56. capitan

    (54)Т.е. вы считаете что поиском ПОДОБНО &Наименование

    «цем иск 50», найдется «Цемент (ОАО «Искитимцемент») 50кг /25″

    ???

    Reply
  57. Diversus

    (52)

    Бред, а не решение. Автор этого решения, видимо, даже не подумал о том, что 99% этих буквосочетаний не будут нужны никогда. Потому что в 99.99% случаев пользователи ищут по началу слова, а не по середине, если нужны «туфли», то никто не будет писать «уфл».

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

    Reply
  58. FreeArcher

    (57) Если разбить по словам и сделать несколько запросов то найдется.

    Reply
  59. Dach

    Почему не попробовали сделать «составной» реквизит — поле поиска? Например: КлючАналитикиПоиска (строка, 200, индекс) = Наименование + Код + ПолнАртикул + ….;

    Во-первых, такая строка 99% будет уникальной, а значит и индекс будет селективным.

    Во-вторых, это будет один индекс, а не 3 (5,10 и т.д.), в плане будет поиск по 1-му индексу, а не по 3-м и последующая конкатенация результатов.

    Очевидное решение, лежит на поверхности, неужели никто не догадался???

    Reply
  60. Drak0n

    (5)Результат Вашего запроса не будет равен изначальному… )

    Reply
  61. Dach

    (61) плюс можно сделать такой реквизит чуть более «интеллектуальным», проверять при сложении ключевых полей их строковое «покрытие» друг другом и не дублировать строки при сложении, например:

    Наименование = Стол дубовый

    Код = 00012345;

    Артикул = 12345;

    ПолноеНаименование = Стол дубовый лаковый производство Россия

    КлючАналитикиПоиска = 00012345 Стол дубовый лаковый производство Россия

    Еще можно административно принять в компании шаблон заполнения всех этих полей, написать обработчики на эти поля, шаблон поиска для подстановки в запрос формировать также, как сам ключ. Уже масса вариантов. А пока на «оптимизацию» ну никак не тянет, уж извините

    Reply
  62. spacecraft

    (64) и чем этот индекс поможет в поиске, скажем «стол»? Потребуется искать по Like %стол%. Будет так же полное сканирование всего индекса. А из-за селективности = 1, будет такое же количество записей, как и в самой таблице. Да, тут будет только 1 индекс, но не сильно будет отличаться от просто полного сканирования таблицы.

    Да еще и длины строки может не хватить поместить все выбранные реквизиты.

    Reply
  63. Dach

    (66) именно так, полное сканирование индекса в этом случае. Только там проверка по всем 3 полям, а тут по 1-му. Должно быть быстрее в любом случае. Плюс все-таки сортировка же есть в индексе, а в самой таблице (кластерном индексе) — там сортировка по ссылке. Так что быстрее все-таки будет

    Reply
  64. spacecraft

    (68) сортировка в данном случае (при полном сканировании) не играет никакой роли. Да, Сравнений будет меньше, но принципиальной разницы не получится.

    Reply
  65. Dach

    (69) Вы забываете еще и про статистику, коллега. И касаемо фулл-скана таблицы справочника навряд ли она будет использована, потому что поиск идет не по ссылке. А вот в случае с отдельным реквизитом — да. Согласно документации, статистика создается автоматически при создании индекса и дальше уже заполняется. Так что после ваших нескольких поисков like %стол% — она заполнится и запрос отработает быстрее. Система будет знать, что часто ищут по %стол% и будет знать, какие строки соответствуют этому условию.

    Это конечно требует проверки на практике, но повторюсь — решение то очевидное.

    Reply
  66. spacecraft

    (70)

    статистика создается автоматически при создании индекса и дальше уже заполняется.

    И как поможет тут статистика? Статистика это не еще одна разновидность индекса.

    Reply
  67. Dach

    (71) думаю, что поможет

    Начиная с версии MS SQL 2005:

    «String summary statistics: частота распределения подстрок при анализе символьных полей. Помогает оптимизатору лучше оценивать селективность условий с оператором LIKE.»

    «Объект статистики содержит сводную строковую статистику, позволяющую уточнить оценку количества элементов для предикатов запроса, использующих оператор LIKE, например WHERE ProductName LIKE ‘%Bike’. Сводная строковая статистика хранится отдельно от гистограммы и создается в первом ключевом столбце объекта статистики, если он имеет тип char, varchar, nchar, nvarchar, varchar(max), nvarchar(max), text или ntext.»

    Ссылки на пруфы могу прикрепить, но думаю и сами найдете легко и просто

    Reply
  68. spacecraft

    (72)

    позволяющую уточнить оценку количества элементов для предикатов запроса

    Вот это ни о чем не говорит? Эта статистика нужна оптимизатору плана запросов для выбора таблиц/индекса в котором делать поиск. Т.к. поиск по определению тут невозможен, то будет выбор: или перебор таблицы или индекса. Никакого дополнительного увеличения быстродействия статистика не даст.

    Reply
  69. igordynets

    (45) Спасибо за критику)

    Самое главное — сколько секунд ищется такой конструкцией

    запрос с ПОДОБНО только по одному полю выполнялся после повышения совместимости около 5 секунд

    запрос на равенство — меньше 0,5 секунды.

    и по какому полю чаще всего пользователи ищут

    и если они в большинстве случаев правильно вводят начало слова а я думаю 100% они не ищут по середине — то можно искать по равенству, а не по подобию — это будет 0.5 сек к примеру вместо 5 сек

    то что на равенство будет работать в десятки раз быстрее — сомнений нет)

    По поводу «100% не ищут по середине» — тоже так думали, но вариант с поиском по строке с фиксированным началом не устроил пользователей — искали и по середине тоже, хотя работал он быстрее.

    Reply
  70. Dach

    (73) Логика построения плана согласно статистике — это все хорошо и понятно.

    Вы меня раззадорили. Я не поленился и провел эксперимент.

    У меня есть в тестовой базе документ ЭлектронныйЗаказ. Всего 2 млн строк в таблице документа.

    Вот такой запрос:

    ВЫБРАТЬ
    ЭлектронныйЗаказ.Ссылка КАК Ссылка
    ИЗ
    Документ.ЭлектронныйЗаказ КАК ЭлектронныйЗаказ
    ГДЕ
    ЭлектронныйЗаказ.Комментарий ПОДОБНО «%1%»
    

    В поле «Комментарий» пишут адрес доставки, так что цифра «1» там встречается очень и очень часто.

    1. Вариант 1. Поле Комментарий не индексируется.

    Запрос после прогревания кэша стаблильно отрабатывает за 20 с небольшим секунд. Возвращает 178 тыс. строк.

    План запроса точь в точь как у автора (за небольшим исключением, у меня в базе есть еще разделение данных по общему реквизиту «Организация», так что у меня не scan, а seek индекса (но в данном контексте это не существенно).

    seek кластерного индекса (то есть, по сути — самой таблицы) 99% — параллелизм 1%

    Оптимизатор запроса подсказывает, цитирую:

    /*
    Отсутствуют сведения об индексе из v8_66BC_e7.sqlplan
    Обработчик запросов считает, что реализация следующего индекса может сократить стоимость запроса на 90.1642%.
    */
    
    /*
    USE [KRR]
    GO
    CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
    ON [dbo].[Документ.ЭлектронныйЗаказ] ([Организация],[Комментарий])
    INCLUDE ([Ссылка])
    GO
    */
    

    Показать

    2. Вариант 2. Я включил для поля «Комментарий» — «Индексировать с доп. упорядочиванием».

    Тот же самый запрос. Прогрел кэш. Вернулись те же 178 тыс. строк. Отработало за 1.9 секунды.

    План запроса:

    Поиск в индексе (не-кластерный) 100% — Вложенные циклы (внутреннее соединение) 0%

    Compute scalar 0% ——————————

    Оптимизатор никаких индексов до-создать не советует.

    20+ секунд —> 1.9 секунды.

    Так что данная логика вполне жизнеспособна.

    Не верите — возьмите и повторите, как говорится….

    Надеюсь, звучит убедительно.

    Планы прикладываю.

    Reply
  71. igordynets

    (48) Спасибо Вам за развернутый комментарий. Возьму на заметку некоторые моменты)

    PS: прошу прощения за лишнюю резкость в предыдущем посте.

    Все нормально, к критике отношусь положительно — в ней рождается истина)

    Reply
  72. acanta

    (77) можно ли сделать к тому же комментарию четыре разных поиска с условием или?

    Будут ли они параллельно выполнять чтение?

    Reply
  73. Dach

    (80)

    Да можно конечно, только результат будет такой же как у автора — план разобьет эти ИЛИ на несколько seek-ов и потом будет объединять…

    Будет ли параллельно выполнять — это уж как у вас в БД настроен параллелизм.

    Я поэтому и предложил — «составной» строковый реквизит, грамотно заполненный, с отдельным индексом. Думаю, из исходных 5 секунд можно сделать 0.5

    Reply
  74. spacecraft

    (77) я правильно понял, что эксперимент проводили со строковым реквизитом неограниченной длины? И еще ему и индекс сделали?

    А теперь то же самое с нормальным реквизитом. И не %1%, а более осмысленное типа %стул%. Чтобы приблизить к оригиналу.

    И по поводу кеша. Вот один пользовать делает %стол%, второй %белый стол% и т.д. Какая вероятность попадания в кеш при таком поиске?

    Reply
  75. Dach

    (86) Реквизит имеет ограниченную длину. 150 символов.

    Так что он нормальный. %1% вполне осмысленное в моем случае, так как в этом поле хранится что-то вроде:

    «12345 На деревню дедушке»

    «Москва, улица Мира, д. 134, 345671»

    «Позвонить после обработки по телефону +79991234567»

    и т.д.

    Так что мой эксперимент очень близок к оригиналу. Шаблон %1% как видите — не особо избирательный. И тем не менее, на порядок ускорилось.

    Reply
  76. Dach

    (86) я понимаю Ваш скепсис. В теории сказано, что like не может использовать индексы. И тем не менее — результаты налицо. Я доподлинно не знаю, как это работает. Имеется ввиду — «внутри» операций scan и seek. Может в seek там хэши строк вычисляются и сравниваются, может еще что.

    Для алгоритма какая разница, какой шаблон %стол% или %белый стол%? Я думаю, никакой абсолютно.

    Ради интереса, сделал вот такие шаблоны:

    «%аптека%» 98 тыс строк вернулось

    «%ООО%» 59 тыс срок

    «%стол%» 69 строк

    «%стул%» 0 строк (ну не торгуем мы стульями, уж извините xD)

    «%аптека фарм%» 3 строки

    Везде результаты 1.9-2.1 секунды.

    Я на этом эксперимент закончу, можете повторить при желании и отписаться о результатах

    Reply
  77. ildarovich

    (15) Это очень избыточное решение. (52) — движение в верном направлении, Но еще правильнее выделить из заполненной части строк все возможные «суффиксы». Например, «абракадабра» разобьется на «абракадабра», «бракадабра», «ракадабра», «акадабра», «кадабра», «адабра», «дабра», «абра», «бра», «ра», «а». На слова делить не нужно!

    Тогда обычный индекс легко и быстро поможет находить слова любой нужной длины.

    В общем то, полнотекстовый поиск именно так и устроен. Можно еще про суффиксные массивы и деревья почитать. В Копипастомер, кстати, применяется. Избыточность небольшая — для каждой записи справочника создается в среднем L записей, где — L — средняя длина заполненной части строки. Например, для миллиона записей будет 10 миллионов записей суффикса. В случае (15) таких записей будет гораздо больше — L x L / 2.

    По моему, 5 секунд слишком много, нужно либо полнотекстовый поиск настроить, а если не получится, сделать свой, самодельный. То есть, нужно сосредоточить борьбу не на отрезке 5 — 20 секунд, а 0.1 — 5.

    Reply
  78. acanta

    (93) подскажите пожалуйста, где можно подробнее почитать про полнотекстовый поиск и можно ли в 1с как то его регулировать (соотношение обьем-скорость, обновление), кроме того что отключить и поиск и фоновое задание по его обновлению.

    Reply
  79. for_sale

    (93)

    Не понял, чем эти суффиксы помогут для поиска. В вашем примере «абра» попала в суффиксы, потому что она два раза в слове встречается. Возьмём «туфли женские». Начинаю писать «туф», ни один из суффиксов («уфли женские», «фли женские» и т.п.) мне не поможет в поиске. И опять приходим к десяткам миллионов ненужных данных. При этом если у нас была таблица, где есть:

    «ту» (или «туф») — «туфли женские»
    «ту» (или «туф») — «туфли мужские»
    «бо» (или «бот») — «ботинки женские»
    «бо» (или «бот») — «ботинки мужские»
    

    , то поиск занимал бы миллисекунды. Я реализовывал такой поиск городов. Задача была — реализовать внешнюю обработку на базе на замке, соответственно, реестр хранился в виде текста, извлекался оттуда в соответствие, где ключ — две первые буквы названия, значение — массив всех данных о городах, которые начинаются на эти две буквы. В файле было 250 тысяч строк, первичное кэширование (из файла JSON в соответствие) занимало 4 сек, поиск занимал миллисекунды, пользователь вводил от двух букв и больше и ему показывалась выпадающая подсказка, пользователь вообще не ощущал, что что-то в фоне происходит. А в фоне отбирались первые две буквы, получался соответствующий массив из пары сотен-пары тысяч строк и по нему искалось Подобно «ТоЧтоВвёлПользователь%». А уж если использовать не внешние объекты, которые надо конвертировать, а БД, то там и без кэширования можно обойтись.

    В результате размер индекса или равен размеру справочника, или в 2-3 раза больше (если индексировать начало каждого слова в наименовании). Искать можно только по началу слов, но, повторюсь, в моей практике я ни разу не встречал, чтобы кому-то пришло в голову искать «туфли» как «уфли». Более того, надо, наверное, всерьёз поработать над бизнес-процессами и НСИ, если такая нужда у кого-то возникает. Даже, как тут где-то указывалось, если у меня «Искитимцемент цемент мешок 10 кг», то не знаю, зачем бы я искал «мент» или «шок».

    Поэтому, повторюсь, так и не понял, зачем нужно резать слова на суффиксы.

    Про ПП в 1С пишут, что были глюки и ошибки. Сам я когда-то включал ППИ в базе 1С, но ни разу не дождался, чтобы он построился до конца. Было это довольно давно, но осадочек остался.

    Reply
  80. spacecraft

    (95) не всегда можно уложиться в префикс.

    Пример:

    — пеностирол

    — пенополистирол

    — полистирол

    Как найти их все?

    Reply
  81. for_sale

    (96)

    Давайте определимся — мы говорим о пользователе, который ищет конкретную номенклатуру или об абстрактной ситуации, в которой кому-то, например, для отчёта, понадобилась номенклатура со всякими вхождениями?

    В дин.списках 1С есть поле поиска, которое также может помочь в поиске вхождений. Как и форма поиска. Для описанной вами ситуации вполне подойдёт. Если же мы говорим о ситуации из статьи, когда, например, оператору, нужно подобрать определённую позицию номенклатуры в документ, «пенос» даст первый, «пеноп» даст второй, «поли» третий из ваших элементов. Плюс на «пено» выпадут оба первых, можно будет выбрать вручную.

    Reply
  82. spacecraft

    (97) почему принудительно ограничиваете сценарии поиска номенклатуры? К данному примеру, нужно найти утеплитель разновидности стирол. Какой конкретно (поли- пено- пенополи-) может выбирать заказчик. Тут главное найти их все из доступных и ему показать.

    Если ограничивать только узкими рамками для конкретного сценария, то можно сказать, что нечеткий поиск вообще не нужен. «Мы вот сразу знаем наименование всех номенклатур».

    Reply
  83. for_sale

    (98)

    Сценарии могут быть разные, для разных сценариев могут быть разные подходы.

    Для вашего сценария вообще ничего изобретать не нужно. Подходит интересующийся клиент — «А что у вас из стирола есть?» Менеджер вбивает в типовой поиск «стирол» и получает все вхождения. Время ожидания зависит от базы, пусть даже 20 секунд — это не критично для этого сценария, никто не умрёт. За минуту собрал несколько позиций, показал цену, рассказал о товаре.

    Другой сценарий — сидит оператор, например, на складе, и целый день вбивает в документы номенклатуру. Ему нужны «пенос», «поли», «пеноп». Позицию он хотя бы примерно знает. А может и совсем знает, если вбивает по бумажке, например, или по памяти из частых позиций. Время поиска для него критично, 20 секунд на каждую номенклатуру — это не только невыгодно, но и психически сложно, будет бунт.

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

    Поэтому никакого «ограничения» сценариев нет, есть разумное разделение сценариев по нуждам, реализации и затратам. Если есть какая-то панацея — предлагайте. Конечно, одно решение на все случаи жизни лучше, чем несколько. Если нет, тогда два разных эффективных решения или хотя бы одно эффективное на один сценарий — это лучше, чем полный бардак в ожидании панацеи.

    Reply
  84. spacecraft

    (99)

    Поэтому никакого «ограничения» сценариев нет, есть разумное разделение сценариев по нуждам

    это называется подогнать вопрос под ответ.

    Вариантов «приставок» может быть неограниченное количество. Помнить все довольно трудно. Причем это только для одного корня. А этих ситуаций может быть неограниченное количество. Вот корень слова запомнить проще, чем все возможные «приставки»

    Мы же рассматриваем универсальное решение. Вообще такое решение давно придумано: ППД, но в данном случае его отбросили и изобретают свой велосипед.

    Reply
  85. acanta

    (100) я бы её назвала это полнотекстовым поиском.

    Предположи, товар в базе может называться английскими буквами или начинаться с кавычки, слова, которое обычно не произносимо или сокращения.

    Можно конечно настроить rls, но что если оператор один, а привязки rls к клиенту нет?

    К складу эту роль ограничения rls играют остатки, и то, если они есть.

    Reply
  86. for_sale
    это называется подогнать вопрос под ответ.

    Нет, это называется придумать какую-то задачу, которая не решается данным решением, и с радостью заявить, что решение не решает вообще ничего.

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

    По вашему сценарию, очевидно, нужно другое решение. Вы при этом никакого другого решения не предлагаете, при этом заявляете, что решение совершенно другого сценария плохое, потому что оно не решает ваш сценарий. Ну ок, пойду удалю код у клиента, скажу, что был неправ, на форуме сказали, что решение неправильное.

    Reply
  87. acanta

    (102) скорее это попытка определить, какую задачу решает некое почти универсальное решение.

    Reply
  88. for_sale

    (103)

    Задача описана чуть выше, в первом моём комменте. И потом ещё пару раз повторил описание)

    Reply
  89. spacecraft

    (102) все началось с вашего вопроса: «Не понял, чем эти суффиксы помогут для поиска. В вашем примере «абра» попала в суффиксы, потому что она два раза в слове встречается. Возьмём «туфли женские». Начинаю писать «туф», ни один из суффиксов («уфли женские», «фли женские» и т.п.) мне не поможет в поиске»

    Т.е. вы сами придумали себе свой сценарий и под него все подводите. Обсуждение же было про универсальный поиск.

    Никто не говорил, что ваше решение не имеет права на жизнь. Вы просто влезли в обсуждение универсального решения со своим узкоспециализированным и выдаете его как единственно верное.

    Вы при этом никакого другого решения не предлагаете

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

    Удачи вам. Дальше продолжать общения с вами не вижу смысла.

    Reply
  90. for_sale

    (105)

    Повторюсь, сценарий в статье описывал похожий на мой сценарий. Поэтому я привёл решение своего сценария.

    По суффиксам я не понял тогда и не понимаю сейчас, чем они могут помочь. У нас есть справочник с миллионом строк, по которому поиск осуществляется очень долго. Нам предлагается создать ещё один справочник, больше первого в 10-50 раз, запустить работы по его наполнению и поддержке — резать слова, собирать их по буквенно по 2-3-4-5 и так до скольки?, пересобирать куски при каждом изменении каждой номенклатуры и при создании новой, перестраивать индексы базы по этому монстру каждый раз, а с блокировками что? Это в фоне будет выполняеться? Т.е. новая номенклатура найдётся только завтра, после перелопачивания? Или сегодня подождём полчасика, пока всё перестроится? Ночных операторов нанимать, чтобы днём не дай бог никто номенклатуру не поменял)) А колво букв какое — 10? А если пользователь наберёт 11 букв, то мы ему вывалим критикал эррор и выключим 1С, чтобы не повадно было) Или все буквы сколько есть? Представляю, что за индекс будет там, где номенклатура «Шарикоподшипники самзанные КЛМКПСФНС103443КУППРЕТЫФ Искитимглавшарикоподшипник»))

    Т.е. было предложено решение, которое вроде бы как что-то должно решать, но я пока вижу проблемы и не вижу замеров этого «универсального» решения. Поэтому я и предложил сделать из абстрактного «а давайте искать абракадабру по бре!», который лично я не встречал никогда, более жизненный вариант сценария, с которым работал неоднократно — искать по началу слов.

    Дальше продолжать общения с вами не вижу смысла.

    Постараюсь не сильно реветь от этой потери)) Потому что так хочется на техническом форуме читать обидки, а не технические решения, а тут на тебе, обломали меня))

    Reply
  91. ildarovich

    (95) С алгоритмами на строках часто так — они не очевидны. Вот, например, вы хотите найти все вхождения подстроки в строку. Предполагаю, вы думаете, что нужно по очереди прикладывать подстроку к строке и производить сравнение, то есть тратить N х М операций, где М — длина строки, а N — подстроки. Алгоритм Боурера-Мура (изобретенный, кстати в 1984 году, когда кругом повсюду уже были компьютеры) работает по другому и быстрее. Но это я отвлекся…

    Относительно «туфель». Суффикс здесь не лингвистическое понятие. Я же привел пример: «абракадабра» — слово и «абракадара» — его первый «суффикс». То есть «туфли женские» — слово и «туфли женские» — один из его суффиксов.

    Если вы хотите сэкономить и не хранить «уфли женские» как малоиспользуемое сочетание, то «уф» В ЭТОМ МЕСТЕ тоже зря будет храниться.

    А тут вы сможете найти очень быстро и точно за одно обращение к индексу целые «ботинки женские», а боты, ботильоны и другая ботва будет пропущена.

    Вообще минимизировать число разделяющих признаков можно, если задано множество наименований. Но тут мы не говорим про словарь и его возможные ограничения, тут ведь и артикулы и коды есть, то есть строками считаем произвольный набор символов, где и «уфли» могут какой-то смысл иметь. Не расслышал первую букву, например, в названии улицы или фамилии. Акунин или Окунин — как тут найти? — Пиши «кунин», полнотекстовый поиск его сразу найдет.

    То есть предложенная схема хранит одновременно и единички и двойки и тройки и четверки и так далее и все только храня суффиксы, которых гораздо меньше, чем подстрок.

    Reply
  92. buganov

    (16) не совсем так. Like ЧтоТо% очень хорошо в индекс попадет. А вот, если поставить % в начало, то без вариантов индекс будет сканироваться.

    Reply
  93. buganov

    (14) у Вас в условии ПОДОБНО % в начале. Не важно есть индекс или нет, поиска не будет 100%

    Reply
  94. buganov

    (18) по одному полю с «ИЛИ» 1С нормально ищет в индексе

    Reply
  95. ildarovich

    (89) Если я правильно понял, вы ищете объяснение почему

    В теории сказано, что like не может использовать индексы

    То есть в ваших экспериментах (на «практике») как будто бы получается, что индекс каким-то волшебным образом ускоряет не поиск по началу строки — шаблону типа 1%, как должен в теории, но и по середине строки по шаблону %1% ускоряет тоже, хотя в теории не должен.

    Предложу другое объяснение. Индекс — это файл, содержащий индексируемое поле. Он существенно меньше исходной таблицы. Часто помещается в оперативную память и остается в ней. По этому полный скан этого файла в поиске подстроки будет быстрее как раз настолько, насколько получилось у вас, чем сканирование основной таблицы. То есть не за счет каких-то хитрых структур данных или статистики (???). А за счет меньшего размера файла. А когда в теории говорится, что индекс ускоряет поиск по шаблону 1%, речь идет о более существенном ускорении, чем до 2-х секунд.

    Это можно проверить. Будет интересно проверить тут же зависимость времени от длины подстроки в шаблоне %подстрока%. Зависимость должна быть. Чем длиннее строка, тем быстрее поиск.

    Reply
  96. Dach

    (116)

    Добрый день, Сергей. Да, в теории не должен. В плане не полный скан, а именно поиск в индексе, то есть seek. Мне кажется, просто этот оператор для like работает несколько иначе, чем просто перебор строк и разбор каждой на предмет соответствия условию. А вот как именно он это делает — это я уже не знаю.

    Reply
  97. Dach

    (116)

    Собственно, вот похожие ситуации описаны:

    http://qaru.site/questions/690877/how-can-like-seek-on-an-index

    https://social.msdn.microsoft.com/Forums/sqlserver/ru-RU/232d0f1c-9658-463f-afae-ebbcbcae05c4/how-is-it-possible-to-use-index-seek-for-like-searchstring-case

    В обоих случаях пришли к выводу, что реальную работу выполняет Seek Predicate

    Reply

Leave a Comment

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