Имя: Пароль:
1C
1С v8
Иногда SQL удивляет или немного о агрегатных функциях.
, ,
0 H A D G E H O G s
 
18.11.18
19:53
Дня доброго.
Жизнь полна сюрпризов и стереотипов.
Когда-то давно, смотря на план запроса вида

Выбрать
Таблица.ПолеИндексированное как ПолеИдексированное,
Максимум(Таблица.ПолеНеиндексированное как ПолеНеидексированное,
Из Таблица
Где Таблица.ПолеИндексированное=&Отбор
Сгруппировать ПО Таблица.ПолеИндексированное

я увидел длительное время выполнения и 10000 чтений.
Ага, подумал я, операция Максимум() - опасна и ею лучше не грешить.
И сделал зарубку, красный код.

Сегодня у меня возникла ситуация выбрать Первую любую МаркуPDF417 для массива Справок Б. Эту задачу можно было решить либо выборкой одном запросом и группировкой СправокБ по Максимуму() марки, либо запросом в цикле и выбором 1 марки, собственно, вот:
ВЫБРАТЬ
    АСФСостоянияМарок.СправкаБ КАК СправкаБ,
    МАКСИМУМ(АСФСостоянияМарок.МаркаPDF417) КАК МаркаPDF417
ИЗ
    РегистрСведений.АСФСостоянияМарок КАК АСФСостоянияМарок
ГДЕ
    АСФСостоянияМарок.СправкаБ в (&МассивСправокБ)

СГРУППИРОВАТЬ ПО
    АСФСостоянияМарок.СправкаБ

либо вот в цикле
ВЫБРАТЬ ПЕРВЫЕ 1
    АСФСостоянияМарок.СправкаБ КАК СправкаБ,
    АСФСостоянияМарок.МаркаPDF417 КАК МаркаPDF417
ИЗ
    РегистрСведений.АСФСостоянияМарок КАК АСФСостоянияМарок
ГДЕ
    АСФСостоянияМарок.СправкаБ = &МассивСправокБ

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

Однако, стройна теория, мой друг...
Если мы посмотрим структуру индекса, мы увидим, что он отсортирован по возрастанию, и, максимальные значения Марки болтаются где-то вдали от начальной ветки B+ дерева с искомой справкой Б.
Даже если мы заменим Максимум() на Минимум(), мы получим 1 чтение.
Если мы заменим Максимум() на Количество() или КоличествоРазличных() мы получим 19800 чтений, что логично.
Где я не прав?
1 H A D G E H O G s
 
18.11.18
20:04
Все, вопрос снят.
2 H A D G E H O G s
 
18.11.18
20:07
Алгоритм просто проползет до конца субдерева СправкиБ, не перебирая все ветви, а идя по пути в Максимум.
Таким образом, Минимум() использовать оптимальнее.

Если я не прав - ткните.
Нигде не нашел в Инете про это.
3 v77
 
18.11.18
20:26
Я ничо не понял. Я подозреваю, что нужно условия делать и в условиях должны быть индексированные поля. Без условий группировка, максимум, минимум будут сканировать всю таблицу и хоть ты заиндексируйся. Да и деньги индексировать это плохо. Слишком их много в индексе.
4 Sasha_H
 
18.11.18
23:49
Насчет Количество и КоличествоРазличные - это действительно логично! :)

А вот почему решил, что минимум более оптимальнее Максимум. Мне кажется это от сортировки индекса зависит!
5 H A D G E H O G s
 
19.11.18
10:04
(4) Ну индекс в 1С сортируется по возрастанию колонок всегда.
6 Остап Сулейманович
 
19.11.18
10:12
(2) Это о вреде индексирования упорядоченных множеств? Или где?

Так уже давно известно, что индексирование наиболее эффективно для множеств с упорядоченностью типа "белый шум" и наименее эффективно для полностью упорядоченных. За ваши марки не скажу. Но думаю, что они заносятся последовательно? По возрастанию номеров (или ключевого свойства)?
7 Остап Сулейманович
 
19.11.18
10:14
+ (6) Просто нарисуйте двоичное дерево для упорядоченного списка. Получите дерево с одной ветвью. Обход дерева займет времени (теоретически. исключая аномалии реализации) столько же, сколько прямой перебор списка.
8 Остап Сулейманович
 
19.11.18
10:22
+ (7) А вообще - поддержкой агрегатов ИМХО забота прикладного программиста. Поскольку СУБД может поддерживать "на лету" общепринятые агрегаты типа СУММА, МИНИМУМ, МАКСИМУМ... Поддержка агрегатов по выборкам - забота прикладного программиста.
Это конечно не к 1С. Здесь прикладной программист не имеет доступа к хранимкам...
9 H A D G E H O G s
 
19.11.18
10:23
(6) Нет.
(7) Нет.
(8) Нет.
10 H A D G E H O G s
 
19.11.18
10:24
(6) Постарайтесь прочитать ситуацию вдумчиво, не скатываясь к шаблонам в мозгу.
11 Остап Сулейманович
 
19.11.18
10:27
(9) Что "нет"? Вы курс теории БД через окно проходили?
12 H A D G E H O G s
 
19.11.18
10:29
(11) Я его вообще не проходил
13 IVT_2009
 
19.11.18
10:30
Вопрос больше по теме алкоголя. Зачем вам первая марка для справки Б ?
14 H A D G E H O G s
 
19.11.18
10:30
(13) Определить типмарок для справки Б (нетмарок, стараямарка68, новаямарка150)
15 H A D G E H O G s
 
19.11.18
10:32
(11) Вопрос - почему и для функции Минимум() и для функции Максимум() - количество чтений=1. Проход по дереву индекса SQL не считает за чтение?
16 H A D G E H O G s
 
19.11.18
10:34
(11) СправкаБ, для которой я выполняю замеры не лежит в середине списка, тоесть, мы не напарываемся на нее в корне b+ дерева и должны его пройти, вряд ли все прошедшие ветви лежат в одной странице данных SQL. Есть ли возможность узнать, какие страницы данных считывались?
17 Остап Сулейманович
 
19.11.18
10:45
(15) Точно сказать тяжело. Нужно иметь доступ к БД. Но то что видно с первого взгляда :
Пример 1. - Выборка не из источника данных. А из одноэсной таблицы. Потому чтений 1000.
Пример 2 (Максимум) и 2 (Минимум) - выборка из регистра напрямую. И скорее всего агрегаты поддерживаются на уровне СУБД. Если это так - никто не ищет агрегат перебором. В БД указано место хранения минимума и максимума. Потому и нет разницы в количестве чтений.
18 Остап Сулейманович
 
19.11.18
10:47
+ (17) Это как количество записей в таблице ДБФ. Хранится в заголовке. И чтобы взять reccount не нужно перебирать все записи. Аналогично прочие агрегаты.
19 H A D G E H O G s
 
19.11.18
10:47
"В БД указано место хранения минимума и максимума."

Каким образом?
20 Остап Сулейманович
 
19.11.18
10:50
(19) Аналогично количеству записей в таблице ДБФ.
21 nicxxx
 
19.11.18
10:55
(5) Всегда ли? CREATE INDEX ind ON table (field1 DESC) нельзя разве написать?
22 H A D G E H O G s
 
19.11.18
11:17
(20) Есть понимание, что Максимум марки для Справки1 и Максимум марки для Справки2 будут разные - как их хранить то?
23 H A D G E H O G s
 
19.11.18
11:19
(21) Це не справжние индексы 1С.
24 Кирпич
 
19.11.18
11:25
Так в B-дереве одинаково бежать что до самой большой, что до самой маленькой. Сразу с корня прыг и всё.
25 H A D G E H O G s
 
19.11.18
11:27
(24) Корень B дерева начинается с середины диапазона. Так?
26 H A D G E H O G s
 
19.11.18
11:30
(24) Попгрыгать придется не один раз. Сначало ища справку Б, которая у меня лежит ближе к концу диапазона, а потом ища Марку максимума(которая лежит в конце диапазона, а не в середине).
27 H A D G E H O G s
 
19.11.18
11:38
(26) Вот и вопрос - почему прыжки не считаются за чтения?
Вернее, считаются за 1 чтение.
У меня прыжки по некластерному индексу, возможно, SQL в статистику профайлера не учитывает прыжки по индексу (само чтение данных IndexSeek), а учитывает только фактически считанные данные с точки зрения пользователя - сколько он строк таблицы прочитал ? Кто скажет?
28 Кирпич
 
19.11.18
11:43
(27) фиг знает. смотря сколько записей наверное. может там всё на одной странице лежит
29 Сияющий в темноте
 
19.11.18
11:44
Нормализованное дерево,так называемое раскрашенное,да минимум и максимум ищутся примерно одинаково.
Видимо,скуль вам пишет только обращение к данным,а индексы у него внутри и никто не хочет показывать,что у него там.
вообще,если все оптимально,то на первом листе индекса указан весь диапазон от минимума до максимума с делением,сколько влезло.
30 H A D G E H O G s
 
19.11.18
11:51
(28) Порядка 100000.
31 H A D G E H O G s
 
19.11.18
11:53
(29)
"Нормализованное дерево,так называемое раскрашенное,да минимум и максимум ищутся примерно одинаково. "
Полностью согласен, начинаем мы с примерно с середины диапазона, стоимость спуска до минимума и максимума примерно равны.

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

"если все оптимально,то на первом листе индекса указан весь диапазон от минимума до максимума с делением,сколько влезло."

Вот тут нифига не понял.
32 Йохохо
 
19.11.18
12:13
лист с "Справка Б1, Б2" содержит ссылки на нижние листы с заголовками "Б1 пдф 1-1000, Б2 пдф 1-1000" "Б2 пдф 1001-2000"
каску нашел
33 VS-1976
 
19.11.18
13:29
Нужно рассмотреть физически как состоит индекс, алгоритм поиска в составном индексе.

СправкаБ ( к примеру Б )
А
Б ----
В     |
      +
Таблица ссылок на данные
Ссылки на данные ( для oracle rowid )

Таблица ссылок индекса
Указатели в индексе МаркаPDF417 всех связанных со значением Б ( СправкаБ )

Таблица индекса МаркаPDF417 ( часть связанная с Б если небольшая в одном блоке то 1 чтение )

Так как в индекс может быть не перестроен, то в шапке предположительно могут быть данные количества записей всего ( включая удалённые ) тогда поиск макс или мин идёт сразу по индексу к примеру максимум Значение = МаркаPDF417[ 10 записей к примеру всего * N байт занимает 1 запись ( кортеж ) ]

Моё имхо
34 Fram
 
20.11.18
00:07
(2) Только что потестил на таблице с 588 млн записей. Имеем строковую колонку varchar(510) и ascending некластерный индекс по ней. Всего около 2 млн различных значений.
MIN - 0.07 сек
MAX - 0.07 сек
Эти миллисекунды разве стоят заморочки? У твоей системы больше нет узких мест?
35 Fram
 
20.11.18
00:12
ошибся немного - 5.5 млн различных значений
36 H A D G E H O G s
 
20.11.18
00:13
(34) Заморочек стоит мое полное понимание происходящих процессов. Когда я их перестаю понимать - волнуюсь и покрываюсь мурашками.
37 H A D G E H O G s
 
20.11.18
00:14
(34) Как посмотреть, сколько страниц индекса было считано?
38 Fram
 
20.11.18
00:17
(34) поправочка эти миллисекунды похоже уходили на транспорт данных от сервера ко мне. когда сделал
select @s = min(
и
select @s = max(
даже наносекунлы не заняло
39 Fram
 
20.11.18
00:20
хотя наносекунда может и была. SYSDATETIME() только 7 знаков после точки возращает :)
40 rphosts
 
20.11.18
02:46
(2) эээ, индекс - сбалансированное б-дерево, что минимум что максимум должно быть примерно одинаково
41 Провинциальный 1сник
 
20.11.18
07:29
(7) А с чего вы взяли, что СУБД не выполняет эвристическую балансировку дерева при создании? Добавление в порядке последовательного возрастания - весьма частый случай, и логично, что СУБД должна это предусматривать.
42 los_hooliganos
 
20.11.18
08:10
(36) Мурашки это от раздражения периферических нервов. Попейте успокоительного.
AdBlock убивает бесплатный контент. 1Сергей