Mysql 优化频繁运行的查询

Mysql 优化频繁运行的查询,mysql,optimization,Mysql,Optimization,我在我的网站上添加了广告,这些广告在发送给浏览用户之前需要满足相当多的条件。这里有一个详细的解释: 以下是需要解释的字段: start默认为“0000-00-00”,表示广告是否已支付。接受广告付款时,开始设置为客户选择的第二天或任何日期 压痕分别是广告的剩余印象 总印象和每日印象是不言自明的 查询中使用的其他字段只是验证用户是否符合广告的听觉规范的字段 广告必须首先付费才能开始显示,但是可以将其设置为在未来某个日期开始,因此将设置start值,但广告不应在开始前显示。然后,由于客户可以限制每天

我在我的网站上添加了广告,这些广告在发送给浏览用户之前需要满足相当多的条件。这里有一个详细的解释:

以下是需要解释的字段:

start
默认为“0000-00-00”,表示广告是否已支付。接受广告付款时,
开始
设置为客户选择的第二天或任何日期

压痕
分别是广告的剩余印象

总印象
每日印象
是不言自明的

查询中使用的其他字段只是验证用户是否符合广告的听觉规范的字段

广告必须首先付费才能开始显示,但是可以将其设置为在未来某个日期开始,因此将设置
start
值,但广告不应在开始前显示。然后,由于客户可以限制每天的印象,我只需要挑选那些在当天有足够印象的广告。例如,如果一个广告在2013年8月30日开始,每天有10000次和2000次的印象,那么如果今天(2013年8月31日)的印象少于6000次,那么它就不应该出现,因为这是活动的第二天。此外,如果期限为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

从优化的角度来看,您有一个非常复杂的查询

where
子句上可以使用的唯一索引是
ads(印象)
ads(开始)
。因为使用了不等式,所以不能将它们组合起来

能否修改表格结构,使其具有
impressionFlag
?如果有任何印象,则为1,否则为0。如果是这样,那么您可以在
广告上尝试索引(ImpressionFlag,Start)


如果这有助于提高性能,那么下一步就是将查询分解为单独的子查询,并使用
union-all
将它们组合在一起。其目的是设计索引以优化基础查询。

不要引用/反勾选列名。它们只会增加视觉上的混乱,只是你犯语法错误的又一种方式。您需要它们的唯一原因是如果您有一个保留字的列名,而使用保留字的列名是一个糟糕的主意,因此这是两个可以同时避免的坏习惯。没有模式,优化是很困难的。请发布创建表语法。为什么我不能按原样添加一个索引到
impressions
,而不是添加
impressionsFlag
?@php\u nub\u qq。你可以。但是,索引
ads(Impressions,Start)
可能不会用于这两种情况,因为第一种情况是一个不等式。MySQL文档实际上很好地解释了这一点()?我的意思是,就像你说的广告(印象,开始)?很有趣的是,一年后的今天,我面临着同样的任务。当然,现在我的知识比我问这个问题的时候(或者我认为是这样)早了几光年。真正有趣的是,现在我明白你的意思了,这就是我最后独自做的事情。我不知道为什么我没有接受并投票支持这个答案。不管怎样,似乎少了一句谢谢,所以谢谢你<代码>:)
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