views:

137

answers:

2

Hi! What would be an appropriate way to do this, since mySQL obviously doesnt enjoy this. To leave either partitioning or the foreign keys out from the database design would not seem like a good idea to me. I'll guess that there is a workaround for this?

Update 03/24:

http://opendba.blogspot.com/2008/10/mysql-partitioned-tables-with-trigger.html

http://stackoverflow.com/questions/1537219/how-to-handle-foreign-key-while-partitioning

Thanks!

+1  A: 

I would strongly suggest sharding using Date as the key for archiving data to archive tables. If you need to report off multiple archive tables, you can use Views, or build the logic into your application.

However, with a properly structured DB, you should be able to handle tens of millions of rows in a table before partitioning, or sharding is really needed.

Gary
Hi Gary. Sharding is definitely an interesting approach. I'm a bit scared about it resulting in a large number of JOINS being needed in the application logic?
Industrial
I would leave Foreign Keys in your design. Why do you feel you need to partition? We have tables with over one hundred million rows that perform excellent. Shading in my opinion is a better option that partitions. The current partition implementation in MySQL is just too limiting.
Gary
In another Question, I saw that you mentioned that your table has 400K records. You will see no performance benefit partitioning a table of such small size, assuming that it is properly indexed.
Gary
Hi, this table will certainly have more than 400 000 rows. I can't recall asking a question about a 400K table though :)
Industrial
http://stackoverflow.com/questions/2512200/foreign-keys-vs-partitioningYou mentioned 400K in that message. Maybe I misunderstood.
Gary
Hi Gary, that was for a completely different app with much smaller storage needs. Didn't remember that i'd posted that back then at all :)Thanks a lot for your points and your research :)
Industrial
+1  A: 

It depends on the extent to which the size of rows in the partitioned table is the reason for partitions being necessary.

If the row size is small and the reason for partitioning is the sheer number of rows, then I'm not sure what you should do.

If the row size is quite big, then have you considered the following:

Let P be the partitioned table and F be the table referenced in the would-be foreign key. Create a new table X:

CREATE TABLE `X` (
    `P_id` INT UNSIGNED NOT NULL,
        -- I'm assuming an INT is adequate, but perhaps
        -- you will actually require a BIGINT
    `F_id` INT UNSIGNED NOT NULL,
    PRIMARY KEY (`P_id`, `F_id`),
    CONSTRAINT `Constr_X_P_fk`
        FOREIGN KEY `P_fk` (`P_id`) REFERENCES `P`.`id`
        ON DELETE CASCADE ON UPDATE RESTRICT,
    CONSTRAINT `Constr_X_F_fk`
        FOREIGN KEY `F_fk` (`F_id`) REFERENCES `F`.`id`
        ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=INNODB CHARACTER SET ascii COLLATE ascii_general_ci

and crucially, create a stored procedure for adding rows to table P. Your stored procedure should make certain (use transactions) that whenever a row is added to table P, a corresponding row is added to table X. You must not allow rows to be added to P in the "normal" way! You can only guarantee that referential integrity will be maintained if you keep to using your stored procedure for adding rows. You can freely delete from P in the normal way, though.

The idea here is that your table X has sufficiently small rows that you should hopefully not need to partition it, even though it has many many rows. The index on the table will nevertheless take up quite a large chunk of memory, I guess.

Should you need to query P on the foreign key, you will of course query X instead, as that is where the foreign key actually is.

Hammerite
I just reviewed the MySQL manual page on partition restrictions, and found out that not only can you not have a foreign key on a partitioned table, you also cannot have a foreign key *pointing to* a partitioned table. That means that the above isn't quite good enough. You can fix it by removing (obviously) the constraint `Constr_X_P_fk` and adding a second stored procedure whose purpose is to allow deletion of rows in `P` and `X`. Obviously, you should then make sure that any deletes are carried out using the stored procedure, rather than by using a normal `DELETE` statement.
Hammerite