4

I have a table tb_profilecomments:

4,3 GiB -- 8 Million rows total -- InnoDB

with 3 indexes:

Database SHOW INDEX

The query I run is simple:

SELECT *
FROM tb_profilecomments
WHERE profilecomment_user_id=6430
ORDER BY profilecomment_id DESC

Getting a result in less than 1 second (16.000+ rows). When I now add LIMIT 1, 5 to the query then I got to wait more than 2 minutes to get a result.

Don't know what happens in the mysql background why it's slowing down the query so heavily.

When I remove ORDER BY or LIMIT from the query, then everything is fine.

When sorting it by non-indexed profilecomment_date column, then it's slow (7 seconds), but not 2 minutes like when sorting and limiting with the indexed primary key profilecomment_id.

Do you have any idea what's wrong? A broken index maybe? How to find out? How to fix? ANALYZE TABLE says message "ok".

EXPLAIN tb_profilecomments:

EXPLAIN TABLE command

SHOW CREATE TABLE tb_profilecomments:

SHOW CREATE TABLE command

Result EXPLAIN SELECT * FROM tb_profilecomments WHERE profilecomment_user_id=6430 ORDER BY profilecomment_id DESC LIMIT 1, 5:

EXPLAIN SELECT command

lickmycode
  • 2,069
  • 2
  • 19
  • 20

2 Answers2

1

The rows within an index are very definitely ordered. ASC only. Even the 5.7 manual page says

An index_col_name specification can end with ASC or DESC. These keywords are permitted for future extensions for specifying ascending or descending index value storage. Currently, they are parsed but ignored; index values are always stored in ascending order.

MySQL has always had that limitation. (Upgrading won't help.)

But... That does not stop the code from delivering results in DESC order.

That is, MySQL's deficiency of not having DESC indexes rarely matters. Here is one case where it does matter: ORDER BY x ASC, y DESC. No INDEX can be built (in MySQL) to efficient handle that.

The optimal index for your query is

INDEX(user_id, comment_id);

user_id will be used for WHERE user_id = _constant_, then comment_id will be scanned in reverse order to get the rows you desire. With or without a LIMIT.

But... The index must handle all of WHERE, GROUP BY, and ORDER BY before LIMIT short-circuits execution. (Otherwise, there is a filesort, tmp table, etc, before LIMIT can be applied.)

For the extra-slow queries, please provide EXPLAIN SELECT ... and (if possible), EXPLAIN FORMAT=JSON SELECT ....

Do not drop the PRIMARY KEY on an InnoDB table! It is vitally needed. (OK, drop it if you are replacing it.)

Rick James
  • 135,179
  • 13
  • 127
  • 222
  • Hi Rick, just added the result of your suggested EXPLAIN SELECT command, see last picture in question... EXPLAIN FORMAT=JSON wasn't possible, syntax error. – lickmycode Aug 31 '15 at 11:16
  • You _need_ `INDEX(profilecomment_user_id, profilecomment_id)` – Rick James Aug 31 '15 at 14:40
  • Should I drop the other indexes? You mentioned, never dropping the primary key/index (profilecomment_id). When now creating a new index, profilecomment_id would be twice indexed, isn't it? – lickmycode Aug 31 '15 at 15:06
  • According to the `SHOW CREATE`, you currently have 2 indexes (not "3" as mentioned earlier); neither of them overlap with the one I propose. No `DROP`. – Rick James Aug 31 '15 at 15:23
  • Sorry for my late reaction on this topic. This answer is correct and helped! Thanks a lot! – lickmycode Sep 21 '15 at 05:40
0

create index on column profilecomment_id in decreasing order.

Syntax Format:

CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
    [index_type]
    ON tbl_name (index_col_name,...)
    [index_type]

index_col_name:
    col_name [(length)] [ASC | DESC]

index_type:
    USING {BTREE | HASH}

Sample example:

create table t1(id int(9),name varchar(20),
               [UNIQUE] KEY (id DESC));

DESC order will NOT work for primary key. But it will work for UNIQUE or normal index. You may verify on following link: http://sqlfiddle.com/#!9/ddf95/1 & http://sqlfiddle.com/#!9/5c50d/1

Older version ignores DESC and keep order ASC. For details kindly refer below url:

http://dev.mysql.com/doc/refman/5.5/en/create-index.html

seahawk
  • 1,872
  • 12
  • 18
  • I don't think indices have an "order" per se. – Tim Biegeleisen Aug 29 '15 at 11:23
  • I just know "A" for ASC and "NULL" for no sort order. Can you explain how you would re-create the index with decreasing order? – lickmycode Aug 29 '15 at 11:24
  • @lickmycode : by-default sorting order is ascending. ASC and DESC order for index is reserved for future enhancement. I should be implemented by now in latest version as per MySQL documentation. Please let me know the version of MySQL you are using. – seahawk Aug 29 '15 at 11:37
  • MySQL 5.1.73 is the version used – lickmycode Aug 29 '15 at 11:39
  • Would you please give me the syntax based on the table info used in the question instead of copy and paste the mysql documentation? Would be more helpful. – lickmycode Aug 29 '15 at 11:43
  • @lickmycode : its lil old version. Anyway just try it. Just update with `column_name DESC` in your index creation. And let let me know whether it worked. – seahawk Aug 29 '15 at 11:44
  • I know it's an old version, can't change that for now. Could you provide the full command I should use please? Then I test it now. – lickmycode Aug 29 '15 at 11:47
  • I now added this, but like you said, it seems to be ignored. At least, I don't see any hint of DESC after adding the index :-/ – lickmycode Aug 29 '15 at 11:56
  • Okay, mysql 5.1 manual says DESC is valid... how can I confirm it's used? – lickmycode Aug 29 '15 at 11:58
  • @lickmycode : You can spot the difference by looking into `EXPLAIN` plan of both version i.e., with DESC order and without DESC order index. – seahawk Aug 29 '15 at 12:03
  • @lickmycode : I found the solution, instead of using primary key if you use `normal or unique index`. it will work. http://sqlfiddle.com/#!9/ddf95/1 & http://sqlfiddle.com/#!9/5c50d/1 – seahawk Aug 29 '15 at 12:08
  • Sounds promising. Will test it out. What about the 'PRIMARY' index on column (profilecomment_id) I have. Drop it? Can't I just alter it maybe? – lickmycode Aug 29 '15 at 13:02
  • _The chatter in the comments here has multiple errors. I have tried to rectify them in my 'Answer'._ – Rick James Aug 30 '15 at 00:22