powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
40 сообщений из 40, показаны все 2 страниц
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048528
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
... и так, чтобы полученный ряд хорошо ложился в статистики sqlserver.

Сломал голову. Решить не в состоянии, так как теорию вопроса уже забыл (да еще и не знал). Помогите!

Имеется некий набор значений, (n, m, k), который нужно отобразить на ряд целых чисел.
Набор значений k - может меняться, он монотонно растет (очень медленно)
Набор значений n, m - всегда неизменен.

Код: sql
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.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
Select
	*
from
	(
	Values     ( 0  )
	,          ( 1  )
	,          ( 2  )
	,          ( 3  )
	,          ( 4  )
	,          ( 5  )
	,          ( 6  )
	)     n(n)
	cross join
		(
		Values ( 0  )
		,      ( 1  )
		,      ( 2  )
		,      ( 3  )
		,      ( 4  )
		,      ( 5  )
		,      ( 6  )
		,      ( 7  )
		,      ( 8  )
		,      ( 9  )
		,      ( 10 )
		,      ( 11 )
		) m(m)
	Cross join
		(
		Values ( 0  )
		,      ( 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 )
		,      ( 45 )
		,      ( 46 )
		,      ( 47 )
		,      ( 48 )
		,      ( 49 )
		,      ( 50 )
		,      ( 51 )
		,      ( 52 )
		,      ( 53 )
		,      ( 54 )
		,      ( 55 )
		,      ( 56 )
		,      ( 57 )
		,      ( 58 )
		,      ( 59 )
		,      ( 60 )
		) k(k)




Необходимо нарисовать некую функцию x=F(n, m, k), набор х значений которой удовлетворял бы следующим свойствам:
1. Каждому значению (n, m, k) должно соответствовать одно и только одно значение х, и каждому значению х должно соответствовать одно и только одно значение (n, m, k).
2. Набор значений х должен хорошо ложиться в правила формирования статистик mssqlserver, причем преимущественно адекватно должно оцениваться количество наборов с одинаковым k.
Т.е. наборы значений с одинаковым k должны ложиться примерно в один персентиль значений x, с т.з. формирования статистик mssqlserver.
3. Значения x, соответствующие одному k - должны быть интервальными, и не пересекающимися с другими значениями х наборов с другим k.
Т.е. всему множеству (n, m, 60) должен соответствовать некий интервал значений х, например 1...1000, причем никакому другому значению k тот же интервал соответствовать не должен. Т.е. ситуация, когда k = 60 соответствуют значения 1, 3, 5... а k=59 - 2, 4, 6 - недопустима.
4. Набор значений х должен быть максимально компактным. Вместе с тем условия непрерывности на ряд значений х - не накладывается. Т.е., совершенно необязательно, чтобы значения х шли без разрывов и max(x) - min(x) = 5124.
Требуется лишь чтобы по этому набору хорошо строилась статистика, см. п.2.
5. Предположим, у нас есть таблица n, m, k, x рассчитанная.
Значений:
0, 0, 60, х1 - 100
0, 1, 60, х2 - 1 млн.
1, 0, 60, х3 - 1
2, 0, 60, х4 - 10 тыс.
Оптимизатор, при запросе select * from tbl where x = x4 - должен или адекватно оценивать количество строк (10 тыс.), либо полагать их ~ 1 млн.

Возможно, я задаю чересчур жесткие условия, но пока не получается сформулировать с меньшим количеством ограничений...
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048535
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот ведь великие тиоретики...

Код: sql
1.
x=cast(n as varbinary(12)) + cast(m as varbinary(4)) + cast(k as varbinary(4))
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048587
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks222, Неа, не подходит.
Оно не дает int на выходе.
... а хотелось бы вообще smallint, но это мечты.
И гистограмма будет дырявая.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048590
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А у этих n, m, k какие-то пределы есть? никто ж не мешает просто перевести число nmk в десятичную систему счисления. И, раз значения для какой-то переменной, скажем, k, должны лежать плотно - значит. её в старший разряд.

Применительно к показанным значениям, это может быть kmn и, соответственно, (k*12*7 + m*7 + n).
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048595
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster
aleks222, Неа, не подходит.
1. Оно не дает int на выходе.
... а хотелось бы вообще smallint, но это мечты.
И гистограмма будет дырявая.


1. Учиться надо, студент.
2. А чо бы не в bit?
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048597
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aleks222
uaggster
aleks222, Неа, не подходит.
1. Оно не дает int на выходе.
... 2. а хотелось бы вообще smallint, но это мечты.
И гистограмма будет дырявая.


1. Учиться надо, студент.
2. А чо бы не в bit?
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048599
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina
А у этих n, m, k какие-то пределы есть? никто ж не мешает просто перевести число nmk в десятичную систему счисления. И, раз значения для какой-то переменной, скажем, k, должны лежать плотно - значит. её в старший разряд.

Применительно к показанным значениям, это может быть kmn и, соответственно, (k*12*7 + m*7 + n).

Фактически, переделы как раз и озвучены. Количество k может увеличиться на ~10 за несколько лет, количество значений n - на пару-тройку за несколько лет (но можно считать статическим).

Указанный алгоритм не подходит, интервалы получаются не-непрерывные по k, см. п.3.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048602
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks222
uaggster
aleks222, Неа, не подходит.
1. Оно не дает int на выходе.
... а хотелось бы вообще smallint, но это мечты.
И гистограмма будет дырявая.


1. Учиться надо, студент.
2. А чо бы не в bit?

К сожалению, студентом я был 30 лет назад :-(
В bit - хотелось бы, но, к сожалению 5 тыс. значений в трех измерениях в него не поместятся.

Размер имеет значение.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048609
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Подоплека задачи:

Имеется таблица, примерно на миллиард записей.
Каждую запись можно охарактеризовать группой из 3 признаков, в итоге - см. выше.
Хочется сопоставить этим признакам некое число, и использовать его:
1. Как ключ при разбиении на секции
2. Как хеширующий признак при выборках. Именно поэтому важна интервальность, прежде всего - по k, но желательно еще и по n

Сейчас ключ строится как: k*10000 + n * 1000 + m
Но у него совершенно жуткая статистика!
Размах значений в 60 тыс, причем значения разбросаны очень неравномерно.
В результате MSSQLSERVER строит совершенно жуткую гистограмму по этому полю.
Как результат оптимизатор периодически или ударяется в сканирование всего, или рисует нестед лупы, полагая, что для какого-то значения мало записей.
А количество записей с каждым признаком - действительно неравномерное. От 0 до 20-30 млн.
Собственно, поэтому и задача.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048612
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster
aleks222
пропущено...


1. Учиться надо, студент.
2. А чо бы не в bit?

К сожалению, студентом я был 30 лет назад :-(
В bit - хотелось бы, но, к сожалению 5 тыс. значений в трех измерениях в него не поместятся.

Размер имеет значение.


Прогуливал, нибось.

uaggster
Подоплека задачи:

Имеется таблица, примерно на миллиард записей.
Каждую запись можно охарактеризовать группой из 3 признаков, в итоге - см. выше.
Хочется сопоставить этим признакам некое число, и использовать его:
1. Как ключ при разбиении на секции
2. Как хеширующий признак при выборках. Именно поэтому важна интервальность, прежде всего - по k, но желательно еще и по n

Сейчас ключ строится как: k*10000 + n * 1000 + m
Но у него совершенно жуткая статистика!
Размах значений в 60 тыс, причем значения разбросаны очень неравномерно.
В результате MSSQLSERVER строит совершенно жуткую гистограмму по этому полю.
Как результат оптимизатор периодически или ударяется в сканирование всего, или рисует нестед лупы, полагая, что для какого-то значения мало записей.
А количество записей с каждым признаком - действительно неравномерное. От 0 до 20-30 млн.
Собственно, поэтому и задача.


Я фантазий бесплодных люблю громадье...

Ну вставь все свои уникальные k, n, m во вспомогательную таблицу с identity.

Получишь соответствие
( k, n, m ) -> id

И пользуй это id.

ЗЫ. Изобретение непромокаемого пороха на марше.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048619
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks222


Ну вставь все свои уникальные k, n, m во вспомогательную таблицу с identity.

Получишь соответствие
( k, n, m ) -> id

И пользуй это id.

ЗЫ. Изобретение непромокаемого пороха на марше.

Плохая идея. k и n - могут измениться. При этом все признаки пересчитывать?
Т.е. последовательность целых чисел - неустойчиво к изменению количества признаков.

Кроме того - проблемы со статистикой оно никак не решает.
Нужно, чтобы статистика MSSQLSERVER адекватно оценивало количество значений, которое хотя бы соответствует одному k
Т.е., фиг с ним, пусть промахивается при оценке количества для конкретного значения ( k, n, m ). Но пусть оценивает его хотя бы соответствующим количеству значений с определенным k.

А непромокаемый порох давно изобретен.
В виде унитарного патрона :-)
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048623
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot uaggster#22286165]
aleks222


Кроме того - проблемы со статистикой оно никак не решает.
Нужно, чтобы статистика MSSQLSERVER адекватно оценивало количество значений, которое хотя бы соответствует одному k
Т.е., фиг с ним, пусть промахивается при оценке количества для конкретного значения ( k, n, m ). Но пусть оценивает его хотя бы соответствующим количеству значений с определенным k.


Ну так у вас обычный объект статистики по колонке k и будет иметь гистограмму распределения значений.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048653
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff, да, но оно получается слишком грубым приближением.
Я не совсем правильно выразился.
Правильнее так:
Хочется, чтобы оптимизатор правильно оценивал статистику по (k, n, m).
Но уж если по какому то набору это не получается - пусть промахивается, и считает как по диапазону одного значения k, или его подмножеству.
Я понимаю, что 5000 значений в 200 интервалов не уместить, но хоть что-то в этом направлении сделать.

Кроме того ладно, пусть будет "как по k", только поле нужно всё равно кодирующее все 3 признака, и взаимооднозначно.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048689
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster

Имеется некий набор значений, (n, m, k), который нужно отобразить на ряд целых чисел.
Набор значений k - может меняться, он монотонно растет (очень медленно)
Набор значений n, m - всегда неизменен.

Это как позиционная система счисления с разным основанимем в каждом разряде.
Первым делом надо посчитать справочники для m, k и диапазон для n. Допустим
мы знаем что n - bigint (это 2^64 степени). Мощности справочников по m, k - допустим
37 и 61.

Тоесть любой тройке (n, m, k) соотвествует уникальное целое число

Код: sql
1.
offset(n,m,k) = 37 * 61 * n + 61 * M(m) + K(k)



Где M(), K() функции которые декодируют значения m,k (грубо говоря возвращают порядковые номера).

(макс. значение этого отображения будет даже больше чем bigint (2^64 * 37 * 61))

По другим твоим пожеланиям по статистике - сложно... Надо думать.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048706
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mayton, Ненене! Избыточно.
Возможные значения, собственно, перечислены в исходном запросе.
n - максимум 10, сейчас 5, и рост до 10 - в неопределенной перспективе, можно этим пренебречь.
k - 60, максимум - 100 значений.
m - в точности 12 (точнее, 11 и "прочее", так что 12).
Итого в ключе менее 10 тыс. вариантов.
И всё это нормально влазит в smallint. Проблема то как раз в том, чтобы сконструировать это значение таким образом, чтобы по нему нормально создавалась статистика.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048716
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster,

чет я пока не понимаю тогда цели которую вы преследуете.

у вас написано что комбинация (n,m,k) дает всегда уникальное значение.

вам было предложено в виде "хеш-функции" взять бинарное представление, статистика по столбцу binary тоже строится нормально.

Код: sql
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.
45.
46.
47.
48.
49.
50.
use tempdb;

drop table if exists test
create table test(
      n int,
      m int,
      k int,
      fx as cast(n as binary(2)) + cast(m as binary(2)) + cast(k as binary(2))  persisted
)


insert into test
select top (20)
      1,
      1,
      30
from master.dbo.spt_values


insert into test
select top (20)
      1,
      5,
      30
from master.dbo.spt_values


insert into test
select top (50)
      1,
      1,
      60
from master.dbo.spt_values

create statistics fx on test(fx);
update statistics test with fullscan;


select * from sys.stats s
outer apply sys.dm_db_stats_histogram (s.object_id, s.stats_id) h
where s.object_id = object_id('test')

select * from test where fx = cast(1 as binary(2)) + cast(1 as binary(2)) + cast(60 as binary(2)) --estimate 50
select * from test where fx = cast(1 as binary(2)) + cast(5 as binary(2)) + cast(30 as binary(2)) --estimate 50

select * from test where fx = 0x00010001003C option (recompile) --estimate 50
select * from test where fx = 0x00010005001E option (recompile) --estimate 20


drop table test;
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048719
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff,
вам было предложено в виде "хеш-функции" взять бинарное представление, статистика по столбцу binary тоже строится нормально.

На маленьких примерах - всё замечательно работает.
Теперь представьте, что ключей ~ 5000, а количество входов по каждому ключу - от 1 (единицы) до 20 млн.
В среднем - порядка миллиона, но очень неровно.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048721
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster
mayton, Ненене! Избыточно.
Возможные значения, собственно, перечислены в исходном запросе.
n - максимум 10, сейчас 5, и рост до 10 - в неопределенной перспективе, можно этим пренебречь.
k - 60, максимум - 100 значений.
m - в точности 12 (точнее, 11 и "прочее", так что 12).
Итого в ключе менее 10 тыс. вариантов.
И всё это нормально влазит в smallint. Проблема то как раз в том, чтобы сконструировать это значение таким образом, чтобы по нему нормально создавалась статистика.

Почему избыточно? Покажи на практике.

По поводу хешей. Это - самый простой способ отображения - но оно не будет биективно. Тогда надо менять
заголовок этого топика.

По поводу "нормально создавалась статистика". Я не спец в MS-SQL. Я - больше по Oracle.
Но мне не совсем понятно какую цель ты преследуешь. Я тебе дал абсолютно точную и однозначную формулу.
Биекция. Работает в обе стороны. Отображает точку в трехмерном пространстве на число.
Компактное. Я писал о справочниках а не об оригинальных значениях.

Возможно в MS-SQL есть какая-то технология которая по данному целому числу может извлекать знания
из гистограмм. Но мне этот подход кажется сомнительным. Вместо трех гистограмм - у нас будет одна.
Сложная. С пульсациями. Что дальше с ней сделает MSSQL? ХЗ.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048723
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

Возможно в MS-SQL есть какая-то технология которая по данному целому числу может извлекать знания
из гистограмм. Но мне этот подход кажется сомнительным. Вместо трех гистограмм - у нас будет одна.
Сложная. С пульсациями. Что дальше с ней сделает MSSQL? ХЗ.


В том то и дело что ничего.
Если ТС хочет добиться поведения при котором оптимизатор посмотрев объект статистики по любому ключу будет ему выдавать оценку как если бы бы этот самый ключ представлял RANGE_HIGH_KEY значение - то хер.

Лимит шагов в гистограмме 200. точное число строк выдается в виде EQ_ROWS если запрашивается ключ попадающий в RHK.
в случаях если в интервале лежат несколько ключей в расчет будет идти значение AVG_RANGE_ROWS, при этом если в интервале наблюдается сильная дисперсия значений то увы здесь ничего не поделаешь.
здесь только создавать фильтрованные статистики для большей детализации, но автоматом сиквел такую ситуацию не разрулит.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048738
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff
mayton,

Возможно в MS-SQL есть какая-то технология которая по данному целому числу может извлекать знания
из гистограмм. Но мне этот подход кажется сомнительным. Вместо трех гистограмм - у нас будет одна.
Сложная. С пульсациями. Что дальше с ней сделает MSSQL? ХЗ.


В том то и дело что ничего.
Если ТС хочет добиться поведения при котором оптимизатор посмотрев объект статистики по любому ключу будет ему выдавать оценку как если бы бы этот самый ключ представлял RANGE_HIGH_KEY значение - то хер.

Лимит шагов в гистограмме 200. точное число строк выдается в виде EQ_ROWS если запрашивается ключ попадающий в RHK.
в случаях если в интервале лежат несколько ключей в расчет будет идти значение AVG_RANGE_ROWS, при этом если в интервале наблюдается сильная дисперсия значений то увы здесь ничего не поделаешь.
здесь только создавать фильтрованные статистики для большей детализации, но автоматом сиквел такую ситуацию не разрулит.
Ага, примерно этого и хочу, и понимаю, что это - невозможно.
Я понимаю, что 5000 уникальных ключей на 200 интервалов - не отобразишь.
И фильтрованная статистика - не годиться, т.к. она не бывает инкрементальной, а нужна именно инкрементальная.

Я хочу таким образом подобрать значения ключей, чтобы:
1) 1 ключу соответствовал один и только один набор этих трех параметров (n, m, k)
2) При построении статистики по записям с такими ключами статистика вела бы себя, в худшем случае, как построенная по полю k (60 уникальных входов, и в 200 шаговую диаграмму - замечательно укладывается целиком), но, возможно с несколько большей детализацией (т.к. значений k - 60, а шагов в гистограмме - в 3,5 раза больше).
3) При этом чтобы значение ключа было целым числом, а лучше smallint, ибо дорого.
И 4) Можно было достоверно сказать, что диапазон ключа between x1 and x2 - относится к одному и только одному значению k.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048743
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне кажется что тут была неверная постановка. Гистограммы никогда точно и не отражают исходные данные.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048744
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster,

зачем вам инкрементальная? ее гистограммы не используется CE для оценки кол-ва строк.

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

адд: и да, соглашусь с mayton. не имеет смысла гнаться за стопроцентно точной оценкой по гистограммам. потратите больше времени и сил.
можно бороться с какой то конкретной "плохой" оценкой, но это обычно лечится тюнингом запросов нежели изобретением магической палочки
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048746
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Идея с вычислением хэш не такая уж и плохая.
Это хэш можно положить в основу секционирования таблицы, в этом случае компилятор будет иметь довольно точное представление о количестве записей в секции. Я так предполагаю.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048819
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Владислав Колосов
Идея с вычислением хэш не такая уж и плохая.
Это хэш можно положить в основу секционирования таблицы, в этом случае компилятор будет иметь довольно точное представление о количестве записей в секции. Я так предполагаю.

А именно так и сделано уже .
Просто ключ выбран, как мне видится - очень неудачно.
Сейчас он считается как: k*10000 + n * 1000 + m
И это приводит к тому, что набор значений ключа очень "полосатый". Разброс между минимальным значением и максимальным - 600 тыс., и значения ключа, которые соответствуют реальным координатам (n,m,k) - очень "островковые".
Это приводит к тому, что mssqlserver не может построить по нему адекватную гистограмму. Например, выпадают и неверно оцениваются промежутки, соответствующие некоторым k, и он начинает оценивать количество значений, как количество между неким k-3 и k+5 (например), что совсем не в ту степь, т.к., напоминаю, речь идет о миллионах записей.
Поэтому и хочется как то изменить алгоритм построения ключа, чтобы он стал статистически более равномерным, и гистограмма по нему выглядела, ну, как построенная по k в первом приближении. Или чуть более детально, чем по k (в k, напоминаю, 60 уникальных значений, и возможен рост до 100, но не более и не мгновенно, когда-нибудь, короче).

felix_ff статистика должна быть инкрементальной, т.к. таблица пополняется подменой секций. Если на таблице имеется не-инкрементальная статистика - выполнить switch partition не получится.

Я вот думаю, может ключ сделать char(4) и кодировать его значения в 16 или, скажем, 32-ричной системе?
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048852
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster,

хорошо, а если запросы оптимизировать для наибольшей статистики используя подсказку OPTIMIZE FOR и выбрать наибольшее значение?
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40048872
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster,

чтобы секционирование как-то помогало, в запросе должен участвовать ключ секционирования.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40049051
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Владислав Колосов
uaggster,

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

Так он и участвует!
Это тот самый [key]. По нему секционирование и сделано.
И partition elimination тоже выполняется.
Проблема в том, что когда я указываю в запросе [key] = 6001012 (например), сервер оценивает количество записей не равному количеству в секции, а на основе статистике по этому полю, а она - дырявая, см. выше, и частенько полагает количество значений = 1,
Не смотря на то, что секция - полная, и в ней миллионы записей.

OPTIMIZE FOR - хорошая идея, попробую ее.

Кроме того, попробую посмотреть, как будет считаться статистика по такому ключу:
Cast(k as binary(1)) + Cast((n * 16) | Cast(m as binary(1)) as binary(1)) key_bin
Или
Cast(Cast(k as binary(1)) + Cast((n * 16) | Cast(m as binary(1)) as binary(1)) as smallint) key_int

Интересно, что получится.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40049116
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Создал таблицу, на той же самой партишн схема, что и оригинальная таблица, но из 4х столбцов: кластерного индекса (ид строки + ключ партиционирования, старый), ключ small int, ключ binary(2).
Создал статистики по полям.
Удивительно, но получил разные характеристики статистики ключей в виде smallint и binary(2).
Причем существенно разные.
Не смотря на то, что это одни и те же данные в байтовом виде.
Почему так, интересно???
Причем, обратите внимание, в таблице 1437 уникальных значений ключа.
Почему для бинарного ключа другая плотность?
Я специально перепроверил - и там, и там значения, в смысле байтов - одинаковые.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40050515
Gerros
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вам обязательно хранить все строки в одной таблице?

Для ваших данных формулу непрерывной функции уже озвучивали, x = k*7*12 + n*12 + m.
Максимальное значение будет 60*7*12 + 6*12 + 11 = 5123.
В гистограмме 200 шагов, значит нужно сделать 5124/200 + 1 = 26 таблиц. Назовём их s00...s25.
В таблице s00 храним строки для которых 0 <= x <= 199.
В таблице s01 храним строки для которых 200 <= x <= 399.
И так далее.
В каждой таблице делаем поле sx = x % 200, оно всегда в диапазоне [0...199], помещается в tinyint, по нему наверное индекс можно будет построить с детальной гистограммой как вам надо.

Допустим, вам нужно найти строки с набором (k,n,m) = (49,5,1):
x = k*7*12+n*12+m = 4177
s = x / 200 = 20
sx = x % 200 = 177
Здесь s - это номер таблицы.
Соответствуюий запрос будет:
Код: sql
1.
select * from s20 where sx = 177


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

Второй вариант - сделать одну таблицу, но в ней сделать 26 колонок sx00...sx25 и одну колонку s - по ней сделать секционирование.
В "нулевой" секции в колонке sx00 будут значения sx = x % 200, в остальных колонках - null.
В "первой" секции в колонке sx01 будут значения sx = x % 200, в остальных колонках - null. И так далее.
По каждой из этих колонок делаем индекс. Наверное можно будет сделать инкрементный.
Но всё равно будет динамика или специальное приложение:
Код: sql
1.
select * from t where s = 20 and s20 = 177



Функции:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
select
  k = k3*10*10 + k2*10 + k1, n, m,
  x = convert( smallint, (k3*10*10 + k2*10 + k1)*7*12 + n*12 + m),
  s = ((k3*10*10 + k2*10 + k1)*7*12 + n*12 + m) / 200,
  sx= ((k3*10*10 + k2*10 + k1)*7*12 + n*12 + m) % 200
from( values (0),(1),(2),(3),(4),(5),(6)) n(n) --7
cross
join( values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11)) m(m) --12
cross
join( values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) k1(k1) --10
cross
join( values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) k2(k2) --10
cross
join( values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) k3(k3)
where (k3*10*10 + k2*10 + k1)*7*12 + n*12 + m <= 32767
  and k3*10*10 + k2*10 + k1 <= 60
order by k, n, m
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40050528
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Gerros, т.е. не только порезать данные на 5000 секций, но и на ~ 10 таблиц?
Теоретически - возможно, но боюсь оптимизатор с ума сойдет, строя планы по view из секционированных таблиц.
Фишка в том, что выборки считаются по всему набору данных, которые нужно пополнять большими кусками.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40050559
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster,

smallint имеет знак, может поэтому? Длина ключа разная, кроме того.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40050657
Gerros
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster
Gerros, т.е. не только порезать данные на 5000 секций, но и на ~ 10 таблиц?
Теоретически - возможно, но боюсь оптимизатор с ума сойдет, строя планы по view из секционированных таблиц.
Фишка в том, что выборки считаются по всему набору данных, которые нужно пополнять большими кусками.

Либо несколько таблиц, либо несколько полей в одной (возможно секционированной) таблице.
У Вас всего 5124 комбинации ключей. Чтобы гистограмма была точной, нужно чтобы поле содержало не более 200 различных значений.

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

Второй вариант - таблица одна, но в ней 26 полей. Опять-таки гистограмма будет точная. При этом саму таблицу можно секционировать.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40050700
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Владислав Колосов
uaggster,

smallint имеет знак, может поэтому? Длина ключа разная, кроме того.

Три раза перепроверил - это одно и то же значение, если рассматривать бинарное представление. Т.е. я ничего не напутал. Одно и то же число в бинарном виде и в виде smallint в поле дает разную плотность и, гистограмму разную.
Причем, обратите внимание, в таблице 1437 уникальных значений ключа.
Плотность должна быть 1/1437 ~ 0.00006
Какого черта она для бинарного представления в два раза больше???
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40050706
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster,

нет, плотность рассчитана верно - 6.95E-4

А бинарная плотность ровно вдвое выше.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40050709
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Gerros
uaggster
Gerros, т.е. не только порезать данные на 5000 секций, но и на ~ 10 таблиц?
Теоретически - возможно, но боюсь оптимизатор с ума сойдет, строя планы по view из секционированных таблиц.
Фишка в том, что выборки считаются по всему набору данных, которые нужно пополнять большими кусками.

Либо несколько таблиц, либо несколько полей в одной (возможно секционированной) таблице.
У Вас всего 5124 комбинации ключей. Чтобы гистограмма была точной, нужно чтобы поле содержало не более 200 различных значений.

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

Ну, в моем варианте, скорее 60 таблиц, но не суть.
Это было опробовано.
Секционированное представление оказалось даже более "тормознутым", чем секционированная таблица.
Плюс ко всему, если запрос затрагивает несколько секций представления - сервер ошибается (в нашем случае) - еще фатальнее.
Хотя, в принципе, мы не исследовали вариант глубоко - может и прокатить.

Вьюха по таблицам сделает невозможным использование индекса.

Это почему это?
Нормальное секционированное представление. Констрейнт на ключ, по которому осуществляется секционирование, и создание выровненных индексов, по аналогии с секционированной таблицей - и всё нормально используется.
Разумеется ключ секционирования должен участвовать в запросе.
Второй вариант - таблица одна, но в ней 26 полей. Опять-таки гистограмма будет точная. При этом саму таблицу можно секционировать.
Нет это не тот случай.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40050713
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Владислав Колосов, см. статистику по regstamp_bin
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40050719
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster,

по regstamp_int плотность 6.95E-4, по regstamp_bin вдвое выше: 13.8E-4. (Почему?)
1/1437 не ~0.00006, а ~0.0006
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40050770
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Владислав Колосов,
Это я нолик перекрутил, когда ответ печатал. :)
На картинке видно.

Для поля regstamp_int - плотность 1/1437, а для _bin - вдвое выше, не смотря на то, что это одно и то же число, в бинарном представлении.
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40050790
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster,

есть запрос, которым это можно смоделировать? Неохота самому писать :)
...
Рейтинг: 0 / 0
Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
    #40051258
Gerros
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster
Плюс ко всему, если запрос затрагивает несколько секций представления - сервер ошибается (в нашем случае) - еще фатальнее.
Вы изначально в качестве примера целевого запроса приводили
Код: sql
1.
select * from tbl where x = x4

Такой запрос в принципе не может затрагивать больше одной секции. По крайней мере в том варианте секционирования, который предложил я.
Если у Вас другие целевые запросы, можете привести пример?
...
Рейтинг: 0 / 0
40 сообщений из 40, показаны все 2 страниц
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как биективно отобразить множество на ряд целых чисел, как можно компактнее?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]