2013-10-07 20 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

感谢您的建议,但他们似乎并没有解决问题。 –

相关问题