假设我有以下数据库设置(我实际拥有的简化版本):
Table: news_posting (500,000+ entries)
| --------------------------------------------------------------|
| posting_id | name | is_active | released_date | token |
| 1 | posting_1 | 1 | 2013-01-10 | 123 |
| 2 | posting_2 | 1 | 2013-01-11 | 124 |
| 3 | posting_3 | 0 | 2013-01-12 | 125 |
| --------------------------------------------------------------|
PRIMARY posting_id
INDEX sorting ON (is_active, released_date, token)
Table: news_category (500 entries)
| ------------------------------|
| category_id | name |
| 1 | category_1 |
| 2 | category_2 |
| 3 | category_3 |
| ------------------------------|
PRIMARY category_id
Table: news_cat_match (1,000,000+ entries)
| ------------------------------|
| category_id | posting_id |
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 2 | 2 |
| 3 | 2 |
| 1 | 3 |
| 2 | 3 |
| ------------------------------|
UNIQUE idx (category_id, posting_id)
我的任务如下。我必须得到50个最新的新闻贴子(在一些偏移处),这些贴片是活动的,在今天的日期之前,并且是在请求中指定的20个左右类别中的一个。在我选择要返回的50个新闻帖子之前,我必须按降序按令牌排序相应的新闻帖子。我的查询目前类似于以下内容:
SELECT DISTINCT posting_id
FROM news_posting np
INNER JOIN news_cat_match ncm ON (ncm.posting_id = np.posting_id AND ncm.category_id IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20))
WHERE np.is_active = 1
AND np.released_date < '2013-01-28'
ORDER BY np.token DESC LIMIT 50
只有一个指定的category_id
,查询不涉及filesort
并且速度相当快,因为它不必处理重复结果的删除。但是,在具有多个EXPLAIN
的上述查询上调用category_id
会返回一个表格,表明要完成filesort
。而且,我的数据集查询速度非常慢。
有没有办法优化表格设置和/或查询?
答案 0 :(得分:0)
通过按如下方式重写,我能够使上述查询的运行速度比使用单值类别列表版本更快:
SELECT posting_id
FROM news_posting np
WHERE np.is_active = 1
AND np.released_date < '2013-01-28'
AND EXISTS (
SELECT ncm.posting_id
FROM news_cat_match ncm
WHERE ncm.posting_id = np.posting_id
AND ncm.category_id IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
LIMIT 1
)
ORDER BY np.token DESC LIMIT 50
现在我的数据集不到一秒钟。
可悲的是,这比指定的category_id
更快。那是因为新闻项的子集比只有一个category_id
更大,所以它可以更快地找到结果。
现在我的下一个问题是,对于一个类别只有少量新闻及时传播的情况,是否可以对此进行优化?
以下在我的开发机器上仍然很慢。虽然它在生产服务器上足够快,但我想尽可能优化它。
SELECT DISTINCT posting_id
FROM news_posting np
INNER JOIN news_cat_match ncm ON (ncm.posting_id = np.posting_id AND ncm.category_id = 1)
WHERE np.is_active = 1
AND np.released_date < '2013-01-28'
ORDER BY np.token DESC LIMIT 50
有没有人有任何进一步的建议?