我有这个问题:
SELECT cl.title, cl.URL, cl.ID AS ad_id, cl.cat_id, cl.price, cs.name AS cat_name, pix.file_name, area.area_name
FROM classifieds cl
FORCE INDEX (advertiser_id)
INNER JOIN classifieds_pix pix ON cl.ID = pix.classified_id
INNER JOIN cat_names_sub cs ON cl.cat_id = cs.ID
INNER JOIN zip_codes zip ON cl.zip_id = zip.zip_id
INNER JOIN area_names area ON zip.area_id = area.id
WHERE cl.confirmed = 1 AND cl.price != '' AND cl.country = 'de'
GROUP BY cl.advertiser_id
ORDER BY cl.timestamp DESC
LIMIT 5
需要> classifieds
包含168k行时为1秒,这太长了。 FORCE INDEX (advertiser_id)
允许我在没有ORDER BY
子句的情况下将其降低到0.00x秒。 timestamp
列也已编入索引,我尝试添加FORCE INDEX (timestamp)
,但它没有帮助。
EXPLAIN
在Using where; Using temporary; Using filesort
表的第一个SELECT
上说classifieds
- 这显然会导致性能问题。
你可以帮我解决这个问题吗?
提前致谢!
PS:此查询的目的是获取5个最新的分类广告(包括一些其他信息,如图片,类别,邮政编码和地区名称)。此外,每个广告客户只能展示一个分类。这可能会这么难吗?
PPS:我试图尽可能地解决问题并最终得到这个问题:
SELECT cl.title
FROM classifieds cl
GROUP BY cl.advertiser_id
ORDER BY cl.timestamp DESC
LIMIT 5
令人难以置信的23秒!使用FORCE INDEX (advertiser_id)
我可以将它带到1秒。如果我删除GROUP BY或ORDER BY,它会下降到0.0003秒。
我的表/索引有问题吗?我不应该FORCE INDEX
(顺便说一句:USE INDEX
不起作用 - 我需要强制它!)它不应该花那么长时间!
答案 0 :(得分:3)
我不认为有任何办法可以避免排序168k行需要做的事情,无论索引如何。通过索引在表中查找行是一回事,但一旦找到它们,引擎仍然需要对它们进行排序。
1s对我来说似乎很合理。
(已删除编辑建议替代索引; OP尝试此操作但未成功)
答案 1 :(得分:2)
虽然稍作重组,但我会考虑在您的分类广告表上查看您的where子句,看看是否有任何索引可供使用......例如确认,价格,国家/地区。无论哪个可用的最低可能记录数我先列出 - 可能先把国家放在首位,然后再确认。 Addiitonally,删除组。您没有与查询关联的聚合函数。
SELECT STRAIGHT_JOIN
cl.title,
cl.URL,
cl.ID AS ad_id,
cl.cat_id,
cl.price,
cs.name AS cat_name,
pix.file_name,
area.area_name
FROM
( select clMax.advertiser_id,
max( clMax.TimeStamp ) as AdvMaxTime
from findix.classifieds clMax
where clMax.confirmed = 1
AND clMax.price != ''
AND clMax.country = 'de'
group by 1
order by 2 desc
limit 5 ) clQualified,
findix.classifieds cl,
findix.classifieds_pix pix,
findix.cat_names_sub cs,
findix.zip_codes zip,
findix.area_names area
WHERE
clQualified.advertiser_id = cl.advertiser_id
AND clQualified.AdvMaxTime = cl.timestamp;
AND cl.ID = pix.classified_id
AND cl.cat_id = cs.ID
AND cl.zip_id = zip.zip_id
AND zip.area_id = area.id
通过更改以匹配您的资格,我将其移至内部预查询,该内部预查询获取符合条件的每个广告客户,获取最新的最大时间戳条目订单,并将限制为5作为查询的第一个“表格”为结果集。从那时起,我有5条记录加入到其他表中,这些记录在您遇到时几乎是瞬间完成的。
答案 2 :(得分:1)
您是否尝试过多指数?
像这样:
CREATE INDEX adv_tt ON classifieds ( advertiser_id , `timestamp` );
甚至这个:
CREATE INDEX adv_tt ON classifieds
( confirmed , price , country , advertiser_id , `timestamp` );
PS:我不知道MySQL首先应用GROUP BY还是ORDER BY,如果它首先是ORDER BY,你必须更改INDEX中的列顺序(... timestamp
,advertiser_id )
答案 3 :(得分:0)
您是否尝试更新表格中的统计信息?
答案 4 :(得分:0)
您的查询是F * ed up ..您有GROUP BY cl.advertiser_id
但ORDER BY cl.timestamp
DESC
时间戳不在Group BY
这不应该被允许!
为什么你有一个Group BY
!
拿出来。删除force index.
然后修复你的代码,使它没有任何重复,这不是什么组合。
编辑: 尝试
SELECT cl.title, cl.URL, cl.ID AS ad_id, cl.cat_id, cl.price, cl.timestamp
cs.name AS cat_name, pix.file_name, area.area_name
FROM findix.classifieds cl
INNER JOIN findix.classifieds_pix pix ON cl.ID = pix.classified_id
INNER JOIN findix.cat_names_sub cs ON cl.cat_id = cs.ID
INNER JOIN findix.zip_codes zip ON cl.zip_id = zip.zip_id
INNER JOIN findix.area_names area ON zip.area_id = area.id
WHERE cl.confirmed = 1 AND cl.price != '' AND cl.country = 'de'
ORDER BY cl.timestamp DESC
或
SELECT cl.advertiser_id,cl.title, cl.URL, cl.ID AS ad_id, cl.cat_id, cl.price, cl.timestamp
max(cs.name) AS cat_name, max(pix.file_name) as file_name, max(area.area_name) as area.area_name
FROM findix.classifieds cl
INNER JOIN findix.classifieds_pix pix ON cl.ID = pix.classified_id
INNER JOIN findix.cat_names_sub cs ON cl.cat_id = cs.ID
INNER JOIN findix.zip_codes zip ON cl.zip_id = zip.zip_id
INNER JOIN findix.area_names area ON zip.area_id = area.id
WHERE cl.confirmed = 1 AND cl.price != '' AND cl.country = 'de'
Group By cl.advertiser_id,cl.title, cl.URL, cl.ID AS ad_id, cl.cat_id, cl.price, cl.timestamp
ORDER BY cl.timestamp DESC