#sql-server-2012 #database-metadata #range-partitions
#sql-server-2012 #база данных-метаданные #диапазон-разделы
Вопрос:
У меня есть уникальное требование для поиска минимального / максимального значения из значений диапазона раздела. Идея состоит в том, чтобы увеличить время отклика, запрашивая метаданные, а не саму таблицу.
например, у меня есть таблица, разделенная на рабочие даты. когда я делаю минимальное / максимальное / отдельное количество рабочих дат в таблице — результат не совпадает, когда я пытаюсь применить ту же логику к системной таблице диапазона разделов SQL Server.
Код:
SQL Server, запрос # 1
Select
Min(BusinessDate) min_date,
Max(BusinessDate) max_date,
Count(Distinct BusinessDate) as working_days
From tbl_History
Вывод: min_date = 7/13/2018, max_date = 9/10/2020, working_days = 396
Запрос SQL Server # 2
Select
Object_Name(t.object_id),
Min(lv.value) min_left_val,
Max(lv.value) max_left_val, -- only this matches with Query 1's max date
Min(rv.value) min_right_val, -- checked min value on RIGHT boundary
Max(rv.value) max_right_val, -- checked max value on RIGHT boundary
(DateDiff(dd, Cast(Min(lv.value) As Date), Cast(Max(lv.value) As Date)) 1) - (DateDiff(wk, Cast(Min(lv.value) As Date), Cast(Max(lv.value) As Date)) *2) - (Case When DateName(dw, Cast(Min(lv.value) As Date)) = 'Sunday' Then 1 Else 0 End)
- (Case When DateName(dw, Cast(Min(lv.value) As Date)) = 'Saturday' Then 1 Else 0 End) As working_days -- this is off by a day which is ok
From
sys.partitions p
join
sys.allocation_units au on p.hobt_id = au.container_id
join
sys.indexes i on p.object_id = i.object_id and i.index_id = 1 and p.rows > 0
join
sys.tables t on t.object_id = i.object_id and t.object_id = Object_Id('tbl_History')
join
sys.partition_schemes s on i.data_space_id = s.data_space_id
join
sys.partition_functions f on s.function_id = f.function_id
left join
sys.partition_range_values rv on f.function_id = rv.function_id and p.partition_number = rv.boundary_id
left join
sys.partition_range_values lv on f.function_id = lv.function_id and p.partition_number - 1 = lv.boundary_id
group By
Object_Name(t.object_id)
Вывод:
object_name=tbl_History, min_lv=3/6/2019, max_lv=9/10/2020, min_rv=3/6/2019, max_rv=3/6/2019, working_days=397
—
tbl_History — это ЛЕВЫЙ диапазон, разделенный на нашем конце, и очевидно, что даты вывода между запросом 1 и запросом 2 согласуются только с максимальным значением границы ЛЕВОГО диапазона. Я скорректировал index_id (среди кластеризованных и некластеризованных), а также разделов с номером строки > 0, но это не сильно помогло.
Я хотел бы знать, почему и достижимо ли это (т. Е. Соответствие минимальному значению).
Ответ №1:
То, что вы пытаетесь сделать, невозможно с вашей текущей настройкой, потому что фактическая минимальная дата (2018-07-13) меньше первой границы (2019-03-06).
Чтобы выполнить то, что вы хотите, вам понадобится граница для каждой даты в таблице. С RANGE LEFT
функцией вы можете создать и поддерживать контрольное ограничение, чтобы убедиться, что нет строк меньше первой границы, но вам придется убедиться, что у вас есть границы разделов без пробелов.