172 похожих чатов

Здравствуйте, Есть табличка на 80млн records: --postgres 9.6 CREATE TABLE user_project (

id varchar(255) NOT NULL,
user_email varchar(255) NULL,
-- и еще около 20 колонок
CONSTRAINT user_project_pkey PRIMARY KEY (id)
);
хочу добавить табличку:
create table app_user (
id varchar default uuid_generate_v4(),
email varchar not null
);
и заменить в user_project колонку user_email на user_id которая будет foreign key на app_user.
в результате навалял скрипт который очень медленный:
-- наполняем app_user существующими имейлами, их получиться ~10 млн.
-- возможно ли наполнить табличку быстрее чем здесь?
insert into app_user(email) select distinct user_email from user_project;
alter teble app_user add constraint idx_unique_email unique (email);
alter table app_user add constraint pk_id_app_user primary key (id);
-- делаем копию таблицы с новой колонкой user_id
-- тут вопрос, что должно быть быстрее: join или вложеный select?
create table new_user_project as SELECT user_project.*, (select u.id from app_user as u where user_email = u.email) as user_id FROM user_project;
alter table new_user_project drop column user_email;
--восстановляем индексы

34 ответов

15 просмотров

А что именно тормозит (какой этап)? Т.е. в зависимости от этого стоит оптимизировать. > решили что хуже так как ресурсы или проекты следуючего юзера можно будет по id выцепить если где то с секюрити беда По-моему, это shitcurity, Вы меня извините. Т.е. Вы используете UUID не по назначению (за его "стоимость" не получая никаких реальных преимуществ).

Viktor Fedinchuk
инсерт в app_user ~3 часа

А покажите EXPLAIN select distinct user_email from user_project; Да и \dt+ user_project неплохо бы...

Viktor-Fedinchuk Автор вопроса
Yaroslav Schekin
А покажите EXPLAIN select distinct user_email from...

QUERY PLAN | -----------------------------------------------------------------------------------------------------------------| Unique (cost=0.56..2286451.29 rows=601016 width=22) | -> Index Only Scan using idx_user_project_user on user_project (cost=0.56..2138610.90 rows=59136156 width=22)|

Viktor Fedinchuk
QUERY PLAN ...

А что за индекс idx_user_project_user? Вообще, легче "\d+ user_project" показать, мне кажется.

Viktor-Fedinchuk Автор вопроса
Yaroslav Schekin
А что за индекс idx_user_project_user? Вообще, лег...

CREATE TABLE public.user_project ( id varchar(255) NOT NULL, is_archived bool NULL, creation_time timestamp NULL, last_access_time timestamp NULL, modification_time timestamp NULL, modified_by varchar(255) NULL, is_preview_archived bool NULL, product_group_name varchar(255) NULL, "location" varchar(255) NULL, s3_location varchar(255) NULL, sku_name varchar(255) NULL, user_email varchar(255) NULL, storage_id varchar(255) NULL, application_type varchar(255) NULL, design_theme_name varchar(255) NULL, is_incomplete bool NULL, mergedata_filename varchar(255) NULL, "name" varchar(255) NULL, product_profile varchar(255) NULL, related_project_id varchar(255) NULL, target_id varchar(255) NULL, template_name varchar(255) NULL, "type" varchar(255) NULL, "usage" varchar(255) NULL, application_id varchar(255) NULL, CONSTRAINT user_project_pkey PRIMARY KEY (id), CONSTRAINT fk5yfr73bfdu6qm35hnylpkspqn FOREIGN KEY (application_id) REFERENCES application(application_id), CONSTRAINT fk_u1461udx5gt5qubyxpst3yby FOREIGN KEY (storage_id) REFERENCES storage(id) ); CREATE INDEX idx_gin_user_project_id ON public.user_project USING gin (id gin_trgm_ops); CREATE INDEX idx_gin_user_project_name ON public.user_project USING gin (name gin_trgm_ops); CREATE INDEX idx_gin_user_project_product_group ON public.user_project USING gin (product_group_name gin_trgm_ops); CREATE INDEX idx_gin_user_project_sku_name ON public.user_project USING gin (sku_name gin_trgm_ops); CREATE INDEX idx_gin_user_project_user_email ON public.user_project USING gin (user_email gin_trgm_ops); CREATE INDEX idx_user_project_creation_time ON public.user_project USING btree (creation_time); CREATE INDEX idx_user_project_id ON public.user_project USING btree (id); CREATE INDEX idx_user_project_last_access_time ON public.user_project USING btree (last_access_time); CREATE INDEX idx_user_project_modification_time ON public.user_project USING btree (modification_time); CREATE INDEX idx_user_project_related_project_id ON public.user_project USING btree (related_project_id); CREATE INDEX idx_user_project_sku_name ON public.user_project USING btree (sku_name); CREATE INDEX idx_user_project_target_id ON public.user_project USING btree (target_id); CREATE INDEX idx_user_project_type ON public.user_project USING btree (type); CREATE INDEX idx_user_project_user ON public.user_project USING btree (user_email);

Viktor Fedinchuk
CREATE TABLE public.user_project ( id varchar(25...

я думал в докладах все врут, да тут индексы индексов...

Viktor Fedinchuk
CREATE TABLE public.user_project ( id varchar(25...

Хмм... а какой размер таблицы / этого индекса (\dt+ / \di+)? Не должно это (именно SELECT) тормозить, казалось бы — что там за "железо" (может, медленные HDD)?

Viktor Fedinchuk
CREATE TABLE public.user_project ( id varchar(25...

я не спец, но... application_type varchar(255) NULL, . . application_id varchar(255) NULL,

Viktor Fedinchuk
CREATE TABLE public.user_project ( id varchar(25...

Но вообще да, это ужас. Прямо можно в пример worst practice приводить (можно посчитать кол-во нарушений https://wiki.postgresql.org/wiki/Don%27t_Do_This в одной этой таблице). И ещё и дубликаты индексов. :(

Viktor-Fedinchuk Автор вопроса
Yaroslav Schekin
Хмм... а какой размер таблицы / этого индекса (\dt...

это развернутый локальный снепшот бд, железо так себе і5 4го поколения и ссд, должны сделать копию РДС на амазоне как мне говорили "скоро", пока так колупаю

Yaroslav Schekin
Но вообще да, это ужас. Прямо можно в пример worst...

Ладно, там GIN и BTREE... Метод доступа разный.

Viktor Fedinchuk
это развернутый локальный снепшот бд, железо так с...

Вы размеры из принципа не показываете? ;) В любом случае, мне кажется, что при таком железе можно и EXPLAIN (ANALYZE, BUFFERS) этого SELECT попробовать — не должен он очень долго работать, по идее.

Viktor Fedinchuk
screenshot

Покажите EXPLAIN (ANALYZE, BUFFERS) select distinct user_email from user_project; Опять-таки, это не должно быть очень долго, по идее (если не выполнится за приемлемое время — просто отмените).

Viktor-Fedinchuk Автор вопроса
Yaroslav Schekin
Покажите EXPLAIN (ANALYZE, BUFFERS) select distin...

QUERY PLAN | -----------------------------------------------------------------------------------------------------------------------------------------------------------------------| Unique (cost=0.56..2286451.29 rows=601016 width=22) (actual time=13.347..18427.660 rows=10077119 loops=1) | Buffers: shared hit=35288332 read=310747 | -> Index Only Scan using idx_user_project_user on user_project (cost=0.56..2138610.90 rows=59136156 width=22) (actual time=13.344..13604.696 rows=59136155 loops=1)| Heap Fetches: 0 | Buffers: shared hit=35288332 read=310747 | Planning time: 0.197 ms | Execution time: 18693.525 ms |

Viktor Fedinchuk
QUERY PLAN | -------------------------------------...

Так, т.е. "тормозит" именно INSERT, получается. Вы пробовали советы из https://www.postgresql.org/docs/9.6/populate.html ? Причины торможения, связанные с WAL, можно отбросить (или убедиться, что проблема именно там), если (только для эксперимента!) создать таблицу как UNLOGGED. Но, вообще, может и просто генерация этих "прекрасных" текстовых UUID-ов тормозить.

Viktor-Fedinchuk Автор вопроса
Yaroslav Schekin
Так, т.е. "тормозит" именно INSERT, получается. Вы...

я попробую как ранее писал @Warstone сделать только без uuid, что бы исключить этот вариант

Yaroslav Schekin
А что именно тормозит (какой этап)? Т.е. в зависим...

Вообще это не то чтобы shitcurity, а вполне адекватная практика. При достаточно рандомных UUID никтотне может, зная какое-то одно значение, даже не может прикинуть куда в диапазоне из этих 128бит прицеливаться для поиска перебором. Блин, да даже гуглодрайв имеет вариант расшарить папку или файл для всех, кто сможет по сгенерированному уникальному url постучаться.

sexxst
Вообще это не то чтобы shitcurity, а вполне адеква...

> Вообще это не то чтобы shitcurity, а вполне адекватная практика. Кто это сказал? UUID-ы для этого никогда не предназначались, по крайней мере. И, опять-таки, почему именно этот размер "нормален" для всех применений? > При достаточно рандомных UUID никто не может И с "достаточно рандомными" тоже бывали (и запросто ещё будут) проблемы, кстати (можно погуглить) — но это если не говорить только о PostgreSQL. > Блин, да даже гуглодрайв Хмм... это что, аргумент? ;)

Yaroslav Schekin
> Вообще это не то чтобы shitcurity, а вполне адек...

"Не предназначались" не означает их неприменимость для данной задачи. Про "нормальный размер" я ничего не говорил. Просто рандомный id в 128 бит лучше последовательного в 64 бита с данной позиции и всё. Проблемы возможны, да. Но, далеко не сразу и вряд ли у автора наберётся достаточно много миллиардов записей учеток пользователей для их проявления. Зы: Гугл в плане обеспечения безопасности для меня лично вполне аргумент, они, в общем-то, в этом неплохо разбираются. Да и , в конце концов, те же ключи всякого сессионного шифрования работают по аналогичному принципу "охренеешь подбирать наугад", разве что они банально длиннее будут.

sexxst
"Не предназначались" не означает их неприменимость...

> "Не предназначались" не означает их неприменимость для данной задачи. Дело в том, что генерация UUID-ов обычно (в т.ч. в PostgreSQL) просто использует системный генератор случайных чисел, какого он качества (в данный момент) — кто его знает (к примеру, https://security.stackexchange.com/a/186097 ). Т.е. это выбор решения "как повезёт" с тем размером, который дают (128 бит) вместо надёжного решения задачи "скрыть идентификаторы / сделать так, чтобы нельзя было подобрать". И делается это потому, что "просто и почти наверняка сработает на практике", а не из каких-то "достойных" соображений, IMHO. ;) "Цена" этого решения может быть выше, чем нормального (индексирование и доступ к случайным данным — не сахар), кстати. > Гугл в плане обеспечения безопасности для меня лично вполне аргумент, они, в общем-то, в этом неплохо разбираются. Хмм... откуда это известно?

Yaroslav Schekin
> "Не предназначались" не означает их неприменимос...

Блин, я не говорю что это "идеальная практика", я говорю "нормальная практика" и "при достаточно рандомных UUID". Ежу понятно, что, если urandom выдаёт, условно говоря, три варианта значений, то всё это превращается в тыкву. Ящитаю у автора в компании люди в состоянии оценить риски и качество выхлопа системного генератора.

sexxst
Блин, я не говорю что это "идеальная практика", я ...

Ну есть же генераторы энтропии для этого (haveged)

sexxst
Блин, я не говорю что это "идеальная практика", я ...

> Блин, я не говорю что это "идеальная практика" Вот и я говорю то же самое — это shitcurity. > Ящитаю у автора в компании люди в состоянии оценить риски и качество выхлопа системного генератора. А считаю, что на самом деле оценить качество выхлопа системного генератора.могут только профессиональные криптографы, а прочие просто [очень] самонадеянны. ;)

Аггей Лоскутников
Ну есть же генераторы энтропии для этого (haveged)

Если на входе генераторов энтропии источники оставляют желать лучшего, то и на выходе тоже будет такое себе. Не просто так в том же CloudFlare стену из лава ламп снимают на камеру высокого разрешения, а другие чуваки из детекторов дыма наковыряли материалов для счётчика радиоактивных распадов и это на вход заливают. Я не так давно захотел собрать ГСЧ на бананах (бананы содержат много калия, в том числе и калия-40, который нестабилен и имеет детектируемый β−-распад . Только оказалось что для таких невысоких энергий очень сложно найти и купить подходящий детектор и идея заглохла(

Yaroslav Schekin
> Блин, я не говорю что это "идеальная практика" ...

Распределение значений на большой выборке посмотреть - не rocket science.

Аггей Лоскутников
Ну есть же генераторы энтропии для этого (haveged)

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

sexxst
Распределение значений на большой выборке посмотре...

Да оно даже у очень плохих ГПСЧ с виду "ничего". Т.е. это просто несерьёзно.

Yaroslav Schekin
Да оно даже у очень плохих ГПСЧ с виду "ничего". Т...

Nope. Вот типичный "плохой". Всё глазами видно буквально. Кроме того есть даже софт, который всасывает поток байтов и говорит сколько там энтропии и насколько качественный он с точки зрения случайности. Но это уже спор за пределами темы группы, предлагаю оставить его.

sexxst
screenshot Nope. Вот типичный "плохой". Всё глазами видно бук...

Нет да. ;) Вы в TAOCP видели прекрасные с виду графики явно "плохих" ГПСЧ (там их было несколько, если правильно помню), например? > Кроме того есть даже софт Вот это — другое дело. Но тут уже нужно что-то знать. ;) > Но это уже спор за пределами темы группы, предлагаю оставить его. Хорошо.

Yaroslav Schekin
Нет да. ;) Вы в TAOCP видели прекрасные с виду гра...

Видел) Типа такого. Но это же тоже очевидно плохой ГСЧ. Ибо и тут есть чёткий паттерн: слишком равномерно распределены значения. Такого в случайном мире не бывает, по крайней не на таких размерах выборок. Ну тут уже у кого как глаз видит вестимо, потому и софт точно лишним не будет.

Похожие вопросы

Обсуждают сегодня

30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
6
в JclConsole объявлено так: function CtrlHandler(CtrlType: DWORD): BOOL; stdcall; - где ваше объявление с stdcall? у вас на картинке нет stdcall
Karagy
8
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
~ 2m21s  nix shell github:nixos/nixpkgs#stack ~  stack ghc -- --version error: … while calling the 'derivationStrict' builtin at /builtin/derivation.nix:...
Rebuild your mind.
6
Карта сайта