Skoro klucze są identyczne to jaki jest sens ich dublowania? Masz kolumny, która zawsze są identyczne, co jest zwyczajnym marnotrawieniem miejsca. Na dodatek masz na tych kolumnach indeks jeszcze założony, co jest już podwójnie niekorzystne pod względem zajętości. Wystarczy, że jest ta kolumna tylko raz. To co zrobiłeś nazywa się partycjonowaniem pionowym tabeli. A co jest w tym złego? Popatrz na to tak... Zrób jeszcze 10 takich kolumn w drugiej tabeli

To też tylko referencje "do siebie". Samo powiązanie masz już zrobione i nie musisz nic zmieniać. Zauważ, że id_uzytkownik(PK), da_id(FK) rozdzielone nie są potrzebne. Bo przecież ktoś, kto jest użytkownikiem ma także dane autentykacyjne, a więc id_uzytkownik jest równoznaczne wtedy z da_id i tworzenie kolejnego klucza jest bezcelowe, skoro nie widzę byś przewidywał, żeby ktoś miał więcej niż 1 rolę (nie można być jednocześnie userem, adminem i sprzedawcą).
Poza tym widzę, że nie zauważasz faktu, iż tabela może zawierać "luki". Kto powiedział, że każda tabela musi mieć kolumnę z autoinkrementującym się id? Skoro pewne wiersze nie muszą mieć wpisu w tej tabeli to je olej(!) i zwyczajnie do niej nie dodawaj(!). Dla silnika bazy nie ma znaczenia zbytniego czy po rekordzie 1 jest 2 czy 100. Może po rekordzie 100 być nawet 32, czyli teoretycznie wcześniejszy. I tak podczas JOINowania jeśli nie napotka pasującego wiersza, to w brakujących kolumnach wstawi NULL. Twoim kluczem głównym i jednocześnie kluczem obcym w userach jest id_uzytkownik. To czego nie zauważasz, to fakt, że ów rekord nie zawsze musi być dodawany. Wiem, że wrzucanie on cascade lub innych modyfikatorów jest wygodne i zrzuca z odpowiedzialności za poprawność, ale może się kończyć tak jak podałeś -> wstawianiem rekordów zbędnych. Dla mnie sensowne jest jedynie wstawianie rekordu do tabeli userów gdy wykryje, że ma do czynienia z klientem. Ściąga to ze mnie konieczność późniejszego kombinowania czy wpis w tabeli user to rzeczywiście user czy nie. Ja to po prostu wtedy wiem. Nie user nie ma tam wpisu i tyle.
Przykład? Sam mam tabelę, gdzie mam kilka różnych "ról". Jest user, jest klient itp. Mam więc główną tabelę z danymi usera niezbędnymi do logowania, tabelę z danymi usera i tabelę z danymi klienta. Powiązanie jest takie, że klient jest jednocześnie userem, ale już w drugą stronę nie. W efekcie mam tak, że mam strukturę na zasadzie:
auth_id, typ(user, firma, admin czy jakieś inne), inne kolumny
profil_id (równy auth_id), inne kolumny
klient_id (równy auth_id), inne kolumny
Czy ilość rekordów we wszystkich tabelach jest identyczna? Ależ skąd! Tylko auth i profil mają tyle samo. Klientów jest zdecydowanie mniej, ponieważ istnieją w tej tabeli tylko rekordy tych, których auth.typ = klient. U Ciebie jest z tego co widzę identycznie.
Nawet gdybym na pałę napisał JOIN, gdzie auth_id = klient_id to mi baza to zrobi, ale sama uzupełni brakujące dane nullami. Mogę nawet JOINować wszystkie trzy po owych id i też dostanę wyniki. Ale tylko klienci będą mieć wszystkie. Jeśli zaś będę chciał tylko klientów to główna tabelą do której będę łączył pozostałe będzie już nie auth, ale klient. To mi wyeliminuje userów. Pozbywam się dodatkowego WHERE typ=klient z zapytania. Nie po to wprowadza się kilka metod JOIN (left, right, inner, cross, natural, outer) by się różniły nazwami