簡體   English   中英

使用訂單查詢慢連接

[英]Slow join with order query

我的查詢速度有問題。 問題與此類似,但找不到解決方案。 解釋說 MySQL 正在使用:Using where; 使用索引; 使用臨時; 使用文件排序慢查詢:

select 
    distinct(`books`.`id`)
from `books`
join `books_genres` on `books_genres`.`book_id` = `books`.`id`
where 
    `books`.`is_status` = 'active' and `books`.`master_book` = 'true'  
    and `books_genres`.`genre_id` in(380,381,384,385,1359)
order by 
    `books`.`livelib_read_num` DESC, `books`.`id` DESC
limit 0,25
#25 rows (0.319 s)

但是如果我從查詢中刪除訂單語句,它真的很快:

select sql_no_cache
    distinct(`books`.`id`)
from `books`
join `books_genres` on `books_genres`.`book_id` = `books`.`id`
where 
    `books`.`is_status` = 'active' and `books`.`master_book` = 'true'  
    and `books_genres`.`genre_id` in(380,381,384,385,1359)
limit 0,25
#25 rows (0.005 s)

解釋:

   +------+-------------+--------------+--------+---------------------------------------------------------------------------------------------------------------------+------------------+---------+--------------------------------+--------+-----------------------------------------------------------+
| id   | select_type | table        | type   | possible_keys                                                                                                       | key              | key_len | ref                            | rows   | Extra                                                     |
+------+-------------+--------------+--------+---------------------------------------------------------------------------------------------------------------------+------------------+---------+--------------------------------+--------+-----------------------------------------------------------+
|    1 | SIMPLE      | books_genres | range  | book_id,categorie_id,book_id2,genre_id_book_id                                                                      | genre_id_book_id | 10      | NULL                           | 194890 | Using where; Using index; Using temporary; Using filesort |
|    1 | SIMPLE      | books        | eq_ref | PRIMARY,is_status,master_book,is_status_master_book,is_status_master_book_indexed,is_status_donor_no_ru_master_book | PRIMARY          | 4       | knigogid3.books_genres.book_id |      1 | Using where                                               |
+------+-------------+--------------+--------+---------------------------------------------------------------------------------------------------------------------+------------------+---------+--------------------------------+--------+-----------------------------------------------------------+
2 rows in set (0.00 sec)

我的表:

CREATE TABLE `books_genres` (
  `book_id` int(11) DEFAULT NULL,
  `genre_id` int(11) DEFAULT NULL,
  `sort` tinyint(4) DEFAULT NULL,
  UNIQUE KEY `book_id` (`book_id`,`genre_id`),
  KEY `categorie_id` (`genre_id`),
  KEY `sort` (`sort`),
  KEY `book_id2` (`book_id`),
  KEY `genre_id_book_id` (`genre_id`,`book_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `books` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `is_status` enum('active','parser','incorrect','extremist','delete','fulldeteled') NOT NULL DEFAULT 'active',
  `livelib_book_id` int(11) DEFAULT NULL,
  `master_book` enum('true','false') DEFAULT 'true'
  PRIMARY KEY (`id`),
  KEY `is_status` (`is_status`),
  KEY `master_book` (`master_book`),
  KEY `livelib_book_id` (`livelib_book_id`),
  KEY `livelib_read_num` (`livelib_read_num`),
  KEY `is_status_master_book` (`is_status`,`master_book`),
  KEY `livelib_book_id_master_book` (`livelib_book_id`,`master_book`),
  KEY `is_status_master_book_indexed` (`is_status`,`master_book`,`indexed`),
  KEY `is_status_donor_no_ru_master_book` (`is_status`,`donor`,`no_ru`,`master_book`),
  KEY `livelib_url_master_book_is_status` (`livelib_url`,`master_book`,`is_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

books_genres問題。

  • 它沒有PRIMARY KEY
  • 所有列都可以為空。 你會插入帶有任何NULLs的行嗎?

推薦(在所有列上都說NOT NULL之后):

PRIMARY KEY(`book_id`,`genre_id`)
INDEX(genre_id, book_id, sort)

並刪除所有其余的。

我在表中沒有看到livelib_read_num ???

在另一個表中,刪除與某個其他索引的確切前綴相同的所有索引。

這些可能有助於提高速度。 (同樣,過濾掉多余的前綴索引。)(這些是“覆蓋”索引,這有點幫助。)

books:  INDEX(is_status, master_book, livelib_read_num, id)
books:  INDEX(livelib_read_num, id, is_status, master_book)

第二個索引可能會導致優化器優先使用ORDER BY (這是一個有風險的優化,因為它可能必須掃描整個索引而沒有找到 25 個相關行。)

SELECT sql_no_cache
       `books`.`id`
    FROM
        `books` 
    use index(books_idx_is_stat_master_livelib_id)
    WHERE
        (
            1 = 1 
            AND `books`.`is_status` = 'active' 
            AND `books`.`master_book` = 'true'
        ) 
        AND (
            EXISTS (
                SELECT
                    1 
                FROM
                    `books_genres` 
                WHERE
                    (
                        `books_genres`.`book_id` = `books`.`id`
                    ) 
                    AND (
                        `books_genres`.`genre_id` IN (
                            380, 381, 384, 385, 1359
                        )
                    )
            )
        ) 
    ORDER BY
        `books`.`livelib_read_num` DESC,
        `books`.`id` DESC LIMIT 0,
        25;
25 rows in set (0.07 sec)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM