блокеры разобраны замером: три стали задачами, один закрыт

- находки 48 и 49: единицы не менялись ни разу; настоящих столкновений 0.65%,
  несравнимых наборов полей нет, тай-брейк берёт меньшее в 96% случаев
- edinicy-metriki-v-razreze закрыт: гипотеза не подтвердилась замером
- тай-брейк отложен до каталога рода агрегации
This commit is contained in:
av
2026-08-01 19:33:47 +03:00
parent 37413bb551
commit 349a227ab1
8 changed files with 211 additions and 165 deletions
+72
View File
@@ -1541,6 +1541,78 @@ type sourceName sourceVersion creationDate startDate endDate value
То есть обе распространённые схемы хранения теряют данные ровно там, где мы это
измерили, а единственная принятая схема дедупликации — это `start`+`end`.
## 48. Единицы метрики на живом потоке не менялись ни разу
Замер по всем 99 доставкам архива: **30 различных метрик, ни у одной единицы не
менялись**. Ни между доставками, ни внутри одной.
Это снимает основание под гипотезой «единицы — часть координаты объекта»: разряд
`метрика + слой + единицы + час` защищал бы от события, которого поток не
производит. Сегодняшнее поведение (сохранённые единицы побеждают, расхождение —
`MergeStats.UnitsConflicts` и `WARN`) правильно ровно тем, что превращает
гипотезу в **наблюдаемое** событие: если единицы когда-нибудь поедут, это будет
видно в логе в тот же день, а не через квартал при сверке с экспортом.
Оговорка, которая остаётся верной и с этим решением: единицы не входят в хеш
содержимого, поэтому доставка с теми же точками и другими единицами уходит по
ветке «ничего не изменилось». При правиле «сохранённое побеждает» это не
расхождение, а то же самое правило, — но если правило когда-нибудь поменяют,
хеш придётся менять вместе с ним.
## 49. Столкновений 0.65%, несравнимых наборов полей нет, тай-брейк системно берёт меньшее
Замер по всем 99 доставкам, ключ — реальный (`метрика + слой + начало + конец`),
сравнение — по канонической форме с округлением до 12 значащих цифр
(находка 30).
| что мерялось | столкновений | из 444 256 |
|---|---|---|
| без слоя в ключе | 53 678 | 12.29% |
| со слоем, побайтово | 47 235 | 10.63% |
| **со слоем, после канонизации** | **2 897** | **0.65%** |
Первая строка меряет не то: без слоя часовая точка сталкивается с минутной, и
это не столкновение, а два разных ряда. Разница между второй и третьей —
дребезг последних разрядов `float64`, то есть **94% побайтовых расхождений
канонизация схлопывает**. Это же и есть независимое подтверждение находки 30:
округление до 12 цифр выбрано верно.
Разложение настоящих 2 897:
| случай | сколько | что делает правило |
|---|---|---|
| наборы полей **сравнимы** (одно надмножество другого) | 981 | правило полноты работает верно |
| наборы полей **равны**, значения разные | 1 916 | срабатывает тай-брейк |
| наборы полей **несравнимы** | **0** | не встречается вовсе |
**Ноль несравнимых наборов** — важный результат: объединение полей при
несравнимых наборах, самая дорогая часть обсуждавшегося правила слияния, на
живом потоке не срабатывает ни разу. Правило полноты сводится к «надмножество
побеждает», и это не упрощение из лени, а измеренная форма данных.
А вот тай-брейк при равной полноте измеримо смещён. Там, где сравнение чисел
определено (1 912 случаев из 1 916), лексикографический порядок канонических
форм выбирает **меньшее значение в 1 847 случаях — 96%**:
```
heart_rate 985
walking_running_distance 562
step_count 509
active_energy 409
basal_energy_burned 385
apple_stand_time 14
```
Четыре метрики из шести — накопительные, которые HAE досчитывает задним числом
(находка 10): там «меньшее» это систематический недосчёт, порядка 0.4%
координат. Но самая крупная группа, `heart_rate`, — мгновенная, и там «большее»
не правильнее, там просто пересэмплирование.
Отсюда вывод, которого не было до замера: **правильный тай-брейк зависит от
рода метрики**, а род по замыслу проекта измеряется сверкой слоёв между собой.
Значит выбирать тай-брейк до каталога рода агрегации — значит угадывать ровно
то, что через задачу станет известно точно.
## Инструмент
Разбор ведётся скриптом `tmp/research/hl.py` (Python 3, только стандартная