Modeling of a many-to-many relationship in a dimension

Hi, I use AWM and I need to create a dimension of book which includes books on their authors.

My table is: BRIDGE_TABLE_BOOKS (book_key, author_key)

Its data are for example:

Book - author
1 - 1
1 - 2
2 - 1
3 - 2
4 - 1
4 - 2
5 - 1

because a book can be written by 1 or more authors.
I wish that AWM could aggregate them with authors as follows:

1
-> 1
-> 2
-> 4
-> 5

2
-> 1
-> 3
-> 4

It is possible in AWM?

I do not know if find you it in the documentation, but it is a very simple test you can do yourself.

Thank you
Brijesh

Tags: Business Intelligence

Similar Questions

  • Is an extra Associative entity automatically created when we do a lot of many relationships?

    Hello

    I use SQL DEVELOPER DATA MODELER Version 4.0.2.840.

    My question is when we create many to-many between two main entities let PRODUCT and SALES (master). then we want to create a table associative entity SALES_DETAIL (details of sales)

    Is there an option that allows me to create an associative entity automatically with two associations of old masters. As it is automatically created with TOAD DATAMODELER.

    Thank you.

    Hello

    many-to-many relationship is transformed into associative array / intersection during the engineering to the relational model. If you add attributes to the relationship that they will turn to the columns of this table. Use "Show > attributes of the relationship" in the context menu of the diagram so that they are visible on the diagram.

    Philippe

  • How to create the Group of cache for many to many relationship tables?

    Hi, Chris,.
    Page 4-4 < < the user manual of the Oracle Database Cache in memory > > there is a saying,
    A child table cannot reference multiple parent tables.
    If there is a many-to-many relationship table in Oracle and I want to cache in TT, there is not a la carte approach that?
    Or I have to logically break his references to the two tables in one of them?
    I forgot to mention that I have a root table and one of its child tables is a many-to-many relationship table.

    Yes, that's correct. You can not exactly this model in TimesTen. You to omit some of the relationships so that things are defined in TimesTen as a pure parent/child relationship. You can also consider putting the tables into groups separate cache. Of course, there are consequences to this:

    1. the 'missing' relationship cannot be run by TimesTen. The application must respect/run it. If this is not some updates may not to be propagated to Oracle if they violate the relationship in Oracle.

    2 If the parallel AWT is configured (to improve the performance of spread) it will not be used for all tables where they lack of relationships. All updates to the tables in the order will apply.

    Chris

  • one-to-many relationship

    Read the article here...

    http://www.databaseprimer.com/relationship_1tox.html

    To illustrate the one-to-many relationship consider the table of sampling plan and data below:
    authors table
    ============
    author_id (primary key)
    LastName
    FirstName
    book_id (foreign key - link to table books book_id)


    table Books
    ===========
    book_id (primary key)
    title
    author_id  lastname  firstname   ->     book_id  title
    ---------  --------  ---------   ->     -------  ------
    0001       henry     john        ->     0001     a database primer
                                            0002     building datawarehouse
                                            0003     teach yourself sql
    0002       johnson   mary        ->     0004     101 exotic recipes
    0003       bailey    harry       ->     0005     visiting europe
    0004       smith     adam
    then how the data on the "authors" table columns 'author_id' and 'book_d '?

    don't know how to frame the table 'authors '...

    It would become the relation 1-1... is it normal?

    Please help how data will be in the "authors" table

    Thank you

    You do not want to have a database template that you have illustrated below. Why? Well to start tt does not pass even the first normal form. Secondly, if you had ever updated the author's name, you will need to update in several places, which could lead to problems of data integrity. A database designed to reduce redundancy, the structure that you have proposed increases it.

    If you had been modelling a one-to-many relationship, it would be more appropriate:

    CREATE TABLE authors
    ( author_id  NUMBER        PRIMARY KEY
    , last_name  VARCHAR2(200) NOT NULL
    , first_name VARCHAR2(200) NOT NULL
    );
    
    CREATE TABLE books
    ( book_id NUMBER        PRIMARY KEY
    , title   VARCHAR2(200)
    );
    
    CREATE TABLE authors_of_books
    ( author_id NUMBER NOT NULL REFERENCES authors(author_id)
    , book_id   NUMBER NOT NULL PRIMARY KEY REFERENCES books(book_id)
    );
    

    This models your one-to-many relationship with a "join" table or "bridge." The drawing above gives you the ability to change the author freely or to book the title attributes in the same place increases your data integrity.

    However, a many-to-many relationship may be more appropriate since multiple authors can write a book. So you would change the tables authors_of_books as follows:

    CREATE TABLE authors_of_books
    ( author_id NUMBER NOT NULL REFERENCES authors(author_id)
    , book_id   NUMBER NOT NULL REFERENCES books(book_id)
    , CONSTRAINT authors_of_books_pk PRIMARY KEY (author_id, book_id)
    );
    

    I hope this helps!

  • many-to-many relationship, recording is not linktable

    Got a little a legacy application that previously had flushAtRequestEnd set to true.  We have knocked down the flag, and now our many-to-many relationships do not work properly.  Save individual records very well, BUT the link table records are not created.  Here's how the entities are essentially in place.

    persistent component = "true" table = {'encounters'

    ...

    property

    name = "CaseFollowUps".

    SingularName = "CaseFollowUp".

    FieldType = "many-to-many.

    CFC = "FollowUp_NEW."

    LinkTable = "EncounterFollowUp."

    fkcolumn = "EncounterID."

    inversejoincolumn = "FollowUpID;

    ....

    public function addCaseFollowUp (fu) {} void

    ArrayAppend (variables. CaseFollowUps, fu);

    arguments.fu.addEncounter (this);

    }

    ...

    }

    persistent component = "true" table = {'FollowUp_NEW'

    property

    name = 'encounters '.

    SingularName = "meeting".

    FieldType = "many-to-many.

    CFC = "meeting".

    LinkTable = "EncounterFollowUp."

    fkcolumn = "FollowUpID.

    inversejoincolumn = "EncountersID";

    }

    I call the practical method of "addCaseFollowUp" a pre-existing meeting within a transaction.  No error thrown.  I see this code of Hibernate for the insertion of the FollowUp_NEW registration:

    Insert

    in

    FollowUp_NEW

    (Note, UserDateTime, UpdateDateTime, CreateDateTime, DispositionID, FollowUpRequestID, CommunicationTypeID, username)

    values

    (?, ?, ?, ?, ?, ?, ?, ?)

    But I don't see a request to Hibernate for the insertion of the EncounterFollowUp record.


    Suggestions?

    pnahtanoj wrote:

    But I don't see a request to Hibernate for the insertion of the EncounterFollowUp record.

    Is it perhaps a query that updates EncounterFollowUp? If there is nothing, then run the code as one only. This woud the fact rule the ORM session ended prematurely.

  • Cascading list of values with a many-to-many relationship

    Hi all

    I have three paintings; semester, subject and half of subject. Each semester has a lot of topics and a subject can be taught in several semesters.

    create table semester(
         id number not null,
         name varchar2(50) not null,
         primary key(id)
    );
    create table subject(
         id number not null,
         name varchar2(50) not not null,
         primary key(id)
    );
    create table semester_subject(
         id number not null,
         semester_id number not null,
         subject_id number not null,
         primary key(id),
         foreign key(semester_id) references semester(id),
         foreign key(subject_id) references subject(id),
         constraint semester_subject_uq unique(semester_id, subject_id)
    );
    
    

    EDIT: I have a page with a report that shows all students who are currently enrolled in the selected for the selected session object.

    There are two selection lists at the top of the report, one for the half and the other for the subject.

    What I try to do is when you select a semester in the half selection list, the topic selection list should contain only the subjects for the half of some (not all) in the subject of the painting.

    h

    If the relationship was of 1 to many that I could write to see half of value

    select name, id
    from semester
    order by 1
    
    

    and for the purpose of value list

    select name, id
    from subject
    where semester_id = :PX_SEMESTER
    
    

    But now that the relationship depends on the table of semester_subject, I can't find a way to achieve this and Googling has not helped.

    Thanks in advance for any help.

    I believe that this issue has also been implemented on stack overflow plsql - list of values cascading with many-to-many relationship - stack overflow and received a very wide response. If the OP has not yet verified, he may want to.

    (FYI: I'm not the person who answered there.)

  • How to implement many of many relationships?

    I've been google searching for articles on the implementation of many-to-many relationships and find as many hits I'm swamped.
    Someone at - he preferred an article on this topic?

    In my example, I have a number to-many between the table 'user' and 'project' of the table.
    Why do some articles indicate that the primary key of the table of links 'UserProject' contains two foreign keys for 'user' and 'project '? If we want to find all projects for a given "user.id", we not specifying the "project.id". It will not be reduced in a linear search then?

    I thought we should receive the 'fk_user' foreign key as the primary key and create an index of the "fk_project" (or vice versa). So if we specify the "user.id" we can quickly find all the corresponding values of 'project.id '.

    There are oracle-specific issues I should know about?

    Thank you
    Siegfried

    As you guessed, a primary key is intended to preserve the unique character.
    If you have a composite primary key, so if you provide columns in the predicate (where clause) that are the primary key columns, then they can help you with an effective search.

    If you have a requirement that you have aquery that always uses the 2nd and 3rd in the columns of the primary key, but never the first column, then you might want to add a composite index on these two columns.

    Remove the referential integrity of a production database is pretty much one of the worst things you can do.
    Think about the consequences: you'll have records of children who do not have a parent record or worse have the incorrect parent record. It is best to not leave a record get in the database to allow incorrect data.

    Incorrect data are a nightmare to fix, as its very difficult to find the source, and worse still, it can remain unnoticed for years.

    Your mantra should be to avoid bad data in the database. This by applying constraints at the level of the database.
    This means that all data entered with conform to these rules.

  • How to handle many-to-many relationship

    Hello friends,
    I'm confused, how do many many relationships in my application:

    I have agents and projects of two tables.
    Each agent can manage several projects.
    Each project can be handled by several agents.

    Example of table INIT_PROJECT:
    ID , PROJECT
    1  , X Tower
    2  , Y Tower
    3  , Z Tower
    Example of table INIT_AGEN:
    ID , Agent
    1  , A
    2  , B
    3  , C
    What is the correct way to join or to represent the relationship between the two tables to get a table that servers as a lookup table also:

    is - it to be like this:

    Example 1 in new_table
    Project_ID , Project_name, handled_by1, handled_by2, handled_by3, handled_by4
    1             , X tower        ,  A              , B
    or is it:
    ID            , Project_name, handled_by
    1             , X tower        ,  A            
    2             , X tower        ,  B              
    3             , X tower        ,  C   
    4             , Y tower        ,  A              
    5             , Y tower        ,  B              
    ........
    .....             
               
      
    Then, on a FORM I have lists of values.
    Projects and Agents.
    When the user selects a project, he or she can only see the agents engaged in this project in the list of Agents of values.
    I use a shuttle box for inserting the values "managed by".

    Or do like this:
    Example 2 of new_table
    ID , PROJECT,...,HANDLED_BY
    1  , X Tower,... ,A:B:C:D
    2  , Y Tower,... ,A:F:G:I
    3  , Z Tower,... ,F:A:I:W
    I have two lists of values:
    'Project name' and 'Agent '.
    When the user selects a project, then he must see only the values of the handled_by that are associated with this project only.

    I used this query to prepare the values in the list of officers of the value
    SELECT  
      distinct REGEXP_SUBSTR(handled_by, '[^:]+', 1, LEVEL)  d , REGEXP_SUBSTR(handled_by, '[^:]+', 1, LEVEL) r
       
      FROM  (
             SELECT   project, ROWNUM AS id
             ,      handled_by
             FROM   projects 
            ) where project = :P8_project
      CONNECT BY INSTR(handled_by, ':', 1, LEVEL-1) > 0
             AND id = PRIOR id
             AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL; 
    Can you please advice what is the right way?

    Best regards
    Fateh

    Somone was asked once to use the relation tables in that many many cases and I used it since with no problems until now.

    To apply in your case, I therefore project table, agent and a relationship table call PROJECT_AGENT_R which has

    (1) project
    (2) Agent_ID

    The primary key for each table as a foreign key.

    You can update the relationship via process page in your table when after you have created a project for an agent.

    Do not use string concatenated as your code above as it can be annoying and not really a good practice.

  • With a many to many relationship data in a table - recursive sql?

    Hello
    I'm trying to group data associated with a many to many relationships in a number of unique group using SQL only. The table looks like this.

    AMOUNT OF THE CHECK PLAN

    1 10
    A 15 2
    2 11 B
    3 12 B
    4 13 B
    4 16 C
    5 17 D

    The result should look like this. Since A is linked to 2, 1 and 2 correspond to the B and B are related to 3 and 4, 4 is related to C, these lines should be considered as a group. Any direction on where I should start looking for or if there is no function of Oracle that will be much appreciated. The version of oracle's 10g.

    CHECK THE PLAN AMOUNT GROUPID

    1-10-1
    2-15-1
    2 11 1 B
    3 12 1 B
    1 13 4 B
    4-16-1 C
    5 17 2 D



    CREATE THE TABLE PAS_DBA. GRPDEL
    (
    CHECKID VARCHAR2 (5 BYTE),
    PLAN OF INTEGER,
    AMOUNT NUMBER (6.2)
    );

    TOGETHER TO DEFINE
    Insert into PAS_DBA. GRPDEL
    (CHECKID, PLAN, SUM)
    Values
    ('A', 1, 10);
    Insert into PAS_DBA. GRPDEL
    (CHECKID, PLAN, SUM)
    Values
    ('A', 2, 15);
    Insert into PAS_DBA. GRPDEL
    (CHECKID, PLAN, SUM)
    Values
    ("B", 2, 11);
    Insert into PAS_DBA. GRPDEL
    (CHECKID, PLAN, SUM)
    Values
    ("B", 3, 12);
    Insert into PAS_DBA. GRPDEL
    (CHECKID, PLAN, SUM)
    Values
    ("B", 4, 13);
    Insert into PAS_DBA. GRPDEL
    (CHECKID, PLAN, SUM)
    Values
    ("C", 4, 16);
    Insert into PAS_DBA. GRPDEL
    (CHECKID, PLAN, SUM)
    Values
    (A ', 5, 17);
    COMMIT;

    Hello

    Good thing you're uisng Oracle 10. I don't think you could do this in pure SQL using any earlier version, but the CONNECT BY NOCYCLE feature, introduced in Oracle 10, makes this possible.

    WITH     got_groupname     AS
    (
         SELECT     checkid, plan, amount
         ,     MIN (CONNECT_BY_ROOT checkid)     AS groupname
         FROM     grpdel
         CONNECT BY NOCYCLE     (     checkid     =  PRIOR checkid
                           AND     plan     != PRIOR plan
                        )
                   OR     (     checkid != PRIOR checkid
                        AND     plan     =  PRIOR plan
                        )
         GROUP BY  checkid, plan, amount
    )
    SELECT       g.*
    ,       DENSE_RANK () OVER (ORDER BY groupname)     groupid
    FROM       got_groupname      g
    ORDER BY  checkid
    ,            plan
    ;
    

    Output:

    CHECK PLAN AMOUNT GROUPNAME GROUPID
    ----- ---- ------ --------- -------
    A        1     10 A               1
    A        2     15 A               1
    B        2     11 A               1
    B        3     12 A               1
    B        4     13 A               1
    C        4     16 A               1
    D        5     17 D               2
    

    You did not ask the groupname column, but I realized just to help show how it works. The subquery got_groupname associates each checkid with each other the checkid, regardless how many not deleted the two lines are. MIN finds the lowest checkid that each is bound, which generates a unique group identifier. Personally, I sould like usage of groupname as identifier. It tells you in the blink of an eye that B is a member of the same group has. However, it is not the same as that of a certain number, so if you need a number, you can derive from groupname with the analytical DENSE_RANK function.
    In many versions of Oracle, CONNECT BY queries do not work properly if they contain functions analyric. I don't know if this is the case in your version, but I don't think it's worth taking a chance. By CONNECT BY in a subquery no analytical function and then by the analytical function in a super-requete, we eliminate any chance of such a conflict.

    Thanks for posting the CREATE TABLE and INSERT statements; It is very useful.
    You want to be more useful? Do not publish the name of schema, PAS_DBA. Not many people who want to help you have a schema called PAS_DBA, and they probably won't create a. He probably doesn't. ' t help, either; probably, you connect PAS_DBA to create the table in any case.

  • Satellite 3000 - x 4: this model has how many memory slots?

    Hello

    I have a question on this model of Toshiba Satellite 3000 - x 4 PS301E - 000 K 8 - EN I took the chassis on this model today to do a repair for someone in my family work. When I took the VGA card, I discovered what looked like an another memory location.
    So my question is how many slots memory model there?

    I read online and I checked the profile page and they all point to this model with two memory locations.
    If this is the case then what is this thing that resembled a memory slot under the vga card?
    I had to buy another piece of RAM for this model today make three, but I decided on a little hand to check it out first.

    There are already two sticks of laptop memory already, 512 MB, and 128 MB. This model can take up to 1 GB.
    So, what do you think is there memory locations two or three on this model?

    Thank you

    Hello

    As far as I know, this unit has 2 memory slots and 1 slot for PC card for 2 Type II cards or 1 Type III card.
    Please also see this Toshiba product site:
    HTTP://UK.COMPUTERS.TOSHIBA-EUROPE.COM/CGI-BIN/TOSHIBACSG/SELECTED_PRODUCT_OPTION.JSP?SERVICE=UK&ACTION=PRIN T_WITH_BACK & PRODUCT_ID = 15932 & DISC_MODEL = 0

  • How to display a many-to-many relationship?

    Hello
    I wonder how would you present the master-detail-data of an n: m-relationship in the ADF?

    Suppose we have a table x and a y in the table, the xy table is our cross refrence table.

    I know that you could represent the realtionship via associations and display links, it is not clear to me how to display the detail data but I don't want to show the features of the cross-reference-table (xy).
    Instead, the data in the table there should be presented as details of table x.

    I hope you understand what I'm shooting.

    Thanks in advance.

    This can help you
    http://mjabr.WordPress.com/2011/05/21/how-to-implement-many-to-many-Association/

  • AWM - many-to-many relationship into a hierarchy of levels

    Hi, I use awm 11.2 and the problem is, how to create the relationship in this case:

    I have a customer dimension with a hierarchy that has the following levels:

    1. women
    2 date_of_birth
    3 countries
    4 city
    5 adresse_rue
    6 first_last_name


    Problem is the relationship between sex and date of birth, because they have the same number of dates of birth sex and vice versa.

    Is it possible to do in MN and how?

    Thank you

    Basically, you're right, but it still isn't a solution, if we have a case as I wrote.

    You can make your design work if you make each Member map to exactly one parent. Dates of birth must roll for exactly one sex. In other words, for the date of birth 01/01/1980 you will need a male and female version: M_1/1/1980 and F_1/1/1980. Everyone can have a description of 01/01/1980 or "1 January 1980" or whatever you want, so that they can be combined. But the value of full member must be different.

    So, technically, you have a solution to force it to work, but I still don't see how this particular dimension made a lot of sense as expected.

  • Repository many-to-many relationship, a side not updated.

    Hello.

    We have a point called creditCardInstallments descriptor and in a list of products.

    < table name = "lc_install_products" type = "multi" id-column-names = "install_id" >

    < property name = data type "productList" = "dΘfinir" column-name = 'product_id' component-type of element 'product' = repository = "/ atg/commerce/catalog/ProductCatalog '>

    < attribute name = "References" value = "true" / >

    < / property >

    < /table >

    And in the point-product descriptor, we are referencing the payments, only for display.

    < table name = "lc_install_products" type = "multi" id-column-names 'product_id' = >

    < property name = "installmentList" = "dΘfinir" column-name = "install_id" component-type of item = "creditCardInstallment" repository = data type ' / yyy/repository/zzzRepository " write = 'false' readable ="true">

    < attribute name = "References" value = "true" / >

    < / property >

    < /table >

    But when you add a product in a creditCardInstallment, is not updated the list of range in the product. Missing something?

    You must have your definition below to make it work, the only side reading would be fixed, and the accessible side in writing would be list.

    For creditCardInstallments point-descriptor having ownership of products available in writing

    And in the point-product descriptor, we are referencing the payments, only for display.

    Table constraints should be as below.

    KEY(install_id,SEQUENCE_NUM) primary SCHOOL;

    KEY (product_ID) FOREIGN REFERENCES CATA. DCS_product (product_ID);

    This should refer to the id column from the primary table where the installation item is registered

    KEY (install_id) FOREIGN REFERENCES CATA. INSTALLATIONs_TABLE (install_id);

  • One-to-many relationship repository

    Hello.

    When a repository item have a data type = "list" and a type of COMPONENT-component-, is there a way to remove the items referenced all when calling the Set accessor for the list?

    Because we have to replace the entire list and we do not want to keep the old data.

    I see two ways to possibly go about,

    First of all, as you substitute completely the list of itemdescriptor property, so when you set the listproperty for itemdescriptor in your code, first delete this list (which would be a component item type) put cascade = remove its property that is referenced in xml format, and then create the list with the values you want and that you assign this list to your itemdescriptor listproperty

    http://docs.Oracle.com/CD/E41069_01/platform.11-0/ATGRepositoryGuide/HTML/s0610cascadedelete01.html

    Another approach I can think in case you do not want delete listtype property is that you can use the type of consumer or the custom property for list of property and override the method for this property setPropertyValue.

    http://docs.Oracle.com/CD/E41069_01/platform.11-0/ATGRepositoryGuide/HTML/s0715userdefinedpropertytypes01.html

    in thing first method setPropertyvalue you can do is get all referenced items associated with this particular list item from the repository id, it is possible via Reposiory query, and then delete the referenced articles and then call the super.setPropertyValue method to set the new values in this listproperty.

  • Performance-to-many problem (using the model of the FAQ)

    After reading "HOW TO: post a request for tuning SQL - model showing statement" I gathered:

    I have included some general information at the bottom of the post

    The following SQL statement has been identified as a bad performance. It takes ~ 160 seconds to run, but similar (indicated below first statement) SQL statements run in ~ 1 second.

    SQL taking 160 seconds:
    SELECT
    a.*
    FROM
    table_a a
    INNER JOIN table_a_b ab ON a.id = ab.media_fk
    WHERE
    ab.channel_fk IN (7, 1);
    SQL in ~ 1 second or less
    ...
    ab.channel_fk IN (7);
    Or:
    ...
    ab.channel_fk IN (6, 9, 170, 89);
    The purpose of the SQL is to return lines from table_a associated table_b (not in SQL) through the junction table table_a_b.

    The version of the database is 10.2.0.4.0

    These are the parameters relevant for the optimizer:
    show parameter optimizer;
    
    NAME                                               TYPE        VALUE
    -------------------------------------------------- ----------- -----------------------------------------
    optimizer_dynamic_sampling                         integer     2
    optimizer_features_enable                          string      10.2.0.4
    optimizer_index_caching                            integer     0
    optimizer_index_cost_adj                           integer     100
    optimizer_mode                                     string      ALL_ROWS
    optimizer_secure_view_merging                      boolean     TRUE
    
    show parameter db_file_multi;
    
    NAME                                               TYPE        VALUE
    -------------------------------------------------- ----------- -----------------------------------------
    db_file_multiblock_read_count                      integer     16
    
    show parameter db_block_size;
    
    NAME                                               TYPE        VALUE
    -------------------------------------------------- ----------- -----------------------------------------
    db_file_multiblock_read_count                      integer     16
    
    select sname, pname, pval1, pval2 from sys.aux_stats$;
    
    SNAME                          PNAME                          PVAL1                  PVAL2
    ------------------------------ ------------------------------ ---------------------- -------------------
    SYSSTATS_INFO                  STATUS                                                COMPLETED
    SYSSTATS_INFO                  DSTART                                                07-18-2006 23:19
    SYSSTATS_INFO                  DSTOP                                                 07-25-2006 23:19
    SYSSTATS_INFO                  FLAGS                          0
    SYSSTATS_MAIN                  SREADTIM                       5.918
    SYSSTATS_MAIN                  MREADTIM                       7.889
    SYSSTATS_MAIN                  CPUSPEED                       1383
    SYSSTATS_MAIN                  MBRC                           8
    SYSSTATS_MAIN                  MAXTHR                         1457152
    SYSSTATS_MAIN                  SLAVETHR                       -1
    Here is the output of the EXPLAIN PLAN of:
    PLAN_TABLE_OUTPUT
    Plan hash value: 3781163428
    
    ----------------------------------------------------------------------------------------------------
    | Id  | Operation             | Name               | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT      |                    |  1352K|   771M|       | 60042   (3)| 00:05:56 |
    |*  1 |  HASH JOIN            |                    |  1352K|   771M|    27M| 60042   (3)| 00:05:56 |
    |*  2 |   INDEX FAST FULL SCAN| SYS_IOT_TOP_316310 |  1352K|    11M|       |  1816   (4)| 00:00:11 |
    |   3 |   TABLE ACCESS FULL   | TABLE_A            |  2190K|  1230M|       | 32357   (4)| 00:03:12 |
    ----------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - access(""AB"".""MEDIA_FK""=""A"".""ID"")
       2 - filter(""AB"".""CHANNEL_FK""=1 OR ""AB"".""CHANNEL_FK""=7)
    
    Note
    -----
       - 'PLAN_TABLE' is old version
    For reference, the EXPLAIN PLAN when using
    ...
    ab.channel_fk IN (6, 9, 170, 89);
    that runs in ~ 1 second is:
    PLAN_TABLE_OUTPUT
    Plan hash value: 794334170
    
    ----------------------------------------------------------------------------------------
    | Id  | Operation          | Name      | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT   |           |   143K|    81M|       | 58982   (3)| 00:05:50 |
    |*  1 |  HASH JOIN         |           |   143K|    81M|  2952K| 58982   (3)| 00:05:50 |
    |   2 |   INLIST ITERATOR  |           |       |       |       |            |          |
    |*  3 |    INDEX RANGE SCAN| C_M_INDEX |   143K|  1262K|       |  1264   (1)| 00:00:08 |
    |   4 |   TABLE ACCESS FULL| TABLE_A   |  2190K|  1230M|       | 32357   (4)| 00:03:12 |
    ----------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - access(""AB"".""MEDIA_FK""=""A"".""ID"")
       3 - access(""AB"".""CHANNEL_FK""=6 OR ""AB"".""CHANNEL_FK""=9 OR
                  ""AB"".""CHANNEL_FK""=89 OR ""AB"".""CHANNEL_FK""=170)
    
    Note
    -----
       - 'PLAN_TABLE' is old version
    Here is the output of SQL * Plus AUTOTRACE, including CALENDAR information:
    SQL> set autotrace traceonly arraysize 100;
    SQL> SELECT
      2  a.*
      3  FROM
      4  table_a a
      5  INNER JOIN table_a_b ab ON a.id = ab.media_fk
      6  WHERE
      7  ab.channel_fk IN (7, 1);
    
    1336148 rows selected.
    
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 3781163428
    ----------------------------------------------------------------------------------------------------
    | Id  | Operation             | Name               | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT      |                    |  1352K|   771M|       | 60042   (3)| 00:05:56 |
    |*  1 |  HASH JOIN            |                    |  1352K|   771M|    27M| 60042   (3)| 00:05:56 |
    |*  2 |   INDEX FAST FULL SCAN| SYS_IOT_TOP_316310 |  1352K|    11M|       |  1816   (4)| 00:00:11 |
    |   3 |   TABLE ACCESS FULL   | TABLE_A            |  2190K|  1230M|       | 32357   (4)| 00:03:12 |
    ----------------------------------------------------------------------------------------------------
    
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - access("AB"."MEDIA_FK"="A"."ID")
       2 - filter("AB"."CHANNEL_FK"=1 OR "AB"."CHANNEL_FK"=7)
    
    Note
    -----
       - 'PLAN_TABLE' is old version
    
    
    Statistics
    ----------------------------------------------------------
          10586  recursive calls
              0  db block gets
         200457  consistent gets
         408343  physical reads
              0  redo size
      498740848  bytes sent via SQL*Net to client
         147371  bytes received via SQL*Net from client
          13363  SQL*Net roundtrips to/from client
             49  sorts (memory)
              0  sorts (disk)
        1336148  rows processed
    The TKPROF output for that statement looks like the following:
    TKPROF: Release 10.2.0.4.0 - Production on Mon Oct 1 12:23:21 2012
    
    Copyright (c) 1982, 2007, Oracle.  All rights reserved.
    
    Trace file: ..._ora_4896.trc
    Sort options: default
    
    ********************************************************************************
    count    = number of times OCI procedure was executed
    cpu      = cpu time in seconds executing
    elapsed  = elapsed time in seconds executing
    disk     = number of physical reads of buffers from disk
    query    = number of buffers gotten for consistent read
    current  = number of buffers gotten in current mode (usually for update)
    rows     = number of rows processed by the fetch or execute call
    ********************************************************************************
    
    ALTER SYSTEM SET TIMED_STATISTICS = TRUE
    
    
    call     count       cpu    elapsed       disk      query    current        rows
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    Parse        1      0.00       0.00          0          0          0           0
    Execute      1      0.00       0.03          0          0          0           0
    Fetch        0      0.00       0.00          0          0          0           0
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    total        2      0.00       0.03          0          0          0           0
    
    Misses in library cache during parse: 0
    Parsing user id: 21
    ********************************************************************************
    
    SELECT
    a.*
    FROM
    table_a a
    INNER JOIN table_a_b ab ON a.id = ab.media_fk
    WHERE
    ab.channel_fk IN (7, 1)
    
    call     count       cpu    elapsed       disk      query    current        rows
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    Parse        1      0.01       0.00          0          0          0           0
    Execute      1      0.00       0.00          0          0          0           0
    Fetch        2     27.23     163.57     179906     198394          0          16
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    total        4     27.25     163.58     179906     198394          0          16
    
    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 21
    
    
    
    ********************************************************************************
    
    OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS
    
    call     count       cpu    elapsed       disk      query    current        rows
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    Parse        2      0.01       0.00          0          0          0           0
    Execute      2      0.00       0.03          0          0          0           0
    Fetch        2     27.23     163.57     179906     198394          0          16
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    total        6     27.25     163.62     179906     198394          0          16
    
    Misses in library cache during parse: 1
    
    
    OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS
    
    call     count       cpu    elapsed       disk      query    current        rows
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    Parse        0      0.00       0.00          0          0          0           0
    Execute      0      0.00       0.00          0          0          0           0
    Fetch        0      0.00       0.00          0          0          0           0
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    total        0      0.00       0.00          0          0          0           0
    
    Misses in library cache during parse: 0
    
        2  user  SQL statements in session.
        0  internal SQL statements in session.
        2  SQL statements in session.
    ********************************************************************************
    Trace file: ..._ora_4896.trc
    Trace file compatibility: 10.01.00
    Sort options: default
    
           1  session in tracefile.
           2  user  SQL statements in trace file.
           0  internal SQL statements in trace file.
           2  SQL statements in trace file.
           2  unique SQL statements in trace file.
          46  lines in trace file.
         187  elapsed seconds in trace file.
    DBMS_XPLAN. Output DISPLAY_CURSOR:
    select * from table(dbms_xplan.display_cursor('474frsqbc1n4d', null, 'ALLSTATS LAST'));
    
    PLAN_TABLE_OUTPUT
    SQL_ID  474frsqbc1n4d, child number 0
    -------------------------------------
    SELECT /*+ gather_plan_statistics */ c.* FROM table_a c INNER JOIN table_a_b ab ON c.id = ab.media_fk WHERE ab.channel_fk IN (7, 1)
    
    Plan hash value: 3781163428
    
    ---------------------------------------------------------------------------------------------------------------------------------------------------
    | Id  | Operation             | Name               | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  | Writes |  OMem |  1Mem | Used-Mem |
    ---------------------------------------------------------------------------------------------------------------------------------------------------
    |*  1 |  HASH JOIN            |                    |      1 |   1352K|   1050 |00:00:40.93 |     198K|    182K|    209K|    29M|  5266K| 3320K (1)|
    |*  2 |   INDEX FAST FULL SCAN| SYS_IOT_TOP_316310 |      1 |   1352K|   1336K|00:00:01.34 |   10874 |      0 |      0 |       |       |          |
    |   3 |   TABLE ACCESS FULL   | TABLE_A            |      1 |   2190K|   2267K|00:02:45.56 |     187K|    182K|      0 |       |       |          |
    ---------------------------------------------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - access(""AB"".""MEDIA_FK""=""C"".""ID"")
       2 - filter((""AB"".""CHANNEL_FK""=1 OR ""AB"".""CHANNEL_FK""=7))
    Thank you for reading I'm waiting for suggestions to improve the performance of this statement.

    -----

    H3. Backgroud

    There are many years my company made decided to maintain many-to-many relationships in our database using pipe delimited fields. An example of field value:
    '|ABC|XYZ|VTR|DVD|'
    Each delimited value refers to a unique "short" code TABLE_B (there is also a real digital foreign key to TABLE_B, which is what I use in the junction table). We are regularly using these columns with the next SQL style:
    ...
    WHERE
    INSTR(pipedcolumn, '|ABC|') > 0
    OR INSTR(pipedcolumn, '|XYZ|' > 0
    ...
    Appropriate indexes have been created over the years to make this process as soon a possible.

    We now have an opportunity to correct some of these errors of design and implementation of junction tables to replace the current field. Before that, we have decided to take a copy of a database to a client with the largest set of records and test. I created a new junction table:
    TABLE_A_B DDL:
    
        CREATE TABLE TABLE_A_B (
            media_fk NUMBER,
            channel_fk NUMBER,
            PRIMARY KEY (media_fk, channel_fk),
            FOREIGN KEY (media_fk) REFERENCES TABLE_A (ID),
            FOREIGN KEY (channel_fk) REFERENCES TABLE_B (ID)
        ) ORGANIZATION INDEX COMPRESS;
    
        CREATE INDEX C_M_INDEX ON TABLE_A_B (channel_fk, media_fk) COMPRESS;
    And the analysis on a pipe delimited field, populated by this new table.

    I then compared the performance of the following SQL:
    SELECT
    a.*
    FROM
    table_a a
    INNER JOIN table_a_b ab ON a.id = ab.media_fk
    WHERE
    ab.channel_fk IN (x, y, n); -- Can be Many Minutes
    
    --vs.
    
    SELECT
    a.*
    FROM
    table_a a
    WHERE
    INSTR(OWNERS,'|x|')    >0
    OR INSTR(OWNERS,'|y|')    >0
    OR INSTR(OWNERS,'|n|')    >0; -- About 1 second seemingly regardless
    When x, y, n are values that occur less frequently in the TABLE_A_B.CHANNEL_FK performance are comparable. However once the frequency of x, y, n increases, performance suffers. Here is a summary of the data CHANNEL_FK in TABLE_A_B:
    --SQL For Summary Data
    SELECT channel_fk, count(channel_fk) FROM table_a_b GROUP BY channel_fk ORDER BY COUNT(channel_fk) DESC;
    
    CHANNEL_FK             COUNT(CHANNEL_FK)
    ---------------------- ----------------------
    7                      780741
    1                      555407
    2                      422493
    3                      189493
    169                    144663
    9                      79457
    6                      53051
    171                    28401
    170                    19857
    49                     12603
    ...
    I noticed that whenever I use any combination of values that occur over approximately 800 000 times (i.e. IN (7, 1) = 780741 + 555407 = 1336148) then I get performance problems.

    I find it very difficult to accept that the old pipe delimited fields are a better solution (without taking into account any other than this search criterion!).

    Thank you for reading this far. I really look forward to suggestions on how to improve the performance of this statement.

    Published by: user1950227 on October 1, 2012 12:06
    Table of link renamed in DDL.

    davebcast wrote:

    The following SQL statement has been identified as a bad performance. It takes ~ 160 seconds to run, but similar (indicated below first statement) SQL statements run in ~ 1 second.

    Keep in mind that the enforcement timeframe has elapsed is a poor metric to use for benchmarking of SQL. The reason is that the same workload does not mean that the same elapsed execution time.

    The workload for example shows a block of 1000 readings. There will be a difference marked by this workload reading data of the slow physical disks, or making this workload by reading data from memory in memory cache. And if it happens to be in memory or on disk is a kind of "random" thing (depends on many environment and factors of execution).

    Thus, rather than measure the elapsed time and use it to compare, rather compare actual workloads. A workload of 500 block reading is faster and better than a block of 1000 DSL - despite the fact that a point of elapsed time can show the 500 read being slow (e/s physical) block a block of 1000 to read (e/s logic).

Maybe you are looking for

  • Can I ban Firefox to access specific web pages?

    If my son type a URL such as sex.com, I would like the software to deny access. I have a specific list of URLS.

  • 12 iTunes AppleScript list but the song

    I have this script. It allows to work. Now, when I run it, song after song are displayed at the top of their middle iTunes window (without playing) but they are not the one I selected :-) After it's over, I see that the good song are changed. What sh

  • Laptop - 14-ac000na: RAM upgrade

    Hello I have a laptop HP - 14 - ac000na (ENERGY STAR) computer laptop which came with only 2 GB of RAM, but for my daily use is not enough for me. I was wondering is it possible to increase the RAM for this laptop? Thank you in advance, sbudvytis.

  • How to obtain a backup copy of Windows XP due to move on to another PC

    My PC Gateway 2002 recently 'died' because the hard drive crashed and I moved to an iMac and recently installed "Parallels" to allow me to run Apple applications and Windows.  My original CD of Windows XP operating system has been damaged which preve

  • Win 10 technical preview will expire when the final version comes out?

    Hi all: I have Windows 8 Preview double version started with Windows 7 and since missing out on sales of windows 8 $40 student never succeeded in upgrading to the preview version. All works even better than win 7 because my PC has low spec, it stops