MySql Indexes Sort and Where - mysql

I would like to know how MySql handle the indexes priority. I have the following table.
CREATE TABLE table (
colum1 VARCHAR(50),
colum2 VARCHAR(50),
colum3 ENUM('a', 'b', 'c'),
PRIMARY KEY(colum1, colum2, colum3)
);
CREATE INDEX colum1_idx ON table (colum1);
CREATE INDEX coloum2_idx ON table (colum2);
const query = `SELECT * FROM table
WHERE colum1 = ?
ORDER BY colum2
LIMIT ?,?`;
Basically my PK is composed by all fields (I need to use INSERT IGNORE) and I am query using colum1 as WHERE clause and ORDER by colum2.
My question is should I create 2 different indexes or create 1 index with (colum1 and colum2)?

Thanks to #JuanCarlosOpo
I find the answer here: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#algorithm_step_2c_order_by_
It's more performant using a compound index using both columns.
CREATE INDEX colum_idx ON table (colum1,colum2);
Thanks a lot!

Related

CONTAINS doesn't return any result

I know LIKE can be used instead of CONTAINS but CONTAINS is relatively faster as compared to LIKE. Here, the following query doesn't return me any result. Why?
Query:
SELECT CustomerName FROM members WHERE CONTAINS(Country, 'Mexico');
DATABASE:
MySQL Solution
select customername
from members
where match(country) against ('Mexico')
MS SQL Server Solution
Full text indexes aren't necessarily always populated after creation.
Use the following code to ensure the index updates:
ALTER FULLTEXT INDEX ON members SET CHANGE_TRACKING AUTO;
More info: https://msdn.microsoft.com/en-us/library/ms142575.aspx
Full example (including change tracking option on index creation rather than in a later alter statement):
use StackOverflow
go
create table myTable
(
id bigint not null identity(1,1)
constraint myTable_pk primary key clustered
, name nvarchar(100)
);
create fulltext catalog StackOverflow_Catalog;
create fulltext index
on myTable(name)
key index myTable_pk
on StackOverflow_Catalog
with change_tracking auto;
insert myTable
select 'Mexico'
union select 'London';
select *
from myTable
where contains(name,'Mexico');
Have you tried using in it might be even faster if it works in your case
SELECT CustomerName
FROM members
WHERE Country IN ('Mexico')
But in your case you may put %% in contains is actually faster then contain so just use this
SELECT CustomerName
FROM members
WHERE CONTAINS(Country, '"*Mexico"');
try this
If there is Full-Text Search Index on column Country.
SELECT CustomerName FROM members
WHERE CONTAINS(Country, 'Mexico');
Otherwise just do
SELECT CustomerName FROM members
WHERE Country LIKE N'%Mexico%';
there is a unicode character é, you need to prefix the string with N

"order by" kills performance

I'm not a MySQL guy, actually I'm doing this to help a friend.
I have these tables in a MySQL database:
create table post (ID bigint, p text)
create table user (ID bigint, user_id bigint)
and I'm querying them by this script:
select * from post
where ID in (select user_id from user where ID = 50)
order by ID DESC --this line kills performance.
limit 0,20
As I mentioned in comment, when there is no order by ID DESC, the query executes very fast. But when I add that to the query, it got very very slow with a huge CPU usage. Do you have any idea what am I doing wrong?
You should define ID as Primary Key for your table. This will add an index and increase performance. At least as a first step, it's a good one.
This query should do the trick:
create table post (
ID bigint,
p text,
PRIMARY KEY (ID));
Thanks to #frlan the problem got solved by indexes:
CREATE INDEX IDX_POST_ID ON post (ID);
CREATE INDEX IDX_USER_ID ON user (ID);
CREATE INDEX IDX_USER_USERID ON user (user_id);

Improve MySQL searches on huge tables

How to deal with thousands of tuples in a table? How can be searching improved if there is no primary key in my table?
ex:
id attr
1 I'm
1 Too
1 Damn
2 Slow
2 To
2 Search
I can group the data together using group_concat() but i'm unsure that will it search my complete table to get the end result? And if yes, then how it can be improved?
Create an index on column you want to use in search query to improve search.
e.g if your table is CREATE TABLE T1(A INT PRIMARY KEY, B INT, C CHAR(1));
then index can create using this on column B, CREATE INDEX B ON T1 (B);

Search by primary key and then sort

I'm using MySQL and I have a database that I'm trying to use as the canonical version of data that I will be storing in different indexes. That means that I have to be able to retrieve a set of data quickly from it by primary key, but I also need to sort it on the way out. I can't figure out how to let MySQL efficiently do that.
My table looks like the following:
CREATE TABLE demo.widgets (
id INT AUTO_INCREMENT,
-- lots more information I need
awesomeness INT,
PRIMARY KEY (id),
INDEX IDX_AWESOMENESS (awesomeness),
INDEX IDX_ID_AWESOMENESS (id, awesomeness)
);
And I want to do something along the lines of:
SELECT *
FROM demo.widgets
WHERE id IN (
1,
2,
3,
5,
8,
13 -- you get the idea
)
ORDER BY awesomeness
LIMIT 50;
But unfortunately I can't seem to get good performance out of this. It always has to resort to a filesort. Is there a way to get better performance from this setup, or do I need to consider a different database?
This is explained in the documentation ORDER BY Optimization. In particular, if the index used to select rows in the WHERE clause is different from the one used in ORDER BY, it won't be able to use an index for ORDER BY.
In order to get an optimized query to fetch and retrieve like that, you need to have a key that orders by sort and then primary like so:
create table if not exists test.fetch_sort (
id int primary key,
val int,
key val_id (val, id)
);
insert into test.fetch_sort
values (1, 10), (2, 5), (3, 30);
explain
select *
from test.fetch_sort
where id in (1, 2, 3)
order by val;
This will give a query that only uses the index for searching/sorting.

SQL trigger, insert into statement

I have two sql tables called scan_sc and rescan_rsc. The scan table looks like this:
CREATE TABLE scan_sc
(
id_sc int(4),
Type_sc varchar(255),
ReScan_sc varchar(255),
PRIMARY KEY (id_sc)
)
When a scan a document I insert a row into the scan table. If the result of this scanning is poor I have to do a rescan, and therefore I have a rescan table.
CREATE TABLE rescan_rsc
(
id_rsc int(4),
Scan_rsc varchar(255),
PRIMARY KEY (id_rsc)
)
The problem is, I want to have a trigger that will fill in the column ReScannet_sc with an "x", in the scan_sc table, so I can see that there has been some problems here.
The trigger has to do it where the id from the rescan table is the same as in the scan table.
Hope you all understand my question.
Thanks in advance.
Do you really need the ReScan_sc column and the trigger?
With a simple JOIN, you can find out the records in your scan_sc table that have been re-scanned, without using the ReScan_sc column at all.
There are several possibilities:
Show all scans, with an additional column with the Rescan ID, if any:
SELECT scan_sc.*, rescan_sc.id_rsc
FROM scan_sc
LEFT JOIN rescan_sc ON scan_sc.id_sc = rescan_sc.id_rsc
Show only the scans which have been re-scanned:
SELECT scan_sc.*
FROM scan_sc
INNER JOIN rescan_sc ON scan_sc.id_sc = rescan_sc.id_rsc
(I assume that id_sc and id_rsc are the primary keys and that PRIMARY KEY (id_sd) is a typo, like marc_s pointed out in his comment)