Does creating a FK automatically index the column? - sql

I am using mySQL 5.1 and am wondering, is it necessary to add CREATE INDEX syntax on a column after you have defined it in a FK relationship. Common sense tells me that if a column is a key (foreign or otherwise), then it needs to be indexed - but you never know ...
Do I have to EXPLICITLY create an index on my FK - or does creating an FK implicitly creates an index on the column ?

Quoting this page of the MySQL manual : 13.6.4.4. FOREIGN KEY Constraints :
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.

Related

Does adding a foreign key to a table affect its insertion time?

Is the assumption that each foreign key added a to a table also adds a CHECK constraint that ensures that values inserted in the foreign key column is from the set of values from the table where that key is the primary key.
This would imply that a table with more foreign keys would take longer to insert a value into. Is this correct?
I am using Microsoft SQL Server 2014.
Yes. Foreign key relationships are checked when data is inserted or modified in the table.
The foreign key needs to be to a primary key or unique key. This guarantees that an index is available for the check.
In general, looking up the value in the index should be pretty fast. Faster than the other things that are going on in an insert, such as finding a free page for the data and logging the data.
However, validating the foreign key is going to add some overhead.
Don't mix up foreign keys and checks - there are two different constraint types. For example check accepts nulls and foreign keys not (exception: on delete set null fk option).
When rows are inserted/updated in database set od step is beeing executed, e.g. checking existance of tables, columns, veryfing privileges. Where you have fk database engine must verify contraint before inserting/updateing data to the table - it's additional step to execute.
I have never expirienced situation, when fk painfully slowed down the database operations duration.

Changing column to just a regular column instead of foreign key

I have a specific situation where I have a column type in my DB where the column is currently of type int and it is a foreign key type that allows nulls...
My question is: is it possible to change now this column simply to a int type which isn't a foreign key without messing up the data in both tables, and leaving the values intact?
For example:
alter table xy
alter column ForeignKeyIdColumn int null
Would something like this work?
Can someone help me out?
A foreign key is not a property of the columns of a table, it's a database object that defines the relationship between tables.
You can drop the foreign key constraint (though I wouldn't recommend it) using ALTER TABLE with DROP CONSTRAINT, but you have to know the name of the constraint to do it (this is why it's best practice to name everything in SQL SERVER):
ALTER TABLE xy
DROP CONSTRAINT <constraint name here>;
However, as I wrote, I wouldn't recommend dropping foreign key constraints.
Foreign keys are the database way to enforce referential integrity - meaning that a value referenced by another table can't be changed or deleted without changing or deleting the referencing value as well.
Dropping foreign keys means your database will not be able to enforce referential integrity any more and that might lead to corrupt data.
For more information, read Delete Foreign Key Relationships

Does creation of a foreign key mean creation of an index?

If I have a column a inside table Foo, and I create a new table Bar with a column b that is a foreign key to Foo.a, is column b automatically indexed for Bar, or must I still create an index on Bar.b if I want to efficiently search for all rows in Bar with b = 1?
(If it matters, I am using SQLite.)
Foreign keys are just used to 'force exists relationships between tables', but not automatically indexed based on their related column's index. Indexing Foo.a will speed up inserts/updates on Bar.b, while indexing Bar.b will speed up selects on Bar.b.
Creating a Foreign Key in SQLite is only creating a constraint. You should create the index yourself.
From the documentation, near the end of paragraph 3:
So, in most real systems, an index should be created on the child key
columns of each foreign key constraint.
You have to create the index yourself. At least I know no DBMS that does it automatically.

Do I need to create indexes on foreign keys on Oracle?

I have a table A and a table B. A has a foreign key to B on B's primary key, B_ID.
For some reason (I know there are legitimate reasons) it is not using an index when I join these two tables on the key.
Do I need to separately create an index on A.B_ID or should the existence of a foreign key provide that?
The foreign key constraint alone does not provide the index on Oracle - one must (and should) be created.
Creating a foreign key does not automatically create an index on A.B_ID. So it would generally make sense from a query performance perspective to create a separate index on A.B_ID.
If you ever delete rows in B, you definitely want A.B_ID to be indexed. Otherwise, Oracle will have to do a full table scan on A every time you delete a row from B to make sure that there are no orphaned records (depending on the Oracle version, there may be additional locking implications as well, but those are diminished in more recent Oracle versions).
Just for more info: Oracle doesn't create an index automatically (as it does for unique constraints) because (a) it is not required to enforce the constraint, and (b) in some cases you don't need one.
Most of the time, however, you will want to create an index (in fact, in Oracle Apex there's a report of "unindexed foreign keys").
Whenever the application needs to be able to delete a row in the parent table, or update the PK value (which is rarer), the DML will suffer if no index exists, because it will have to lock the entire child table.
A case where I usually choose not to add an index is where the FK is to a "static data" table that defines the domain of a column (e.g. a table of status codes), where updates and deletes on the parent table are never done directly by the application. However, if adding an index on the column gives benefits to important queries in the application, then the index will still be a good idea.
SQL Server has never put indexes onto foreign key columns automatically - check out Kim Tripp's excellent blog post on the background and history of this urban myth.
It's usually a good idea to index your foreign key columns, however - so yes, I would recommend making sure each FK column is backed up by an index; not necessarily on that one column alone - maybe it can make sense to create an index on two or three columns with the FK column as the first one in there. Depends on your scenario and your data.
For performance reasons an index should be created. Is used in delete operations on primary table (to check that the record you are deleting is not used) and in joins that usually a foreign key is involved. Only few tables (I do not create them in logs) could be that do not need the index but probably, in this cases probably you don't need the foreign key constraint as well.
BUT
There are some databases that already automatically create indexes on foreign Keys.
Jet Engine (Microsoft Access Files)
Firebird
MySQL
FOR SURE
SQL Server
Oracle
DOES NOT
As with anything relating to performance, it depends on many factors and there is no silve bullet e.g. in a very high activilty environment the maintainance of an index may be unacceptable.
Most salient here would seem to be selectivity: if the values in the index would be highly duplicated then it may give better performance to drop the index (if possible) and allow a table scan.
UNIQUE, PRIMARY KEY, and FOREIGN KEY constraints generate indexes that enforce or "back" the constraint (and are sometimes called backing indexes). PRIMARY KEY constraints generate unique indexes. FOREIGN KEY constraints generate non-unique indexes. UNIQUE constraints generate unique indexes if all the columns are non-nullable, and they generate non-unique indexes if one or more columns are nullable. Therefore, if a column or set of columns has a UNIQUE, PRIMARY KEY, or FOREIGN KEY constraint on it, you do not need to create an index on those columns for performance.

How to delete unique index referenced by foreign keys?

I have a table, let's call it Users. This table has primary key called Id. Despite having Id as primary key (unique clustered), it has other index (unique nonclustered) on the same column(Id).
I would like to drop this constraint, but foreign keys reference this unique nonclustered index and I get The constraint ... is being referenced by table... error.
What is the best way to drop such index? Do you have any scripts that drop, do something, and recreate foreign key on specific column in specific table? There is a lot of foreign keys, so it would be nice if I could do it automatically. I could use INFORMATION_SCHEMA and other system object to extract information about these keys, but I don't want to write, what have already been written or can be done in other way.
In order to drop a nonclustered index that is referenced by a foreign key you must furst drop the foreign key constraint.
Take a look at the following scrips available from a poster over at SQL Server Central. They may require some tweaking for your "exact" requirements however they provide the basis for scripting out and then subsequently rebuilding foreign keys.
Scrip out Foreign Keys
The two-index approach can make sense:
The second index is probably much smaller than the clustered index, and would more easily fit into memory
The second index might include a selection of columns that benefit specific queries
For dropping the second index, you'll have to drop all foreign keys that refer to it first. Here is a link to the script I use to drop & recreate foreign keys.