Quick question about relational one-to many database - mysql

I'm doing a venue/events database and I've created my tables and would like some confirmation from someone if I did everything right :)
I have 2 tables:
Venues
Events
The primary key of Venues is VENUE_ID, which is set to auto_increment. I have the same column in Events, which will contain the number of the Venue ID. This should connect them, right?
Also, the table engine is MyISAM.

It does not automatically link the tables to each others, and the referenced columns don't necessarily have to have the same name (in fact, there are situations where this is impossible: e.g. when a table has two columns that both reference the same column in another table).
Read up on foreign keys; they're standard SQL and do exactly what you want. Note, however, that the MyISAM storage engine cannot enforce foreign key constraints, so as long as any of the tables involved uses MyISAM, the foreign key declaration doesn't add much (it does, however, document the relationship, at least in your SQL scripts).
I suggest you use InnoDB (or, if that's feasible, switch to PostgreSQL - not only does it provide foreign key constraints, it also has full support for transactions, unlike MySQL, which will silently commit a pending transaction whenever you do something that's not supported in a transaction, with potentially devastating results). If you have to / want to use MySQL, I suggest you use InnoDB for everything, unless you know you need the extra performance you can get out of MyISAM and you can afford the caveats. Also keep in mind that migrating large tables from MyISAM to InnoDB later in production can be painful or even outright impossible.

Your db structure is right.
You can use Innodb for adding foreign key contraints. Also don't forget to add index to the second table for faster joining two tables.
More info about FK http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
Note to comments:
Innodb allows you to make concurrent select/(insert/update) but MyIsam allows you to do the same things if you don't delete from MyIsam table. Otherwise MyIsam will lock your whole table.

Generally, yes. This is how you indicate a one-to-many relation between two tables. You may also specifically encode the relationship into the database by setting up a Foreign Key constraint. This will allow add'l logic such as cascading.

Related

MySql, engine:MyISAM, what index can be used instead of Foreign Key

I am creating a MySQL DB with MyISAM engine. I believe it is not possible to use foreign key with MyISAM. All the tables in DB have primary key, but all of them also need at least 1 FK.
1)Can any of the other options available (apart from PK): such as: UNIQUE, INDEX FULLTEXT or SPATIAL be used instead of FK that serves the same purpose?
2)If the answer to 1) is <0, what else can be done (except changing to InnoDB)?
It smells like you don't understand the purpose of a FOREIGN KEY. It is for one thing:
Referential integrity. But this is not a requirement, it is a feature that you can live without if you write good code.
A FK has a side effect: It builds an INDEX. But the only purpose of an index is:
Faster lookups. This includes WHERE clauses and JOINs between tables.
It is a somewhat common misconception that you need a FK to JOIN two tables. That is totally false. Nor is an INDEX required.
Bottom line...
Get the schema written and your queries written.
When you hit performance problems (which might happen when you have a few thousand rows in a table), look into adding INDEX(es).
Regardless, move to InnoDB.
The answer to your question is no, there is no real alternative in MyISAM.
Depending on your version of MySQL. You could look at before triggers but you would have to write a trigger in place of each foreign key that you would normally create under Innodb. This isn't recommended though, you're reinventing the wheel by doing this and could encounter problems if the logic in the trigger is incorrect. Defeating the purpose.
Unless there's a feature of MyISAM that you can't get with Innodb, I would highly recommend using Innodb and optimizing where necessary.
Hope that helps.
No, MyISAM does not support FK constraints. You can't enforce referential integrity in MyISAM. You could code it yourself using triggers, but this is not recommended.
You can create an index, either unique or non-unique, to provide query optimization for searching or sorting. But this does not provide referential integrity.
ALTER TABLE MyTable ADD INDEX (column1, column2);
or
ALTER TABLE MyTable ADD UNIQUE INDEX (column1, column2);
Don't use a UNIQUE index unless you want the columns to have a unique constraint in addition to the index.
Don't use FULLTEXT or SPATIAL index unless you mean to do fulltext or spatial queries. Those indexes are for those special purposes, and in general they are not interchangeable with ordinary indexes.
And for the record, you should be using InnoDB.

MySQL does FK reduce insert/update operations?

Does anybody know, does FK reduce insert/update operations in MySQL?
I use engine INNODB.
Having a FK on a table implicitly creates (and maintains) an index.
When doing certain write operations, the FK's implicit INDEX is checked to verify the existence of the appropriate row in the other table. This is a minor performance burden during writes.
When doing SELECT ... JOIN for which you failed to explicitly provide the appropriate index, the implicit index produced by some FK may come into play. This is a big benefit to some JOINs, but does not require an FK, since you could have added the INDEX manually.
If the FK definition includes ON DELETE or UPDATE, then even more work may be done, especially for CASCADE. The effect of CASCADE can be achieved with a SELECT plus more code -- but not as efficiently as letting CASCADE do the work.
FKs are limited in what they can do. Stackoverflow is littered with question like "How can I get an FK to do X?"
Does any of this sound like "reducing insert/update operations"?
does FK reduce insert/update operations in MySQL?
It's not about MySQL but yes it does. Creating FK on a column will create a secondary index and thus upon DML operation those indexes needs to be updated as well in order to have a correct table statistics. So that, DB optimizer can generate a correct and efficient query plan

MySQL & FK constraints

Is there any point in defining FK constraints in MyISAM? MyISAM doesn't enforce referential integrity, right? So maybe there is no point to FK constraints.
Although MySQL parses and ignores them on MyISAM tables, I think you should write them for three reasons.
Preparation: Your code will be ready when MyISAM gets there.
Documentation: Everybody will know what you intended. Much better than trying to figure out where foreign keys are supposed to go a year from now.
Insurance: If MyISAM fails you, you can move directly to InnoDB tables.
http://dev.mysql.com/doc/refman/5.0/en/ansi-diff-foreign-keys.html
At the end of second column:
At a later stage, foreign key constraints will be implemented for
MyISAM tables as well.
apparently in mysql 5.0 'latter stage' has not come yet
constraints are needed as an additional validation

Session / Log tables keys design question

I have almost always heard people say not to use FKs with user session and any log tables as those are usually High write tables and once written data almost always tays forever without any updates or deletes.
But the question is I have colunms like these:
User_id (link a session or activity log to the user)
activity_id (linking the log activity table to the system activity lookup table)
session_id (linking the user log table with the parent session)
... and there are 4-5 more colunms.
So if I dont use FKs then how will i "relate" these colunms? Can i join tables and get the user info without FKs? Can i write correct data without FKs? Any performance impact or do people just talk and say this is a no no?
Another question I have is if i dont use FKs can i still connect my data with lookup tables?
In fact, you can build the whole database without real FKs in mysql. If you're using MyISAM as a storage engine, the FKs aren't real anyway.
You can nevertheless do all the joins you like, as long as the join keys match.
Performance impact depends on how much data you stuff into a referenced table. It takes extra time if you have a FK in a table and insert data into it, or update a FK value. Upon insertion or modification, the FK needs to be looked up in the referenced table to ensure the reference integrity.
On highly used tables which don't really need reference integrity, I'd just stick with loose columns instead of FKs.
AFAIK InnoDB is currently the only one supporting real foreign keys (unless MySQL 5.5 got new or updated storage engines which support them as well). Storage engines like MyISAM do support the syntax, but don't actually validate the referential integrity.
FK's can be detrimental in "history log" tables. This kind of table wants to preserve the exact state of what happened at a point in time.
The problem with FK's is they don't store the value, just a pointer to the value. If the value changes, then the history is lost. You DO NOT WANT updates to cascade into your history log. It's OK to have a "fake Foreign key" that you can join on, but you also want to intensionally de-normalize relevant fields to preserve the history.

When should you choose to use InnoDB in MySQL?

I am rather confused by the hurt-mongering here.
I know how to do them, see below, but no idea why? What are they for?
create table orders (order_no int not null auto_increment, FK_cust_no int not null,
foreign key(FK_cust_no) references customer(cust_no), primary key(order_no)) type=InnoDB;
create table orders (order_no int not null auto_increment, FK_cust_no int not null,
foreign key(FK_cust_no) references customer(cust_no), primary key(order_no));
InnoDB is a storage engine in MySQL. There are quite a few of them, and they all have their pros and cons. InnoDB's greatest strengths are:
Support for transactions (giving you support for the ACID property).
Row-level locking. Having a more fine grained locking-mechanism gives you higher concurrency compared to, for instance, MyISAM.
Foreign key constraints. Allowing you to let the database ensure the integrity of the state of the database, and the relationships between tables.
Always. Unless you need to use MySQL's full-text search or InnoDB is disabled in your shared webhost.
InnoDB:
The InnoDB storage engine in MySQL.
InnoDB is a high-reliability and high-performance storage engine for MySQL. Key advantages of InnoDB include:
Its design follows the ACID model, with transactions featuring commit, rollback, and crash-recovery capabilities to protect user data.
Row-level locking (without escalation to coarser granularity locks) and Oracle-style consistent reads increase multi-user concurrency and performance.
InnoDB tables arrange your data on disk to optimize common queries based on primary keys. Each InnoDB table has a primary key index called the clustered index that organizes the data to minimize I/O for primary key lookups
To maintain data integrity, InnoDB also supports FOREIGN KEY referential-integrity constraints.
You can freely mix InnoDB tables with tables from other MySQL storage engines, even within the same statement. For example, you can use a join operation to combine data from InnoDB and MEMORY tables in a single query.
InnoDB Limitations:
No full text indexing (Below-5.6 mysql version)
Cannot be compressed for fast, read-only
More Details:
Refer this link
I think you are confused about two different issues, when to use InnoDB instead of MyISAM, and when to use foreign key (FK) constraints.
As for the first issue, there have been many answers that do a great job of explaining the differences between MyISAM and InnoDB. I'll just reiterate that, in tvanfosson's quote from an article, MyISAM is better suited for system with mostly reads. This is because it uses table level locking instead of row level like InnoDB, so MyISAM can't handle high concurrency as well, plus it's missing features that help with data integrity such as transactions and foreign keys (again, already mentioned by others).
You don't have to use FK constraints in your data model. If you know what the relationships between your tables is, and your application is free of bugs, then you'll get by without FKs just fine. However, using FKs gives you extra insurance at the database layer because then MySQL won't let your application insert bad data based on the constraints that you created.
In case you aren't clear on why to use primary keys (PK), making a column such as id_order for example the PK of the orders table means that MySQL won't let you INSERT the same value of id_order more than once because every row in a PK column must be unique.
A FK would be used on a table that has a dependency on another table, for example, order_items would have a dependency on orders (below). id_order_items is the PK of order_items and you could make id_order_items the FK of the orders table to establish a one-to-many relationship between orders and order_items. Likewise, id_item could be a FK in the order_items table and a PK in the items table to establish a one-to-many relationship between order_items and items.
**Then, what the FK constraint does is prevent you from adding an id_item value to theorder_itemstable that isn't in theitemstable, or from adding aid_order_itemstoordersthat isn't in theorder_items `table.
All a FK does is insure data integrity, and it also helps convey relationships among your tables to other developers that didn't write the system (and yourself months later when you forget!), but mainly it's for data integrity.**
Extra credit: so why use transactions? Well you already mentioned a quote that says that they are useful for banking system, but they are useful in way more situations than that.
Basically, in a relational database, especially if it's normalized, a routine operation such as adding an order, updating an order, or deleting an order often touches more than 1 table and/or involves more than one SQL statement. You could even end up touching the same table multiple times (as the example below does). Btw Data Manipulation Language (DML) statements (INSERT/UPDATE/DELETE) only involve one table at a time.
An example of adding an order:
I recommend an orders table and an order_items table. This makes it so can you can have a PK on the id_order in the orders table, which means id_order cannot be repeated in orders. Without the 1-to-many orders - order_items relationship, you'd have to have multiple rows in the orders table for every order that had multiple items associated with it (you need an items table too for this e-commerce system btw). This example is going to add an order and touch 2 tables in doing so with 4 different INSERT statements.
(no key constraints for illustration purposes)
-- insert #1
INSERT INTO orders (id_order, id_order_items, id_customer)
VALUES (100, 150, 1)
-- insert #2
INSERT INTO order_items (id_order_items, id_item)
VALUES (4, 1)
-- insert #3
INSERT INTO order_items (id_order_items, id_item)
VALUES (4, 2)
-- insert #4
INSERT INTO order_items (id_order_items, id_item)
VALUES (4, 3)
So what if the insert #1 and insert #2 queries run successfully, but the insert #3 statement did not? You'd end up with an order that was missing an item, and that would be garbage data. If in that case, you want to rollback all the queries so the database is in the same state it was before adding the order and then start over, well that's exactly what transactions are for. **You group together queries that you either want all of them done, or in case of an exception, then none at all, into a transaction.
So like PK/FK constraints, transactions help insure data integrity.**
In your example, you create foreign keys. Foreign keys are only supported for InnoDB tables, not for MyISAM tables.
You may be interested in this article from Database Journal which discusses the InnoDB table type in MySQL.
Excerpt:
Last month we looked at the HEAP table
type, a table type which runs entirely
in memory. This month we look at
setting up the InnoDB table type, the
type of most interest to serious
users. The standard MyISAM table type
is ideal for website use, where there
are many reads in comparison to
writes, and no transactions. Where
these conditions do not apply (and
besides websites, they do not apply
often in the database world), the
InnoDB table is likely to be the table
type of choice. This article is aimed
at users who are familiar with MySQL,
but have only used the default MyISAM
table type.
I wouldn't be put off by the other question. Keep proper backups of your database, of any type -- and don't drop tables by accident ;-) -- and you'll be ok whatever table type you choose.
In general for me the most important point is that InnoDB offers per row locking, while MyISAM does look per table. On big tables with a lot of writes this might make a big performance issue.
On the otherhand MyISAM table have a easier file structure, copying and repairing table on file level is way easier.
A comment has a command to convert your databases to InnoDB here.
Everywhere! Deprecate myisam, innodb is the way to go. Is not only about performance, but data integrity and acid transactions.
A supplement to Machine and knoopx's answer about transactions:
The default MySQL
table type, MyISAM, does not support
transactions. BerkeleyDB and InnoDB
are the transaction-safe table types
available in open source MySQL,
version 3.23.34 and greater.
The definition of the transaction and an banking example
A transaction is a sequence of
individual database operations that
are grouped together. -- A good
example where transactions are useful
is in banking.
Source of the citations