I decided to try this out and see what happens.
Starting with the customers table, I ran this statement...
CREATE TABLE customers (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255),
created_at DATETIME,
updated_at DATETIME,
PRIMARY KEY (id)
);
I then created the following...
CREATE TABLE orders (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
customer_id INT(11) UNSIGNED,
created_at DATETIME,
updated_at DATETIME,
PRIMARY KEY (id, customer_id)
);
Note here if you use PRIMARY KEY (customer_id, id)
, it will result in a SQL error. This makes me believe the DB2 functionality you are trying to replicate will not work exactly the same on MySQL and we actually need a foreign key.
Then after filling these tables with test data, I ran the following...
EXPLAIN SELECT *
FROM customers
INNER JOIN orders ON customers.id = orders.customer_id;
This results in
+------+-------------+-----------+------+---------------+------+---------+------+--------+-------------------------------------------------+
| id | select_type | TABLE | TYPE | possible_keys | KEY | key_len | ref | ROWS | Extra |
+------+-------------+-----------+------+---------------+------+---------+------+--------+-------------------------------------------------+
| 1 | SIMPLE | customers | ALL | PRIMARY | NULL | NULL | NULL | 4 | |
| 1 | SIMPLE | orders | ALL | NULL | NULL | NULL | NULL | 262402 | USING WHERE; USING JOIN buffer (flat, BNL JOIN) |
+------+-------------+-----------+------+---------------+------+---------+------+--------+-------------------------------------------------+
I then added the foreign key...
ALTER TABLE orders ADD FOREIGN KEY customer_id (customer_id) REFERENCES customers (id) ON DELETE CASCADE ON UPDATE CASCADE;
And running the same exact explain query before with the same exact data, I now get the results...
+------+-------------+-----------+------+---------------+-------------+---------+-----------------------+-------+-------+
| id | select_type | TABLE | TYPE | possible_keys | KEY | key_len | ref | ROWS | Extra |
+------+-------------+-----------+------+---------------+-------------+---------+-----------------------+-------+-------+
| 1 | SIMPLE | customers | ALL | PRIMARY | NULL | NULL | NULL | 4 | |
| 1 | SIMPLE | orders | ref | customer_id | customer_id | 4 | cookbook.customers.id | 43751 | |
+------+-------------+-----------+------+---------------+-------------+---------+-----------------------+-------+-------+
As you can see, much fewer rows are being evaluated when I add the foreign key which is exactly what we are looking for. Surprising for me probably because I'm not a DBA, running the following produces the same results...
EXPLAIN SELECT * FROM orders WHERE customer_id = 4;
Even in this case, the composite primary key isn't doing anything for you however the foreign key is helping immensely.
With all that said, I think it's safe to forego the composite primary key and just set the id
up as primary and set the customer_id
up as a foreign key. This also gives you the benefit of being able to cascade deletes and updates.
$table->primary(array('id', 'customer_id'));
! – Marabocexplain select...
– user1669496orders
through the primary key index (customer_id, id) when I query the order table withcustomer_id
, sincecustomer_id
would be the first column of the primary key index. I've worked on DB2 and it was done that way, but i'm guessing MySQL does it differently? – user3489502