MySQL Workbench creates extra index - mysql

When I use MySQL Workbench to create a simple table with a single primary key, it not only creates the PK index (cool) but also a second Unique Index (?). Here's an example output:
CREATE TABLE `tbl_example` (
`tbl_example_ID` INT(10) UNSIGNED NOT NULL ,
`field1` VARCHAR(45) NULL ,
`field2` VARCHAR(45) NULL ,
PRIMARY KEY (`tbl_example_ID`) ,
UNIQUE INDEX `tbl_example_ID_UNIQUE` (`tbl_example_ID` ASC) )
ENGINE = MyISAM
It's my understanding that a PK assumes unique index so the UNIQUE INDEX line is unnecessary, correct? Just looking for some confirmation before I update a bunch of tables.

You are right. A Primary Key is (for MySQL) a unique index with the name 'PRIMARY KEY'. So having a Primary Key and a unique index on the same column(s) is a pointless waste of resources.

Related

mysql choose between unique key and primary key for user id

Im creating a user database ... i want to separate user - cellphone number from 'user' table and create another table for it (user_cellphone (table))
but i have a problem to select best index !
in user_cellphone table, we get user_id and cellphone number ... but all SELECT queries are more based on 'user_id' so i want to know if it's better to choose 'user_id' column as primary key or not !!!
(Also each user have only one cellphone number !)
which option of these 2 options are better ?
CREATE TABLE `user_cellphone_num` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`cellphone_country_code` SMALLINT UNSIGNED NOT NULL,
`cellphone_num` BIGINT UNSIGNED NOT NULL,
`user_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `cellphone` (`cellphone_country_code`, `cellphone_num`),
UNIQUE INDEX `user_id` (`user_id`)
)
CREATE TABLE `user_cellphone_num` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`cellphone_country_code` SMALLINT UNSIGNED NOT NULL,
`cellphone_num` BIGINT UNSIGNED NOT NULL,
`user_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`user_id`),
UNIQUE INDEX `id` (`id`),
UNIQUE INDEX `cellphone` (`cellphone_country_code`, `cellphone_num`)
)
choosing 'user_id' as primary key or just set 'user_id' as a unique key ?! is there any different here in performance ? (Im talking about when i have millions of rows)
in future im going to use some queries like this:
select u.*,cell.* FROM user AS u LEFT JOIN user_cellphone AS cell ON cell.user_id = u.id
so which one of these options give me better performance for some queries like this ?
May I offer some hard-won data design advice?
Do not use telephone numbers as any kind of unique or primary key.
Why not?
Sometimes multiple people use a single number.
Sometimes people make up fake numbers.
People punctuate numbers based on context. To my neighbors, my number is (978)555-4321. To a customer in the Netherlands it is +1.978.555.4321. Can you write a program to regularize those numbers? Of course. Can you write a correct program to do that? No. Why bother trying. Just take whatever people give you.
(Unless you work for a mobile phone provider, in which case ask your database administrator.
Read this carefully. https://github.com/google/libphonenumber/blob/master/FALSEHOODS.md
InnoDB tables are stored as a clustered index, also called an index-organized table. If the table has a PRIMARY KEY, then that is used as the key for the clustered index. The other UNIQUE KEY is a secondary index.
Queries where you look up rows by the clustered index are a little bit more efficient than using a secondary index, even if that secondary index is a unique index. So if you want to optimize for the most common query which you say is by user_id, then it would be a good idea to make that your clustered index.
In your case, it would be kind of strange to separate the cellphones into a separate table, but then make user_id alone be the PRIMARY KEY. That means that only one row per user_id can exist in this table. I would have expected that you separated cellphones into a separate table to allow each user to have multiple phone numbers.
You can get the same benefit of the clustered index if you just make sure user_id is the first column in a compound key:
CREATE TABLE `user_cellphone_num` (
`user_id` INT UNSIGNED NOT NULL,
`num` TINYINT UNSIGNED NOT NULL,
`cellphone_country_code` SMALLINT UNSIGNED NOT NULL,
`cellphone_num` BIGINT UNSIGNED NOT NULL,
PRIMARY KEY (`user_id`, `num`)
)
So a query like SELECT ... FROM user_cellphone_num WHERE user_id = ? will match one or more rows, but it will be an efficient lookup because it's searching the first column of the clustered index.
Reference: https://dev.mysql.com/doc/refman/8.0/en/innodb-index-types.html

Foreign keys and unique index on the same table

I have this table:
CREATE TABLE `sites_routing` (
`origin_site_id` int(11) NOT NULL,
`destination_site_id` int(11) NOT NULL,
`distance_meters` int(11) DEFAULT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(45) NOT NULL DEFAULT 'walking',
PRIMARY KEY (`id`)
)
I want to create two foreign keys for columns origin_site_id and destination_site_id and than another unique index on 3 columns: origin_site_id, destination_site_id and type. If I'm doing that mysql becomes really slow on reading and writing to the table and I can see in the error log stuff like:
sites_routing contains 4 indexes inside InnoDB, which is different from the number of ns 4 indexes inside InnoDB, which is different from the number of indexes 3 defined in the MySQL
Still, if I try to drop the fks and the indexs and recreate the fks when the unique key exists, mysql allows me to create only one fk using the unique key as index but for the other one it automatically creates another index.
What's the best way to go here?

Should the normal Key include the primary key?

This question is related to
Do MySQL tables need an ID?
There is a meaningless auto_incremental ID acting as PRIMARY KEY for a table, then when I create other KEYs, should I include this ID in the KEYs?
For example, in this table:
CREATE TABLE `location` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`country` varchar(50),
`states` varchar(50),
`city` varchar(50),
`county` varchar(50),
`zip` int(5),
PRIMARY KEY(ID),
KEY zip1 (zip),
KEY zip2 (zip, ID)
} ENGINE=InnoDB ;
Because I need to search the table using zip code a lot, so I need a KEY start from zip code. I should use either KEY zip1 or KEY zip2. Which one of these two KEYs is better?
For InnoDB, the primary key is always included in secondary indexes;
All indexes other than the clustered index are known as secondary indexes. In InnoDB, each record in a secondary index contains the primary key columns for the row, as well as the columns specified for the secondary index. InnoDB uses this primary key value to search for the row in the clustered index.
In other words, ID is already included in zip1, and does not have to be mentioned as it is in in zip2.

Primary and foreign key in SQL?

I am not sure about this , but do I need to create foreign key explicitly in the SQL command?
This guy did this:
CREATE TABLE languages (
lang_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
lang VARCHAR(60) NOT NULL,
lang_eng VARCHAR(20) NOT NULL,
PRIMARY KEY (lang_id),
UNIQUE (lang)
);
CREATE TABLE threads (
thread_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
lang_id TINYINT(3) UNSIGNED NOT NULL,
user_id INT UNSIGNED NOT NULL,
subject VARCHAR(150) NOT NULL,
PRIMARY KEY (thread_id),
INDEX (lang_id),
INDEX (user_id)
);
In this case, does it mean that INDEX(lang_id) becomes FOREIGN KEY automatically? I know INDEX makes search go faster, but I don't understand the part about foreign key
I would really appreciate any answer
No. An index is just that... an index on a field. A foreign key tells MySQL that "this particular field MUST have a matching record in that table over there".
MySQL's internal design requires that all fields used as foreign keys be indexed, but modern versions will automatically create that index for you.
The converse is not true, whoever. Adding an index to a field does not turn it into a foreign key - a foreign key definition must also include what the foreign table/field is, and a simple index declaration has none of that information.
For your sample table, you'd need to have
...
INDEX (lang_id),
FOREIGN KEY (lang_id) REFERENCES languages (lang_id),
...
to produce a foreign key.
A foreign key means that the value(s) must exist in the referenced column(s). It is not automatic - you need to write it explicitly.
FOREIGN KEY lang_id REFERENCES languages (lang_id)
No a foreign key has to be explicitly declared
CREATE TABLE threads (
thread_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
lang_id TINYINT(3) UNSIGNED NOT NULL FOREIGN KEY FK_1 REFERENCES languages(lang_id),
user_id INT UNSIGNED NOT NULL,
subject VARCHAR(150) NOT NULL,
PRIMARY KEY (thread_id),
INDEX (lang_id),
INDEX (user_id)
);
What you now have are two tables with primary keys and indexes on those primary key values.
You could stop here if you want but you won't have declared referential integrity enforcing that relationship between laguage and threads tables.
To do that you would explicitly create a foreign key relationship as explained here - http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
The differences are as follows :-
The primary key identifies a record uniquely in a table with multiple rows.
An index is a generic term, where by you can create more than one index for a table, in this case the database creates indexes based on the columns that you specified, so that when you query the appropriate index will kick in and give you results faster.
A foreign key on the other hand says that this column in table b, is the primary column in table A, so that whenever you enter rows into table B the databse will check that the specified column/data exists in table A otherwise it will throw an error.

What's the point of adding NOT NULL to primary key field in MySQL?

What's the point of adding NOT NULL to a primary key field? Primary key is already not null + unique.
Here is an example:
CREATE TABLE student (
id int(11) AUTO_INCREMENT NOT NULL,
name varchar(255),
PRIMARY KEY(id)
)
Why not to define it like this instead:
CREATE TABLE student (
id int(11) AUTO_INCREMENT,
name varchar(255),
PRIMARY KEY(id)
)
They are the same. Primary key got NOT NULL automatically.
You are asking, why do people bother adding the NOT NULL when it is unnecessary? Just because it is good style, I guess. And makes it explicit to the reader.
NULL is not equivalent to NULL(as NULL indicates an unknown or absent value), so you will be permitted to have multiple records that have NULL for the id, even though there's a primary key / unique constraint defined, hence the use of NOT NULL. That's if MySql even allows you to define a primary key on a nullable field.
In addition, as a primary key is often used in a foreign key in other tables, having one or more NULL values wouldn't make sense.
If PRIMARY KEY is declared without NOT NULL, NOT NULL is added to PRIMARY KEY implicitly so PRIMARY KEY with or without NOT NULL is the same.
The MySQL documentation says as shown below:
A unique index where all key columns must be defined as NOT NULL. If
they are not explicitly declared as NOT NULL, MySQL declares them so
implicitly (and silently). A table can have only one PRIMARY KEY. The
name of a PRIMARY KEY is always PRIMARY, which thus cannot be used as
the name for any other kind of index.
And also, the MySQL documentation says as shown below:
The primary key for a table represents the column or set of columns
that you use in your most vital queries. It has an associated index,
for fast query performance. Query performance benefits from the NOT
NULL optimization, because it cannot include any NULL values. ...