* Chris W
> I have two tables with a one to many relationship: boys and their toys.
>   I want to know if there are any advantages or disadvantages for each
> of the following two ways to create the tables.  I am mainly interested
> in performance.  Either way the insert and select queries aren't any
> more difficult than the other way.
>
> CREATE TABLE boy (
> BoyID INT NOT NULL AUTO_INCREMENT,
> name CHAR(30) NOT NULL,
> PRIMARY KEY (BoyID)
> );
>
> CREATE TABLE toy (
> BoyID INT NOT NULL,
> ToyID INT NOT NULL AUTO_INCREMENT,
> name CHAR(30) NOT NULL,
> PRIMARY KEY (BoyID,ToyID)
> );

This design is without a key for 'toys', the table could have been named
'boystoys' or similar to make that more clear. But that may be okay for you
if you are sure this design covers your needs. My immediate instinct says I
would need three tables, one for boys, one for toys and one for the
ownerships ("boystoys"). That way multiple boys could own the same toy
(sharing a toy, or if that is not relevant, sharing a "class of toys", like
'bicycle'), or toys could be sold/bought/traded, such that the owner of the
toy changes over time. But this will of course depend on the application.

The ToyID will start from 1 for each boy, is this something you need? If
yes, this is the way to do it. If no, I would go for the second design.

> OR
>
>
> #no change here
> CREATE TABLE boy (
> BoyID INT NOT NULL AUTO_INCREMENT,
> name CHAR(30) NOT NULL,
> PRIMARY KEY (BoyID)
> );
>
> #slight change here
> CREATE TABLE toy (
> ToyID INT NOT NULL AUTO_INCREMENT,
> BoyID INT NOT NULL,
> name CHAR(30) NOT NULL,
> PRIMARY KEY (ToyID)
> );

This design has a "real" toy table, the design is easy to extend, for
instance with a 'toytype' or 'boystoys' table, but it lacks an index on the
BoyID column. This will be slow when you select toys for a specific boy. It
can be fixed simply by adding an index on BoyID. And because MySQL can
optimize queries where all relevant info is in the index, one can often
benefit from combining keys in a single index:

ALTER TABLE toy ADD UNIQUE (BoyID,ToyID)

If you query like this:

SELECT boy.name
  FROM boy, toy
  WHERE
    toy.BoyID = boy.BoyID AND
    toy.ToyID < 100

This would give you the name of boys who own the 100 'oldest' toys (unless
you have deleted some toys...), and it would be able to use the combined
index, which means it does not need to physically read the toy table at all.
In contrast, this statment must also read the physical toy row to check the
name of the toy:

SELECT boy.name
  FROM boy, toy
  WHERE
    toy.BoyID = boy.BoyID AND
    toy.name = "bicycle"

This query would have benefited from an index on toy.name:

ALTER TABLE toy ADD INDEX (name)

  or

ALTER TABLE toy ADD UNIQUE (BoyID,name)

This final index could be used instead of the (BoyID,ToyID) index, if the
"ToyID < 100" type of criteria is not needed, but the boy.name column is.
Note that you would probably also need an index with 'name' as the first or
the only column, at least if there are many toys and you sometimes need to
search for a toy based on the name of the toy.

The 'name' column is a CHAR(30) (why not a VARCHAR?), you can index on a
substring, for instance:

ALTER TABLE toy ADD INDEX (name(10))

This would make an index on only the first ten characters of the toy name.
This can be faster in some cases, but I don't know which...

You should probably also have an index on boy.name.

If you need more specific information, please include some details about
your application: what kind of queries, how many simultaneous users, how
much data, what kind of hardware, what OS...

HTH,

--
Roger


-- 
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe:    http://lists.mysql.com/[EMAIL PROTECTED]

Reply via email to