ob separate tabellen für verschiedene produkttypen erstellt werden sollen oder nicht?
<p>ich bin gerade dabei, eine datenbank zu entwerfen, und habe bedenken hinsichtlich meiner anfänglichen entwurfsentscheidungen ...</p><p>folgende produkttypen stehen zur verfügung ... modelle, teile, ersatzteilsätze und optionen.</p><p>option a (erstes design): ich plante separate tabellen für die oben genannten produkttypen. ich würde sagen, dass 75% der felder in jeder tabelle gleich sind.</p><p>ich habe jeden produkttyp aufgrund der assoziationen, die ich zwischen ihnen erstellen muss, als separate tabellen erstellt. beispielsweise kann ein modell viele optionen haben und eine option kann viele modelle haben. eine option kann auch viele teile haben und ein teil kann viele optionen haben ... und so weiter ...</p><p>option b: anstatt separate tabellen zu haben, könnte ich eine tabelle mit dem namen produkt erstellen, die modell-, teil-, ersatzteil-kits und optionen umfasst. ich könnte ein feld namens typ haben, um zwischen modell, optionen usw. zu unterscheiden. ich nehme an, ein nachteil ist, dass für bestimmte produkttypen niemals mehrere felder verwendet werden (links null). ich vermute, hier würden "nicht best practices" ins spiel kommen.</p><p>option b würde die komplexität des datenbankdesigns erheblich reduzieren. ich müsste mich auch nicht darum kümmern, auf eine reihe von tabellen zu verweisen, wenn ich daten für abfragen abrufe ...</p>
<p>wenn dies meine entwurfsentscheidung wäre, würde ich wahrscheinlich eher eine option c (modifizierte option a) wählen.</p><h3>erstens, warum nicht 'option b':</h3><p>zum einen gefällt mir die klarheit, dass jedes produkt seinen eigenen tisch hat. wenn es sich nur um eine große tabelle mit einem feld zur bestimmung des typs handelt, ist die beziehung nicht so klar.</p><p>zum anderen würde die indizierungsstrategie immer erfordern, dass dieses typfeld aufgelistet wird. da es sich nur um 4 typen handelt, ist die indexkardinalität extrem niedrig (<code>select * from product\_table where type='x'</code> führt im grunde sowieso einen vollständigen tabellenscan durch)</p><h3>option c.</h3><ul> <li>erstellen sie eine übergeordnete tabelle, die nur die spalten enthält, die alle typen gemeinsam nutzen</li> <li>erstellen sie jeden produkttyp als eigene tabelle mit ihren einzelnen spalten, mit einem zusätzlichen: ein link zur übergeordneten tabelle</li> <li>erstellen sie jede 'link'-tabelle: product\_option, model\_option usw. mit links zu den jeweiligen schlüsseln.</li> <li>für diejenigen mit wechselseitigen links (model\_option, option\_model) erstellen sie auch diese tabellen. dies erhöht die klarheit ihrer joins für alle, die sich das ansehen.</li> </ul><p>der nachteil ist die komplexität, sicherzustellen, dass waisen vermieden werden, wenn dinge aktualisiert/gelöscht werden, und zunächst die abfragen zu entwerfen, die diese tabellen verwenden.</p>
<p>ich denke, dies wirft weitere fragen und potenzielle probleme auf:</p><ol> <li>ist es wirklich notwendig, zwei getrennte arten von feldern für diese arten von zahlen zu haben? die tatsache, dass sie probleme haben, sie richtig zu kennzeichnen, bedeutet, dass dies wahrscheinlich zu einer schlechten benutzererfahrung führt.</li> <li>was ist, wenn der benutzer der meinung ist, dass die antwort eine dezimalstelle enthält, aber nur eine ganze zahl eingeben darf? sollten sie auf- oder abrunden?</li> <li>gibt es eine möglichkeit, sie nur mit einem nummernfeld zu versehen und den rest programmgesteuert zu erledigen? vielleicht dezimalstellen runden oder entfernen?</li> </ol><p>wenn sie sie nicht zu einem feldtyp kombinieren können, können sie sie auf jedem etikett explizit angeben:</p><ul> <li>geben sie eine zahl ein (dezimalstellen erlaubt)</li> <li>geben sie eine zahl ein (keine dezimalstellen)</li> </ul> <p>ich würde mich zur tabs-lösung beugen. im moment verwenden sie viel vertikalen raum, und wenn zwei listen übereinander liegen, ist die anzeige schwierig. stellen sie sich vor, sie haben diese beiden toolboxen aus ihrem beispiel übereinander.</p><p>der ansatz mit registerkarten spart platz und ermöglicht es ihnen, einige coole dinge zu erledigen, z. b. kleine hinweise im apple-stil auf der registerkarte, die die anzahl neuer oder wichtiger elemente in dieser registerkarte anzeigen. sie müssen nicht einmal per se "tabulatoren" sein - nur schaltflächen, die den status des bedienfelds unter ihnen umschalten.</p> <p>es gibt keine einfache antwort auf ihre frage, aber hier sind einige dinge, über die sie nachdenken sollten.</p><p>erstens ist die skalierung nicht das einzige, worüber man sich sorgen machen muss. was sie mit ihren daten machen, ist. wenn sie 500 tabellen mit 30 tb daten) haben und einfach oltp mit sehr wenig berichterstellung) arbeiten, werden sie wahrscheinlich nicht zu viele probleme haben es gibt 32-tb-datenbanken auf postgresql. gleichzeitig wird sich die leistung jedoch etwas verschlechtern, da die festplatte auf alles übertragen werden muss. wenn sie über 50 tb daten verfügen, aber häufig einen treffer von etwa 100 gb haben, können sie dies auch erstellen sie einen server mit genügend ram, um diesen teil der datenbank im speicher zu halten, und sie sind golden.</p><p>wenn sie jedoch versuchen, den modus (häufigster wert) aus 1 tb daten zu entfernen, spielt es keine rolle, welches system sie verwenden. dies wird <em> schmerzhaft sein </em> mit oder ohne scherben. (bearbeiten: sharding kann dieses problem <em> tatsächlich verschlimmern. </em>)</p><p>die hauptprobleme, auf die sie mit riesigen datenbanken unter mysql und postgresql stoßen werden, sind die tatsache, dass keine der beiden parallelen zwischen abfragen unterstützt. mit anderen worten, eine abfrage wird von einem einzelnen thread als einzelner block ausgeführt und kann nicht in teile zerlegt und separat ausgeführt werden. dies ist meistens ein problem, wenn große analytische abfragen über große datenmengen ausgeführt werden. hier kommen postgres-xc und green plum zur rettung, da sie speicher von ausführung trennen und dies auf koordinatorebene tun können. beachten sie, dass postgres-xc und green plum im wesentlichen intern sharding verwenden, die koordinatoren jedoch die gesamte konsistenz global erzwingen.</p><p>mit intraquery-parallelität können sie die abfrage aufteilen, verschiedene prozessoren/festplatten-e/a-kanäle teile davon ausführen lassen und teile der ergebnismenge zurückmelden, die zusammengestellt und an die anwendung zurückgegeben werden sollen. auch dies ist normalerweise am hilfreichsten bei analytischen und nicht bei transaktionsverarbeitungslasten.</p><p>die zweite sache ist, dass einige systeme wie vertica oder greenplum informationsspalten zusammen speichern. dies erschwert die verwendung des systems aus der perspektive von oltp] und verringert die leistung dort, erhöht jedoch die leistung für große analytische workloads drastisch. dies ist also ein workload-spezifischer kompromiss.</p><p>die antwort ist also, dass sie <em>, sobald sie über 1-2 tb in der größe) </em> stehen, möglicherweise mit einer zahl konfrontiert werden dies ist wiederum spezifisch für datenbanken, größe der arbeitssätze usw. an diesem punkt müssen sie sich jedoch wirklich für schneeflockensysteme entscheiden, dh solche, die einzigartig und auf ihre arbeitslast zugeschnitten sind.</p><p>dies bedeutet natürlich, dass die grenzwerte im allgemeinen nicht quantifizierbar sind.</p><p><strong>bearbeiten</strong>: ich habe jetzt mit einer 9-tb-datenbank gearbeitet, die eine mischung aus entscheidungsunterstützung und transaktionsverarbeitungs-workloads in postgresql verarbeitet. die größte herausforderung besteht darin, dass sie bei fragen, die große teile des datensatzes betreffen, eine weile auf die antwort warten müssen.</p><p>bei sorgfältiger beachtung der grundlagen (einschließlich indizes, autovakuum, funktionsweise auf niedrigem niveau usw.) und ausreichender rechenressourcen sind diese jedoch vollständig verwaltbar (und ich schätze, dass sie bis weit in den 30-tb-bereich in pg verwaltbar sind).</p><p><strong>edit2</strong>: sobald sie 100 tb erreicht haben, hängt es von ihrem datensatz ab, was funktioniert. ich arbeite gerade an einem, der nicht in diesen bereich skaliert, da er zuerst das limit von 32 tb pro tabelle in postgresql erreicht.</p> <p>verwenden sie <code>addfield()</code>. hier ist ein beispiel:</p><pre><code>$query = db\_select('super\_long\_table', 'slt'); $query-&gt;addfield('slt', 'mys\_super\_long\_field', 'mslf'); </code></pre><p>an <code>addfield()</code> übergebene argumente sind:</p><ul> <li>tabellenalias</li> <li>feld - ihr langer feldname wird hier sein</li> <li>alias ​​- ihr kurzfeld-alias ​​wird hier sein</li> </ul><p>lesen sie mehr darüber <a href="https://api.drupal.org/api/drupal/includes!database!select.inc/function/selectqueryinterface%3a%3aaddfield/7">hier</a> .</p> <p>es ist eine einschränkung des dbms - soweit ich weiß in allen. und das nicht nur beim hinzufügen einer spalte, sondern auch beim neuanordnen von spalten. wenn wir eine <code>unique</code> -einschränkung für <code>(a1, a2)</code> haben, können wir keine <code>foreign key</code> hinzufügen, die <code>references (a2, a1)</code>, es sei denn, es gibt eine eindeutige einschränkung für diese <code>(a2, a1)</code> das ist im wesentlichen redundant.</p><p>es wäre nicht besonders schwierig, dies als feature hinzuzufügen:</p><blockquote> <p>wenn es eine <code>unique</code> -einschränkung für <code>(a)</code> gibt, ist auch jede <code>(a, b, c, ..., z)</code> oder <code>(b,c, ...a, ...z)</code> kombination garantiert <code>unique</code>.</p> </blockquote><p>oder die verallgemeinerung:</p><blockquote> <p>wenn für <code>(a1, a2, ..., an)</code> eine <code>unique</code> -einschränkung besteht, ist auch jede <code>(a1, a2, ..., an, b1, b2, ..., bm)</code> - kombination oder neuanordnung <code>unique</code> garantiert.</p> </blockquote><p>es scheint, dass es nicht gefragt wurde oder nicht als hoch genug eingestuft wurde, um implementiert zu werden.</p><p>sie können jederzeit - im jeweiligen kanal - eine anfrage für die zu implementierende funktion stellen. oder implementieren sie es sogar selbst, wenn das dbms open source ist, wie postgres.</p> Also als Berater halte ich sämtliche Koppelprodukt für falsch. Wenn jemand VL macht soll er VL machen und icht mit der BAV oder Riester koppel. Das gleiche gilt auch für Riester und BAV. Jeder Vertrag einzeln bringt Flexibilität. Bei gekoppelten Verträgen weiß man nicht welche Kosten vbei welchem Produkt abgezogen werden etc. Es sind alles unteschiedliche Produkt und das sollten sie der Übersicht wegen auch bleiben. Gerade VL, kann man wählen ob man verlängert, neu abschließt oder sich den Betrag auch einmal auszahlen lässt für einen bestimmten Zweck. <p>die erste antwort ist gut und gibt einige strukturelle antworten, aber ein anderer ansatz besteht darin, darüber nachzudenken, was sie tun. bei modulen geht es darum, methoden bereitzustellen, die sie für mehrere klassen verwenden können - stellen sie sich diese als "bibliotheken" vor (wie sie es in einer rails app) sehen würden. bei klassen geht es um objekte, bei modulen um funktionen.</p><p>beispielsweise sind authentifizierungs- und autorisierungssysteme gute beispiele für module. authentifizierungssysteme funktionieren über mehrere klassen auf app-ebene (benutzer sind authentifiziert, sitzungen verwalten die authentifizierung, viele andere klassen verhalten sich je nach authentifizierungsstatus anders), sodass authentifizierungssysteme als gemeinsam genutzte apis fungieren.</p><p>sie können ein modul auch verwenden, wenn sie methoden für mehrere apps gemeinsam nutzen (auch hier ist das bibliotheksmodell gut).</p> <p>in stl gibt es einen entsprechenden typ, der <code>std::map</code> heißt.</p><p>es hat die gleiche grundfunktionalität wie ein .net dictionary, die implementierung ist jedoch sehr unterschiedlich. <code>std::map</code> basiert intern auf einer rot-schwarzen baumdatenstruktur, während <code>dictionary</code> intern eine hashtabelle verwendet.</p><p>wenn sie nur nach etwas suchen, das dasselbe verhalten aufweist, reicht <code>std::map</code> aus. wenn sie jedoch große datenmengen haben, müssen sie sich der unterschiedlichen leistungsmerkmale bewusst sein.</p> <p>hier ist eine liste der unterschiede. ich habe oracle-spezifische funktionen hervorgehoben, und hoffentlich kann die community auch den unterschied anderer anbieter hinzufügen. unterschiede, die bei den meisten anbietern üblich sind, können direkt unter den überschriften gehen, wobei die unterschiede unten hervorgehoben werden.</p><p><hr></p><h1>gesamtübersicht</h1><p>wenn sie alle zeilen schnell aus einer tabelle löschen möchten und wirklich sicher sind, dass sie dies tun möchten und keine fremdschlüssel für die tabellen haben, ist ein truncate wahrscheinlich schneller als ein delete .</p><p>verschiedene systemspezifische aspekte müssen berücksichtigt werden, wie im folgenden beschrieben.</p><p><hr></p><h1>anweisungstyp</h1><p>löschen ist dml, truncate ist ddl</p><p><hr></p><h1>commit und rollback</h1><p>variabel nach anbieter</p><p><strong>sql server</strong></p><p>abschneiden kann zurückgesetzt werden.</p><p><strong>postgresql</strong></p><p>abschneiden kann zurückgesetzt werden.</p><p><strong>oracle</strong></p><p>da ein truncate ddl ist, sind zwei commits vor und nach der ausführung der anweisung erforderlich. abschneiden kann daher nicht rückgängig gemacht werden, und ein fehler im abgeschnittenen prozess hat ohnehin ein commit ausgelöst.</p><p>siehe jedoch flashback weiter unten.</p><p><hr></p><h1>weltraumgewinnung</h1><p>löschen stellt keinen speicherplatz wieder her, truncate stellt speicherplatz wieder her</p><p><strong>oracle</strong></p><p>wenn sie die klausel reuse storage verwenden, werden die datensegmente nicht freigegeben. dies kann geringfügig effizienter sein, wenn die tabelle mit daten erneut geladen werden soll. die hochwassermarke wird zurückgesetzt.</p><p><hr></p><h1>zeilenumfang</h1><p>löschen kann zum entfernen aller zeilen oder nur einer teilmenge von zeilen verwendet werden. abschneiden entfernt alle zeilen.</p><p><strong>oracle</strong></p><p>wenn eine tabelle partitioniert ist, können die einzelnen partitionen isoliert abgeschnitten werden, sodass eine teilweise entfernung aller tabellendaten möglich ist.</p><p><hr></p><h1>objekttypen</h1><p>löschen kann auf tabellen und tabellen innerhalb eines clusters angewendet werden. abschneiden gilt nur für tabellen oder den gesamten cluster. (kann oracle-spezifisch sein)</p><p><hr></p><h1>datenobjektidentität</h1><p><strong>oracle</strong></p><p>das löschen wirkt sich nicht auf die datenobjekt-id aus. abschneiden weist jedoch eine neue datenobjekt-id zu. <em>sofern nicht</em> die tabelle hat seit ihrer erstellung noch nie eine einfügung vorgenommen. selbst eine einzelne zurückgesetzte einfügung führt zu einem neuen datenobjekt id, die beim abschneiden zugewiesen werden soll.</p><p><hr></p><h1>flashback (oracle)</h1><p>flashback funktioniert über alle löschvorgänge hinweg, ein abschneiden verhindert jedoch, dass der status vor der operation zurückgesetzt wird.</p><p>ab 11gr2 erlaubt dies die flashback archive-funktion, außer in der express edition</p><p> <a href="https://stackoverflow.com/questions/25950145/use-of-flashback-in-oracle">verwendung von flashback in oracle</a> <a href="http://docs.oracle.com/cd/e11882\_01/appdev.112/e41502/adfns\_flashback.htm#adfns638">http://docs.oracle.com/cd/e11882\_01/appdev.112/e41502/adfns\_flashback.htm#adfns638</a> </p><p><hr></p><h1>privilegien</h1><p>variable</p><p><strong>oracle</strong></p><p>das löschen kann für eine tabelle für einen anderen benutzer oder eine andere rolle erteilt werden, das abschneiden kann jedoch nicht ohne die drop any table-zuweisung erfolgen.</p><p><hr></p><h1>wiederholen rückgängig</h1><p>löschen erzeugt eine kleine anzahl von wiederholungen und eine große menge von rückgängig. abschneiden erzeugt jeweils eine vernachlässigbare menge.</p><p><hr></p><h1>indizes</h1><p><strong>oracle</strong></p><p>ein abgeschnittener vorgang macht unbrauchbare indizes wieder verwendbar. löschen geht nicht.</p><p><hr></p><h1>fremde schlüssel</h1><p>eine kürzung kann nicht angewendet werden, wenn ein aktivierter fremdschlüssel auf die tabelle verweist. die behandlung mit löschen hängt von der konfiguration der fremdschlüssel ab.</p><p><hr></p><h1>tischverriegelung</h1><p><strong>oracle</strong></p><p>das abschneiden erfordert eine exklusive tabellensperre, das löschen eine gemeinsame tabellensperre. durch das deaktivieren von tabellensperren können sie das abschneiden von operationen in einer tabelle verhindern.</p><p><hr></p><h1>löst aus</h1><p>dml-trigger werden nicht bei einem abschneiden ausgelöst.</p><p><strong>oracle</strong></p><p>ddl-trigger sind verfügbar.</p><p><hr></p><h1>remote-ausführung</h1><p><strong>oracle</strong></p><p>abschneiden kann nicht über eine datenbankverknüpfung ausgegeben werden.</p><p><hr></p><h1>identitätsspalten</h1><p><strong>sql server</strong></p><p>abschneiden setzt die reihenfolge für identity-spaltentypen zurück, löschen nicht.</p><p><hr></p><h1>ergebnis gesetzt</h1><p>in den meisten implementierungen kann eine <code>delete</code>-anweisung die gelöschten zeilen an den client zurückgeben.</p><p>z.b. in einem oracle pl/sql-unterprogramm können sie:</p><pre><code>delete from employees\_temp where employee\_id = 299 returning first\_name, last\_name into emp\_first\_name, emp\_last\_name; </code></pre> <ul> <li> <p><strong>wählen sie option 1, wenn</strong> die site enthält 'einfache' daten. zum beispiel einfacher text, ein kommentar oder etwas öffentliches</p> </li> <li> <p><strong>wählen sie option 3, wenn</strong> sie möchten nicht, dass der benutzer seitenelemente versehentlich ändert. zum beispiel würde ich in einem buchhaltungsprogramm definitiv option 3 verwenden, aber in einer einfachen notizblock-app (insbesondere auf mobilgeräten) würde ich definitiv option 1 wählen.</p> </li> </ul>