Search Postgresql Archives

Re: multiple UNIQUE indices for FK

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Rafal:

These are my opinions, somebody else may think they are not correct,
comments are wellcome.

On Fri, Mar 4, 2016 at 2:30 PM, Rafal Pietrak <rafal@xxxxxxxxx> wrote:

>> This is normally a sympton of your schema not being appropiately normalized.
> OK. I'd apreciate some guidance here. I've sattled for a schema
> suggested in this thread a fiew posts before. In short went like this:
>
> CREATE TABLE persons(person_id primaty key, ...);
> CREATE TABLE msgs_person(msg_id, person_id references
> persons(person_id), rel_type, the_message_itself, primary
> key(message_id, person_id,rel_type),....);
>
> where:
> person_id - sender or recepient of the message
> msg_id - an ID uniquely assigned by sender
> rel_type - a role a row in msgs_person table is assigned to this
> particular relation: person+message; this role can be either SENDER or
> RECEPIENT

For this particular case ( person must be either a UNIQUE sender or a
multiple recipient ) my opinion will be:
0.- Table persons is OK.
1.- Move sender to msg.
CREATE TABLE messages (
    message_id primary key,
    sender_person_id NOT NULL  references persons,
    message_ts timestamp ( or other ordering imposing field, more on
this below).
    ....rest of fields.
)
2.- Make a recipients table:
CREATE TABLE recipients (
    message_id references messages,
    receipient_person_id references persons,
    primary key (message_id, person_id) -- to avoid duplicate senders.
)

Also, it will be useful to know if the sender can be a recipient to (
like with e-mail ).

Make sender_person_id NOT NULL in messages if you want to insure every
message ahs exactly ONE SENDER, leave it out if you want to allow
senderless messages. An FK column must either link to a record or be
null.

Then, if you want to have a msgs-person ''table'' I would use a view:

CREATE VIEW msgs_persons as
SELECT message_id, sender_person_id as person_id, 'SENDER' as role from messages
UNION ALL
SELECT message_id, recipient_person_id as person_id, 'RECIPIENT' as
role from recipients



> And now, apart from the above, I'm trying to put a NEXT field into the
> MSGS_PERSON table, so that I can (sort of):
> ALTER TABLE  msgs_person ADD CONSTRAINT next_fk FOREIGN KEY
> (next,person_id,rel_type) REFERENCES msgs_person(msg_id,person_id,
> rel_type); ...( just for: rel_type=SENDER).
> What should I do with this to have it "appropriately normalized"?

The normalization problem is more in the msgs-person table, as it
contains heterogeneous data, this is why I would use the recipients
table approach.

I do not know what you want to achieve with the NEXT. It seem you are
trying to build a linked list of sent messages. In my approach, if you
really need this, you just put the next field on messages, index it on
(sender_id+message_id) and make (sender_id+next_message_id) reference
that index.

But if you are just trying to know the last message for a sender, I
would put an ordering column, like timestamp ( my personal preference,
if message_id has a total ordering ( I suppose it's an integer or an
string ) would be to add message_ts, fill it with the message
sending/reception timestamp ( I do not know which kind of messages you
are storing, so not too sure aabout this, so lets say row insertion
timestamp ), use the message-id as a tie breaker ( in case you get
many messages with the same timestamp ) ( Or, if you have an external
ordered field, use that, more knowledge of the particular system is
needed ), index the table on message_ts ( or message_ts + message_id,
if lots of dupes ) to speed up queries and just do a query on messages
for a sender id, order by message_ts desc, message_id desc limit 1 for
the last message.


> "generic constraint's"? - pls elaborate regarding schema I've just
> schetched above.

You can check anything in a constraint on a table by using a function
to do things. Although, IIRC, there were some problems if you made
queries, and the thing was something better done with triggers. The
problem is difficult, and this is why when dessigning tables thinks
like linked list and similar are best avoided, as you enter a
difficult zone when you begin to consider visibility rules for the
data ( when many transactions, with different isolation levels, are
concurrently manipulating the same set of tuples). Your app may not do
this, but servers are dessigned to allow it.

> In that case, pls forgive my language - all I ment is that this
> "implementation detail", in postgresql is in fact "enforced policy" ...

Nothing to forgive, I was just trying to explain some things.

> but this isn't actually the problem here. I'm quite happy with a system
> that helps me avoid performence pitfalls.
> The problem I see is different - and the reason I'm asking about
> theoretical background of the implementation is different.
> The problem is that once one accepts the requirement for a unique index
> as FK target column "mandatory performance support", then I fail to see
> real reazon, where *ENY* unique index shouldn't do that role too. They
> are unique (within  domains of their conditions) and by definition yield
> a single row for FK (or nothing); that should be sufficient for the
> engine to keep data consistancy as expected, shouldn't it?

Maybe. I'm not following too much what you try to do here. Either you
are way above my level or you have a mental model of how postgres
should work which does not correspond to how it does.

> Naturally I undestand that there might be some deep reasons for
> exclusion of partial indexed as FK target "selectors" - I'd apreciate
> further explanations. But in case those reasons exist, I'd expect
> workarounds to exist too - like "SQL idioms" - that people normally use
> for cases like these. Would those "generic constraint" be be idiom?

Please, forget anything I said about generic constraint, my fault, I
was trying to express something, failed at it, and do not know how to
fix it.

What I personally do to avoid these kind of problems is to avoid
dessigning something which needs references to a partial index. And
I've been successful at it for a long time. I'm not going to recover
the complete thread to recap on why you exactly are doing these kind
of really advanced things, but I suppose you need them for some reason
and I do not have the resources to study it.

> So as I said before, I'm looking for some guidence here. (I'm really
> emotionally bond to that NEXT field there :)

ON this I cannot help you too much. I do not see what you are trying
to achieve with the NEXT field. These will need more explanations, and
more study, and as I said before, I do not have the available
resources for them.

Sorry for the tme I've taken, but I feel I can not be of any help here.

Best regards.

Francisco Olarte, over & out.


-- 
Sent via pgsql-general mailing list (pgsql-general@xxxxxxxxxxxxxx)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Postgresql Jobs]     [Postgresql Admin]     [Postgresql Performance]     [Linux Clusters]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Postgresql & PHP]     [Yosemite]
  Powered by Linux