Планы запросов — это просто!

56 Comments

  1. spezc

    В принципе интересно написано)

    Reply
  2. rusmil

    Спасибо, написано очень доступно для понимания

    Reply
  3. DenisCh

    написано живенько, для новичков вполне подойдёт

    Reply
  4. vasilev2015

    я тоже пытался раскрыть тему скорости соединений http://infostart.ru/public/534444/

    Но что-то пошло не так )))

    Надеюсь, Андрею повезет больше. Удачи.

    Reply
  5. Famza
    опять же, в переводе с языка вероятного противника

    Зачет!

    Reply
  6. asved.ru

    Самое главное упущено:

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

    Однако некоторым операторам для возврата первой строки необходимы все строки, возвращаемые предыдущим оператором. Это Sort (Что логично, пока мы не получим последнюю строку, мы не можем завершить сортировку), это для одного из наборов строк — Hash join и т.п.

    Т.е. когда мы видим оператор Sort в запросе динамического списка — можно начинать ругаться не глядя 🙂

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

    Reply
  7. asved.ru

    А вот неплохой доклад по теме:

    https://www.youtube.com/watch?v=4yHc8-Idf-w

    Reply
  8. Evil Beaver

    (6)отчего же упущено? Написано же: на входе одно множество, на выходе — другое. Сортировка сюда подходит.

    Reply
  9. Новиков

    Мне кажется, для 1сника будет интересен также ответ на вопрос: что происходит в субд, когда он жмет F5 (или какую-то другую команду на выполнение) в среде исполнения запроса. По MS SQL такой инфы с нуля я не находил. По PostgreSQL есть шикардосная статья: Путешествие запроса Select через внутренности Постгреса

    Reply
  10. brr

    Спасибо, как раз хотел объяснить дочери (4 класс) реляционные базы, она интересовалась, текст как основа подойдет. «Быстродействие тетеньки из регистратуры» это пять.

    Reply
  11. swimdog

    Статью не читал, но имею сказать по существу) «Наверное, каждый 1С-ник задавался вопросом «что быстрее, соединение или условие в ГДЕ?» или, например, «сделать вложенный запрос или поставить оператор В()»?» — лучше чем проверка разных вариантов практически, ничего нет. Один и тот же запрос на разных базах может работать по разному. Например, в одной базе номенклатуры 1000, а в другой 100000. И хорошо работающий запрос из базы с небольшой номенклатурой будет дико тормозить в другой базе. Но если вы не писатель типовых программ или отраслевых решений, то достаточно замеров времени выполнения на вашей конкретной базе. А для понимания работы запросов советую курсы. Они быстрее помогут разобраться новичкам, как писать текст запросов, чем копание в планах запроса. Это совет, но ни в коем случае не отрицательный отзыв на статью!

    Reply
  12. Evil Beaver

    (11)

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

    Вот это я прямо в рамочку поставлю!

    Reply
  13. FreeArcher

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

    Вобщем очень хорошо информация ложится в голову с такими простыми примерами.

    Автору спасибо!

    Reply
  14. artbear

    (0) Очередная отличная юморная статья от владельца статуэтки Инфостарт 🙂

    Reply
  15. kolya_tlt

    Хорошая статья, но кажется не законченной, так как всё равно нет ответа на поставленной вопрос:

    «что быстрее, соединение или условие в ГДЕ?» или, например, «сделать вложенный запрос или поставить оператор В()»?
    Reply
  16. asved.ru

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

    Reply
  17. asved.ru

    (15) Ответа на этот вопрос не существует: сам вопрос поставлен некорректно.

    Кстати, в случае достаточно простых условий план для этих вариантов будет один и тот же.

    Reply
  18. sommid

    спасибо, ждем-с продолжения

    Reply
  19. swimdog

    (12) 1) Идея была в другом. Сначала набрать основу, как правильно писать запросы, а потом лезть внутрь SQL. Набрать основу проще всего: 1) на курсах 2) читая статьи на ИТС или спецресурсах 3) спрашивая на форумах. Поэтому я предложил сначала получить базу на курсах.

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

    3) Для простых случаев не вижу ничего плохого в использовании замера времени. Вот когда замеры вопроса не решают, тогда да. Тогда и КИП лишним не будет.

    Reply
  20. Evil Beaver

    (14) это не статуэтка, а параллелепипед )

    Reply
  21. swimdog

    Аггрегация

    Reply
  22. starik-2005

    Дочитал до nested loops, пришла мысль, что автор недопонимает, но осилил дочитать до конца, после чего понял, что нужно дочитывать до конца.

    Reply
  23. Evil Beaver

    (22) прочитал комментарий до конца. Два раза, после чего, так и не понял, это была критика или одобрение?

    Reply
  24. starik-2005

    (23)

    это была критика или одобрение?

    Как сказала наш тренер по публичным выступлениям и работе с аудиторией, что если чувства после реплики противоречивые, то однозначно вами манипулируют!

    Reply
  25. HAMMER_59

    Какой кошмар написан про индексы, ведь полно статей на инфостарте, где все правильно расписано.

    «Пользователь захочет записать в середину индекса» придётся всё двигать? Какой ужас.

    Еще в начале статьи написано, что дальше массивов никуда не ушли. А как же STL, как же списки, очереди?

    Индексы хранятся в виде бинарных деревьев: во первых хранятся блоками, где заранее предусмотрено место под вставку, во вторых передвинуть блок в дереве не проблема, проблема — сбалансировать дерево.

    Reply
  26. Evil Beaver

    (25) а вам не пришло в голову, что это необходимое упрощение?

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

    Reply
  27. МимохожийОднако

    Начало статьи было хорошее. Планируется продолжение? Осталось ощущение недосказанного, оборванного вдруг…

    Reply
  28. HAMMER_59

    (26) Может Вам лучше всё-таки узнать как утроены деревья, а не смеяться на тем чего не знаете? Я Вам конкретно указал, что не существует выдуманной Вами проблемы вставки элемента в середину дерева. Списки, деревья, каталоги, очереди — это уже совсем не массивы, про которые Вам рассказали в школе. Стандартная библиотека шаблонов, довольно, кардинально изменила подход в работе с данными.

    Необходимое упрощение? Т.е. эта такая мелочь, что именно с помощью индексов достигается масштабируемость?

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

    Консоль запросов — умеет замерять затраты на отдельные части запроса. Видим, в каком месте проблема, а проблема всегда в одном — не используются индексы. И разбираемся почему не используются, как правило, запрос написан так, что SQL или другой СУБД слишком сложно разобрать запрос. Проблема решается, как правило, дроблением огромного запроса, на несколько мелких.

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

    Подытожим:

    Какой смысл заглядывать в план построения запроса? Чтобы найти узкое место? Так его можно найти намного проще.

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

    Reply
  29. HAMMER_59

    (26)

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

    Для списка мы храним ссылку на первый элемент, в случае пустого списка храним NULL.

    Каждый элемент, хранит

    — Ссылку на данные.

    — Ссылку на следующий элемент списка. Последний элемент хранит NULL.

    В чём проблема вставить элемент в середину списка? Сколько это займёт времени?

    Reply
  30. starik-2005

    (30)

    В чём проблема вставить элемент в середину списка?

    Всегда интересовался, как в таком списке найти некий элемент X. Приведите пример его поиска, отличного от scan.

    Reply
  31. DarkUser

    Спасибо, понравилось!

    Reply
  32. HAMMER_59

    (31)

    На Си со времен института не писал, могу ошибаться в названии объектов.

    Создаём MultiSet, в этот объект добавляем ключ (реквизит по которому будем осуществлять поиск), и ссылку на элемент списка. Собственно индексы подобным образом и работают.

    А поиск по MultiSet очень быстро отработает.

    Говоря языком 1С, то же самое что добавить индекс к таблице значений.

    Reply
  33. starik-2005

    (33)

    А поиск по MultiSet очень быстро отработает.

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

    Дальше Вам надо что-то по кластерному индексу найти. В итоге это уже или скан, что нехорошо, или сик. Второе — это поиск в кластерном индексе (читай — в таблице) по полям этой таблицы, которые уже лежат в неком списке со ссылкой на элементы, которые больше, и на элементы, которые меньше —B-TREE. Так вот и индекс в виде такого дерева хранится, а не в виде мультисета (если, конечно, это обычный индекс, который юзается в 1С, а не gist/hash-индексы, которые в 1С не юзаются).

    Reply
  34. Evil Beaver

    (29)

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

    Я такого не писал. Я писал о невыдуманной мной проблеме вставки в середину файла. И написал, как она решается. Кроме того, сбалансированные деревья я также упомянул.

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

    Поверьте, довольно большой процент «программистов 1С» на собеседованиях не знает даже этого. У них есть мантра «включить индексирование», а что это и зачем, и как вообще выглядит — не знают.

    Reply
  35. Evil Beaver

    (30) проблема вставки в середину списка заключается в поиске середины списка. Мне неизвестно иного способа, кроме сканирования списка.

    Reply
  36. HAMMER_59

    (34)

    Вот есть у Вас тот мультисет — это просто список с хештаблицей к элементам, полагаю.

    Неверно предполагаете, мультисет — это дерево, а дерево это есть частный случай списка.

    Структура списка:

    — Ссылка на данные

    — Следующий элемент

    Структура дерева :

    — Ссылка на данные

    — Левая ветвь

    — Правая ветвь

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

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

    А я пишу про обычное дерево (обычный индекс), и я не вижу никаких проблем в добавление нового элемента в дерево. Да, каждый раз перед записью будет происходить поиск нужного узла дерева, но это не так долго, для глубины дерева в 20 элементов это уже 1 млн значений, и чем больше глубина тем больше разница, т.е. при глубине дерева 30 элементов это уже 1 млрд. значений.

    Да, при количестве элементов в 1 млн, при каждой записи будет осуществлен перебор до 20 элементов (может и с первого раза повезет), но 20 элементов перебрать всяко лучше чем 1 млн.

    Reply
  37. Evil Beaver

    (37) я не совсем понимаю, с чем конкретно вы пытаетесь спорить, и в чем нас убеждаете?

    Reply
  38. HAMMER_59

    (38) Так Вы читайте, а не только пишите и станет всё понятно.

    Не ленивый, повторю ещё раз.

    Почему Вы решили, что запись в индекс происходит долго? Я не вижу никаких оснований, т.к. индекс не что иное как дерево, а дерево это частный случай списка.

    Ну и так по мелочи:

    Я так и не понял зачем лезть в план запроса.

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

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

    Reply
  39. Evil Beaver

    (39)

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

    Поделитесь, пожалуйста, как можно ДОСТОВЕРНО получить сведения о том какая часть запроса отрабатывает медленно, не заглядывая в план запроса. Эмпирически, основываясь на собственном опыте — да можно. Но эта информация будет носить вероятностный характер. План запроса ДОСТОВЕРНО показывает — какая часть запроса работает медленно здесь и сейчас. Вот и вся причина туда заглядывать.

    Reply
  40. artbear

    (42) Сами себе противоречите 🙁

    (39) — Я так и не понял зачем лезть в план запроса.

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

    Если нужно найти узкое место, зачем лезть в план построения запроса? Можно и без этого получить данные какая часть запроса отрабатывает медленно, и сделать соответствующие выводы.
    (42)

    консоль запросов позволяет получить исчерпывающие ответы.



    вывод плана выполнения запроса, а также SQL-текст запроса, сформированного в СУБД. Для СУБД Microsoft SQL Server план выполнения выводится в виде дерева, а для остальных СУБД – в текстовом формате технологического журнала. Для упрощения анализа запросов также предусмотрено два режима отображения текстов запросов: с именами таблиц и колонок СУБД или с именами объектов метаданных и реквизитов конфигурации (только в обработке для «1С:Предприятие» версии 8.3).
    Reply
  41. herfis

    Отличный слог, хорошие статьи. Пишите еще!

    Ссылка на вашу «Под капотом управляемых форм» у меня вообще, можно сказать, в буфере обмена. Раздаю направо и налево.

    Эта тоже хороша, жалко для меня пользы нет. Ждем продолжения 🙂

    Reply
  42. HAMMER_59

    (43)

    Сами себе противоречите 🙁

    В чём Вы видите противоречие?

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

    Консоль позволяет вывести план запроса, и? С чего вы решили что раз позволяет, значит это крайне ценная информация?

    Несерьезно какая-то у Вас тут атмосфера. Показал Вам инструмент, чтобы Вы колесо не изобретали. Сразу все на меня накинулись: «Да как я могу иметь другую точку зрения». У Вас тут что, секта?

    Reply
  43. starik-2005

    (45)

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

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

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

    Reply
  44. JohnyDeath

    Неповторимый слог Андрея, повествующих о, казалось бы,замороченных вещах в очень доступной и простой форме.

    Ты точно будешь удостоен вторым параллелепипедом!

    Reply
  45. Serg O.

    Отлично написано!

    Объяснить сложные вещи простым языком — это дано не каждому.

    На фразе «тут мы приближаемся к быстродействию тетеньки из регистратуры»

    — ржал минут 10, это просто супер!!

    Большой респект автору.

    Reply
  46. Поручик

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

    зы Статуэтка от Инфостарта есть.

    Reply
  47. mvxyz

    Спасибо за статью! Написано живо и доходчиво. Ждем продолжения.

    Reply
  48. JohnConnor

    годнота

    Reply
  49. primara

    Большое спасибо! Наконец-то нашелся автор, который объяснил наглядно и доходчиво! Даже мне все стало понятно) Очень жду продолжения!

    Reply
  50. ArchLord42

    (11) по секрету вам скажу, изучив планы запроса несколько раз, через какое-то время, вы начнете писать запросы, которые будут одинакого быстро работать в разных базах с первого раза! только тссс…

    Reply
  51. ArchLord42

    Статья хороша для тех, кто еще не знаком с планами запроса, жалко ее небыло тогда, когда я проходил курсы на эксперта по 1С, потратил бы меньше времени на осознание 🙂

    Reply
  52. swimdog

    (53) Только недавно пришлось разбираться в плане запросов, так как все остальное себя исчерпало. Но то ли я дурак, то ли лыжа не едут)) Ничем мне не помогла портянка запроса в терминах SQL. Да, я увидел, что совсем криминального там ничего нет, но причины зависания запросов я так и не нашел. В результате максимально выкинул все возможное и ограничив оставшееся через «выразить». Тогда запрос начал работать стабильнее.

    В общем, пока остался при своем мнении, что план запроса последняя мера. По крайней мере для меня, в сегодняшних реалиях.

    Reply
  53. ArchLord42

    (55)

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

    А вообще есть в инете много инфы как работать с планом запроса и профайлером, ну и советую курс от Гилева по подготовке к 1с эксперту, сам его проходил, там очень много посвящено работе с планом запроса и как раз много практических примеров.

    Reply
  54. juker

    (48) Блиц из Зверополиса ))

    Reply
  55. juker

    Статья отличная. Давно не читал технических статей написанных таким живым языком.

    Спасибо автору.

    Reply
  56. starik-2005

    (37)

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

    Да, мультисет — это не просто список, а упорядоченный список, т.е. упорядоченное хранилище кеу->value с прямым и обратным итератором. Вставка и поиск в мультисете — это log2(N), при этом в неупорядоченный список вставить можно за О(1). А для вставки в деревья SQL-базы необходимо записать страницу, в которую вставили данные или индекс, на диск, а т.к. на диск пишется не просто двадцать, допустим, байт индекса, а кластер целиком, то стоимость операции вставки при множестве индексов равна как минимум времени случайной записи такого количества кластеров, которое равно количеству индексов плюс один — сама таблица с данными. При этом если страницы хранения индекса не хватит, то придется на каждый такой индекс и таблицу записать еще по одному кластеру. И если у нас дисковая подсистема допустим выдает 40к IOPS на операциях записи 4к-блоков, то в лучшем случае вставка у на с в индексированную таблицу ограничится этими IOPS деленными на количество индексов + таблица. Из-за этого БД могут эксплуатировать дисковую систему при множественных непоследовательных вставках достаточно сильно, выдавая этакие 1к TPS при записи (тот же pg_bench).

    Reply

Leave a Comment

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