I create the foreign key to one field in my table, the index was automatically created to that field. why the index was automatically created to foreign key fields?
The indices are created on foreign keys to improve performance. If you have a foreign key is common to want to get related items, an index allows you to quickly get these items. Also the conditions imposed on foreign keys (delete, update) take advantage of the index to work fast. Finally you need to perform integrity checks when creating foreign keys, this requires performing searches, these searches take advantage of the indexes.
Foreign Key fields link to the contents of fields in other tables.
If we create a table like so:
Table Patient
id
name
address
And a table Illness
Table Illness
id
patient_id foreign key to patient.id
description
MySQL checks to see if a foreign link to table patient actually matches up with the id in Illness. It also does the reverve, if a patient is deleted, it checks to make sure it is not referenced in illness.
In order to do this effiently it needs to index these fields, otherwise it will have to do a spend too much time doing full table lookups.
Besides, the word key is a synonym for index so it makes sense to index keys :-).
Related
I know that foreign keys need not reference only primary keys but they can also reference a field that has a unique constraint on it. For my scenario, I am setting up a quiz where for each test, I have a set of questions. My table design is like this
The point is, in my 2nd table where I will put all the answer options, I want the question number field to link to the first table question number. How do I do this? Or is there an alternative to this design?
Thank you
Ideally there should be a question_id primary key column in the test_question table, and you would use this as the foreign key in the test_answer table.
With your composite primary key in the test_question table, you should make a corresponding composite foreign key:
CONSTRAINT FOREIGN KEY (test_id, question_no) REFERENCES test_question (test_id, question_no)
This is in addition to the foreign key just for the test_id column.
Add another table purely for answers, and link them via the question_no field.
A DB table should hold information on one sort of item. Questions and answers are separate sorts of information so should be in separate tables. Adding a separate table also allows changes to questions and answers independently. Additionally, if they are separate, you could add a language field to each table and have a multi-lingual quiz
Short answer:
You can JOIN on any columns or expressions. There is no "requirement" for a FOREIGN KEY, PRIMARY KEY, UNIQUE, or anything else.
Long answer:
However,... For performance (in large tables), some things make a difference.
If you are JOINing to a PK, Unique key, or even an indexed column, the query cold run faster.
Why have a FOREIGN KEY? An FK is two things:
A "constraint" that says that the value must exist in the other table. Also, with things like ON DELETE CASCADE, it can provide actions to take if the indicated row is removed. The constraint requires looking in the other table each time a write occurs (eg INSERT).
An Index. That is, specifying a FK automatically adds an INDEX (if not already present) to make the constraint faster.
Getting the id
Here is the "usual" way to do a pair of inserts, where you need the second to 'point' to the first:
INSERT INTO t1 ... -- with an AUTO_INCREMENT id
grab LAST_INSERT_ID() -- that id
INSERT INTO t2 ... -- and include the id from above
For AUTO_INCREMENT to work it must be the first column of some key. (Note: a PRIMARY KEY is a UNIQUE is a key (aka INDEX).)
Optionally you can specify a FK on the second table to point out the connection between the tables.
And, as spelled out in other answers, a FK could involve more than one column.
Entities and Relations
Sometimes, a set of tables like yours is best 'designed' this way:
Determine the "entities": users, tests, questions, answers
Relations and whether they are 1:1, 1:many, or many:many... Users:test is many-to-many; tests:questions is 1:many (unless you want questions to be shared between tests).
Answers is more complex since each 1 answer depends on the user and question.
1:1 -- rarely practical; may as well merge the tables together.
1:many -- a link (FK?) in one table to the other.
many:many -- need a bridge table with (usually) 2 columns, namely ids linking to the two tables.
I am using MySQL foreign key in Innodb, I wonder how Mysql enforce foreign key constraint when we insert into the child table. Innodb seems to build index on the foreign key column automatically, How is this feature useful in enforcing the foreign key constraint?
In sum, for normal index, we can create index file, which use the B+ tree structure. What structure is used for a foreign key?
It's an ordinary INDEX. And, in particular, a BTree.
SHOW CREATE TABLE will demonstrate that it is such (and has a fabricated name for the index).
Q: How is this feature [the index on the foreign key column(s) in the child table] useful in enforcing the foreign key constraint?
A: It's useful when an attempt is made to delete a row in the parent table. Or when an attempt is made to update a value in a column that is referenced by a foreign key.
For example, consider an attempt to delete a row in the parent table. The foreign key is a constraint that says: if there are any rows in child table that reference the row in parent table, the delete operation will not succeed and will return an error. (We're assuming for the sake of this example that the foreign key constraint is declared as ON DELETE RESTRICT.)
When a row is deleted from the parent, the child table needs to be checked. Think of performing that check in terms of running a query on the child table, to find out: are there any rows in the child table that reference the row in the parent table. (That is, are they are any rows that have a particular value in the foreign key column?)
If the database wasn't enforcing the constraint, and we were doing the check in the application instead, we would need to run a query something like this:
SELECT 1
FROM child_table
WHERE foreign_key_col = :referenced_key_value
LIMIT 1
And that query would benefit from a suitable index, and index with foreign_key_col as the leading column. Using an index, MySQL can quickly eliminate vast swaths of rows that it knows can't have that value, narrowing in very quickly to the block(s) that would contain a matching row.
For non-trivial sets, using an appropriate index to locate a row is much more efficient than performing a full scan operation, examining every row in the table, to verify there are no rows that match.
In this case, the ideal index ... ON child_table (foreign_key_column), ...)`
In addition to that performance benefit, the database can also use the index to prevent other sessions from inserting a row into child_table (rows that would violate the foreign key constraint), using a lock mechanism. Without an index, the database would need to lock the entire child_table. And that would kill concurrency.
(This is an overly simplified explanation. The actual mechanics are more involved. But this should explain why an index on foreign key columns is "useful". To define a foreign key constraint, InnoDB requires that a suitable index be defined. And if one doesn't exist, InnoDB will create one.
Q: What structure is used for a foreign key?
The same structure used for any other column in the table, or any other index on the table.
A FOREIGN KEY is a constraint. There's nothing "special" about a column used in a foreign key constraint. There is a requirement that the column(s) used in a foreign key constraint must be the leading columns in an index. As explained in the answer to your first question.
I have roles for users.
User can have multiple roles. I have a table called users_roles.
I have three columns - id,user,role.
id is an auto-increment column.
So,
Is it a good idea to drop the id column since I never use that in code?
If yes, then what column should be the index for this table? Or should it not have an index at all?
I agree that if user is userid then you dont need the id column, userid can be your indexed PK.
If user is the name of the user then you are going to want to keep the id, or create a user_id so that you can have a valid key to index.
users_roles is a many many link table.
There are at least 2 common approaches to primary keys on many:many tables:
users_roles has its own surrogate Primary key, as in the case here (users_roles.id)
OR, you create a composite key consisting of (user, role), since a user shouldn't be in the same role more than once.
There are many discussions on simple vs composite keys e.g. Why single primary key is better than composite keys?
Note that indexes and primary keys are different concepts. Primary Key is for uniqueness, Index is for performance. (You can have multiple indexes on a table, but only one PK)
If, as you seem to be saying, that no other tables reference user_roles, then you don't actually need a primary key.
If your users_roles table gets large, you will likely want to add an index on the users column, and possibly also the roles table, e.g. if you often search for users in a particular role.
If you are supposing to delete the "id" field then how you will make a relation between user and user_roles table.
It is always better to define a primary key. The default index is created when you define the primary key. And it somehow increases the performance.
Also when you define a foreign key the foreign Key index will also be generated. And hence your table query execution will become faster.
This is your first answer:
According to your requirements, for the current time being you can delete the "id" primary key from user_roles table as it is just use as a relationship table between users and roles.
But in most of PHP frameworks, this is not a good practice to drop a primary key even in relationship table.
This is your second answer: If you would drop a primary key, then you will have to maintain the indexes on "user" and "role" field as a foreignKey index. And if you are not going to drop a primary key from user_roles table. Then 3 indexes would be generated for "id", "user" and "role" fields. First index will be the primary index and rest two are foreignKey index.
Explicitly defining of more indexes on a table also causes some extra overhead on query execution.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
mySQL's KEY keyword?
Like
PRIMARY KEY (ID),
KEY name (name),
KEY desc (desc),
etc.
what are they useful for?
Keys are used to enforce referential integrity in your database.
A primary key is, as its name suggests, the primary identification of a given row in your table. That is, each row's primary key will uniquely identify that row.
A unique key is a key that enforces uniqueness on that set of columns. It is similar to a primary key in that it will also uniquely identify a row in a table. However, there is the added benefit of allowing NULL in some of those combinations. There can only be 1 primary key, but you can have many unique keys.
A foreign key is used to enforce a relationship between 2 tables (think parent/child table). That way, a child table can not have a value of X in its parent column unless X actually appears in the parent table. This prevents orphaned records from appearing.
The primary key constraint ensures that the column(s) are:
not null
unique (unique sets if more than one column)
KEY is MySQL's terminology in CREATE TABLE statements for an index. Indexes are not ANSI currently, but all databases use indexes to speed up data retrieval (at the cost of insertion/update/deletion, because of maintenance to keep the index relevant).
There are other key constraints:
unique
foreign key (for referential integrity)
...but your question doesn't include examples of them.
keys are also called indexes. They are used for speeding up queries. Additionally keys can be constrains (unique key and foreign key). The primary key is also unique key and it identifies the records. The record can have other unique keys as well, that do not allow to duplicate a value in a given column. Foreign key enforces referential integrity (#Derek Kromm already wrote excellent description). The ordinary key is used only for speeding up queries. You need to index the columns used in the WHERE clause of the queries. If you have no index on the column, MySQL will need to read the whole table to find the records you need. When index is used, MySQL reads only the index (which is usually a B+ tree) and then read only those record from the table it found in the index.
Primary KEY is for creating unique/not null constraint for each row in the table. Also searching by this key is the fastest. You can create only one PK in the table.
Ordinary key/index is key for speeding your searching by this column, sorting, grouping and joining with other table by this key.
Indexes drawback:
Adding new indexes to table will influence on speed or running insert/update/delete statements. So you should select columns for indexing in your table very carefully.
Key are used for relation purposes between tables and you are able to create joins in order to select data from multiple tables
What, you didn't fine the wikipedia entry comprehensive? ;-)
So, a key, in a relational database (such as MySQL, PostgreSQL, Oracle, etc) is a data constraint on a column or set of columns. The most common keys are the Primary key and foreign keys and unique keys.
A foreign key specifically relates the data of one table to data in another table. You might see that a table blog_posts has a foreign key to users based on a user_id column. This means that every user_id in blog_posts will have a corresponding entry in the users column (this is a one-to-many relationship -- a topic for another time).
If a column (or group of columns) has a unique key, that means that there can only be one such incidence of the key in the table. Often you'll see things like email addresses be unique keys -- you only want one email address per user. I've also seen a combination of columns match to a unique key -- the five columns, first_name, last_name, address, city, and state, will often be a unique key -- realistically, there can only be one William Gates at 1835 73rd Ave NE, Medina, Washington. (I do realize that it is possible for a William Gates Jr. to be born, but the designers of that database didn't really care).
The primary key is the primary, unique identifier of a given table. By definition it is a unique key. It is something which cannot be null and must be unique. It holds a special place of prominence among the indexes of a given table.
Does MySQL index foreign key columns automatically?
Yes, but only on innodb. Innodb is currently the only shipped table format that has foreign keys implemented.
Apparently an index is created automatically as specified in the link robert has posted.
InnoDB requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist. (This is in contrast to some older versions, in which indexes had to be created explicitly or the creation of foreign key constraints would fail.) index_name, if given, is used as described previously.
InnoDB and FOREIGN KEY Constraints
For those who are looking for quote from 5.7 docs:
MySQL requires indexes on foreign keys and referenced keys so that
foreign key checks can be fast and not require a table scan. In the
referencing table, there must be an index where the foreign key
columns are listed as the first columns in the same order. Such an
index is created on the referencing table automatically if it does not
exist. This index might be silently dropped later, if you create
another index that can be used to enforce the foreign key constraint.
index_name, if given, is used as described previously.
You don't get the index automatically if you do an ALTER TABLE (instead of CREATE TABLE), at least according to the docs (the link is for 5.1 but it's the same for 5.5):
[...] When you add a foreign key constraint to a table using ALTER TABLE, remember to create the required indexes first.
As stated it does for InnoDB. At first I thought it was strange that many other (in particular MS SQL and DB2) doesn't. TableSpace scans are only better than index scans when there are very few table rows - so for the vast majority of cases a foreign key would want to be indexed. Then it kind of hit me - this doesn't necessarily mean it has to be a stand alone (one column) index - where it is in MySQL's automatic FK Index. So, may be that is the reason MS SQL, DB2 (Oracle I'm not sure on) etc leave it up to the DBA; after all multiple indexes on large tables can cause issues with performance and space.
Yes, Innodb provide this. You can put a foreign key name after FOREIGN KEY clause or leave it to let MySQL to create a name for you. MySQL automatically creates an index with the foreign_key_name name.
CONSTRAINT constraint_name
FOREIGN KEY foreign_key_name (columns)
REFERENCES parent_table(columns)
ON DELETE action
ON UPDATE action
It's not possible to get index key automatically use
ALTER TABLE (NAME OF THE TABLE) ADD INDEX (FOREIGN KEY)
Name of the table which you have created for example photographs and FOREIGN KEY for example photograph_id. The code should be like this
ALTER TABLE photographs ADD INDEX (photograph_id);