powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / вычесть множества
25 сообщений из 31, страница 1 из 2
вычесть множества
    #35250587
xtron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Помогите плиз ускорить запрос !
есть две таблицы:
CREATE TABLE a(id INT NOT NULL, PRIMARY KEY(id));
CREATE TABLE b(id INT NOT NULL, PRIMARY KEY(id));
таблица a содержит множество числел (скажем 2.5 миллиона уникальных идетификаторов),
таблица b содержит те-же числа либо какие-то из них отсутствуют.

кто нибудь может предложить вариант как увидеть числа которые есть в таблице a но нету в таблице b иначе как таким запросом:
SELECT * FROM a LEFT OUTER JOIN b ON (a.id = b.id) WHERE b.id IS NULL;

EXCEPT то-же пробывал - работает еще медленней чем LEFT JOIN
может есть что-нибудь турбированное postgreSQL специфичное ???

слить в одну таблицы нельзя потому как на самом деле в реальности в таблице b есть еще один ключ который участвует в выборке.

пробывал создавать таблицу b как
CREATE TABLE c(id INT NOT NULL, PRIMARY KEY(id), FOREIGN KEY(id) REFERENCES a(id));
и как
CREATE TABLE d(id INT NOT NULL, FOREIGN KEY(id) REFERENCES a(id));
по идее FOREIGN KEY долен указывать оптимизатору что ключи то один и общие и существенно ускорять запрос а в реальности это наоборот все замедляет.
...
Рейтинг: 0 / 0
вычесть множества
    #35250852
Oleg Bartunov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xtronПомогите плиз ускорить запрос !
есть две таблицы:
CREATE TABLE a(id INT NOT NULL, PRIMARY KEY(id));
CREATE TABLE b(id INT NOT NULL, PRIMARY KEY(id));
таблица a содержит множество числел (скажем 2.5 миллиона уникальных идетификаторов),
таблица b содержит те-же числа либо какие-то из них отсутствуют.

кто нибудь может предложить вариант как увидеть числа которые есть в таблице a но нету в таблице b иначе как таким запросом:
SELECT * FROM a LEFT OUTER JOIN b ON (a.id = b.id) WHERE b.id IS NULL;

EXCEPT то-же пробывал - работает еще медленней чем LEFT JOIN
может есть что-нибудь турбированное postgreSQL специфичное ???

слить в одну таблицы нельзя потому как на самом деле в реальности в таблице b есть еще один ключ который участвует в выборке.

пробывал создавать таблицу b как
CREATE TABLE c(id INT NOT NULL, PRIMARY KEY(id), FOREIGN KEY(id) REFERENCES a(id));
и как
CREATE TABLE d(id INT NOT NULL, FOREIGN KEY(id) REFERENCES a(id));
по идее FOREIGN KEY долен указывать оптимизатору что ключи то один и общие и существенно ускорять запрос а в реальности это наоборот все замедляет.


Надо бы на планы и времена посмотреть, а то напишут медленно, вот и думай, что он имел ввиду.
...
Рейтинг: 0 / 0
вычесть множества
    #35251160
xtron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Oleg BartunovНадо бы на планы и времена посмотреть, а то напишут медленно, вот и думай, что он имел ввиду.
Ok. В таблицах a,b,c,d аюсолюно одинаковые данные - 2500000 уникальных ключей.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
postgres=# EXPLAIN ANALYZE SELECT count(*) FROM a LEFT OUTER JOIN b ON (a.id = b.id) WHERE b.id IS NULL;
                                                           QUERY PLAN                                                           
--------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost= 166484 . 18 .. 166484 . 19  rows= 1  width= 0 ) (actual time= 10164 . 228 .. 10164 . 229  rows= 1  loops= 1 )
   ->  Hash Left Join  (cost= 66054 . 45 .. 163359 . 15  rows= 1250010  width= 0 ) (actual time= 10164 . 220 .. 10164 . 220  rows= 0  loops= 1 )
         Hash Cond: (a.id = b.id)
         Filter: (b.id IS NULL)
         ->  Seq Scan on a  (cost= 0 . 00 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 0 . 018 .. 1490 . 635  rows= 2500000  loops= 1 )
         ->  Hash  (cost= 34804 . 20 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 3863 . 981 .. 3863 . 981  rows= 2500000  loops= 1 )
               ->  Seq Scan on b  (cost= 0 . 00 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 0 . 020 .. 1679 . 415  rows= 2500000  loops= 1 )
 Total runtime:  10172 . 649  ms
( 8  rows)

Время:  10173 , 423  мс

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
postgres=# EXPLAIN ANALYZE SELECT count(*) FROM a LEFT OUTER JOIN c ON (a.id = c.id) WHERE c.id IS NULL;
                                                           QUERY PLAN                                                           
--------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost= 166484 . 18 .. 166484 . 19  rows= 1  width= 0 ) (actual time= 10153 . 691 .. 10153 . 692  rows= 1  loops= 1 )
   ->  Hash Left Join  (cost= 66054 . 45 .. 163359 . 15  rows= 1250010  width= 0 ) (actual time= 10153 . 684 .. 10153 . 684  rows= 0  loops= 1 )
         Hash Cond: (a.id = c.id)
         Filter: (c.id IS NULL)
         ->  Seq Scan on a  (cost= 0 . 00 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 0 . 023 .. 1488 . 573  rows= 2500000  loops= 1 )
         ->  Hash  (cost= 34804 . 20 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 3859 . 074 .. 3859 . 074  rows= 2500000  loops= 1 )
               ->  Seq Scan on c  (cost= 0 . 00 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 0 . 020 .. 1673 . 198  rows= 2500000  loops= 1 )
 Total runtime:  10161 . 866  ms
( 8  rows)

Время:  10162 , 482  мс


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
postgres=# EXPLAIN ANALYZE SELECT count(*) FROM a LEFT OUTER JOIN d ON (a.id = d.id) WHERE d.id IS NULL;
                                                           QUERY PLAN                                                           
--------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost= 166484 . 18 .. 166484 . 19  rows= 1  width= 0 ) (actual time= 10162 . 737 .. 10162 . 738  rows= 1  loops= 1 )
   ->  Hash Left Join  (cost= 66054 . 45 .. 163359 . 15  rows= 1250010  width= 0 ) (actual time= 10162 . 729 .. 10162 . 729  rows= 0  loops= 1 )
         Hash Cond: (a.id = d.id)
         Filter: (d.id IS NULL)
         ->  Seq Scan on a  (cost= 0 . 00 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 0 . 019 .. 1489 . 039  rows= 2500000  loops= 1 )
         ->  Hash  (cost= 34804 . 20 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 3854 . 430 .. 3854 . 430  rows= 2500000  loops= 1 )
               ->  Seq Scan on d  (cost= 0 . 00 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 0 . 018 .. 1666 . 894  rows= 2500000  loops= 1 )
 Total runtime:  10170 . 912  ms
( 8  rows)

Время:  10171 , 504  мс

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
postgres=# EXPLAIN ANALYZE SELECT count(*) FROM a LEFT OUTER JOIN b USING(id) WHERE b.id IS NULL;
                                                           QUERY PLAN                                                           
--------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost= 166484 . 18 .. 166484 . 19  rows= 1  width= 0 ) (actual time= 10146 . 809 .. 10146 . 810  rows= 1  loops= 1 )
   ->  Hash Left Join  (cost= 66054 . 45 .. 163359 . 15  rows= 1250010  width= 0 ) (actual time= 10146 . 802 .. 10146 . 802  rows= 0  loops= 1 )
         Hash Cond: (a.id = b.id)
         Filter: (b.id IS NULL)
         ->  Seq Scan on a  (cost= 0 . 00 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 0 . 021 .. 1487 . 165  rows= 2500000  loops= 1 )
         ->  Hash  (cost= 34804 . 20 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 3864 . 204 .. 3864 . 204  rows= 2500000  loops= 1 )
               ->  Seq Scan on b  (cost= 0 . 00 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 0 . 018 .. 1676 . 746  rows= 2500000  loops= 1 )
 Total runtime:  10154 . 974  ms
( 8  rows)

Время:  10155 , 553  мс

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
postgres=# EXPLAIN ANALYZE SELECT count(*) FROM a LEFT OUTER JOIN c USING(id) WHERE c.id IS NULL;
                                                           QUERY PLAN                                                           
--------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost= 166484 . 18 .. 166484 . 19  rows= 1  width= 0 ) (actual time= 10144 . 469 .. 10144 . 469  rows= 1  loops= 1 )
   ->  Hash Left Join  (cost= 66054 . 45 .. 163359 . 15  rows= 1250010  width= 0 ) (actual time= 10144 . 461 .. 10144 . 461  rows= 0  loops= 1 )
         Hash Cond: (a.id = c.id)
         Filter: (c.id IS NULL)
         ->  Seq Scan on a  (cost= 0 . 00 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 0 . 024 .. 1487 . 858  rows= 2500000  loops= 1 )
         ->  Hash  (cost= 34804 . 20 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 3858 . 556 .. 3858 . 556  rows= 2500000  loops= 1 )
               ->  Seq Scan on c  (cost= 0 . 00 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 0 . 019 .. 1676 . 051  rows= 2500000  loops= 1 )
 Total runtime:  10152 . 645  ms
( 8  rows)

Время:  10153 , 218  мс

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
postgres=# EXPLAIN ANALYZE SELECT count(*) FROM a LEFT OUTER JOIN d USING(id) WHERE d.id IS NULL;
                                                           QUERY PLAN                                                           
--------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost= 166484 . 18 .. 166484 . 19  rows= 1  width= 0 ) (actual time= 10142 . 770 .. 10142 . 770  rows= 1  loops= 1 )
   ->  Hash Left Join  (cost= 66054 . 45 .. 163359 . 15  rows= 1250010  width= 0 ) (actual time= 10142 . 762 .. 10142 . 762  rows= 0  loops= 1 )
         Hash Cond: (a.id = d.id)
         Filter: (d.id IS NULL)
         ->  Seq Scan on a  (cost= 0 . 00 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 0 . 022 .. 1489 . 045  rows= 2500000  loops= 1 )
         ->  Hash  (cost= 34804 . 20 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 3848 . 772 .. 3848 . 772  rows= 2500000  loops= 1 )
               ->  Seq Scan on d  (cost= 0 . 00 .. 34804 . 20  rows= 2500020  width= 4 ) (actual time= 0 . 019 .. 1665 . 416  rows= 2500000  loops= 1 )
 Total runtime:  10150 . 961  ms
( 8  rows)

Время:  10151 , 504  мс
...
Рейтинг: 0 / 0
вычесть множества
    #35251348
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xtron пишет:

> кто нибудь может предложить вариант как увидеть числа которые есть в
> таблице a но нету в таблице b иначе как таким запросом:
> SELECT * FROM a LEFT OUTER JOIN b ON (a.id = b.id) WHERE b.id IS NULL;

select * from a
where not exists ( select * from b where b.id = a.id )

или

select * from a
where a.id not in ( select b.id from b )

что почти одно и то же.

> EXCEPT то-же пробывал - работает еще медленней чем LEFT JOIN
> может есть что-нибудь турбированное postgreSQL специфичное ???

Вычитание множеств - по жизни сложная операция и небыстрая.
O(N*M) N,M - мощности множеств. Если у вас будет индек на id
(а он есть), то - O(N*log(M)), но не быстрее.

Хотя нет, есть еще sort merge join, O(max(N*M)), но не знаю,
поддерживает ли его PG.

> пробывал создавать таблицу b как
> CREATE TABLE c(id INT NOT NULL, PRIMARY KEY(id), FOREIGN KEY(id)
> REFERENCES a(id));
> и как
> CREATE TABLE d(id INT NOT NULL, FOREIGN KEY(id) REFERENCES a(id));
> по идее FOREIGN KEY долен указывать оптимизатору что ключи то один и
> общие и существенно ускорять запрос а в реальности это наоборот все
> замедляет.

Ничего это не замедляет (замедляться будут только модификации),
но и ускорять не должно. FOREIGN KEY оптимизатору до фени.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
вычесть множества
    #35251436
xtron, по моему опыту, длинные, кривые или медленные запросы возникают при плохо поставленной или плохо решенной задаче. Вы бы рассказали, зачем вам вычитание и насколько велика таблица b.
...
Рейтинг: 0 / 0
вычесть множества
    #35260513
xtron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
PostreSQL начинающийxtron, по моему опыту, длинные, кривые или медленные запросы возникают при плохо поставленной или плохо решенной задаче. Вы бы рассказали, зачем вам вычитание и насколько велика таблица b.
Задача простая: в первой таблице события который нужно раздать клиентам, а во второй отметки клиентов о том что они событие получили. получать они должны только новые события отсюда вычитание. величина второй таблицы это величина первой помноженная на количество клиентов. в чем тут кривизна ???
...
Рейтинг: 0 / 0
вычесть множества
    #35260523
xtron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivВычитание множеств - по жизни сложная операция и небыстрая.
Кстати по моим тестам что
SELECT count(*) FROM a LEFT OUTER JOIN b ON (a.id = b.id) WHERE b.id IS NULL;
что
SELECT count(*) FROM a, b WHERE a.id = b.id;
те что вычитание что сложение выполняются в PostgreSQL одинаковое время на разных количествах записей (проверял на 2.5 и 10 миллионах)
...
Рейтинг: 0 / 0
вычесть множества
    #35260537
xtron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
xtronчто вычитание что сложение выполняются в PostgreSQL одинаковое время
обе таблицы заполнены, в случае если во второй меньше записей то сложение быстрее
...
Рейтинг: 0 / 0
вычесть множества
    #35260990
> получать они должны только новые события отсюда вычитание

Логику раздачи опишите. Какие-то атрибуты (время получения, например) из второй таблицы используются или просто регистрируется факт?

> величина второй таблицы это величина первой помноженная на количество клиентов. в чем тут кривизна???

Я не могу придумать задачу, которая требовала бы такой реализации. Произведение - вот это и есть криво.
...
Рейтинг: 0 / 0
вычесть множества
    #35261189
Andrey Daeron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну вот пример на вычитание.
Есть внешняя система А, которая вообще не факт что RDBMS или её трогать нельзя. (Пример Active Directory).
Есть некий момент времени, когда пользователь заново хочет закачать эти данные в систему. При этом в изначальной системе с ними могло происходить практически всё что угодно. Соответсвенно нужно найти разницу и с ней что-то согласно бизнес-логики сделать (пример - внести заново отношения подразделений из AD в мою БД, обновить имена и атрибуты пользователей).
...
Рейтинг: 0 / 0
вычесть множества
    #35261394
> Есть некий момент времени, когда пользователь заново хочет закачать эти данные в систему

Где здесь произведение?
...
Рейтинг: 0 / 0
вычесть множества
    #35261627
Andrey Daeron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PostreSQL начинающий> Есть некий момент времени, когда пользователь заново хочет закачать эти данные в систему
Где здесь произведение?
А я и не говорил, что это пример на умножение. Это на вычитание точнее на исключающую разность, но это ИМХо ньюансы реализации.
Вы чуть раньше спрашивали про вычитание.
...
Рейтинг: 0 / 0
вычесть множества
    #35261818
Andrey Daeron, извините, неправильно понял пример. Да, вы правы.
Автору вопроса я бы предложил сначала подумать о простых ограничениях: трудно представить, чтобы всегда требовались все данные, скорее всего, значительную часть можно держать в архиве. Если действительно необходим лог персональной регистрации получения, есть смысл также оптимизировать лог доставки (таблица b), разделив его на несколько частей в зависимости от поведения подписчиков.
...
Рейтинг: 0 / 0
вычесть множества
    #35262366
xtron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
PostreSQL начинающийAndrey Daeron, извините, неправильно понял пример. Да, вы правы.
Автору вопроса я бы предложил сначала подумать о простых ограничениях: трудно представить, чтобы всегда требовались все данные, скорее всего, значительную часть можно держать в архиве. Если действительно необходим лог персональной регистрации получения, есть смысл также оптимизировать лог доставки (таблица b), разделив его на несколько частей в зависимости от поведения подписчиков.
Требуются ВСЕ данные. Ограничение по времени тут не ввести.
...
Рейтинг: 0 / 0
вычесть множества
    #35262425
Andrey Daeron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xtron PostreSQL начинающийAndrey Daeron, извините, неправильно понял пример. Да, вы правы.
Автору вопроса я бы предложил сначала подумать о простых ограничениях: трудно представить, чтобы всегда требовались все данные, скорее всего, значительную часть можно держать в архиве. Если действительно необходим лог персональной регистрации получения, есть смысл также оптимизировать лог доставки (таблица b), разделив его на несколько частей в зависимости от поведения подписчиков.
Требуются ВСЕ данные. Ограничение по времени тут не ввести.
Бррр. Может я как-то невнимательно прочитал или понял постановку.
Есть события, которые происходят (таблица А). Есть клиенты (таблица Б). Это две разные таблицы. Есть таблица с данными, которые просто являются перемножением этих двух таблиц (таблица В). И в этой таблице отмечаются события полученные/отправленные пользователю? Т.е. в таблице В всегда А*Б записей?
...
Рейтинг: 0 / 0
вычесть множества
    #35262442
Andrey Daeron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Че-то рука дрогнула.

При такой организации (поддерживается триггерами, невелика проблема) вычитаний вроде не нужно простой индексированный SELECT по таблице. Накладные расходы по организации - тоже невелики. Тока филфактор нужно в 40-50% выставить что бы UPDATE быстрее бегали.
...
Рейтинг: 0 / 0
вычесть множества
    #35262451
xtron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Andrey Daeron
Бррр. Может я как-то невнимательно прочитал или понял постановку.
Есть события, которые происходят (таблица А). Есть клиенты (таблица Б). Это две разные таблицы. Есть таблица с данными, которые просто являются перемножением этих двух таблиц (таблица В). И в этой таблице отмечаются события полученные/отправленные пользователю? Т.е. в таблице В всегда А*Б записей?
Нет. Есть таблица A - там события. И есть таблица B там отметки от получении событий клиентами.
Больше таблиц нет все что я там выше привел это пыпытки ускорить выборку не полученных клиентами событий.
Дело в том что клиент может отказаться от события даже старого а выбирать нужно все не полученные клиентами события поэтому ограничение по времени ввести нельзя.
...
Рейтинг: 0 / 0
вычесть множества
    #35262481
Andrey Daeron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xtron Andrey Daeron
Бррр. Может я как-то невнимательно прочитал или понял постановку.
Есть события, которые происходят (таблица А). Есть клиенты (таблица Б). Это две разные таблицы. Есть таблица с данными, которые просто являются перемножением этих двух таблиц (таблица В). И в этой таблице отмечаются события полученные/отправленные пользователю? Т.е. в таблице В всегда А*Б записей?
Нет. Есть таблица A - там события. И есть таблица B там отметки от получении событий клиентами.
Больше таблиц нет все что я там выше привел это пыпытки ускорить выборку не полученных клиентами событий.
Дело в том что клиент может отказаться от события даже старого а выбирать нужно все не полученные клиентами события поэтому ограничение по времени ввести нельзя.
1. Т.е. таблицы клиентов нет? Как-то странно, и не логично - клиенты есть таблицы с нимим нет
2. То, что нарисовал я - это предложение уйти от динамического формирования умножения таблиц, в сторону его статической реализации. Благо - всё равно отметки ставить нужно. Не хочет клиент его видеть ваще - пожалуйста или удаляем запись из этой таблицы, либо ставим признак - клиент забил на событие.

У меня такая схема в рассылках сделана. Одно и то же сообщение могут получать люди и отделы, есть подвтерждение о получении, отказ от получения, забивание... статическая таблицка формируется быстро (по сути - куча инсертов или по количеству клиентов, либо по количеству сообщений), а удобств много. В частности быстрая аналитика в любом разрезе, возможность введения дополнительных признакофф. Надеюсь занимаемое место Вас не беспокоит :)
...
Рейтинг: 0 / 0
вычесть множества
    #35262529
xtron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Andrey Daeron
1. Т.е. таблицы клиентов нет? Как-то странно, и не логично - клиенты есть таблицы с нимим нет

Смотрите есть таблица А:
CREATE TABLE a(id INT NOT NULL, PRIMARY KEY(id), info text);
те события скажем (1, 'первое событие'), (2, 'второе событие')

и есть таблица B:
CREATE TABLE b(id INT NOT NULL, PRIMARY KEY(id), client_id INT NOT NULL);
те отметки о получении клиентами событий скажем:
(1, 1), (2, 1), (2, 2) - те первый клиент получил 1 и 2 события, а второй клиент только второе событие.

Нужно быстро выбрать НЕ полученные клинетом события !

те SELECT * FROM a LEFT OUTER JOIN b ON (a.id = b.id) WHERE b.id IS NULL AND d.client_id = 2;

Andrey Daeron
2. То, что нарисовал я - это предложение уйти от динамического формирования умножения таблиц, в сторону его статической реализации. Благо - всё равно отметки ставить нужно. Не хочет клиент его видеть ваще - пожалуйста или удаляем запись из этой таблицы, либо ставим признак - клиент забил на событие.
У меня такая схема в рассылках сделана. Одно и то же сообщение могут получать люди и отделы, есть подвтерждение о получении, отказ от получения, забивание... статическая таблицка формируется быстро (по сути - куча инсертов или по количеству клиентов, либо по количеству сообщений), а удобств много. В частности быстрая аналитика в любом разрезе, возможность введения дополнительных признакофф. Надеюсь занимаемое место Вас не беспокоит :)

Может я чего то не понимаю... Объясните как я по шагам вашу мысль плиз ! Место не совершенно не беспокоит. Беспокоит только скорость получения не полученных конкретным клиентом событий.
...
Рейтинг: 0 / 0
вычесть множества
    #35262624
Andrey Daeron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xtron
Может я чего то не понимаю... Объясните как я по шагам вашу мысль плиз ! Место не совершенно не беспокоит. Беспокоит только скорость получения не полученных конкретным клиентом событий.
Попробую.

Table A: CREATE TABLE messages(id serial, msg text)
Table B: CREATE TABLE clients(id serial, name text)
Table C: CREATE TABLE cl_mesg(id serial, client_id integer, message_id integer, is_obtain integer, is_obstructed integer, time_reciving timestamp, time_read timestamp);

Индексы уникальности - по вкусу/задаче.

Triggers on A (messages):
1. On Insert (добавление для всех клиентов этого сообщения. Можно вводить критерии, может мёртвым клиентам уже они не нужны, может еще кому не нужны):
INSERT INTO cl_mesg (client_id,message_id) SELECT id, new.id (это будет ID message) FROM clients;
2. On update (по идее нафиг не нужно, но если меняем что-то в сообщении, то может нужно перпослать):
INSERT INTO cl_mesg (client_id,message_id) SELECT id, new.message_id FROM clients;
3. On delete (прибить все сообщения, вне зависимости от того прочитаны или нет)
по идее тут FK должны отреботать каскадно.

Triggers on B (clients) - аналогично, только со стороны сообщений. Клиент - берётся как new.id

Для таблицы cl_mesg - будет прикольно попробовать поиграться с fillfactor, что бы обновления на то, что клиент получил событие проходили быстрее.

Тогда Ваш запрос- "а кто еще не получил что-то", это просто
SELECT id FROM cl_mesg WHERE is_reciev IS NULL;
...
Рейтинг: 0 / 0
вычесть множества
    #35262701
> Есть таблица A - там события. И есть таблица B там отметки от получении событий клиентами.

Вы написали это в первом сообщении, это понятно. У вас три задачи: первая - отдать новые сообщения всем пользователям, вторая - хранить лог получений, третья - дать возможность пользователям изменять статус соообщений (почему это нужно - для меня загадка: если пользователь получил сообщение, то не очень понятно, как он может от него отказаться и зачем ему второй (третий, четвертый и т. д.) раз предлагать то же самое сообщение; ну, да ладно, это не важно).

Зачем держать вместе лог полученных сообщений и не полученных, если отдавать нужно только не полученные, а менять статус можно только у полученных?

А вообще странная задача, как я уже сказал. Я по-прежнему не могу придумать ничего похожего в реальной жизни.
...
Рейтинг: 0 / 0
вычесть множества
    #35262733
xtron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Andrey DaeronТогда Ваш запрос- "а кто еще не получил что-то", это просто
SELECT id FROM cl_mesg WHERE is_reciev IS NULL;
те вы предлагаете при возникновении события генерировать для всех клиентов отметки об этом событии,
а при получении клиентом события помечать его как полученное ?
...
Рейтинг: 0 / 0
вычесть множества
    #35262745
xtron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
PostreSQL начинающийне очень понятно, как он может от него отказаться
Может.

PostreSQL начинающий
Зачем держать вместе лог полученных сообщений и не полученных, если отдавать нужно только не полученные, а менять статус можно только у полученных?
В таблице B храняться ТОЛЬКО полученные сообщения. Отказ от сообщения - удаление строки с пометкой получения сообщения.
...
Рейтинг: 0 / 0
вычесть множества
    #35262832
> В таблице B храняться ТОЛЬКО полученные сообщения.

Ну и зачем вы пишите, что содержимое таблицы - это произведение? Других решений у этой задачи, отличных от уже приведенных, нет. А задача все-таки кривая. Ну не бывает так, чтобы сообщения только добавлялись и всегда одномоментно были нужны все сразу.
...
Рейтинг: 0 / 0
вычесть множества
    #35262848
Andrey Daeron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xtron Andrey DaeronТогда Ваш запрос- "а кто еще не получил что-то", это просто
SELECT id FROM cl_mesg WHERE is_reciev IS NULL;
те вы предлагаете при возникновении события генерировать для всех клиентов отметки об этом событии,
а при получении клиентом события помечать его как полученное ?
Да.
...
Рейтинг: 0 / 0
25 сообщений из 31, страница 1 из 2
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / вычесть множества
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]