Welcome to Sign in | Help
in Search

Baza de date cu structura necunoscuta

Last post 10-25-2009, 3:06 AM by B_gd_n[ ]Sahlean. 5 replies.
Sort Posts: Previous Next
  •  10-22-2009, 9:29 AM 7723

    Baza de date cu structura necunoscuta

    Buna ziua

    Daca ma imi puteti sugera un mod de abordare asupra urmatoarei probleme

    Am de creat o baza de date care sa contina inregistrari de la mai multi clienti doar ca inregistrarile au o parte comuna (adica la fel pentru toti) si o parte care variaza de la un client la altu (fara sa stiu dinainte acele cimpuri). Problema este la cautarea inregistrarilor unde in functie de client trebe sa caut si dupa partea variabila
    ex.
     client1 (nume - varchar, datanasteri - datetime)
     client2 (nume - varchar, greutate - decimal)
     client2 (nume - varchar, nevasta - varchar, copii - int)

    As avea doua moduri de abordare a acestor rezolari

    1. cite o tabela customizata pentru fiecare client in parte care sa contina inregistrarile specifice clientului si o tabela care sa contina inregistrarile comune

    2. o tabela cu propietati (nume, tip) si pentru fiecare inregistrare din tabela principala sa fac un map "propietatea x" - "valoarea x" - "inregistrarea tabela comuna x"

    Ma omoara ideia de a cauta si complexitatea solutiei:
    prima varianta ar functiona dupa mine cel mai bine ma refer din punct de vedere al cautari - dar nu stiu cit de eficace este din punct de vedere al administratiei (o groaza de tabele pentru fiecare client)
    a doua varianta ar merge insa groaznic pentru cautare

    Ce metoda imi sugerati sa abordez - sau daca aveti o abordare mai inteligenta ...
    Va multumesc
    Petre

     

  •  10-22-2009, 10:02 AM 7724 in reply to 7723

    Re: Baza de date cu structura necunoscuta

    Alta abordare ar fi sa faci adaugi la tabela initiala de clienti( cu acele cimpuri comune) inca 100(?) de cimpuri, si inca o tabela Denumiri in care sa tii denumirile acelor 100(?) de cimpuri.
    Cauti in ea direct - doar afisezi pe interfata numele cimpurilor din tabela Denumiri...
    Vezi si sparse columns de la SqlServer 2008

    Ignat Andrei
    http://serviciipeweb.ro/iafblog
  •  10-22-2009, 10:26 AM 7725 in reply to 7724

    Re: Baza de date cu structura necunoscuta

    Alta varianta ar fi sa stochezi partea variabila intr-un camp de tip xml,ma rog e mai complicat pentru a trebuie sa stii xquery pentru a manipula datele din acel camp ...
    Secolul XXI ori va fi religios ori nu va fi deloc
  •  10-23-2009, 3:01 PM 7740 in reply to 7725

    Re: Baza de date cu structura necunoscuta

    Salut.

    Da, cred si eu ca XML ar fi solutia, deoarece vorbim de date semi-structurate.

    toate cele bune,
    calin

  •  10-23-2009, 8:00 PM 7742 in reply to 7723

    Re: Baza de date cu structura necunoscuta

    Dute la http://sqlcat.com/whitepapers/archive/2008/09/03/best-practices-for-semantic-data-modeling-for-performance-and-scalability.aspx si citeste documentul de acolo, care explica destul de detaliat cum se abordeaza si rezolva o astfel de problema.
    http://rusanu.com
  •  10-25-2009, 3:06 AM 7743 in reply to 7742

    Re: Baza de date cu structura necunoscuta

    [1] Dacă este vorba de SQL2008 atunci sparse columns (dupa cum a recomandat si Andrei).
    Uite o comparatie sparse columns vs. XML netipizat vs. XML tipizat.
    La mine scorul a fost următorul:
    sparse columns  80.922 MB
    XML netipizat  140.484 MB
    XML tipizat    181.703 MB


    CREATE TABLE Persoana1
    (
      IDPersoana INT IDENTITY(1,1) PRIMARY KEY,
      Nume VARCHAR(50) NOT NULL,
      DataNasterii DATETIME SPARSE NULL,
      Greutate DECIMAL SPARSE NULL,
      Nevasta VARCHAR(50) SPARSE NULL,
      Copii INT SPARSE NULL
    );
    GO

    CREATE TABLE Persoana2
    (
      IDPersoana INT PRIMARY KEY,
      Nume VARCHAR(50) NOT NULL,
      Alte XML NOT NULL
    );
    GO

    CREATE XML SCHEMA COLLECTION XMLAlte AS
    '<?xml version="1.0" encoding="utf-8" ?>
    <xs:schema blockDefault="" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:complexType name="TipAlteInformatii">
    <xs:choice>
    <xs:element name="DataNasterii" type="xs:string" />
    <xs:element name="Greutate" type="xs:decimal" />
    <xs:sequence>
    <xs:element name="Nevasta" type="xs:string" />
    <xs:element name="Copii" type="xs:integer" />
    </xs:sequence>
    </xs:choice>
    </xs:complexType>
    <xs:element name="Alte" type="TipAlteInformatii" />
    </xs:schema>'
    ;
    GO

    CREATE TABLE Persoana3
    (
      IDPersoana INT PRIMARY KEY,
      Nume VARCHAR(50) NOT NULL,
      Alte XML (XMLAlte) NOT NULL
    );
    GO

    DECLARE @i INT
    SET @i=1
    WHILE @i <= 1000000
    BEGIN
      DECLARE @tipPersoana INT
      SET @tipPersoana = ABS( CAST( CAST( NEWID() AS VARBINARY ) AS INT) )
      IF @tipPersoana % 3 = 0
        INSERT INTO Persoana1 ( Nume, DataNasterii ) VALUES ( NEWID(), CAST( CAST( CAST( NEWID() AS VARBINARY ) AS SMALLINT ) AS DATETIME ) )
      ELSE
      IF @tipPersoana % 3 = 1
        INSERT INTO Persoana1 ( Nume, Greutate ) VALUES ( NEWID(), CAST( RAND()*1000000 AS INT )%100 )
      ELSE
      IF @tipPersoana % 3 = 2
        INSERT INTO Persoana1 ( Nume, Nevasta, Copii ) VALUES ( NEWID() , NEWID() , CAST( RAND()*1000000 AS INT )%10 )
      
      SET @i = @i + 1
    END
    GO
    SELECT COUNT(*) AS NrTabelaPersoana1 FROM Persoana1
    GO

    INSERT INTO Persoana2
    SELECT IDPersoana,
      Nume,
      '<Alte>'+
      CASE
      WHEN DataNasterii IS NOT NULL THEN '<DataNasterii>'+CAST(DataNasterii AS VARCHAR(25))+'</DataNasterii>'
      WHEN Greutate IS NOT NULL THEN '<Greutate>'+CAST(Greutate AS VARCHAR(25))+'</Greutate>'
      WHEN Nevasta IS NOT NULL THEN '<Nevasta>'+Nevasta+'</Nevasta> <Copii>'+CAST(Copii AS VARCHAR(2))+'</Copii>'
      END+
      '</Alte>'
    FROM Persoana1
    GO
    SELECT COUNT(*) AS NrTabelaPersoana2 FROM Persoana2
    GO

    INSERT INTO Persoana3 (IDPersoana,Nume,Alte)
    SELECT IDPersoana,
      Nume,
      '<Alte>'+
      CASE
      WHEN DataNasterii IS NOT NULL THEN '<DataNasterii>'+CAST(DataNasterii AS VARCHAR(25))+'</DataNasterii>'
      WHEN Greutate IS NOT NULL THEN '<Greutate>'+CAST(Greutate AS VARCHAR(25))+'</Greutate>'
      WHEN Nevasta IS NOT NULL THEN '<Nevasta>'+Nevasta+'</Nevasta> <Copii>'+CAST(Copii AS VARCHAR(2))+'</Copii>'
      END+
      '</Alte>'
    FROM Persoana1
    GO
    SELECT COUNT(*) AS NrTabelaPersoana3 FROM Persoana3
    GO

    EXEC sp_spaceused 'dbo.Persoana1'
    EXEC sp_spaceused 'dbo.Persoana2'
    EXEC sp_spaceused 'dbo.Persoana3'


    [2] Pentru SQL < 2008 : partitionare pe orizantala > trei tabele separate + view cu union all + eventual triger-e INSTEAD OF INSERT/ DELETE/ UPDATE
View as RSS news feed in XML
Powered by Community Server (Commercial Edition), by Telligent Systems