我需要有关 sql select 的帮助。 MySQL 5.7版本
这是我的 table
create table if not exists OffersDayReport
(
id int auto_increment
primary key,
aff_id int not null,
aff_manager_id int not null,
source text null,
adv_id int not null,
adv_manager_id int not null,
offer_id int not null,
offer_category_id int not null,
country char(2) null,
browser varchar(255) null,
deviceType varchar(255) null,
deviceOS varchar(255) null,
preLander varchar(11) null,
goal int null,
offerPage int null,
visits int not null,
clicks int not null,
conversions int not null,
payoutInUSD decimal(10,2) not null,
revenueInUSD decimal(10,2) not null,
profitInUSD decimal(10,2) not null,
brokenRevenueInUSD decimal(10,2) not null,
time int not null,
constraint unique_row
unique (time, aff_id, offer_id, source, country, browser, deviceType, deviceOS, preLander, goal, offerPage)
)
charset=utf8;
这是一个 select 的示例:
SELECT OffersModel.lead as default_lead,
OffersDayReport.offer_id as report_title_offer_id,
OffersModel.name as offers_name,
sum(OffersDayReport.visits) as report_title_visits,
sum(OffersDayReport.clicks) as report_title_clicks,
sum(OffersDayReport.conversions) as report_title_conversions,
sum(OffersDayReport.payoutInUSD) as report_title_payout,
sum(OffersDayReport.revenueInUSD) as report_title_revenue,
sum(OffersDayReport.profitInUSD) as report_title_profit,
sum(OffersDayReport.conversions) / sum(OffersDayReport.clicks) * 100 as report_title_CR
FROM OffersDayReport
LEFT OUTER JOIN Offers as OffersModel ON OffersModel.id = OffersDayReport.offer_id
WHERE OffersDayReport.aff_manager_id IN ({numbers})
AND OffersDayReport.time >= {some start time}
AND OffersDayReport.time <= {some end time}
GROUP BY OffersDayReport.offer_id;
范围可以是 1 天和 6 个月。 where 子句的可变性可能不同 - 使用 aff_manager_id 或 adv_manager_id 或两者等。
所有行的数量很大 - 大约 1000 亿。
现在我的选择大约需要 3-4 分钟,有时会达到 10 分钟。
我尝试了不同类型的索引,但 mysql 分析器宁愿不使用它们。
即使我使用 FORCE INDEX()
- 我尝试过的所有类型的索引,也只会让我的选择缓慢。
最佳答案
确保您有正确的复合索引
table OffersDayReport columns (time, aff_manager_id )
对于 Offers 表,您可以使用冗余复合索引(从索引中检索所有值) 用于过滤值并避免访问表数据
table Offers columns ( id, name, lead)
最后您可以尝试使用内部联接更改 IN 子句..
另一个可能的改进可以通过更改 INNER JOIN 中的 IN 子句来获得。这是因为 IN 子句与多个 OR 子句相同,而 INNER JOIN 只执行一次。 为此
如果 ({numbers}) 来自子查询,您可以尝试使用
FROM OffersDayReport
INNER JOIN (
select your_id
from your_table
.....
) t on t.your_id = OffersDayReport.aff_manager
LEFT OUTER JOIN Offers as OffersModel ON OffersModel.id = OffersDayReport.offer_id
WHERE OffersDayReport.time >= {some start time}
AND OffersDayReport.time <= {some end time}
否则,如果查询未获得 ({numbers}),您可以使用并集构建等效结果
select numbers1 numbers
UNION
select numbers2
UNION
select numbers3
.....
UNION
select numbersN
以及查询
FROM OffersDayReport
INNER JOIN (
select numbers1 my_number
UNION
select numbers2
UNION
select numbers3
.....
UNION
select numbersN
) t on t.my_number = OffersDayReport.aff_manager
LEFT OUTER JOIN Offers as OffersModel ON OffersModel.id = OffersDayReport.offer_id
WHERE OffersDayReport.time >= {some start time}
AND OffersDayReport.time <= {some end time}
关于mysql - 如何使用索引改进我的sql select?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59320682/