optimizing Mysql tables with index - php

SELECT *
FROM sms_report
WHERE R_uid = '159'
AND R_show = '1'
ORDER BY R_timestamp DESC , R_numbers
This is my query. Now it is using filesort i need to add index so that its optimized.
Below is the output of explain
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE sms_report ref R_uid,R_show R_uid 4 const 765993 Using where; Using filesort
The table is MYISAM and i have created indexes on R_smppid, R_uid, R_show, R_timedate, R_numbers
Someone adviced me on adding composite index. can you tell me which all fields should I index and how.

Try using a composite index on R_uid,R_show,R_timestamp,R_numbers - that way it should be able to find exactly the rows you are looking for in 1 index, and have the results already sorted.
EDIT - DESC may throw that optimization... but it may be worth a try

Since MySQL says possible keys == R_uid,R_show, try creating a composite index over just those two.
Try running ANALYZE TABLE sms_report; Maybe also OPTIMIZE TABLE
Also try using EXPLAIN EXTENDED ... to see if it gives you more info.
If you are only interested in some of the columns, only specify those columns instead of *. Some databases (I don't know if MySQL is one of them) can skip reading the table and return the results straight from the index if the index includes all the columns you're interested in. e.g. if you're only interested in R_uid and R_show, then doing SELECT R_uid, R_show FROM ... instead of SELECT * FROM ... could speed things up. (Again, I don't know if this applies to MySQL.)

How to add index:
alter table sms_report add index new_index (uid, show, R_timestamp, R_numbers);
How to force query to use new index
SELECT *
FROM sms_report
USE INDEX new_index
WHERE R_uid=159 AND R_show=1
ORDER BY R_timestamp DESC, R_numbers;

Related

MYSQL where clause slow performance on big table

I have a performance issue when working with a huge table
I add index on column using this :
ALTER table add index column;
and on the text/blob column :
alter table add index (cat(200));
My table has about 6M rows and i am working with InnoDB engine (Mysql 5.5)
This query is very fast now that i add index on "order by" column:
SELECT * from table order by column DESC LIMIT 0,40
But when I add a WHERE clause on this query its very slow and it take about 10 seconds to load even with the column "cat" index like above. //index instead of indexed
SELECT * from table WHERE cat = 'electronic' order by column DESC LIMIT 0,40
the EXPLAIN of this slow query :
EXPLAIN SELECT * from table WHERE cat = 'electronic' order by 'id' DESC LIMIT 0,40
id : 1
select_type : SIMPLE
table : product
type : ref
possible_keys: cat
key: cat
Key_len: 203
ref: const
row : 1732184
extra: using where
The query working fine with small table with 50k rows but with 6M rows its slow. Why?
Do not use prefixing, such as cat(200); it usually makes the index unusable. I have never seen a case where the Optimizer, when faced with INDEX(a(10), b), gets past a and makes any use of b.
Change cat to be VARCHAR(255). That is probably more than sufficient for "categories".
The best index (if it is possible) is
INDEX(cat, `column`)
Note that cat is in the WHERE with =. It handles the entire WHERE, so the index can move on to the ORDER BY. Hence column can be used, too. More discussion of index making .
If cat must be TEXT, then the best you can do is
INDEX(`column`)
Then the Optimizer may decide to use it for avoiding a filesort. But if there are fewer than 40 (see LIMIT) 'electronic' rows, it will take an big scan and probably be slower than not using the index. So, I am not sure that it is even worth having INDEX(column).
For this query:
SELECT t.*
FROM table t
WHERE cat = 'electronic'
ORDER BY column DESC
LIMIT 0, 40;
The best index is a composite index on table(cat, column). You can use a prefix if column is too wide: table(cat, column(200)).
The best option is to index the table, if you dont know how to do it, you can check this doc
So, when you perform the query, the mysql will start searching on the indexed values, skipping a lot of useless data for that request.

groupby with column field having like column

I am using group by for like statement as i have database structure like this.
I want to get the count of workingzone groupby.but if i try to group by, then wrong output will appear as output will group by 99 and 99, as in figure.
My sql code is:
select count(organization),working_zone from `projects` where `district` = 12 and (`working_zone` = 99 or `working_zone` LIKE "99," or `working_zone` LIKE ",99") group by `organization`;
my desired result is:
count |working_zone
____6| 99
____3| 100
(99),(,99),(99,) should be grouped by doing sum and result should be 6.
You have an awful data structure -- although I wouldn't be surprised if the data is okay and you are really working off the result of a (reasonable) query. You should not be storing raw data in comma-delimited lists. Instead, use junction tables.
Why is having a separate row for each pair the SQLish way of storing data? Consider these reasons:
SQL has pretty based string functions (compared to other programming environments).
Data should be stored in its native type; don't store numbers as strings.
Foreign key relationships should be explicitly declared, and you can't declare a foreign key relationship using comma-delimited strings.
The primary SQL mechanism for optimizing queries are indexes, and comma-delimited lists preclude the use of indexes.
Sometimes, though, you are stuck with someone else's bad design decisions. If so, one solution uses a table of working zones:
select count(*), wz.working_zone
from projects p join
working_zones wz
on find_in_set(wz.working_zone, p.working_zone) > 0
where p.district; = 12 and
find_in_set(99, p.working_zone) > 0
group by wz.working_zone;
SELECT COUNT(organization),working_zone FROM table WHERE working_zone HAVING '99'
UNION ALL
SELECT COUNT(organization),SUBSTRING(working_zone,4) FROM table WHERE working_zone = '99,100'

Mysql count slow when filter by category

Why my query fast when I run.
select count(*) as aggregate from `news` where `news`.`deleted_at` is null and `status` = '1'
But, slow when I run.
select count(*) as aggregate from `news` where `news`.`deleted_at` is null and `status` = '1' and `newscategory_id` = '17'
It is my table news structure image, have a look at here.
Sorry because my reputation is less than 8, so I can't attach image.
try adding an composite index on the three columns you are using for your select:
ALTER TABLE news ADD INDEX comp_index (deleted_at, status, newscategory_id);
and check it again.
probably use EXPLAIN to see if any indexes you have are used.
Indexes are used to find rows with specific column values quickly.
Without an index, MySQL must begin with the first row and then read
through the entire table to find the relevant rows. The larger the
table, the more this costs. If the table has an index for the columns
in question, MySQL can quickly determine the position to seek to in
the middle of the data file without having to look at all the data.
This is much faster than reading every row sequentially.
Try to add this in your DB:
CREATE INDEX newCategory_indx ON news (newscategory_id)
CREATE INDEX status_indx ON news (status)
This will give you quick result, as compared to previously generate (non-indexed column) result.
To know more about index and it's importance visit here

How to correctly index the following?

I have the following table (file_category_tbl) to represent connections between files and categories.
fileId - bigint(20)
categoryId - bigint(20)
order - int(10)
So that the files in a category can be ordered, I have an order field...
Therefore my question is what indexes would I require for optimum performance on the following:
SELECT * FROM file_category_tbl WHERE categoryId="3" ORDER BY order ASC
I have a unique index a UNIQUE (fileId ,categoryId);
As there can't be the same fileId with the same categoryId.
I have also got an index on categoryId, as this is what is being searched on.
I have also got an index on order?... but is this neccessary? as it is only doing an orderBy on this...
Kind Regards to any responder... J
As documented under ORDER BY Optimization:
In some cases, MySQL cannot use indexes to resolve the ORDER BY, although it still uses indexes to find the rows that match the WHERE clause. These cases include the following:
[ deletia ]
The key used to fetch the rows is not the same as the one used in the ORDER BY:
SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
Therefore your current indexing cannot be used for performing the sort operation. However, the same page also documents:
The index can also be used even if the ORDER BY does not match the index exactly, as long as all of the unused portions of the index and all the extra ORDER BY columns are constants in the WHERE clause. The following queries use the index to resolve the ORDER BY part:
[ deletia ]
SELECT * FROM t1
WHERE key_part1=constant
ORDER BY key_part2;
Therefore a compound index over (categoryId,order) can be used for both the filter and the sort operations, which is the optimal outcome for this query.
According to my understanding, your indexing is sensible and will help towards performance of your query. But I would also suggest you to have aPrimary Key index in your table rather than only having the combined Unique Index
The reason I'm telling this is, If you want to refer to any of your records of this table, may be to delete it or do any other function, a primary key would be useful. On the other hand it might actually downgrade the performance of your query because you are requiring all the fields and now with the primary key field, you have to bring in 4 fields. As a solution for that, you can specify what columns you want in your result.
Hope this makes sense :-)

How to improve performance of MySQL query with frequent insert rate?

I'm having approx. 200K rows in a table tb_post, and every 5 minutes it has approx. 10 new inserts.
I'm using following query to fetch the rows -
SELECT tb_post.ID, tb_post.USER_ID, tb_post.TEXT, tb_post.RATING, tb_post.CREATED_AT,
tb_user.ID, tb_user.NAME
FROM tb_post, tb_user
WHERE tb_post.USER_ID=tb_user.ID
ORDER BY tb_post.RATING DESC
LIMIT 30
It's taking more than 10sec to fetch all the rows in sorted fashion.
Following is the report of EXPLAIN query:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE tb_user ALL PRIMARY NULL NULL NULL 20950 Using temporary; Using filesort
1 SIMPLE tb_post ref tb_post_FI_1 tb_post_FI_1 4 tb_user.id 4
Few inputs:
tb_post.RATING is Float type
There is index on tb_post.USER_ID
Can anyone suggest me few pointers about how should I optimize this query and improve its read performance?
PS: I'm newbie in database scaling issues. So any kinds of suggestions will be useful specific to this query.
You need an index for tb_post that covers both the ORDER BY and WHERE clause.
CREATE INDEX idx2 on tb_post (rating,user_id)
=> output of EXPLAIN SELECT ...ORDER BY tb_post.RATING DESC LIMIT 30
"id";"select_type";"table";"type";"possible_keys";"key";"key_len";"ref";"rows";"Extra"
"1";"SIMPLE";"tb_post";"index";NULL;"idx2";"10";NULL;"352";""
"1";"SIMPLE";"tb_user";"eq_ref";"PRIMARY";"PRIMARY";"4";"test.tb_post.USER_ID";"1";""
You could try to index tb_post.RATING: MySQL can sometimes use indexes to optimize ORDER BY clauses : http://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html
If you're trying to aggregate data from different tables, you could also check which type of join ( http://en.wikipedia.org/wiki/Join_(SQL) ) you want. Some are better than others, depending on what you want.
What happens if you take the ORDER BY off, does that have a performance impact? If that has a large effect then maybe consider indexing tb_post.RATING.
Karl

Categories