2013-10-07 21 views
1

我的問題是,我有兩個不同的查詢,在不同的 情況下很好地工作。我怎麼能impove這個JOIN操作之間的關鍵表和另一個

SCHEMA

messages 
     message_id, entity_id, message, timestamp 

    subscription 
     user_id, entity_id 

    users 
     user_id 

    entities 
     entity_id 

情況1:消息條目的地段,和至少一個相關訂閱條目

情況2:很少消息條目和/或幾個,或零,即是相關的預訂條目

我的兩個查詢是:

SELECT messages.* 
    FROM messages 
    STRAIGHT_JOIN subscription ON subscription.entity_id = messages.entity_id 
    WHERE subscription.user_id = 1 
    ORDER BY messages.timestamp DESC 
    LIMIT 50 

這種查詢在情況1(.000x秒)中效果很好:很多消息條目和至少一個相關訂閱條目。 thisquery將採取1.7+秒局勢2.

SELECT messages.* 
    FROM messages 
    INNER JOIN subscription ON subscription.entity_id = messages.entity_id 
    WHERE subscription.user_id = 1 
    ORDER BY messages.timestamp DESC 
    LIMIT 50 

該查詢工作在情況2(.000x秒)以及:很少有消息條目和/或幾個,或者爲零,即是相關的訂閱條目。這個查詢將在情況1中花費1.3+秒。

有沒有一個查詢我可以使用,可以得到兩全其美?如果不是, 處理這種情況的最佳方式是什麼?

索引:

(subscription.user_id, subscription.entity_id) 
(subscription.entity_id) 
(messages.entity_id, messages.timestamp) 
(messages.timestamp) 

EXPLAIN INFO

LIMIT 50

| id | select_type | table    | type | possible_keys       | key   | key_len | ref         | rows | Extra  | 
| 1 | SIMPLE  | messages   | index | idx_timestamp       | idx_timestamp | 4  | NULL         | 50 |    | 
| 1 | SIMPLE  | subscription  | eq_ref | PRIMARY,entity_id,user_id    | PRIMARY  | 16  | const, messages.entity_id    | 1 | Using index | 

無限制

| id | select_type | table    | type | possible_keys       | key   | key_len | ref         | rows | Extra   | 
| 1 | SIMPLE  | messages   | ALL | entity_id_2,entity_id     | NULL   | NULL | NUL         | 255069 | Using filesort| 
| 1 | SIMPLE  | subscription  | eq_ref | PRIMARY,entity_id,user_id    | PRIMARY  | 16  | const, messages.entity_id    |  1 | Using index | 

CREATE TABLE語句:

隨着〜5000行

subscription | CREATE TABLE `subscription` (
    `user_id` bigint(20) unsigned NOT NULL, 
    `entity_id` bigint(20) unsigned NOT NULL, 
    PRIMARY KEY (`user_id`,`entity_id`), 
    KEY `entity_id` (`entity_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

與〜255,000行

messages | CREATE TABLE `messages` (
    `message_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    `entity_id` bigint(20) unsigned NOT NULL, 
    `message` varchar(255) NOT NULL DEFAULT '', 
    `timestamp` int(10) unsigned NOT NULL, 
    PRIMARY KEY (`message_id`), 
    KEY `entity_id` (`entity_id`,`timestamp`), 
    KEY `idx_timestamp` (`timestamp`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

回答

0

試着改變你的WHEREAND

SELECT messages.* 
    FROM messages 
    STRAIGHT_JOIN subscription ON subscription.entity_id = messages.entity_id 
     AND subscription.user_id = 1 
    ORDER BY messages.timestamp DESC 
    LIMIT 50 

OR

SELECT messages.* 
    FROM messages 
    INNER JOIN subscription ON subscription.entity_id = messages.entity_id 
      AND subscription.user_id = 1 
    ORDER BY messages.timestamp DESC 
    LIMIT 50 

,或者可以這樣說:

SELECT messages.* 
FROM subscription 
STRAIGHT_JOIN messages ON subscription.entity_id = messages.entity_id 
WHERE subscription.user_id = 1 
ORDER BY messages.timestamp DESC 
LIMIT 50 
+0

感謝您的建議,但他們似乎並沒有解決問題。 –

相關問題