Indexing mysql query - mysql

I have this query in mysql and I wanted to be indexed, what is the best index composition?
SELECT cometchat.id, cometchat.from, cometchat.to, cometchat.message, cometchat.sent, cometchat.read, cometchat.direction
FROM cometchat
WHERE (
(
cometchat.to = '30411'
AND cometchat.direction <>2
)
OR (
cometchat.from = '30411'
AND cometchat.direction <>1
)
)
I've tried these indexes but they didn't work:
ALTER TABLE `cometchat` ADD INDEX ( `from`,`to`,`direction`)
ALTER TABLE `cometchat` ADD INDEX ( `from`,`to`)
ALTER TABLE `cometchat` ADD INDEX ( `to`,`direction`)
ALTER TABLE `cometchat` ADD INDEX ( `from`,`direction`)
Any help would be much appreciated.

Because of the OR in your where clause, you'd need 2 separate indexes to optimaze selects:
ALTER TABLE `cometchat` ADD INDEX index1 ( `to`,`direction`)
ALTER TABLE `cometchat` ADD INDEX index2 ( `from`,`direction`)
I wouldn't bother trying to make these covering indexes--just eat the cost of the point lookup. However, if you want them to be covering you'd need:
ALTER TABLE `cometchat` ADD INDEX index1
( `to`,`direction`, `message`, `sent`, `read` );
ALTER TABLE `cometchat` ADD INDEX index2
( `from`,`direction`,`message`, `sent`, `read`);
The covering indexes will give best select performance, but it's a lot of extra storage and will add to insert overhead--so I'd only use them if performance with the non-covering ones are inadequate and this is a insert light table.
Also, just some general advice, I'd avoid using MySQL reserved words like 'from' when naming databases, tables, or columns. https://dev.mysql.com/doc/refman/5.5/en/reserved-words.html
When you use a reserved as a name for something you're really asking to run into a buggy query that will result in another SP question ;)

Try using only the following:
ALTER TABLE `cometchat` ADD INDEX (`direction`)

Related

How to convert a temporary table to permanent table in a single atomic operation?

How to convert a temporary table to a static table in a single atomic operation, while still being agnostic to the table structure but yet preserving it, in MySQL?
For a pre-created temporary table of:
CREATE TEMPORARY TABLE _tmp SELECT 0 AS Col1, 'text' AS Col2;
ALTER TABLE _tmp ADD UNIQUE INDEX (Col1, Col2);
Of course, one could always go:
CREATE TABLE permanent SELECT * FROM _tmp; -- 1
ALTER TABLE permanent ADD UNIQUE INDEX (Col1, Col2); -- 2
or, which I, for lack of a better solution, am using:
-- mostly agnostic to the structure unless for generated or auto-increment columns
CREATE TABLE permanent LIKE _tmp; -- 1
INSERT INTO permanent SELECT * FROM _tmp; -- 2
As shown above, right now I can only manage to do it with at least 2 (DDL + (DDL or DML)) statements.
Is there a way I can improve this to a single DDL? Perhaps a functionality that facilitates a feature combining LIKE & INSERT?
CREATE TABLE permanent
SELECT * FROM _tmp;
fiddle
or (if you need in unique key presence)
CREATE TABLE permanent ( UNIQUE KEY `Col1` (`Col1`,`Col2`) )
SELECT * FROM _tmp;
fiddle

How can I optimize this SQL query with 100.000 records?

There is my SQL query. Table system_mailer is for logging sent e-mails. When i want to search some data, query is 10 seconds long. It is possible on any way to optimize this query?
SELECT `ID`
FROM `system_mailer`
WHERE `group` = 'selling_center'
AND `group_parameter_1` = '1'
AND `group_parameter_2` = '2138'
Timins is around couple of seconds, how could it be optimised?
You might find the following index on 4 columns would help performance:
CREATE INDEX idx ON system_mailer (`group`, group_parameter_1, group_parameter_2, ID);
MySQL should be able to use this index on your current query. By the way, if you are using InnoDB, and ID is the primary key, then you might be able to drop it from the explicit index definition, and just use this:
CREATE INDEX idx ON system_mailer (`group`, group_parameter_1, group_parameter_2);
Please avoid naming your columns and tables with reserved MySQL keywords like group. Because you made this design decision, you will now be forced to forever escape that column name with backticks (ugly).
just be sure you have a composite index on table system_mailer for the columns
(`group`, `group_parameter_1`, `group_parameter_2`)
and you can use redudancy adding the id to index for avoid data table access in query
(`group`, `group_parameter_1`, `group_parameter_2`, ID)

MySQL - Change index on myIsam table

I have a table where two columns are used in a where condition.
This is a MyIsam table and both columns hold text and use FULLTEXT as index.
The values in both columns are not unique.
The select statement works pretty slow.
Question is: can I simply remove the FULLTEXT index and use another index instead?
The query that is used is just as simple as possbile:
SELECT * FROM tbl WHERE col1=X AND col2=y and col3=z
Thanks!
ALTER TABLE `tableName` DROP INDEX `indexName` ,
ADD INDEX `indexName` ( `ColName` )
This shuld remove the old "FULLTEXT" index and add a "NOT FULTEXT" index.

Pass index to temporary table from regular table?

I am creating a temp table with a query like this:
CREATE TEMPORARY TABLE temp_table
SELECT * FROM regular_table
WHERE 1
But regular_table has FULLTEXT index on some of the fields. I try to do a FULLTEXT search on the new temporary table and I get an error telling me "Can't find FULLTEXT index matching the column list". So obviusly the index is not copying over to the new table. Is there a way to force this?
Thanks.
You could use CREATE TEMPORARY TABLE temp_table LIKE regular_table, but that will create all the indexes, so when you do INSERT INTO temp_table SELECT * FROM regular_table, the indexes will be rebuilt - which could be lengthy.
Or, you can create the table and add the index afterwards:
CREATE TEMPORARY TABLE temp_table
ALTER TABLE temp_table ADD FULLTEXT INDEX (foo,bar,baz)
INSERT INTO temp_table SELECT * FROM regular_table
but the index will be, again, updated on every insert.
Probably the most efficient way would be to create the temp table, insert all, build index afterwards:
CREATE TEMPORARY TABLE temp_table
ALTER TABLE temp_table ADD FULLTEXT INDEX (foo,bar,baz)
ALTER TABLE temp_table DISABLE KEYS
INSERT INTO temp_table SELECT * FROM regular_table
ALTER TABLE temp_table ENABLE KEYS
Again, you will have to wait for the index to build, except it will happen in one chunk, with the last ALTER statement.
A temporary table is exactly the same as any other table except that it will be dropped at the end of the session. The only way to have the same indexes (from within the database) is to create them on the table as you would any other table.
Now there is a bit of a hack. You can copy the physical files on disk to a new name and have a clone of the table which includes indexes but I'm assuming you're doing this within an app so that might not be very practical.

MySQL INDEXES - Adding multuple columns to one index

I am still getting my head around MySQL INDEXES... A quick question...
I have a table that stores a members location. It has a member_id and location_id columns... I do a MySQL query to find all the locations for a specific member...
Would it be better to setup an INDEX like this:
ALTER TABLE `members_locations` ADD INDEX `member_location` ( `member_id` , `location_id` )
Or should I separate them like this>
ALTER TABLE `members_locations` ADD INDEX `member_id` ( `member_id` );
ALTER TABLE `members_locations` ADD INDEX `location_id` ( `location_id` );
Does it make any difference?
This article should be helpful.
Here's an example from it:
ALTER TABLE buyers ADD INDEX idx_name_age(first_name,last_name,age);
Here's another article showing the difference between using a multi-column index and several single-column indexes.
Well,
I guess it would be better to have one index, but it actually depends on how you query it.
If you have both columns (member_id, location_id) in the where clause, they must definitely go into one index.
if you query them independently, e.g. sometimes by member_id, sometimes by location_id only, you might consider two indexes. However, even in that case, one of those index should probably include the second column as well to support queries where both columns are present.
At the end, it all depends what queries you would like to tune.
Although not for MySQL, but for Oracle, my new Web-Book "Use The Index, Luke" describes this in detail. AFAIK all databases are rather similar in that respect.
http://use-the-index-luke.com/where-clause/the-equals-operator/concatenated-keys