Greenplum secrets🎩
698 subscribers
38 photos
8 videos
10 files
67 links
The channel about best practice coding for Greenplum / Канал о том как писать оптимальный код в Greenplum. by @smartyru
Download Telegram
Пятничный квиз
Friday quizz
Вы создали таблицу X в PostgreSQL, после чего выполнили команду
Что не будет удалено автоматически ?
Варианты ответа ниже
You created a table X in PostgreSQL, then executed the command
What will not be deleted automatically

Answer options below

create table x (
id integer unique default nextval('my_seq') ); --создание таблицы // create table

alter table x drop column id cascade; -- команда // command
Greenplum secrets🎩
Варианты ответа // Answer options
Поздравляю всех, кто ответил "Последовательность"!
Congratulations to all those whose answer was Sequence - that's right!
👍1
В программе обещают про Greenplum, я зарегался
Forwarded from Lyubov Medvedeva
Делюсь конфой, если кому будет интересно) за качество одного доклада точно ручаюсь, будет выступать мой близкий друг)

https://rshb.sk.jugru.org/
🔥5
Секрет 28 ( Massacre или опять BDSM на мелких таблицах )
Secret 28 (Massacre or BDSM on small tables again)
2 дня охотился за запросом : вчера не было данных во временных табл-ах Y и Z,
сегодня повезло - "поймал данные" и зверушку в ловушку.
Вчера и сегодня запрос падал через 1ч20м на проде со спиллом 37 TB
И если вчера в табл-е Y было 22 млн строк, то сегодня 0.
В Z же вчера и сегодня 3 строки DISTRIBUTED RANDOMLY
Таким образом, Обе оказались без собранной статистики ввиду настроек gp_autostats_mode_in_functions = on_change и gp_autostats_on_change_threshold > 1 млн
и опущенного по умолчанию флага принудительного сбора статы внутри CDC ф-ии.
I've been hunting for a query for 2 days: yesterday there was no data in temporary tables Y and Z,
I was lucky today - I "caught the data" and the animal in a trap.
Yesterday and today the query crashed after 1 hour 20 minutes on production with a 37 TB spill
And if yesterday there were 22 million rows in table Y, today there are 0.
In Z, yesterday and today there are 3 rows DISTRIBUTED RANDOMLY
Thus, both ended up without collected statistics due to the settings gp_autostats_mode_in_functions = on_change and gp_autostats_on_change_threshold > 1 million
and the forced stats collection flag inside the CDC function that was omitted by default.

Дичь: Wild beast
select t1.id,
t1.collection_id,
t1.c_group_prop::text,
coalesce(t1.c_date_beg, '1900-01-01'::date) as c_date_beg,
t1.effective_date,
row_number()
over (partition by t1.c_group_prop, t1.collection_id, t1.effective_date order by t1.id desc) as prop_rn
from (select a.*
from rdv.mart_properties a
join (select b.properties_rk, b.effective_date, max(b.version_id) version_id
from rdv.mart_properties b
where (b.version_id between :1 and :2)
group by b.properties_rk, b.effective_date) c
using (properties_rk, effective_date, version_id)
where 1=1
and a.version_id between :1 and :2) t1
inner join Y t2 on t1.collection_id = t2.collection_id
where 1 = 1
and t1.c_group_prop::text in
(select property_id from Z)

Вскрытие показало, что проблема была именно в справочнике с фиксированным наполнением Z, а не в вот этой вот всей сложной аналитике в основной части как подумали 70% из вас ( проваливших прошлый тест -) )
Будь у Z либо корректный хэш (property_id), либо собранная статистика, либо и то и то, то запрос выполнится за секунды,
при том что в <rdv.mart_properties between :1 and :2> 3 млрд строк.
Забавно, что сегодня после inner join в итоге на in фильтр должно было придти 0 строк, но это не спасло.
Так пусть же ваши запросы всегда бьют точно в цель, и на работе, и в жизни.
Не стесняйтесь мелочиться и быть занудой, похоже это и есть путь к успеху.

The investigation found out that the problem was in the reference table with fixed content Z, and not in all this complex analytics in the main part, as 70% of you thought (who failed the last test -) )
If Z had either a correct hash (property_id), or collected statistics, or both, then the query would be executed in seconds,
given that in <rdv.mart_properties between :1 and :2> there are 3 billion rows.
It's funny that today after inner join 0 rows should have come to the in filter, but it didn't save.
So let your queries always hit the mark, both at work and in life.
Don't be shy about being petty and boring, it seems that this is the path to success.
👍3
This media is not supported in your browser
VIEW IN TELEGRAM
Тот же секрет картинкой - Валентинкой -) Всем добра!
👍2🐳1
Секрет 29 ( Красиво не значит правильно )
Secret 29 (Beautiful does not mean correct)

Давно я вас не утомлял планами! Подвезли новые,
Часто при построении отчета надо передать параметры в запрос: кто-то материализует их в отдельную табл-у, которую встраивает в запрос, что работает не так быстро, как хар-код, а кто-то умудряется из хард-кода сделать "произведение искусства".
Одно из таких попалось на той неделе, где автор обернул параметры в подзапрос, видимо интуитивно полагая, что
это будет работать так же хорошо как и явный хардкод параметров, но не все так просто.

Выяснилось, что в зависимости от структуры табл-ы, из которой читаем данные, можно получить либо Broadcast,
либо Redistribute, как увидим ниже.
It's been a while since I've bothered you with query plans! We've brought new ones,
Often when building a report, you need to pass parameters to a query: someone materializes them in a separate table, which is embedded in the query,
which does not work as fast as a hard code, and someone manages to make a "work of art" out of a hard code.
One of these came across last week, where the author wrapped the parameters in a subquery, apparently intuitively believing that
this would work as well as an explicit hard code of parameters, but it's not that simple.

It turned out that depending on the structure of the table from which we read the data, you can get either Broadcast,
or Redistribute, as we'll see below.


По традиции создадим синтетику, без ключа и без статы:
As usual, let's create synthetics, without a key and stats:
create table tst_1k_nk_dat_no_stat2   WITH (appendonly=true,orientation=column,compresstype=zstd,compresslevel=1)
as select (generate_series(1,1000))::text n_txt;

и выполним запрос: and run query
explain analyze
with data_batch as (
select rn::int8 rn, mdmId::text mdmId, report_dt::date report_dt, report_from_dt::date report_from_dt, report_to_dt::date report_to_dt
from (
values
(0, 10, '2024-01-01', '2023-01-01', '2023-12-31')
) t(rn, mdmId, report_dt,report_from_dt, report_to_dt)
)
select b.rn
,b.report_from_dt
,b.report_to_dt
,b.report_dt
,s0.*
from tst_1k_nk_dat_no_stat2 s0
join data_batch b
on b.mdmId = s0.n_txt

Получили Broadcast горемычный в плане, где тиражируется не 1 строка с параметрами а данные табл-ы:
We received a poor Broadcast where data from table are replicated:
Gather Motion 348:1  (slice2; segments: 348)  (cost=0.00..431.00 rows=1 width=28) (actual time=21.969..29.806 rows=1 loops=1)
-> Hash Join (cost=0.00..431.00 rows=1 width=28) (actual time=18.992..20.031 rows=1 loops=1)
Hash Cond: (((column2)::text) = n_txt)
" Extra Text: (seg152) Hash chain length 1.0 avg, 2 max, using 999 of 524288 buckets."
-> Result (cost=0.00..0.00 rows=1 width=28) (actual time=0.341..0.341 rows=1 loops=1)
-> Result (cost=0.00..0.00 rows=1 width=32) (actual time=0.267..0.267 rows=1 loops=1)
One-Time Filter: (gp_execution_segment() = 152)
-> Result (cost=0.00..0.00 rows=1 width=32) (actual time=0.041..0.041 rows=1 loops=1)
-> Hash (cost=431.00..431.00 rows=1 width=8) (actual time=16.519..16.519 rows=1000 loops=1)
-> Broadcast Motion 348:348 (slice1; segments: 348) (cost=0.00..431.00 rows=1 width=8) (actual time=0.048..16.214 rows=1000 loops=1)
-> Seq Scan on tst_1k_nk_dat_no_stat2 (cost=0.00..431.00 rows=1 width=8) (actual time=0.093..0.098 rows=9 loops=1)
Planning time: 17.846 ms
(slice0) Executor memory: 447K bytes.
" (slice1) Executor memory: 172K bytes avg x 348 workers, 172K bytes max (seg1)."
" (slice2) Executor memory: 4306K bytes avg x 348 workers, 4307K bytes max (seg0). Work_mem: 32K bytes max."
Memory used: 311296kB
Optimizer: Pivotal Optimizer (GPORCA)
Execution time: 101.132 ms


Уменьшим энтропию, задав ключ: Let's reduce the entropy by setting the key:
alter table tst_1k_nk_dat_no_stat2 set distributed by(n_txt)

и выполним запрос снова.
Получим оптимальный план, который ждали:
We get the optimal plan:
Gather Motion 348:1  (slice1; segments: 348)  (cost=0.00..431.00 rows=1 width=28) (actual time=5.109..5.150 rows=1 loops=1)
-> Hash Join (cost=0.00..431.00 rows=1 width=28) (actual time=2.458..3.223 rows=1 loops=1)
Hash Cond: (((column2)::text) = n_txt)
" Extra Text: (seg26) Hash chain length 1.0 avg, 1 max, using 8 of 524288 buckets."
-> Result (cost=0.00..0.00 rows=1 width=28) (actual time=0.105..0.105 rows=1 loops=1)
-> Result (cost=0.00..0.00 rows=1 width=28) (actual time=0.041..0.041 rows=1 loops=1)
-> Result (cost=0.00..0.00 rows=1 width=32) (actual time=0.016..0.016 rows=1 loops=1)
-> Hash (cost=431.00..431.00 rows=1 width=8) (actual time=0.065..0.065 rows=8 loops=1)
-> Seq Scan on tst_1k_nk_dat_no_stat2 (cost=0.00..431.00 rows=1 width=8) (actual time=0.058..0.061 rows=8 loops=1)
Planning time: 12.860 ms
(slice0) Executor memory: 427K bytes.
" (slice1) Executor memory: 4314K bytes avg x 348 workers, 4316K bytes max (seg0). Work_mem: 1K bytes max."
Memory used: 311296kB
Optimizer: Pivotal Optimizer (GPORCA)
Execution time: 11.493 ms

Вернем табл-у в исходное, но соберем стату:
Let's return the table to its original state, but collect the stats:
alter table tst_1k_nk_dat_no_stat2 set distributed randomly;
analyze tst_1k_nk_dat_no_stat2;


В результате исходного запроса попали на Redistribute:
The original query switched to Redistribute:
Gather Motion 348:1  (slice2; segments: 348)  (cost=0.00..431.05 rows=1000 width=23) (actual time=16.175..19.786 rows=1 loops=1)
-> Hash Join (cost=0.00..431.00 rows=3 width=23) (actual time=12.145..13.017 rows=1 loops=1)
Hash Cond: (((column2)::text) = n_txt)
" Extra Text: (seg26) Hash chain length 1.0 avg, 1 max, using 8 of 524288 buckets."
-> Result (cost=0.00..0.00 rows=1 width=28) (actual time=0.182..0.183 rows=1 loops=1)
-> Result (cost=0.00..0.00 rows=1 width=28) (actual time=0.091..0.091 rows=1 loops=1)
-> Result (cost=0.00..0.00 rows=1 width=32) (actual time=0.031..0.031 rows=1 loops=1)
-> Hash (cost=431.00..431.00 rows=3 width=3) (actual time=11.607..11.607 rows=8 loops=1)
-> Redistribute Motion 348:348 (slice1; segments: 348) (cost=0.00..431.00 rows=3 width=3) (actual time=5.425..11.602 rows=8 loops=1)
Hash Key: n_txt
-> Seq Scan on tst_1k_nk_dat_no_stat2 (cost=0.00..431.00 rows=3 width=3) (actual time=0.081..0.086 rows=8 loops=1)
Planning time: 12.717 ms
(slice0) Executor memory: 447K bytes.
" (slice1) Executor memory: 172K bytes avg x 348 workers, 172K bytes max (seg0)."
" (slice2) Executor memory: 4226K bytes avg x 348 workers, 4235K bytes max (seg260). Work_mem: 1K bytes max."
Memory used: 311296kB
Optimizer: Pivotal Optimizer (GPORCA)
Execution time: 63.870 ms


Почему в первом варианте есть One-Time Filter: (gp_execution_segment() = 152) для генерации параметров, а в последнем - нет, не понял, но лучше избегать такого подхода, когда кортеж констант базируется в СТЕ.
Why the first option has One-Time Filter: (gp_execution_segment() = 152) for generating parameters, but the last one doesn't, I don't understand, but it's better to avoid such approach when the constant tuple is based on CTE.
👏3
Секрет 30 (Девиз GUCCI) Secret 30 (GUCCI motto)

Сегодня на проме попалась PL/pgSQL ф-я на 1k строк, которая упорно давала осечку с ошибкой workfile per query size limit exceeded
, генеря каждый раз спилл более 30 TB.

Я прогнал ее под своей учеткой в песочнице и вдруг она сразу отработала без спилла за 10 мин.
Я всегда явно выставляю на мою сессию принудительный сбор статы через set gp_autostats_mode_in_functions = on_no_stats;

Т.к. данный параметр в оригинальной ф-ии установлен не был, я решил проверить, берется ли он из GUC для тех учеток, которые используются в даге (DAG – Directed Acyclic Graph) где выполняется ф-я.
=========================================================================
Today I came across a PL/pgSQL function on 1k lines on PROD, which stubbornly misfired with the error workfile per query size limit exceeded, generating a spill of more than 30 TB each time.
I ran it under my account in the sandbox and suddenly it immediately worked without a spill in 10 minutes.
I always explicitly set forced stats collection for my session via set gp_autostats_mode_in_functions = on_no_stats;
Since this parameter was not set in the original function, I decided to check whether it is taken from GUC for those accounts that are used in the DAG (DAG – Directed Acyclic Graph) where the function is executed.

Запрос
select u.usename, * from pg_db_role_setting x, pg_database d, pg_user u
where x.setdatabase = d.oid
and x.setrole = u.usesysid
and u.usename in ('dtpl-cdm-etl-tec', 'dtpl-cdm-ddl-tec');

выявил, что параметр сбора статистики задан в профиле GUC только для для УЗ dtpl-cdm-etl-tec:
{gp_autostats_mode=on_change,gp_autostats_mode_in_functions=on_change,gp_autostats_on_change_threshold=100000}

А т.к. в этой ф-ии на 100% используются CTAS запросы, т.е. DDL по сути, то выполнялась она под dtpl-cdm-ddl-tec, а значит для нее действует глобальный параметр БД,
который выдает show all, а он запрещает сбор статы (gp_autostats_mode_in_functions=none).
Ну а что бывает с запросами, которые join-ят табл-ы без статы думаю я уже вам все уши прожужжал - с большой вероятностью как фишка ляжет.

Таковы последствия нарушения принципа GUC Continuous Integration - что то не доехало до конфигурации учетки, в итоге - ничего не поехало.

Если верить книге Во имя Гуччи, основатель легендарного дома моды сказал: "Качество помнят еще долго после того, как забывается цена".

Гениально. и ведь это про создание кода тоже. Само написание кода это лишь малая часть затрат, и на коде, написанном на скору руку,
без отрисовки блок-схемы если хотите, без проверки сход-развала, читай настроек профиля GUC в этом случае, далеко не уедешь.
=========================================================================
The query above revealed that the statistics collection parameter is set in the GUC profile only for the dtpl-cdm-etl-tec account:
{gp_autostats_mode=on_change,gp_autostats_mode_in_functions=on_change,gp_autostats_on_change_threshold=100000}

And since this function uses 100% CTAS queries, i.e. DDL in essence, it was executed under dtpl-cdm-ddl-tec, which means that the global DB parameter is in effect for it,
which gives show all, and it prohibits the collection of stats (gp_autostats_mode_in_functions=none).
Well, what happens with queries that join tables without stats, I think I've already told you all about it - most likely it will work out.

These are the consequences of violating the GUC Continuous Integration principle - something didn't make it to the account configuration, and as a result, nothing went.

According to the book In the Name of Gucci, the founder of the legendary fashion house said: "Quality is remembered long after the price is forgotten."

Brilliant. And this is also about creating code. Writing the code itself is only a small part of the costs, and you won't get far with code written in a hurry,
without drawing a block diagram if you like, without checking the wheel alignment, read the GUC profile settings in this case.
👍61
Сорри за оффтоп-)
Forwarded from MarketTwits
🇷🇺#бизнес #россия
Gucci зарегистрировала одноименный бренд в РФ — данные Роспатента
😁4
Праздничный квест.
В табл-е 5 млр строк, в GP 1000 сегментов.
Какой ключ распределения для X в запросе лучше, чем текущий ключ 'b' :

Holiday quest.
There are 5 billion rows in the table, 1000 segments in the GP.
Which distribution key for X in the query is better than the current 'b' :

select a, b, c , deleted_flg, dt_from, dt_to,
min(case when deleted_flg is true then null else dt_from end)
over(partition by a, b) as mn_dt_from
from X
Варианты ответа Options for quiz above
Anonymous Poll
9%
a
57%
ab
34%
DISTRIBUTED RANDOMLY
С праздником, мужики!
🎉4
Ответ на quest.
Еще вчера я бы поверил, что randomly - корректный ответ.
Вот мои доводы, запасайтесь поп корном!

Серия тестов на проде показала, что независимо от ключа, план запроса не меняется, который привожу в оригинале для точности ( cession_deal_rk, credit_deal_rk - это наши a и b в задаче )
Gather Motion 1056:1  (slice1; segments: 1056)  (cost=0.00..1231650.10 rows=5456054272 width=97) (actual time=25171.537..1101746.845 rows=5456054066 loops=1)
-> Result (cost=0.00..65032.75 rows=5166719 width=97) (actual time=88416.959..108735.578 rows=8879058 loops=1)
-> WindowAgg (cost=0.00..64531.58 rows=5166719 width=97) (actual time=88415.738..106450.656 rows=8879058 loops=1)
" Partition By: cession_deal_rk, credit_deal_rk"
-> Sort (cost=0.00..64531.58 rows=5166719 width=96) (actual time=88415.691..98580.905 rows=8879058 loops=1)
" Sort Key: cession_deal_rk, credit_deal_rk"
Sort Method: external merge Disk: 417165856kB
-> Seq Scan on x (cost=0.00..891.35 rows=5166719 width=96) (actual time=7.464..3897.447 rows=8879058 loops=1)
Planning time: 67.970 ms
(slice0) Executor memory: 2000K bytes.
"* (slice1) Executor memory: 50717K bytes avg x 1056 workers, 67008K bytes max (seg240). Work_mem: 48410K bytes max, 1595169K bytes wanted."
Memory used: 540672kB
Memory wanted: 4785705kB
Optimizer: Pivotal Optimizer (GPORCA)
Execution time: 1346019.073 ms


Мой опорный вывод, что шаг Sort Method: external merge в плане выполняет сортировку слиянием отсортированных ранее частей табл-ы на сегментах,
а значит ровно рассыпаная по сегментам табл-а дает на этом шаге оптимальный результат.

В пользу этого говорит следующий факт.
Если выбрать ключом a, табл-а ( в нашем конкретном бизнес кейсе) станет сильно перекошена при максимуме 285 млн строк на сегменте, что
почти на 2 порядка выше среднего на сегмент ~5 млн строк (= 5 млрд сток в табл-е / 1056 сегментов),
В результате запрос валится по тайм-ауту после часа выполнения, тогда как при randomly выполняется меньше минуты.
Иными словами, такое поведение намекает, что сортировка происходит локально сначала именно на сегментах, и не все ее способны вынести.

В исходном коде проекта был обнаружен ключ b, который гораздо ровнее чем a, хотя и далек от равномерного.
Если в цифрах, для ключа по a,b skew составил 0.4, для randomly 0.001, т.е. данные почти без перекоса.
Считали skew как (max tuples(среди всех сегментов) - avg tuples(по всем сегментам)) / max tuples.

Таким образом, ключ оконки в partittion by не имеет значения, и подстраивать под него ключ дистрибуции для больших таблиц я бы не стал.
Конечно, если конкретный ключ дает равномерное распределение, то как вариант - можно оставить его, но универсальный способ - лучше раскидать таблицу по сегментам максимально равномерно.
Но в нашем квесте речь шла о решении конкретной узкой задачи.

Но не все так просто, ибо
я выявил баг с ALTER TABLE SET DISTRIBUTED BY.
Меня удивило, что данная операция смены ключа с a,b в randomly на табл-е в 5 млрд отработала мгновенно (0.2 с) и я решил проверить, все ли тут чисто.

После смены ключа с randomly на a,b ключ честно поменялся.
После отката к randomly (через ALTER TABLE SET x DISTRIBUTED RANDOMLY) ключ поменялся только в метаданных, т.е. pg_get_table_distributedby вернул RANDOMLY,
но по факту skew остался 0.4, вместо ожидаемого отсутствия перекоса.
🐳3
И что хуже, эта фейковая смена ключа в RANDOMLY не отразилась на реальном плане, где при DISTRIBUTED RANDOMLY должен появиться Redistribute:
Gather Motion 1056:1  (slice2; segments: 1056)  (cost=0.00..1233203.18 rows=5456056832 width=97) (actual time=69988.544..1143226.306 rows=5456056682 loops=1)
-> Result (cost=0.00..66585.28 rows=5166721 width=97) (actual time=70230.562..99398.590 rows=9020522 loops=1)
-> WindowAgg (cost=0.00..66084.11 rows=5166721 width=97) (actual time=70229.410..94669.119 rows=9020522 loops=1)
" Partition By: cession_deal_rk, credit_deal_rk"
-> Sort (cost=0.00..66084.11 rows=5166721 width=96) (actual time=70229.304..76381.228 rows=9020522 loops=1)
" Sort Key: cession_deal_rk, credit_deal_rk"
Sort Method: external merge Disk: 417165728kB
-> Redistribute Motion 1056:1056 (slice1; segments: 1056) (cost=0.00..3366.42 rows=5166721 width=96) (actual time=173.046..30055.350 rows=9020522 loops=1)
" Hash Key: cession_deal_rk, credit_deal_rk"
-> Seq Scan on x (cost=0.00..891.35 rows=5166721 width=96) (actual time=23.282..11751.681 rows=5173811 loops=1)
Planning time: 55.041 ms
(slice0) Executor memory: 2044K bytes.
" (slice1) Executor memory: 1839K bytes avg x 1056 workers, 1839K bytes max (seg0)."
"* (slice2) Executor memory: 77215K bytes avg x 1056 workers, 100128K bytes max (seg9). Work_mem: 48410K bytes max, 1620584K bytes wanted."
Memory used: 540672kB
Memory wanted: 4862049kB
Optimizer: Pivotal Optimizer (GPORCA)
Execution time: 1392286.244 ms

Соотв-но, randomly в итоге д.б. не самый эффективный согласно плану.

А теперь сухие цифры рез-тов тестов, 3 прогона CTAS исходного запроса для каждого ключа:
ab:
35 s 877 ms
30 s 125 ms
31 s 277 ms
среднее: 32.426 s

randomly:
35 s 682 ms
34 s 57 ms
27 s 515 ms
среднее: 32.418 s

b:
39 s 936 ms
34 s 546 ms
33 s 234 ms
среднее: 35.905 s

Т.е. ключ ab и randomly показали почти одинаковый рез-т
Ну и чтобы вас совсем добить, скажу , что на DR с большим отрывом победил исходный ключ b, дав по скорости 2.5 мин против 4 мин для ab и 5 5 мин у randomly в среднем на 2х прогонах.
Почему такая аномалия, теряюсь в догадках, но число сегментов на DR втрое меньше.

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

Что интересно, для ключа b и ab план одинаков, т.е. для b GPORCA не счел нужным сделать Redistribute как для RANDOMLY.

В заключение, у меня только один вопрос, почему материализация данных запросов через CTAS работает менее 1 мин, а explain analyze исходного селекта висит более 20 мин.
1👍1🐳1
Вопрос 1
Друзья, призываю в помощь!
Идентичный код прикладной PL/pgSQL ф-ии в 500 строк ( набор SQL запросов ) на одних и тех же данных и одном и том же железе в одной РГ дает сильно разный спилл при повторных запусках , то 20 TB(вчера), то <1(сегодня).
Число строк на выходе ф-ии отличается на 0.01%
Спилл появляется эпизодами, за последниий месяц всплеск спилла был в 4 из 27 запусков ф-ии.
Есть идеи, чем вызван такой разброс ?

Question 1
Friends, I need help!
An identical PL/pgSQL function code of 500 lines (a set of SQL queries) on the same data and the same hardware
in one Resource Group gives a very different spill upon repeated launches, sometimes 20 TB, sometimes less than 1TB.
The number of lines in the output of the function differs by 0.01%
Spill appears sporadically, in the last month it happened 4 times of 27 launches
Any ideas what caused this spread?
Друзья, 5 минут до начала!!!
🔥2
Forwarded from Lyubov Medvedeva
Делюсь конфой, если кому будет интересно) за качество одного доклада точно ручаюсь, будет выступать мой близкий друг)

https://rshb.sk.jugru.org/
👍5🤡1🐳1