Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Java Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3 4 5   вперед  Ctrl      все
 Как лучше сделать  [new]
Zzz79
Member

Откуда:
Сообщений: 569
Смотрите - такая ситуация
нам приходит файл csv с 10 тысячами строк
мы его парсим и превращаем в ДТО и пишем в базу
при парсинге формируется List<Dto>
так как буфер у нас не резиновый - мы делаем это батчами- по 1000 строк

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

вот такой вопрос как сделать так чтобы мы не падали

1.Формировать при парсинге не лист,а сет,но тогда нет гарантии что дубликат не улитит в следущем батче
2.сделать это поле уникью- но как резольвить конфликт

3.Ваше решение
16 июн 20, 12:46    [22151532]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
hck1
Member [заблокирован]

Откуда:
Сообщений: 144
Zzz79,

типичный подход писать в staging таблицу как есть и по ней уже валидировать и разрешать конфликты
16 июн 20, 13:06    [22151544]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
Zzz79
Member

Откуда:
Сообщений: 569
hck1
Zzz79,

типичный подход писать в staging таблицу как есть и по ней уже валидировать и разрешать конфликты

ну а как ты это сделаешь если например у нас две одинаковые записи - то какую взять ?
вот пришел реквест - нам надо его обогадить как раз данными из этой таблицы- и тут мы попадаем впросак ибо мы ищем по уникальному полю и нам в бд дают две записи- которые мы пытаемся положить в кэш и конечно же у нас все падает

понянто что в идеальном мире такого быть не должно - файл должен приходить без дубликатов- но эти файлы формируются руками и поэтому зачастую там ошибки- вот одна из таких это дубляж
16 июн 20, 13:19    [22151556]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
chpasha
Member

Откуда:
Сообщений: 9552
Zzz79
сделать это поле уникью-

ну да. я так понимаю уникальность глобальная, а не в пределах файла, так?

Zzz79
но как резольвить конфликт

а как надо по бизнес-логике? если файл не должен содержать, но содержит - слать нахер. если не должен, но содержит и это не страшно, то игнорировать (или апдейтить, опять же таки что там с бизнес-логикой?). Как игнорировать зависит от используемых средств и сервера бд. В том же постгрес начиная с 9.5 кажется есть INSERT INTO ON CONFLICT DO NOTHING, кроме того есть rules и триггеры.

Zzz79
то какую взять ?

опять же таки, в бизнес-логике что по этому поводу? если на самом деле записи не одинаковы, а дубликаты возникли из-за описки, то имхо лучше вообще ничего не импортировать, а кидать ошибку и информировать отправителя.
16 июн 20, 13:22    [22151559]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
Герой дня
Member

Откуда: obmanula.ru
Сообщений: 30549
Zzz79,

создай бин, в котором будет поле Map<id, уникальное значение>, думаю, памяти хватит хранить и сравнивать по двум полям
16 июн 20, 13:24    [22151562]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
artas
Member

Откуда: Киев сити
Сообщений: 1077
Zzz79,

тут вам нужно у заказчика узнать бизнес логику,и что подразумевается под уникальностью
1) Лично я бы кидал исключение, а ля ИД заиси НЕ уникальны
2) Построчный MERGE решит проблему, но могут быть проблемы, если
ИД 1 1
Нейм1 а б
Нейм2 б а
запишет последнее
3) 10 тыс строк, это немного, можно всю кучу
4) SET это некруто, по причине из пп2
16 июн 20, 13:33    [22151570]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
crutchmaster
Member

Откуда: оттуда.
Сообщений: 1492
Zzz79,

Считаешь хеш чего там надо, при чтении каждой строчки проверяешь, чтобы такого не было. Всё, что не нужно выбрасываешь. Не понял проблемы.
16 июн 20, 13:37    [22151575]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
hck1
Member [заблокирован]

Откуда:
Сообщений: 144
Zzz79

вот пришел реквест - нам надо его обогадить как раз данными из этой таблицы- и тут мы попадаем впросак ибо мы ищем по уникальному полю и нам в бд дают две записи- которые мы пытаемся положить в кэш и конечно же у нас все падает

именно по этому мы и ввели staging, где будут выявлены и помечены дубликаты, поэтому в target таблицу ETL процесс запишет выверенные и чистые данные, без дублей и которые безопасно отдавать бизнес логике.

Zzz79

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

данные должны валидироваться перед загрузкой не зависимо от того как их готовят. в программе выгрузки для тебя данных тоже обязательно будут и ошибки и мутные сбои, приводящие к дублированию.
16 июн 20, 13:38    [22151576]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
Zzz79
Member

Откуда:
Сообщений: 569
chpasha

а как надо по бизнес-логике? если файл не должен содержать, но содержит - слать нахер. если не должен, но содержит и это не страшно, то игнорировать (или апдейтить, опять же таки что там с бизнес-логикой?). Как игнорировать зависит от используемых средств и сервера бд. В том же постгрес начиная с 9.5 кажется есть INSERT INTO ON CONFLICT DO NOTHING, кроме того есть rules и триггеры.

.

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

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

тоесть по сути мне нужно распарсить файл - и если там есть дубликаты ничего не писать и выдать ошибку- но как это сделать если мы читаем по 1000 строк и отправляем
16 июн 20, 14:00    [22151611]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
Zzz79
Member

Откуда:
Сообщений: 569
Герой дня
Zzz79,

создай бин, в котором будет поле Map<id, уникальное значение>, думаю, памяти хватит хранить и сравнивать по двум полям

так нельзя - я бы тогда увеличил батчу количество строк например до 10000 и спокойно бы нашел там дубликат

у меня ограничение на каждый батч в 1000 строк к сожалению
16 июн 20, 14:02    [22151612]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
mayton
Member

Откуда: loopback
Сообщений: 47969
Zzz79

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

Если доступна локальная файловая сисема - то посмотри в сторону таких библиотек:

LevelDb https://github.com/google/leveldb
RockDb https://github.com/facebook/rocksdb

На них можешь создать 1 NoSQL файловую базячку и в нее в режиме unique сразу кидай свои объекты.
Если будет дубликат ключа то сразу словишь Exception.

Это такой переходной вариант когда поднимать базу лень а java-memory уже не хватает.
16 июн 20, 14:09    [22151621]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
Zzz79
Member

Откуда:
Сообщений: 569
hck1

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

данные должны валидироваться перед загрузкой не зависимо от того как их готовят. в программе выгрузки для тебя данных тоже обязательно будут и ошибки и мутные сбои, приводящие к дублированию.[/quot]
вот я тоже про это думаю
вообщем нам сказали что если есть дубликаты - ничего не писать а кидать ошибку
осталось понять как это узнать,что есть дубликаты
16 июн 20, 14:22    [22151641]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
chpasha
Member

Откуда:
Сообщений: 9552
Zzz79
тоесть на этапе отправки мы уже не сможем ничего сделать так как первый батч и второй могут содержать в теории одинаковые записи


Zzz79
тоесть инсертить неправильный файл -тоже неправильно


я не понимаю, что ты хочешь мне сказать - именно по этому контроль уникальности должен быть именно в единственном источнике правды - БД. Она просто не пропустит дубликаты, ни откуда ни при каких обстоятельствах. А вот уже что делать при непропуске, зависит от.

Или поля все-таки не уникальны глобально, а только в пределах файла?
16 июн 20, 14:27    [22151648]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
SpringMan
Member

Откуда:
Сообщений: 207
Можно добавить unique и падать просто. Можно все запихать в табличку, проверить sql запросом какие есть дубликаты, если дубликаты есть, то кинуть исключение и откатить транзакцию.
16 июн 20, 14:29    [22151654]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
забыл ник
Member

Откуда:
Сообщений: 3370
Zzz79
hck1
hck1

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

данные должны валидироваться перед загрузкой не зависимо от того как их готовят. в программе выгрузки для тебя данных тоже обязательно будут и ошибки и мутные сбои, приводящие к дублированию.

вот я тоже про это думаю
вообщем нам сказали что если есть дубликаты - ничего не писать а кидать ошибку
осталось понять как это узнать,что есть дубликаты

Если там 10000 строк то в чем проблема держать Set(uniqueIds) и перед отправкой батче проверять что в этом батче нет дубликатов, попутно добавляя новые айди в Set?
Ну вы развели конечно

Сообщение было отредактировано: 16 июн 20, 14:28
16 июн 20, 14:29    [22151655]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
Zzz79
Member

Откуда:
Сообщений: 569
забыл ник
Zzz79
пропущено...

вот я тоже про это думаю
вообщем нам сказали что если есть дубликаты - ничего не писать а кидать ошибку
осталось понять как это узнать,что есть дубликаты

Если там 10000 строк то в чем проблема держать Set(uniqueIds) и перед отправкой батче проверять что в этом батче нет дубликатов, попутно добавляя новые айди в Set?
Ну вы развели конечно

я сам не знаю зачем ограничение в 1000 строк поставили
типо чтобы нагрузки не было на сервер)
хотя в теории может быть и миллион строк - тогда буфер треснет
вобщем пока непонятно как это сделать - заводить новую таблицу нельзя,писать файл с дубликатами нельззя
нужно выдавать ошибку по дубликату ,но при этом процесс записи происходит батчами ,по 1000 строк
16 июн 20, 14:39    [22151675]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
mayton
Member

Откуда: loopback
Сообщений: 47969
Zzz79, покажи как выглядят ключи. Целые числа? UUID ?
16 июн 20, 14:41    [22151679]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
забыл ник
Member

Откуда:
Сообщений: 3370
Zzz79
забыл ник
пропущено...

Если там 10000 строк то в чем проблема держать Set(uniqueIds) и перед отправкой батче проверять что в этом батче нет дубликатов, попутно добавляя новые айди в Set?
Ну вы развели конечно

я сам не знаю зачем ограничение в 1000 строк поставили
типо чтобы нагрузки не было на сервер)
хотя в теории может быть и миллион строк - тогда буфер треснет
вобщем пока непонятно как это сделать - заводить новую таблицу нельзя,писать файл с дубликатами нельззя
нужно выдавать ошибку по дубликату ,но при этом процесс записи происходит батчами ,по 1000 строк

Еще раз, что мешает тебе хранить в памяти промежуточный Set с уникальными айди уже записанными в батчах?
val uniqueIds = Set()
val data = read(1000)
val unique= extractUniqueIds(data)
if(!allIdsUnique(unique, uniqueIds)) {
  throw new Exception("data is invalid")
} else {
  uniqueIds.addAll(unique)
  writeBatch(data)
}
16 июн 20, 14:47    [22151691]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
mayton
Member

Откуда: loopback
Сообщений: 47969
Если ключи - монотонная последовательность то можем фиксировать объекты Range.
Если - плотное заполнение в диапазоне с дырками - то может быть биткарта.

Если ключи очень длинные то тоже хитрости есть. Чтоб приберечь heap.
16 июн 20, 14:49    [22151696]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
Zzz79
Member

Откуда:
Сообщений: 569
mayton
Zzz79, покажи как выглядят ключи. Целые числа? UUID ?

String
16 июн 20, 15:08    [22151707]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
mayton
Member

Откуда: loopback
Сообщений: 47969
Zzz79
mayton
Zzz79, покажи как выглядят ключи. Целые числа? UUID ?

String

Какая средняя длина?
16 июн 20, 15:09    [22151709]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
Zzz79
Member

Откуда:
Сообщений: 569
забыл ник

Еще раз, что мешает тебе хранить в памяти промежуточный Set с уникальными айди уже записанными в батчах?
val uniqueIds = Set()
val data = read(1000)
val unique= extractUniqueIds(data)
if(!allIdsUnique(unique, uniqueIds)) {
  throw new Exception("data is invalid")
} else {
  uniqueIds.addAll(unique)
  writeBatch(data)
}

вот это должно подойти ,спасибо щас попробую реализовать
16 июн 20, 15:11    [22151714]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
chpasha
Member

Откуда:
Сообщений: 9552
Zzz79
вот это должно подойти ,спасибо щас попробую реализовать

а если у тебя в файле прилетит id, дубликата которого в файле нет, а в базе есть? если мы говорим об ошибках оператора, то нет никакой гарантии, что такого не случится.
16 июн 20, 16:11    [22151759]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
забыл ник
Member

Откуда:
Сообщений: 3370
chpasha
Zzz79
вот это должно подойти ,спасибо щас попробую реализовать

а если у тебя в файле прилетит id, дубликата которого в файле нет, а в базе есть? если мы говорим об ошибках оператора, то нет никакой гарантии, что такого не случится.

Я так предполагаю что ему нужно найти дубликаты во время единоразовго процесса импорта, допустим за сегодняшнюю дату - это типично для ETL. Если ему нужно глобальный uniqueness - то конечно так не получится
16 июн 20, 16:22    [22151764]     Ответить | Цитировать Сообщить модератору
 Re: Как лучше сделать  [new]
mayton
Member

Откуда: loopback
Сообщений: 47969
Ну да. Если это sequence то как-то сделать предположения на основе
монотонности ETL данных. Типа ключи от 0 до 10_000 были загружены
вчера. И следовательно имеет смысл проверять что новые данные старше
чем максимальное значение.
16 июн 20, 16:27    [22151766]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3 4 5   вперед  Ctrl      все
Все форумы / Java Ответить