Почему количество обращений к разделам изменяется при запросе внутримесячных записей в разделенной на месяц таблице? - PullRequest
0 голосов
/ 16 октября 2018

У меня есть tbl, который PK'ed на pkey, и имеет следующий DDL раздела:

PRIMARY INDEX ( pkey )
PARTITION BY ( RANGE_N(STRT_DT  BETWEEN '2014-12-31' AND '2020-12-31' EACH 
INTERVAL '1' MONTH ,
NO RANGE),CASE_N( some_cd = 2, some_cd = 3 , some_cd = 11, ... some_cd=199 NO CASE) ); 

Есть 32 some_cds, поэтому, если я выбираю для конкретной даты, я должен ожидать получитьДоступ 33 разделов.Эта часть работает.Но если я сделаю диапазон дат за один месяц, я получу 66 частей.Кроме того, если я выберу период с начала месяца (09-01) до конца месяца (09-30), я получу доступ к 99 разделам.Я не уверен, почему было бы в два или три раза больше доступа к частям, когда все они должны содержаться в одной части месяца, и должны были получить доступ только к 33.

Explain SEL * 
FROM   db.tbl 
WHERE strt_dt between '2018-09-02' and '2018-09-04';

  1) First, we lock db.tbl for read on a reserved
     RowHash in all partitions to prevent global deadlock.

  2) Next, we lock db.tbl for read.

  3) We do an all-AMPs RETRIEVE step from **66 partitions** of
     db.evnt_tbl with a condition of (
     "(db.tbl.STRT_DT <= DATE
     '2018-09-04') AND (db.tbl.STRT_DT >=
     DATE '2018-09-02')") into Spool 1 (group_amps), which is built
     locally on the AMPs.  The size of Spool 1 is estimated with no
     confidence to be 15,582,768 rows (28,046,193,392 bytes).  The
     estimated time for this step is 43.56 seconds.

  4) Finally, we send out an END TRANSACTION step to all AMPs involved
     in processing the request.
  -> The contents of Spool 1 are sent back to the user as the result of
     statement 1.  The total estimated time is 43.56 seconds.

1 Ответ

0 голосов
/ 16 октября 2018

Поскольку вы определили свой раздел RANGE_N на основе даты как

STRT_DT  BETWEEN '2014-12-31' AND '2020-12-31' EACH INTERVAL '1' MONTH

, ваше 1 month разбиение начинается в последний день месяца.Таким образом, выбрав записи из таблицы для полного диапазона месяцев, вы фактически охватите два раздела (66 с дополнительным разделением).

Это похоже на логику, используемую в предложении EXPAND ON, где диапазон дат, используемый для определения периода 1 month, основан на дате начала диапазона дат.

Вы можете убедиться в этом, добавив PARTITION к вашему предложению SELECT, чтобы увидеть, куда извлекается каждая запись.

Например:

CREATE TABLE tmp (pkey INTEGER, somedate DATE)
PRIMARY INDEX (pkey)
PARTITION BY (RANGE_N(somedate BETWEEN DATE '2016-12-31' AND DATE '2017-12-31' EACH INTERVAL '1' MONTH));

INSERT INTO tmp SELECT ROW_NUMBER() OVER (ORDER BY calendar_date), calendar_date FROM Sys_Calendar.calendar WHERE calendar.calendar_date BETWEEN DATE '2016-12-31' AND DATE '2017-12-31';

SELECT tmp.*, PARTITION FROM tmp;

ДляSeptember вы увидите, что вы охватили два раздела (в данном примере 9 и 10):

245 2017-09-01  9
246 2017-09-02  9
247 2017-09-03  9
248 2017-09-04  9
249 2017-09-05  9
250 2017-09-06  9
251 2017-09-07  9
252 2017-09-08  9
253 2017-09-09  9
254 2017-09-10  9
255 2017-09-11  9
256 2017-09-12  9
257 2017-09-13  9
258 2017-09-14  9
259 2017-09-15  9
260 2017-09-16  9
261 2017-09-17  9
262 2017-09-18  9
263 2017-09-19  9
264 2017-09-20  9
265 2017-09-21  9
266 2017-09-22  9
267 2017-09-23  9
268 2017-09-24  9
269 2017-09-25  9
270 2017-09-26  9
271 2017-09-27  9
272 2017-09-28  9
273 2017-09-29  9
274 2017-09-30  10

Чтобы исправить это, заново создайте таблицу и используйте 1-е число месяца, чтобы определить дату началаваш диапазон разбиения:

STRT_DT  BETWEEN '2014-12-01' AND '2020-12-31' EACH INTERVAL '1' MONTH
...