There is no context, the question is too isolated, and the answers are very limited. The flow is incomplete.
First, for understanding, the table of friends presented does not exist by itself. It is a child of the User table, which has a UserId PK. Both UserId and FriendId are FKs for UserId.
Since friendship is a two-way street or bidirectional (we exclude non-reciprocal lovers and stalkers here!), One row identifies the relationship in both directions.
There are serious consequences in the name of any column, so I would avoid (UserId, FriendId), which implies a hierarchy or one-way relationship, which is false. I suggest (Friend1, Friend2), and of course you need PK ((Friend1, Friend2).
What was not identified, we still did not prevent duplication ([5,12] and [12, 5]), that is, the very redundancy that you are trying to prevent. We need a rule to ensure that Friend1 is always smaller than Friend2.
There are other relationships, such as Bill Materials or the family tree, in which there are Assemblies and Copies that require something more. For example (AssemblyId, ComponentId) or (ParentID, ChildId), where this rule does not apply: a part may be a Component in the assembly, as well as the Network itself. This requires two lines. There are still no duplicates.
Performancedba
source share