Разделы SQL Server: поиск минимального / максимального значения из метаданных (т. Е. sys.partition_range_values), а не из самой таблицы

#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 функцией вы можете создать и поддерживать контрольное ограничение, чтобы убедиться, что нет строк меньше первой границы, но вам придется убедиться, что у вас есть границы разделов без пробелов.