我已经在我的网站上添加了广告,这些广告在交付给浏览用户之前有很多条件可以满足。这是一个详细的解释:
这些是需要解释的字段:
start
默认为'0000-00-00',表示广告是否已付款。接受广告付款时,start
设置为客户选择的第二天或任何日期。
impresssions
分别是广告的剩余展示次数
impressions_total
和impressions_perday
是不言自明的
以及查询中使用的其他字段只是验证用户是否符合广告听觉规范的字段
必须先支付广告才能开始显示,但是可以将其设置为在将来的某个日期开始,以便设置start
值,但广告不应在之前显示时间到了。然后,由于客户可以限制每天的展示次数,因此我只需要获取当天正在获得足够展示次数的广告。例如,如果广告是在2013年8月30日开始的,每天有10,000次展示和2,000次展示,那么它今天(2013年8月31日)如果展示次数少于6,000次就不应该展示,因为它是第二次展示活动当天。如果期限为5天,过了5天,则无论剩余的印象如何,都必须显示广告。然后还有其他比较来验证用户是否适合展示此广告,整个事情变得如此复杂。
我对mysql不太满意,虽然我已经设法构建了一个有效的查询,但我非常关心优化它。我最确定我使用的方法效率很低,但我找不到更好的在线方式。这就是为什么我在这里问这个问题,如果有人能帮助我提高这个查询的性能呢?
SELECT `fields`,
FROM `ads`
WHERE (`impressions`>0 && `start`!='0000-00-00')
AND `start`<CURDATE() AND
(
`impressions`>(`impressions_total`-(CONVERT(CURDATE()-date(`start`), UNSIGNED)*`impressions_perday`))
OR (`impressions_total`/`impressions_perday` < CURDATE()-date(`start`))
-- this is the part where I validate the impressions for the day
-- and am most concerned that I haven't built correctly
)
AND
(
(
(YEAR(NOW())-YEAR("user's birthday") BETWEEN `ageMIN` AND `ageMax`)
AND (`sex`=2 OR `sex`="user's gender")
AND (`country`='' OR `country`="user's country")
) OR `applyToUnregistered` = 1
)
ORDER BY $random_order -- Generate random order pattern
模式:
CREATE TABLE `ads` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`headline` varchar(25) NOT NULL,
`text` varchar(90) NOT NULL,
`url` varchar(50) NOT NULL,
`country` varchar(2) DEFAULT '0',
`ageMIN` tinyint(2) unsigned NOT NULL,
`ageMax` tinyint(2) unsigned NOT NULL,
`sex` tinyint(1) unsigned NOT NULL DEFAULT '2',
`applyToUnregistered` tinyint(1) unsigned NOT NULL DEFAULT '0',
`creator` int(10) unsigned NOT NULL,
`created` int(10) unsigned NOT NULL,
`start` date NOT NULL,
`impressions_total` int(10) unsigned NOT NULL,
`impressions_perday` mediumint(8) unsigned NOT NULL,
`impressions` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=27 DEFAULT CHARSET=utf8
答案 0 :(得分:1)
从优化角度来看,您的查询非常复杂。
可以在where
子句上使用的唯一索引位于ads(impressions)
或ads(start)
。因为你使用了不等式,所以你不能将它们组合起来。
您可以修改表格结构以获得ImpressionsFlag
吗?如果有任何展示,则为1,否则为0。如果是,那么您可以在ads(ImpressionsFlag, Start)
上尝试索引。
如果这有助于提高性能,下一步就是将查询分解为单独的子查询,并使用union all
将它们组合在一起。目的是设计索引以优化基础查询。