I use a mariadb 10.3.27 with innodb engine mostly standard configuration.
We create a foreign key that induce creating index.
All seams fine but the index is not use in a simple left join on the fk on complex query
And show index from give a cardinality of 2 for this index. So I optimize the table but nothing change.
I create an index on that column with another name, there is no warning (but there is already an index on that column) and it override existing index.
The cardinality become 154 and execution plan become correct :
Maybe a bug ? Or I misunderstood something ?
Related
I have a table which already have a column with BTREE index on it. Now I want to add a unique key constraint to the same column to avoid race condition from my rails app.
All the reference blogs/article shows I have to add a migration to create a new uniq index on that column like below
add_index :products, :key, :string, unique: true
I want to understand
What happens to BTREE index which is already present?(I need this)
Is it OK to have both the index and they both work fine?
Table has around 30MN entries, will it locks the table while adding index and take huge time to add this UNIQUE index?
You don't need both indexes.
In MySQL's default storage engine InnoDB, a UNIQUE KEY index is also a BTREE. InnoDB only supports BTREE indexes, whether they are unique or not (it also supports fulltext indexes, but that's a different story).
So a unique index is also useful for searching and sorting, just like a non-unique index.
Building an index will lock the table. I suggest using an online schema change tool like pt-online-schema-change or gh-ost. We use the former at my company, and we run hundreds of schema changes per week on production tables without blocking access. In fact, using one of these tools might cause the change to take longer, but we don't care because we aren't suffering any limited access while it's running.
What happens to BTREE index which is already present?(I need this)
Nothing. Creating a new index does not affect existing indexes.
Is it OK to have both the index and they both work fine?
Two indices by the same expression which differs in uniqueness only? This makes no sense.
It is recommended to remove regular index when unique one is created. This will save a lot of disk space. Additionally - when regular and unique indices by the same expression (literally!) exists then server will never use regular index.
Table has around 30MN entries, will it locks the table while adding index and take huge time to add this UNIQUE index?
The table will be locked shortly at the start of the index creation process. But if index creation and parallel CUD operations are executed then both of them will be slower.
The time needed for index creation can be determined only in practice. Sometimes it cannot be even predicted.
I have a not so big table, around 2M~ rows.
Because some business rule I had to add a new reference on this table.
Right now the application is writing values but not using the column.
Now I need to update all null rows to the correct values, create a FK, and start using the column.
But this table has a lot of reads, and when I try to alter table to add the FK the table is locked and the read queries get blocked.
There is any way to speed this?
Leaving all fields in NULL values helps to speed up (since I think there will be no need to check if the values is valid)?
Creating a index before helps to speed up?
In postgres I could create a not valid FK and then validate it(which caused only row lock, not table lock), there is anything similar in MySQL?
What's taking time is building the index. A foreign key requires an index. If there is already an index on the appropriate column(s), the FK will use it. If there is no index, then adding the FK constraint implicitly builds a new index. This takes a while, and the table is locked in the meantime.
Starting in MySQL 5.6, building an index should allow concurrent read and write queries. You can try to make this explicit:
ALTER TABLE mytable ADD INDEX (col1, col2) LOCK=NONE;
If this doesn't work (like if it gives an error because it doesn't recognize the LOCK=NONE syntax), then you aren't using a version of MySQL that supports online DDL. See https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-operations.html
If you can't build an index or define a foreign key without locking the table, then I suggest trying the free tool pt-online-schema-change. We use this at my job, and we make many schema changes per day in production, without blocking any queries.
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.
Today I tried to reorder a column of a table using phpMyAdmin (as I have done many times before).
Although the result was displayed as successful no reordering effectively happened.
It appears the problem is caused by using InnoDB as storage engine which is the default value from MySQL 5.5 onward.
When I changed back to myIsam the problem was solved. It clarified why it was working on some tables.
Is this a solvable mySQL problem? Or is this regular expected behavior for InnoDB ?
In the latter case phpMyAdmin should perhaps be adapted to not offer the functionality while using InnoDB.
MySQL: 5.5.29
phpMyAdmin: 4.0.4
If by ...reordering column... you meant
ALTER TABLE ... ORDER BY ...
then for InnoDB table that has a PRIMARY or UNIQUE KEY it doesn't work. It's by design:
ALTER TABLE
ORDER BY does not make sense for InnoDB tables that contain a
user-defined clustered index (PRIMARY KEY or NOT NULL UNIQUE index).
InnoDB always orders table rows according to such an index if one is
present.
On the other hand if you don't have PRIMARY or UNIQUE KEY in your table, which is highly unlikely, then MySQL will allow you to change the order.
Here is SQLFiddle demo that demonstrates that behavior.
I am running some MySQL queries on a pretty large table (not on Facebook scale, but around a million rows), and I am finding them very slow. The reason, I suspect, is that I am querying on an id field, but that id has not been declared as primary key, and also no index has been declared.
I cannot set the id field to primary key, because it is not unique, although its cardinality is pretty close to 1. Under these circumstances, if I do a alter table to add an index on the id field, is it supposed to boost up the query speed, given that it is not a primary key?
And supposing it does, how long will it take for the index to develop fully so that the queries start executing quickly? I mean, the moment the prompt appears after executing the alter table, or is it that even though the prompt appears the index building will go on internally for quite some time? (I am asking before doing it because I am not sure whether declaring index on non-unique field corrupts the db or not)
Any index will speed up queries that match on the corresponding column. There's no significant difference between the primary key and other indexes in this regard.
The index is created immediately when you execute the ALTER TABLE query. When the prompt returns, the index is there and will be used. There's no corruption while this is happening.