|
Иногда 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) Мурашки это от раздражения периферических нервов. Попейте успокоительного.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |