Why Does Laravel automatically add an index for constrained columns - php

Why Does Laravel automatically add an “INDEX” for this condition?
$table->foreignId('user_id')->nullable()
->constrained('users','id')
->onDelete('no action')
->onUpdate('no action');

From https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html
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.

Laravel only adds a foreign key constraint and doesn't add index implicitly. But some databases such as MySQL automatically index foreign key columns.
When you define a foreign key constraint in your database table, an index will not be created automatically on the foreign key columns , as in the PRIMARY KEY constraint situation in which a clustered index will be created automatically when defining it. It is highly recommended to create an index on the foreign key columns, to enhance the performance of the joins between the primary and foreign keys, and also reduce the cost of maintaining the relationship between the child and parent tables. Before adding any new indexes, it is better to test on a development environment and monitor the overall performance after the implementation, to make sure that the added indexes improve performance and do not negatively impact the system performance.

Related

Laravel MYSQL Foriegn Key

While designing the database for a laravel software using MYSQL, is assigning foreign keys relevant or does Laravel take care of that "Software side".
In the migration we have something like
Table Example:
$table->unsignedBigInteger('user_id');
should i modify the example table in phpmyadmin and make user_id a foreign key? is there a better way or is this not relevant or necessary?
You should define foreign key constraints in your migration. When using code base you should make all the changes using migrations.
Additionally by defining foreign key you actually build a relation between 2 tables otherwise this relation will be at code level. When relation is built database will restrict to have only values which actually exists in main table. Using foreign key you can also do cascading (on update and delete) at db level.
Reference what are the advantages of defining a foreign key
Why should I use foreign keys in database?
if use Laravel 7 ,you can use this short that is a column name user_id foreign to ID user in the table users :
$table->foreignId('user_id')->nullable()->constrained()->onDelete('cascade');

Zf2 Doctrine2 - Can not add relationship in existing database tables which does not have any FK

I am currently doing ZF2 project with Doctrine2. I have existing database where tables does not have foreign key constraints and any relation. Using doctrine can I generate schema based on relation without foreign key constraints.
I tried to add the column without foreign key constraints and its violated. Also I tried the column null able still doctrine try to modify the db schema to add foreign key constraints which eventually fails.
Also tried to add another temporary column as foreign key and later on write a script top transfer existing column to the foreign key constraint column. But it also failed as there have some columns who does not exist in the second table( may be deleted)
still does not find any suitable way to do that.
Any idea? or its not possible?

Should I index my mysql foregin keys

I am using mysql as DB for my Laravel app.
In one table I have 5 fields that are foregin keys, those FK's points to 5 other tables primary keys.
Right now I have only marked them as FK, but do I need to put a index on every FK as well? Or does a FK count as a index?
Thanks in advance,
In mysql when making a FK it automatically indexes that column(s).
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 can read more here at dev.mysql

How to handle cyclic foreign key insertion?

I have a table 'release_group' and another table 'release', like so:
release_group
------------------------
release_group_id (PRIMARY KEY)
name
main_release_id (FOREIGN KEY)
release
------------------------
release_id (PRIMARY KEY)
release_group_id (FOREIGN KEY)
name
If i create a release row, the release_group_id is not available, simply because it hasn't been created yet. But i can't create a release_group row without the main_release_id. So it's kind of a no way situation.
EDIT:
The main_release_id in release_group is to say that the release is the main from the group, the one i will use a reference.
What is the professional way of handling this case?
1.
Remove the foreign key index main_release_id in table release_group and give an attribute ALLOW NULL. Create the release_group row so i can applied it's id in the release row.
2.
Keep the 'main_release_id' foreign key index in table 'release_group' and assign it a temporary integer value of 0. Create the release row and update the foreign key in the release_group accordingly? Keep in mind that if this is the way to go, i could end up inadvertently having foreign keys with value 0, which i don't know if this ethic in a database?
What is the professional way of handling this case?
Thanks
Seeing how a release cannot belong to more than one group, you could remove the complication by:
Dropping the main_release_id field altogether
Add a release_main field to the release table; it would be NULL (not main) or 1 (main).
Add a UNIQUE constraint on (release_group_id, release_main) to make sure there can only be one main release.
Update
If a release can belong to multiple groups, you would need to create a many-to-many table and move the foreign key in both tables into it:
(release_group_id [FK], release_id [FK], is_main)
The primary key would span the first two fields. Ensuring that there can only be one main release requires a spanning unique key over the first and last field.
Old answer
Assuming main_release_id is a nullable field, what I would suggest is the following:
Insert the release_group with main_release_id being null; get last inserted id.
Insert the release entry, passing the id of the previous step; get last inserted id.
Update the release_group table entry, setting the value of main_release_id to the value you got from the previous step.
Commit transaction
Alternatively, you could use sequences so that you know the id before inserting the entries. See an example of this in the manual under LAST_INSERT_ID().
Looks like you are trying to create a many to many relationship. To do this properly, remove the foreign keys from both the release_group and release tables. Add a new table (release_to_release_group) that contains the release_id foreign key and the release foreign key.
Edit: There is no need for cyclic foreign keys here. Remove the main_release_id foreign_key from release_group and add a is_main_release flag to the release table.
It's not usual practice to have the tables reference each other like that. Usually you would have the Parent table (release_group) as a foreign key reference in the child table (release), but not have the release_id as a foreign key in the release_group table.
Maybe add a boolean flag to the release table to indicate it is the Main release and do away with the main_release_id in release_group.

MySQL foreign key relations vs mysql_insert_id to relate tables

This is for a sort of proof of concept draft to get things working, but don't want to have completely crap code. For my database, I tried to get true foreign key relations going using innoDB, but couldn't get it.
Instead of using foreign keys, I decided to just pull mysql_insert_id() after inserts, saving it as a variable, then putting that variable into the related table.
Is this horrible? Everything seems to work well, and I'm able to connect and relate ID's as needed. What benefits would using foreign keys give me over my method (besides updates/deletes cascading)?
To create a relation (master->detail), you have to always supply the keys by yourself, either using mysql_insert_id, natural keys or key generated by your applications. The FOREIGN KEY is not going to make that work for you.
What FOREIGN KEY does is
Helping you enforce the relationship/the integrity of your data (so the "detail" record does not point to an invalid parent)
Handles deletion or key alterations of master records (ON DELETE ..., ON UPDATE ...).
It's also creating an index in your "detail"-table for the "master_id"-row if it doesn't exist yet (okay, you could also do that without FOREIGN KEY)
Has also some kind of documenting purpose for example an ERM-tool could reengineer the relationship model from your schema (okay, this point is a slight long shot)
The cost of adding the FOREIGN KEY constraint statement is small compared to its benefits.

Categories