CREATE TABLE campaigns (
domain varchar(50) DEFAULT NULL,
campaign_id varchar(50) DEFAULT NULL,
node_id varchar(50) DEFAULT NULL,
subscriber_id varchar(50) DEFAULT NULL,
message varchar(21000) DEFAULT NULL,
log_time datetime DEFAULT NULL,
log_type varchar(50) DEFAULT NULL,
campaign_name varchar(500) DEFAULT NULL
KEY `campid_domain_logtype_logtime_subid_index` (`campaign_id`,`domain`,`log_type`,`log_time`,`subscriber_id`),
KEY `domain_logtype_logtime_index` (`domain`,`log_type`,`log_time`)
)
以上是MySql中我们表的模式。一个广告系列可以有多个节点。
索引campid_domain_logtype_logtime_subid_index
适用于w.r.t特定广告系列的报告。
最近我们将node_id添加到此表中,现在我们需要报告w.r.t特定节点。
所以现在我计划更改我们的覆盖索引,如下所示,以支持广告系列级和节点级报告
campid_nodeid_domain_logtype_logtime_subid_index
。
针对特定广告系列的报告的示例查询
SELECT log_type,
count(DISTINCT subscriber_id) AS count,
count(subscriber_id) AS total
FROM stats.campaign_logs USE INDEX(campid_domain_logtype_logtime_subid_index)
where domain = 'aaa' AND campaign_id='12345' AND
log_type in ('EMAIL_SENT','EMAIL_OPENED','EMAIL_CLICKED')
AND log_time BETWEEN CONVERT_TZ('2016-03-13 00:00:00','+01:30','+00:00') AND CONVERT_TZ('2016-04-13 23:59:59','+01:30','+00:00')
GROUP BY log_type;
针对特定广告系列的特定节点ID的报告的示例查询
SELECT
log_type,
count(DISTINCT subscriber_id) AS count,
count(subscriber_id) AS total
FROM stats.campaign_logs USE INDEX(campid_domain_logtype_logtime_subid_index)
where domain='aaa' AND campaign_id='12345' AND
node_id = '56789' and
log_type in ('EMAIL_SENT','EMAIL_OPENED','EMAIL_CLICKED')
AND log_time BETWEEN CONVERT_TZ('2016-03-13 00:00:00','+01:30','+00:00') AND CONVERT_TZ('2016-04-13 23:59:59','+01:30','+00:00')
GROUP BY log_type;
所以我的问题是这个新索引能否有效地满足我们的两种查询,如果没有请建议合适的索引。
更新
表格中的数据分发
1个域可以有多个广告系列,例如20
1 Campaign可以有多个节点,例如10
1 Campaign可以有多种日志类型,例如50
1广告系列可以拥有大量订阅者,例如100,000
1 Campaign可以有很多日志时间,因为我们在存储日志时使用mysql now()。
更新
由于
答案 0 :(得分:0)
根据您的疑问,您应该创建以下索引
KEY `campid_domain_logtype_logtime_subid_index` (
`campaign_id`,
`domain`,
`log_time`,
`node_id`,
`subscriber_id`
);
始终使用 campaign_id
和log_time
,node_id
仅在某些情况下使用domain
。
不确定是否应该离开subscriber_id
和log_type
在查询中看不到所有这些内容。
Campaign id, Log time, Node ID (subscriber_id ?)
也值得商榷。我不相信它具有良好的选择性,只是浪费空间。
<强>更新强>
根据我们在评论中的通讯
如果您经常在查询中使用subscriber_id - 请添加它。
我会删除log_type。
作为选项,尝试创建以下索引:
{
"Header": {
"CutQuantity": 0,
"ETAQuantity": 0,
"IDRPrice": 229000,
"MasterId": 65639,
"Name": "VENICE SATIN DBY 21491 COL 25894",
"POQuantity": 0,
"ProductCode": "GG01054-14B",
"QtyOnHand": 332.1,
"ReservedQuantity": "332.1",
"SellingPrice": 229000,
"TotalAvlQuantity": 0,
"USDPrice": 26
},
"Batches": [{
"AvailableQty": 25.8,
"BatchNo": "A001",
"BinId": 128430,
"BinName": "Dummy-700",
"DeptId": 23,
"DeptName": "G.700",
"MaxBodyId": 128430,
"ProductCode": "GG01054-14B",
"ProductCodeBatch": "GG01054-14B-A001",
"ProductId": 65639,
"ProductName": "VENICE SATIN DBY 21491 COL 25894"
}, {
"AvailableQty": 40,
"BatchNo": "A002",
"BinId": 128433,
"BinName": "Dummy-700",
"DeptId": 23,
"DeptName": "G.700",
"MaxBodyId": 128433,
"ProductCode": "GG01054-14B",
"ProductCodeBatch": "GG01054-14B-A002",
"ProductId": 65639,
"ProductName": "VENICE SATIN DBY 21491 COL 25894"
}]
}
答案 1 :(得分:0)
构建最佳索引的基本规则:
所以第一个查询需要INDEX(domain, campaign_id, log_time)
。 log_type
挡路了;不包括它。
(已添加)“新”查询需要INDEX(campaign_id, node_id, domain, log_time)
。
在这两种情况下,log_time
都应该是最后的;其他列可以按任何顺序排列。重新排列订单可能有助于其他查询。没有一个索引对于两个查询都是最佳的。
然后,不要使用USE INDEX
;它可能会适得其反。
更好的解决方案更复杂:构建和维护经常需要的各种计数器/总和的汇总表。 (也许使用30分钟的时间范围。)警告:COUNT(DISTINCT ...)
无法在汇总表中处理。
为什么这些ID VARCHAR(50)
而不是INT UNSIGNED
?您还可以从domain
等其他字段规范化中受益。 log_type
可以是1字节ENUM
。
您真的需要所有列都可以为空吗?
这些列的任何组合都是唯一的吗? InnoDB真的很喜欢PRIMARY KEY
。