Меню

11 перечислите ошибки параметризации

По сравнению с ранее разработанными системами 3G радиоинтерфейс LTE обеспечит улучшенные технические характеристики. В частности, в LTE ширина полосы пропускания может варьироваться от 1,4 до 20 МГц (по более ранним источникам – от 1,25 МГц), что позволит удовлетворить потребностям разных операторов связи, обладающих различными полосами пропускания. При этом оборудование LTE должно одновременно поддерживать не менее 200 активных соединений (т.е. 200 телефонных звонков) на каждую 5 МГц ячейку. Также ожидается, что LTE улучшит эффективность использования радиочастотного спектра, т.е. возрастет объем данных, передаваемых в заданном диапазоне частот. LTE позволит достичь внушительных агрегатных скоростей передачи данных – до 50 Мбит/с для восходящего соединения (от абонента до базовой станции) и до 100 Мбит/с для нисходящего соединения (от базовой станции к абоненту) в полосе 20 МГц. При этом должна обеспечиваться поддержка соединений для абонентов, движущихся со скоростью до 350 км/ч. Зона покрытия одной базовой станции – до 30 км в штатном режиме, но возможна работа с ячейками радиусом более 100 км. Поддерживаются многоантенные системы MIMO.

Радиоинтерфейс LTE позиционируется в качестве решения, на которое операторы будут постепенно переходить с нынешних систем стандартов 3GPP и 3GPP2, а его разработка является важным этапом в процессе перехода к сетям четвертого поколения 4G. Фактически спецификация LTE уже содержит большую часть функций, изначально предназначавшихся для систем 4G, поэтому ее иногда именуют «технологией 3,9G».

Но развитие технологии LTE продолжается. Уже разрабатываются спецификации следующего поколения 3GPP Release 10, так называемые LTE-Advanced. На сегодня уже сформулированы основные требования, которым должен будет удовлетворять LTE Advanced. По сути, это требования к стандарту мобильных сетей четвертого поколения (4G):

максимальная скорость передачи данных в нисходящем радиоканале до 1 Гбит/с, в восходящем – до 500Мбит/с (средняя пропускная способность на одного абонента – втри раза выше, чем в LTE);

полоса пропускания в нисходящем радиоканале – 70 МГц, в восходящем – 40 МГц;

максимальная эффективность использования спектра в нисходящем радиоканале – 30 бит/c/Гц, в восходящем – 15 бит/c/Гц (втрое выше, чем в LTE);

полная совместимость и взаимодействие с LTE и другими 3GPP системами.

Для решения этих задач предполагается использовать более широкие радиоканалы (до 100 МГц), ассиметричное разделение полос пропускания между восходящим и нисходящим каналом в случае частотного дуплекса; более совершенные системы кодирования и исправления ошибок;

91

гибридную технологию OFDMA и SС-FDMA для восходящего канала, а также передовые решения в области антенных систем (MIMO).

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

92

Раздел 3. Задачи и методы исследования беспроводных сетей связи

3.1. Постановка задачи исследования беспроводных сетей

Исследование беспроводных сетей, характеризующихся стохастическим характером функционирования, осуществляется с использованием различных моделей и методов в зависимости от класса исследуемой сети, ее особенностей и требований, предъявляемых к качеству ее функционирования. В процессе исследования сети решаются две основные задачи:

анализ свойств системы и формирование рекомендаций для проектирования;

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

Основной целью исследования любых систем является проектирование системы с заданными характеристиками функционирования. Для достижения указанной цели решается множество частных задач с использованием математических моделей разных классов.

На системотехническом уровне можно выделить следующие виды проектирования:

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

2)структурное проектирование, заключающееся в определении состава и требований к параметрам оборудования и топологии сети;

3)структурно-функциональное проектирование.

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

В общем случае ограничения налагаются на средние значения uk

времени задержки (доставки) в сети пакетов класса k = 1, H в виде:

uk uk* ,

(3.1)

где uk* — заданное ограничение; H

количество классов пакетов,

передаваемых в беспроводной сети.

Для мультимедийного трафика важной характеристикой качества передачи аудио и видео данных является вариация или джиттер задержки σ uk , задаваемый в виде ограничения для разных типов трафика ( k = 1, H ) :

93

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

Задача функционального проектирования для ограничений любого вида решается с использованием достаточно простых моделей, в частности базовых моделей с неоднородным трафиком, и состоит в определении стратегии управления неоднородным потоком данных. Задачи структурного и структурно-функционального проектирования предполагают, в общем случае, использование более сложных – сетевых моделей, причем при структурном проектировании предполагается, что стратегия управления трафиком либо задана, либо используется бесприоритетная стратегия FIFO.

При решении задач структурного и структурно-функционального проектирования можно выделить два основных этапа:

определение параметров минимальной конфигурации беспроводной сети, обеспечивающих функционирование сети минимальной стоимости без учета ограничений на время задержки пакетов;

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

3.2.Общие принципы моделирования сложных систем

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

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

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

94

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

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

SIMULA, GPSS, SIMDIS.

Система имитационного моделирования GPSS (General Purpose System Simulator) предназначена для разработки имитационных моделей дискретных систем, например систем и сетей массового обслуживания. В системе GPSS моделируемая система представляется с помощью набора абстрактных элементов, называемых объектами, каждый из которых принадлежит к одному из типов объектов. Объект каждого типа характеризуется определенным способом поведения и набором атрибутов, отражающих его свойства. Например, прибор обслуживания имеет некоторую производительность, выражаемую числом заявок, обрабатываемых им в единицу времени. Сама заявка может иметь атрибуты, учитывающие время ее пребывания в системе, время ожидания в очереди и т.д. Характерным атрибутом очереди является ее текущая длина, наблюдая за которой в ходе работы системы (или ее имитационной модели), можно определить ее среднюю длину за время работы (или моделирования). В языке GPSS определены классы объектов, с помощью которых можно задавать приборы обслуживания, потоки заявок, очереди и т.д., а также задавать для них конкретные значения атрибутов.

Имитационная модель беспроводного транспортного сегмента корпоративной сети позволяет провести оценку вероятностно-временных характеристик (ВВХ) трафика: в частности, трафика реального времени и потокового видео с учетом предъявляемых требований.

3.3.Принципы разработки моделей беспроводных сетей

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

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

Достижение разумного компромисса между простотой модели и ее адекватностью исследуемой системе является одной из сложнейших проблем моделирования.

95

3.3.1. Классификация математических моделей

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

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

1)назначения – структурные, функциональные, структурнофункциональные;

2)характера функционирования исследуемой системы

детерминированные, стохастические;

3)режима функционирования системы – стационарные,

нестационарные.

3.3.2. Параметризация моделей

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

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

параметризации модели.

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

96

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

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

3.4. Базовые модели беспроводных сетей

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

3.4.1.Простейшая модель ресурса

Впростейшем случае в качестве модели некоторого ресурса (устройства) сети, обрабатывающего однородные пакеты, поступающие в сеть в случайные моменты времени, может использоваться одноканальная система массового обслуживания (СМО) с одним обслуживающим прибором (ресурсом) с однородным потоком заявок и накопителем неограниченной емкости.

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

Пусть средний интервал между пакетами равен a, и средняя

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

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

Положим, что пакеты, поступающие к ресурсу, образуют простейший поток с интенсивностью λ = 1/ a , а длительность обработки (передачи) одного пакета распределена по экспоненциальному закону

b

= 1) со средним значением b = θ . Тогда среднее время ожидания в

V

накопителе перед ресурсом и полная задержка пакета определяются как:

w =

ρb

;

u = w + b =

b

.

− ρ

1 − ρ

1

3.4.2. Оценка быстродействия ресурса

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

97

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

Нагрузка y и загрузка ρ устройства определяются соответственно

как:

y = λb = λθ ;

ρ = min( y;1) .

V

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

выполнение условия:

y = λθ < 1, из которого следует: V > λθ .

V

Последнее выражение можно рассматривать как ограничение, налагаемое на быстродействие ресурса (скорость работы устройства) и обеспечивающее отсутствие перегрузок в устройстве. Величина V0 = λθ представляет собой нижнее быстродействие устройства. Если быстродействие устройства будет меньше или равно V0 , то устройство будет перегружено, что приведёт к неограниченному возрастанию длины очереди пакетов перед ресурсом.

Для выбранного быстродействия V средняя задержка пакетов в устройстве:

u =

b

=

Θ

.

(3.4)

1 − ρ

V − λΘ

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

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

u < u* ,

(3.5)

где u

среднее время задержки пакетов в устройстве; u* – заданное

ограничение.

С учетом (3.4) неравенство (3.5) запишется в следующем виде:

θ

< u* ,

V − λθ

откуда получим выражение для оценки быстродействия устройства:

V > λθ + θ . u*

3.4.3. Оценка ёмкости накопителя

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

В общем случае для точного решения этой задачи необходимо знать

закон распределения числа

пакетов

в системе: pk

= Pr(K = k ) –

вероятность нахождения в

системе

ровно k пакетов.

Тогда задача

98

определения ёмкости накопителя формулируется следующим образом: определить ёмкость накопителя Е, при которой вероятность потери поступающих пакетов, то есть вероятность того, что количество пакетов К в системе окажется больше ёмкости Е накопителя, не превысит заданное

значение δ * :

Pr( K

>

E ) ≤ δ * .

E

Очевидно, что Pr(K >

E) = pk

= 1− pk .

k = E +1

k =0

Решая задачу на границе ограничения, получим уравнение для

расчёта минимального значения Е ёмкости накопителя:

pk

= δ * .

(3.6)

k = E +1

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

заявок в системе имеет вид:

pk = ρ k (1 − ρ)

(k = 0,1, 2,…) ,

(3.7)

где ρ = λ b < 1 — загрузка системы.

Подставляя

(3.7) в

(3.6), получим: (1 − ρ )

ρ k = δ * .

После

k = E +1

некоторых преобразований окончательно получим уравнение ρ E +1 = δ * ,

решение которого имеет вид: E =

lgδ *

−1.

lg ρ

обычно задается в виде: δ * = 10n ,

Вероятностное ограничение δ *

где степень n принимает целочисленные значения:

n = 2, 3,….

Тогда

последнее выражение может быть представлено в виде:

n

E = −

+1 .

lg ρ

Как видно из представленных зависимостей, для сохранения заданного уровня потерь заявок ёмкость накопителя существенно должна быть увеличена при увеличении загрузки, начиная со значения ρ = 0,6 . В частности, при увеличении загрузки от значения ρ = 0,8 до значения

ρ= 0,9 ёмкость накопителя должна быть увеличена примерно в 2 раза.

3.4.4.Модели систем с несколькими устройствами

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

1) накопители формируются перед каждым устройством, при этом поступивший пакет случайным образом направляется в один из накопителей; такие системы называются системами с индивидуальными накопителями и моделируются в виде совокупности одноканальных СМО,

99

число которых равно числу устройств и, следовательно, числу накопителей;

2) перед всеми устройствами формируется один общий накопитель, в который заносятся пакеты, при этом пакеты из накопителя на обработку поступают в первое освободившееся устройство; такие системы называются системами с общим накопителем и моделируются в виде многоканальной СМО, в которой число обслуживающих приборов равно числу устройств в системе.

Расчёт характеристик системы с индивидуальными накопителями сводится к расчёту N независимых одноканальных СМО с однородным потоком пакетов, причём разные устройства могут иметь разные быстродействия.

В случае равновероятного распределения пакетов по всем N накопителям, интенсивность их поступления ко всем устройствам системы

одинакова и равна λ = λ . Если при этом все приборы идентичны, то

расчёт характеристик системы сводится к расчёту одной одноканальной СМО, поскольку характеристики всех устройств будут одинаковы. Если разные устройства имеют разные быстродействия, расчёт выполняется для всех N одноканальных СМО.

Расчёт характеристик системы с общим накопителем сводится к расчету многоканальных СМО, содержащих N идентичных обслуживающих приборов (устройств) и накопитель неограниченной ёмкости.

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

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

Нагрузка y

и загрузка ρ системы с несколькими устройствами

определяются соответственно как:

y = λb = λθ ;

ρ = min(

y

; 1) .

V

N

Для того чтобы в системе с несколькими устройствами не было

перегрузок, необходимо выполнение условия: ρ = min( y ; 1) < 1, из

N

которого следует:

NV > λθ .

Полученное выражение можно рассматривать как ограничение, налагаемое на суммарное быстродействие системы, обеспечивающее существование установившегося режима в системе. Величина V0 = λθ представляет собой минимально возможную производительность (суммарное быстродействие) системы. Если суммарное быстродействие системы будет меньше или равно V0 , то в системе возникнут перегрузки,

100

Соседние файлы в папке TBS

  • #
  • #
  • #
  • #
  • #
  • Другие части статьи:
  • 1
  • 2
  • вперед »

Итак, блог sqlCMD.ru продолжает цикл публикаций посвященный такой непростой теме, как параметризация запросов. В статье открывающей данный цикл, Параметризация запросов. Ваш лучший друг? мы выяснили что грамотно и к месту примененный данный механизм способен дать выигрыш в итоговой производительности решения столь значительный, что даже подтвержденный сухими цифрами «до» и «после» он все-равно продолжает выглядеть сказочно-невероятным. Были указали и причины такой «сказочности»: анализ запроса, построение нескольких альтернативных планов исполнения для него, выбор из этих возможных кандидатов «лучшего из лучших» — все это чрезвычайно ресурсоемкие задачи, и даже для современных серверов с их мультипроцессорными «фишками». А поэтому пропуск этих задач целиком дает такой прирост в скорости выполнения запроса, какой невозможно обеспечить никаким наращиванием железа (мы, разумеется, говорим о потенциальном увеличении числа/качества CPU сервера; вложения в, допустим, апгрейд дисковой подсистемы помочь именно в вопросах быстрейшей оптимизации запросов не могут никак просто по определению). Так вот чем покупать коробку новых/дополнительных CPU и загружать их работой, выгоднее (с любой точки зрения) не покупать ничего, а воспользоваться работой уже готовой, в смысле результатами такой предварительной работы. Именно так и поступает параметризация, значительно повышая наши (и наших пользователей) шансы взять «готовую работу» из кэша планов (plan cache), вместо осуществления полной и очень трудоемкой цепочки, где первым звеном является запрос на языке T-SQL, а звеном финальным — идеальный (или близкий к таковому) план исполнения, помещаемый, к слову сказать, опять же в тот же самый кэш планов.

Однако указанная статья открывающая цикл завершалась довольно интригующе. В ее заключительном абзаце было сказано, что параметризация это не только удивительно хорошо, но и в тоже самое время… плохо! 8O Обещалось продолжение, в котором должна была проясниться такая двойственность одного и того же процесса, а так же должны были появиться пояснения, почему мы подчас захотим бороться не за параметризацию, а решительно против нее. Ну и описание методов такой «борьбы против» так же были анонсированы. Автор рад сообщить постоянным и новым своим читателям, что такое продолжение — перед вами. Оно, как представляется автору, имеет и самостоятельную ценность, однако крайне и настойчиво рекомендуется к изучению именно как продолжение упомянутой выше статьи. По крайней мере писалось продолжение с тем расчетом, что все идеи, концепции, принципы и примеры кода приведенные в статье стартовой известны читателю и поняты им в полном объеме. Приятного и познавательного чтения, не забудьте открыть в соседнем окне SQL Server Management Studio. ;)

Темная сторона параметризации.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

USE master
go
CREATE DATABASE [~DB~]
ON PRIMARY (
    NAME = ‘~DB~_Data’,
    FILENAME = ‘c:sqlCMD.ru~DB~.mdf’,
    SIZE = 75 MB,
    MAXSIZE = 75 MB )
LOG ON (
    NAME = ‘~DB~_Log’,
    FILENAME = ‘c:sqlCMD.ru~DB~.ldf’,
    SIZE = 100 MB,
    MAXSIZE = 100 MB )
GO
ALTER DATABASE [~DB~] SET PARAMETERIZATION FORCED
GO
USE [~DB~]
GO
create table T1 (ColID int IDENTITY CONSTRAINT PK_id PRIMARY KEY,
    Vendor varchar(5) not null,
    EquipType varchar(10) not null,
    Phone varchar(32) not null,
    FAX varchar(32) not null,
    eMail varchar(15) not null,
    Comment char(300) not null CONSTRAINT DEF_Comment DEFAULT ‘This is а place for comment…’)
GO
SET NOCOUNT ON
BEGIN TRANSACTION
DECLARE @i int
SET @i=1
WHILE @i<=122000
BEGIN
    INSERT T1 (Vendor, EquipType, Phone, FAX, eMail)
    VALUES  (CASE WHEN @i%100=0 THEN ‘IBM’ ELSE ‘DELL’ END,
            CASE WHEN @i%15=0 THEN ‘Notebook’ ELSE ‘Desktop’ END,
            CASE WHEN @i%100=0 THEN ‘1-800-CALL-TO-IBM’ ELSE ‘1-800-CALL-TO-DELL’ END,
            CASE WHEN @i%100=0 THEN ‘1-800-FAX-TO-IBM’ ELSE ‘1-800-FAX-TO-DELL’ END,
            CASE WHEN @i%100=0 THEN ‘ibm@corp.com’ ELSE ‘dell@corp.com’ END)
    SET @i=@i+1
END
COMMIT TRANSACTION
CREATE NONCLUSTERED INDEX IDX_Vendor ON T1(Vendor)
GO
SELECT Vendor, COUNT(*) AS Cnt FROM T1 GROUP BY Vendor

Что мы имеем «на входе»? Некая табличка T1 по учету компьютерной техники на складе/в офисе. Порядка 120тыс. записей сгенерированных таким образом, что фирма DELL становится нашим генеральным поставщиком (99% нашего оборудования получено от нее). С фирмой же IBM мы якобы сотрудничаем по остаточному принципу (лишь 1% записей). Для горячих поклонников оборудования последней фирмы готовых обидеться на подобный дисбаланс, автор предупреждает: все герои его повествования вымышлены, а совпадения с реально существующими фирмами/персонами случайны. :roll: Тем не менее стартовая диспозиция такова как она есть 99-к-1. Оба вендора поставляют нам и десктоп-машины, и ноутбуки, но доля последних значительно меньше первых. Так же таблица T1 имеет два индекса: кластерный по колонке первичного ключа и не кластерный по колонке как раз таки Vendor. Сама тестовая база данных переведена в режим принудительной авто-параметризации, однако мы для нашего теста выберем не ее, а параметризацию ручную, причем из трех вариантов последней остановимся на системной хранимой процедуре sp_executesql. Поскольку пользователи нашей системы обожают фильтровать свои запросы по колонке Vendor именно она становится целью нашей параметризации:

1
2
3
4
5
6
7
8
9
10
11
12

USE [~DB~]
GO
DBCC FREEPROCCACHE
GO
set statistics io ON
DECLARE @query nvarchar(200)
DECLARE @param nvarchar(200)
SET @query = N
SELECT * FROM T1 WHERE Vendor=@my_param

SET @param = N‘@my_param varchar(5)’
EXEC sp_executesql @query, @param, @my_param = ‘DELL’

Как обычно, для начала очищаем кэш планов — каждый наш опыт должен начинаться с «чистого листа». Далее заказываем отображение сведений о том как каждая из команд нагружает HDD, такая информация нам вскоре пригодится. Затем следует наш параметризированный запрос, причем реализовано все с помощью sp_executesql, как мы и наметили. Если опираться на информацию только из открывающей статьи цикла, то мы потрудились на славу — план будет создан (и связанные с этим процессом многочисленные ресурсы будут потрачены) лишь однажды, в момент первого обращения первого клиента предложившему серверу такой запрос. Все прочие обращения того же или последующих клиентов с тем же запросом будут пользоваться готовым планом полностью пропуская ту самую «ресурсоемкую цепочку». Причем что особенно приятно (по крайней мере это кажется нам приятным к текущей точке повествования) такой пропуск будет осуществлен вне зависимости от значения параметра для фильтрации колонки Vendor, главное что бы сам запрос оставался тем же самым.

Итак, пока мы видим сплошные плюсы от проделанной нами работы. Однако позволим пользователям поработать с нашим «идеальным» запросом. Пусть первый из них запросит оборудование поставленное нашим генеральным партнером, то есть фирмой DELL (последняя строчка последнего скрипта). Для анализа «хорошести» получившегося плана нам нужны 3 вещи:

  • отчет по числу логических считываний. В условиях реального анализа вы, вполне возможно, захотите анализировать и физические чтения тоже. В нашем случае почти наверняка вся база будет в памяти вашей тест-машины после скрипта ее создающего и наполняющего данными. А поэтому для нас этот параметр ничего не даст, он (с вероятностью близкой к 100%) будет равен нулю. Но вот логические чтения — это другое дело, они действительно покажут нам степень (не)оптимальности того или иного запроса;
  • сам план в графическом виде, причем мы предпочтем его актуальную, а не предполагаемую разновидность;
  • так же мы захотим открыть окно свойств (клавиша F4) крайнего левого оператора плана (SELECT). А в этом окне нас будет интересовать свойство Parameter List, а более точно два его «под-свойства»:
    • Parameter Compiled Value — значение параметра с которым план был создан, то есть скомпилирован;
    • Parameter Runtime Value — значение параметра с которым план был исполнен;

Итак, для запроса выбирающего 99% всех строк (фирма DELL) число логических чтений составит 5833, а план/свойство Parameter List будут такими:

01_Parametrization_sample1

Быстрая «прикидка в уме» говорит нам что оптимизатор повел себя зело разумно, не захотев заморочиться с индексом по колонке Vendor. И то сказать: извлеки сначала значения первичных ключей для каждой строки удовлетворяющей фильтру, потом с этими ключами «сгоняй» в кластерный индекс и извлеки значения всех прочих столбцов кроме Vendor и ColID… И это зная, что вернуть нужно весь кластерный индекс за вычетом 1%! Ну так не проще просто отбросить из последнего лишние строки и вернуть оставшиеся? Так и сделано, мы видим полный скан по индексу PK_id (кластерный), что в данном случае, пожалуй, оптимально. Что же до параметра (точнее — до его значения) то пока все очевидно — с DELL план создался, с ним же и исполнился.

Теперь, на сервер заходит второй пользователь, и разбираемый нами запрос уже находится в кэше (и чистить его мы, разумеется, не хотим — иначе зачем нужна параметризация вообще?). Этому пользователю нужен фильтр прямо противоположный, по фирме IBM (1% всех записей), и он так и пишет:

1
2
3
4
5
6
7
8

set statistics io ON
DECLARE @query nvarchar(200)
DECLARE @param nvarchar(200)
SET @query = N
SELECT * FROM T1 WHERE Vendor=@my_param

SET @param = N‘@my_param varchar(5)’
EXEC sp_executesql @query, @param, @my_param = ‘IBM’

На этот раз мы имеем все те же 5833 логических чтений, а так же:

02_Parametrization_sample2

Тут нас уже могут начать терзать смутные подозрения… С учетом, что нам нужно-то всего 1% строк — не разумнее ли зайти именно со стороны индекса по колонке Vendor? Это, конечно, потребует дополнительного обращения к кластерному индексу, но зато «база» для финального резалт-сета будет извлечена практически мгновенно. А так мы пробегаем по всем строкам 99% которых нам просто не нужны… Впрочем, параметризация затевается что бы использовать тот же самый план, из кэша. Мы получили то к чему стремились, не так ли? Значения свойства Parameter List лишь подчеркивают этот факт: запрос был скомпилирован для/под параметр DELL, а исполнен для параметра IBM. Самое главное, мы миновали «ресурсоемкую цепочку», а число логических чтений даже если оно и является суб-оптимальным все еще находится в границах вменяемых значений для запроса подобного толка.

Теперь повторим эксперимент с нуля (то есть начнем вновь с чистого кэша), но только два пользователя посетят наш сервер в обратном порядке. Как ни удивительно, но порядок их посещения имеет колоссальное и даже катастрофическое (для пользователя номер 2) значение. Итак, в этот раз на сервер первым успевает «любитель IBM»:

1
2
3
4
5
6
7
8
9
10
11
12

USE [~DB~]
GO
DBCC FREEPROCCACHE
GO
set statistics io ON
DECLARE @query nvarchar(200)
DECLARE @param nvarchar(200)
SET @query = N
SELECT * FROM T1 WHERE Vendor=@my_param

SET @param = N‘@my_param varchar(5)’
EXEC sp_executesql @query, @param, @my_param = ‘IBM’

В этом случае с планом/Parameter List-ом у нас дела такие:

03_Parametrization_sample3

Так мы и предполагали — для столь незначительного числа извлекаемых строк выгоднее «заход» со стороны IDX_Vendor плюс «добор» информации из кластерного индекса. Число логических чтений так же понижается до 3750 — это, конечно, не на порядок меньше, но и раза в полтора тоже неплохо…

Далее приходит опоздавший «поклонник DELL»:

1
2
3
4
5
6
7
8

set statistics io ON
DECLARE @query nvarchar(200)
DECLARE @param nvarchar(200)
SET @query = N
SELECT * FROM T1 WHERE Vendor=@my_param

SET @param = N‘@my_param varchar(5)’
EXEC sp_executesql @query, @param, @my_param = ‘DELL’

Вы уже догадываетесь что его ждет:

04_Parametrization_sample4

Однако мало кто может предположить всего масштаба постигшей нашего бедолагу катастрофы: вместо 5833 логических чтений его запрос теперь требует… 370124!! :arrow: Это настолько «круто», что разница во времени фильтрации по параметру DELL в первом эксперименте и сейчас видна на достаточно мощной тестовой машине просто визуально! И это при том, что наша тест-таблица содержит 120тыс. строк (что в масштабах SQL Server еще даже не есть «много»), а запрос ими оперирующий является «мега-элементарным». Можете легко себе домыслить как это все безобразие будет смотреться на таблице из 50 млн. строк с запросом на десяток-другой джойнов.

Теперь понимаете где столь дружелюбная (на первый взгляд) параметризация раскладывает «грабли» с очень даже жестким «черенком»? Правильно, в том самом месте, где один и тот же запрос (более точно — план такого запроса) идеально работающий с одним набором данных страшно «лажает» с другим. Кстати говоря, «вьювер» графических планов исполнения студии несколько усугубляет эти самые «грабли», и вместо того что бы помочь вам разобраться с ними успешно «затуманивает» картину. Для рассеивания этого «тумана» исполним две команды второго эксперимента в той же последовательности, но одним пакетом (batch):

1
2
3
4
5
6
7
8
9
10
11
12
13
14

USE [~DB~]
GO
DBCC FREEPROCCACHE
GO
set statistics io ON
DECLARE @query nvarchar(200)
DECLARE @param nvarchar(200)
SET @query = N
SELECT * FROM T1 WHERE Vendor=@my_param

SET @param = N‘@my_param varchar(5)’
EXEC sp_executesql @query, @param, @my_param = ‘IBM’
EXEC sp_executesql @query, @param, @my_param = ‘DELL’
set statistics io OFF

Мы уже знаем, что вторая команда при таком раскладе будет столь чудовищно неэффективна, что говорить о каком-то равенстве по этому показателю с командой первой просто смешно. Это даже не учитывая того простого факта, что первая команда извлекает ~1тыс. строк, а вторая ~120тыс, что само по себе исключает любые рассуждения о равенстве, а тут еще сверх того план «заточенный» под IBM… Тем не менее студия бодро рапортует:

05_Two_queries

То есть вроде как цена/время исполнения двух показанных команд будут приблизительно равны, в то время как на самом деле если вам нужен пример двух команд не имеющих ничего общего по таким показателям, то вы их нашли. Это все проистекает из того, что цифры подчеркнутые на последней иллюстрации вычисляются очень просто. У каждого оператора плана каждой команды входящей в пакет есть показатель Estimated Subtree Cost — сколько «стоит» выполнение этого оператора плюс всех прочих операторов расположенных правее данного в графическом представлении плана. Если мы возьмем указанный показатель для оператора SELECT (самого левого на плане) то это и будет итоговая «стоимость» данной команды пакета. Если команд в пакете всего две (как в нашем случае), то показатель для оператора SELECT первой можно обозначить как ESC1, а для того же оператора второй — ESC2. Тогда первая подчеркнутая на иллюстрации цифра вычисляется так: ESC1*100%/(ESC1+ESC2). А вторая, соответственно, ESC2*100%/(ESC1+ESC2). В данном случае оптимизатор (и студия вслед за ним) «думают», что ESC1=ESC2.

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

Смотреть ответ

Потому, что реальный расчет и оценка производятся только для первой команды (ESC1). При выполнении второй команды (ESC2) этап оценки данных/построения плана полностью пропускается (вы же помните нашу и оптимизатора «мета-задачу»?), а план просто берется из кэша «as is», со всеми своими «потрохами», в том числе и оценочными!

И, соответственно, все честно рассчитав по формуле «выкатывают» нам показанные выше цифры — 50% там, и столько же здесь. Ага, мы «верим»… Отсюда — вывод:

При задействованной для данного запроса параметризации относительный Query cost показываемый в заголовке графического плана может не иметь ничего общего с действительностью. Более-менее адекватную оценку относительных ожидаемых затрат на выполнение запроса можно получить из анализа информации возвращаемой командой SET STATISTICS IO ON.

Проверьте свое понимание материала: Параметризация, как известно из статьи предыдущей, бывает двух классов(автоматическая/ручная), а каждый класс еще дополнительно делится на под-классы в зависимости от конкретной реализации данного механизма (простая/принудительная и sp_executesql/хранимая процедура/на стороне клиента соответственно). «Большая проблема» параметризации описанная в данном разделе статьи имеет универсальную природу или от нее страдают лишь некоторые классы/под-классы? Если вы считаете, что верен второй вариант составьте два списка: механизмов параметризации не подверженных указанной проблеме и механизмов попадающих в зависимость от нее.

Смотреть ответ

«Большая проблема» имеет абсолютно универсальную природу и от нее страдает (и будет продолжать) любой механизм пытающийся воспользоваться планом созданным ранее. Корни проблемы гнездятся исключительно в распределении данных и от конкретной реализации механизма не зависят. Если такое распределение в колонке фильтрации [более-менее] равномерное — все отлично, параметризация ваш лучший друг. Как только распределение имеет «перекос» превышающий определенный порог, а особенно когда неравномерность распределения достигает экстремальных величин (как в нашей таблице T1) — параметризация начинает активно работать не на вас, а против. Интересно отметить, что генеральный подход применяемый SQL Server — по умолчанию все планы кэшируются, а если нам это не нужно надо произвести дополнительные «телодвижения» (о чем, кстати, речь впереди) —говорит нам лишь о том, что с точки зрения создателей движка значительно большее число реальных данных имеют нормальное распределение либо незначительный перекос. Если бы победила та точка зрения, что большинство данных имеет хороший такой перекос в своем распределении — мы бы имели прямо противоположную картину: по умолчанию ничего бы не кэшировалось, а включение плана в кэш было бы опцией, которую следовало бы указывать особо в каждом отдельном случае.

Итак, что мы с вами установили доподлинно к текущей точке материала? А то, что значение параметра передаваемого при первом выполнении параметризированного запроса имеет решающее влияние на дальнейшую судьбу этого запроса, а так же на состояние нервной системы пользователя/пользователей обращающихся с тем же запросом (но с иным значением параметра) во второй, третий и все последующие разы. И это все потому, что оптимизатор не просто строит план запроса, а «затачивает» его под это самое конкретное «первое значение». То есть оптимизатору не просто интересно это самое первое значение, а это именно то чем оптимизатор интересуется чуть ли не в первые микросекунды после получения команды от клиента. То есть это попросту одна из важнейших характеристик всего запроса! И вот такая «замороченность» оптимизатора «первым значением» получила отдельное название — «вынюхивание параметра», это если в дословном переводе (на языке оригинала это будет parameter sniffing). Название довольно точно и емко отразило существующее положение дел в буквально паре слов. Действительно, движок (а точнее один из главных его компонентов — оптимизатор) «набрасывается» на каждый новый запрос «аки гончая» и начинает «обнюхивать» его со всех сторон (и особенно со стороны параметров) пытаясь сообразить «как бы нам с ним, с запросом вашим, половчее тут…».

Теперь слова статьи открывающий данный цикл о том, что иногда вы захотите предпринимать «контр-параметризационные» меры с целью недопущения последней, не должны представляться вам нонсенсом. Если подобных мер не предпринимать, то мы попадаем в зависимость от порядка запросов, как в нашем примере с таблицей T1. Причем даже не важно какой из запросов будет выполнен первым. Или, иначе говоря, не важно какое значение параметра запроса будет предложено на «обнюхивание» серверу первым. Факт в том, что как минимум часть последующих идентичных запросов имеющих иное значение параметра будут исполнены неоптимальным образом, может отличаться лишь степень этой неоптимальности, начиная от «не айс, но сойдет» и заканчивая «это просто ужас».

Давайте резюмируем полученные знания. Мы поняли и осознали:

  • почему мы можем захотеть бороться с параметризацией. Потому что план очень хорошо работающий для значения ‘ab’ параметра @p может быть никуда не годным при смене значения того же параметра на ‘cd’;
  • когда мы можем захотеть бороться с параметризацией. Когда селективность одного значения в колонке фильтрации резко отличается (причем не важно в большую или меньшую сторону) от селективности иных значений в той же колонке. Формальное определение селективности можно найти в части 3-й статьи Density, Selectivity, Cardinality или о чем «думает» оптимизатор. А если сказать тоже самое без «большой науки», то мы можем ожидать проблем когда у нас в целевой таблице строк со значением ‘ab’ в колонке Col1 две штуки, а со значением ‘cd’ в той же колонке много и много больше. Обратите внимание, что если перекос в распределении данных присутствует, но «перекошенная» колонка не участвует в фильтрации запросов пользователей — все отлично, нет причин для беспокойства. Однако нам несомненно будут встречаться колонки типа Vendor из нашей тестовой таблицы и прилагающиеся к ней соответствующие запросы.

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

  • Другие части статьи:
  • 1
  • 2
  • вперед »

Коллеги, доброго времени суток!

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

Задача следующая: занялся построением параметрического семейства приварного стального воротникового фланца для труб, само собой с использованием таблиц поиска.

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

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

После параметризации его, при попытке изменения величины ревит ругается, пишет ошибку: «Зависимости не выполняются».

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

$begingroup$

I’m trying to use the parametrized circuits to run a single model of quantum circuit with different values. Here’s part of my code:

from qiskit import IBMQ
provider = IBMQ.load_account()
sim = provider.backends.ibmq_qasm_simulator
backend = provider.get_backend('ibmq_qasm_simulator')

probsu = []
for i in range(L):

    circuit = circuit.assign_parameters({Ei: EWi[i]})
    circuit = qc(Ei) 
    
    job_manager = IBMQJobManager()
    **MExperiment = job_manager.run(circuit, backend=backend, name='MExperiment')**
    result = MExperiment.result()

    Ta = '1'*N
    counts = result.get_counts(circuit)
    if Ta in counts:
        prob = counts[Ta]/sum(counts.values())
    else:
        prob = 0
    probsu.append(prob) 

Where qc(Ei) is a function of the quantum circuit model. EWi is an array of possible parameters that will be used. An error occurred at the line marked with **. Here’s what qiskit shows me:

CircuitError: "Cannot bind parameters (['Ei']) not present in the circuit."

I’m not exactly sure, but it looks like parameterization requires the label ‘Ei’ to appear in the circuit. However, my circuit function takes the argument to accept some input like Ei. Is there a way I can fix this error? Thanks a lot for your help:)

glS's user avatar

glS

20.7k5 gold badges26 silver badges89 bronze badges

asked Dec 26, 2020 at 5:44

ZR-'s user avatar

$endgroup$

$begingroup$

If you want to create a parametrized quantum circuit in Qiskit, you can do it as follow:

%matplotlib inline
# Importing standard Qiskit libraries
from qiskit import QuantumCircuit, execute, Aer, IBMQ
from qiskit.compiler import transpile, assemble
from qiskit.tools.jupyter import *
from qiskit.visualization import *
from iqx import *
from qiskit.circuit import  ParameterVector
# Loading your IBM Q account(s)
provider = IBMQ.load_account()

param_circuit = QuantumCircuit(4)
params = ParameterVector('a', 4)
for i in range(4):
    param_circuit.ry(params[i], i)
param_circuit.cx(0,1)
param_circuit.cx(2,3)
param_circuit.cx(1,2)
param_circuit.cx(0,1)
param_circuit.cx(2,3)
param_circuit.draw('mpl',style={'name': 'bw'},  scale = 1)

enter image description here

You can pass the parameters in this circuit and update them through a classical optimizer etc.

answered Dec 26, 2020 at 7:28

KAJ226's user avatar

KAJ226KAJ226

13k2 gold badges8 silver badges28 bronze badges

$endgroup$

$begingroup$

I’m trying to use the parametrized circuits to run a single model of quantum circuit with different values. Here’s part of my code:

from qiskit import IBMQ
provider = IBMQ.load_account()
sim = provider.backends.ibmq_qasm_simulator
backend = provider.get_backend('ibmq_qasm_simulator')

probsu = []
for i in range(L):

    circuit = circuit.assign_parameters({Ei: EWi[i]})
    circuit = qc(Ei) 
    
    job_manager = IBMQJobManager()
    **MExperiment = job_manager.run(circuit, backend=backend, name='MExperiment')**
    result = MExperiment.result()

    Ta = '1'*N
    counts = result.get_counts(circuit)
    if Ta in counts:
        prob = counts[Ta]/sum(counts.values())
    else:
        prob = 0
    probsu.append(prob) 

Where qc(Ei) is a function of the quantum circuit model. EWi is an array of possible parameters that will be used. An error occurred at the line marked with **. Here’s what qiskit shows me:

CircuitError: "Cannot bind parameters (['Ei']) not present in the circuit."

I’m not exactly sure, but it looks like parameterization requires the label ‘Ei’ to appear in the circuit. However, my circuit function takes the argument to accept some input like Ei. Is there a way I can fix this error? Thanks a lot for your help:)

glS's user avatar

glS

20.7k5 gold badges26 silver badges89 bronze badges

asked Dec 26, 2020 at 5:44

ZR-'s user avatar

$endgroup$

$begingroup$

If you want to create a parametrized quantum circuit in Qiskit, you can do it as follow:

%matplotlib inline
# Importing standard Qiskit libraries
from qiskit import QuantumCircuit, execute, Aer, IBMQ
from qiskit.compiler import transpile, assemble
from qiskit.tools.jupyter import *
from qiskit.visualization import *
from iqx import *
from qiskit.circuit import  ParameterVector
# Loading your IBM Q account(s)
provider = IBMQ.load_account()

param_circuit = QuantumCircuit(4)
params = ParameterVector('a', 4)
for i in range(4):
    param_circuit.ry(params[i], i)
param_circuit.cx(0,1)
param_circuit.cx(2,3)
param_circuit.cx(1,2)
param_circuit.cx(0,1)
param_circuit.cx(2,3)
param_circuit.draw('mpl',style={'name': 'bw'},  scale = 1)

enter image description here

You can pass the parameters in this circuit and update them through a classical optimizer etc.

answered Dec 26, 2020 at 7:28

KAJ226's user avatar

KAJ226KAJ226

13k2 gold badges8 silver badges28 bronze badges

$endgroup$

1. Прежде чем говорить о параметризации, давайте поговорим о простом скрипте оптимизации.

а. Запрос на удаление нецелевых веб-сайтов

б. Некоторые ненужные ресурсы могут быть удалены: js, png, jpeg, css и т. д.

в. Удалите повторяющиеся запросы

г. Время на размышления может быть временно заблокировано

2. Параметризация скрипта

А. Предполагается, что подготовьте тестовые данные, просто используйте для тестирования веб-сайт бронирования авиабилетов, который поставляется с lr. Я зарегистрировал несколько учетных записей заранее: hyp01,123456; hyp02,123456; hyp03,123456, пароли этих учетных записей.

b、Два способа параметризации:

(1) Здесь мы параметризуем учетную запись и пароль системы входа. После выбора поля, которое необходимо параметризовать, щелкните правой кнопкой мыши кнопку «Заменить параметром», чтобы запустить интерфейс параметризации.

(2) Второй метод заключается в следующем:

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

г. В следующей таблице показаны несколько конфигураций параметризации скрипта:

Метод значения Стратегия обновления результат
последовательный each iteration Обновляйте значение один раз за итерацию, чтобы
each occurrence Значение необходимо обновлять каждый раз, когда оно встречается.
once Всегда используйте только первые полученные данные
случайный each iteration То же, что и выше
each occurrence То же, что и выше
once Какое значение выбирается случайным образом, но каждое значение может использоваться только один раз
уникальный each iteration Обновляйте значение один раз за итерацию, но каждое значение можно использовать только один раз
each occurrence Значение обновляется один раз за запрос, но каждое значение может использоваться только один раз.
once Всегда используйте только одно значение, последнее имеет преимущественную силу.

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

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

е. После добавления данных, как мы можем проверить успешность параметризации? Мы можем использовать функцию lr_output_message для печати и попробовать

Как показано ниже,

Результаты операции следующие:

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • 11 ошибок при бритье ног
  • 11 каковы объективные ошибки фотометрических измерений