通过MySQL的大表查询与两个表中的WHERE

时间:2017-05-03 22:47:58

标签: mysql database query-optimization

我有两个大表,两个都有一个venue_id。它不是外键,因为它们是两个独立的值。它们如下:

table: activity_retail
columns: activity_id, venue_id, created_at
indexes: activity_id (PRIMARY), (activity_id, venue_id) INDEX


table: activity
columns: activity_id, item_id, venue_id, created_at
indexes: activity_id (PRIMARY), (created_at) INDEX

我想对它们进行查询,对每个表中venue_id等于X的所有活动进行查询。所以我会这样做:

    SELECT * from activity
    LEFT JOIN activity_retail on activity_retail.activity_id = activity.activity_id
    WHERE activity_retail.venue_id = X or activity.venue_id = X 
ORDER BY activity_retail.created_at desc LIMIT 0, 25

我也可能需要对分页进行此查询:

    SELECT * from activity
    LEFT JOIN activity_retail on activity_retail.activity_id = activity.activity_id
    WHERE activity_retail.venue_id = X or activity.venue_id = X and activity.activity_id > Y
ORDER BY activity_retail.created_at desc LIMIT 0, 25

情况是activity_id中的activity_retail可能不存在,它是一个可选字段,因此我无法进行内连接,必须是左连接。

以下是EXPLAIN

1   PRIMARY activity    index   ix_ivi_created created_at   8   NULL    25  Using where
1   PRIMARY activity_retail eq_ref  PRIMARY PRIMARY 4   activity.activity_id    1   

虽然它是一个小查询(根据EXPLAIN),但执行需要很长时间,并且不会使用EXTRAS区域中的任何内容。

有关如何使其正常工作的任何建议 - 基本上WHERE条件跨两个表OR语句? AND效果很好,但我们需要OR

1 个答案:

答案 0 :(得分:0)

你的左联盟似乎非常接近。但是,只要将条件移动到零售表的WHERE子句中,它就会强制进入内部联接。请尝试以下方法......

SELECT 
      A.*,
      AR.* 
   from 
      activity A
         LEFT JOIN activity_retail AR
            on A.activity_id = AR.activity_id 
           AND AR.Venue_ID = X
   WHERE 
          A.Venue_ID = X
      OR  NOT AR.Activity_ID IS NULL
   ORDER BY 
      AR.created_at desc 
   LIMIT 
      0, 25

注意我移动了" AR.Venue_ID = X"进入JOIN子句。这样它只会匹配IF辅助表具有" X"否则它将始终为空。

现在,where子句测试Venue_ID的活动表(总是测试记录)或者AR_ActivityID是非空的(这意味着它找到了具有适当位置的表中的记录,因此存在被引入结果的DOES集。

希望这能满足您的需求。