由于负载过高,重新设计查询/数据库

时间:2017-10-29 17:34:31

标签: php mysql query-performance

我需要查询或重新设计我的数据库的帮助。我不是数据库管理员,也不是MySQL wiz。

我有以下表格:

CREATE TABLE IF NOT EXISTS `pop_contor` (
  `key` varchar(50) NOT NULL,
  `uniqueHandler` varchar(30) DEFAULT NULL,
  `uniqueLink` varchar(30) DEFAULT NULL,
  `uniqueUser` varchar(30) DEFAULT NULL,
  `owner` varchar(50) NOT NULL,
  `ip` varchar(15) DEFAULT NULL,
  `page` varchar(500) DEFAULT NULL,
  `share` float DEFAULT NULL,
  `cadv` float NOT NULL,
  `os` varchar(50) NOT NULL,
  `browsershort` varchar(50) NOT NULL,
  `browser` varchar(50) DEFAULT NULL,
  `country` varchar(10) DEFAULT NULL,
  `date` date DEFAULT NULL,
  `hour` int(2) NOT NULL,
  `tstamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`key`),
  KEY `contor_IX1` (`uniqueLink`,`ip`),
  KEY `owner` (`owner`,`share`,`hour`),
  KEY `uniqueUser` (`uniqueUser`,`share`,`hour`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

   CREATE TABLE IF NOT EXISTS `pop_links` (
  `unique` varchar(8) NOT NULL DEFAULT '',
  `uniqueUser` varchar(30) DEFAULT NULL,
  `uniqueCategories` varchar(150) DEFAULT NULL,
  `browser` varchar(60) NOT NULL,
  `os` varchar(50) NOT NULL,
  `country` varchar(100) NOT NULL,
  `name` varchar(50) DEFAULT NULL,
  `url` varchar(500) CHARACTER SET ascii DEFAULT NULL,
  `description` varchar(150) DEFAULT NULL,
  `bid` varchar(6) DEFAULT NULL,
  `amount` varchar(5) DEFAULT NULL,
  `remain` varchar(20) DEFAULT NULL,
  `rtoday` varchar(20) NOT NULL DEFAULT '0',
  `frequency` varchar(2) DEFAULT NULL,
  `dlimit` varchar(6) NOT NULL DEFAULT '0',
  `hours` varchar(100) NOT NULL DEFAULT 'all',
  `block` varchar(500) CHARACTER SET ascii NOT NULL,
  `valid` int(1) DEFAULT NULL,
  `payed` int(1) DEFAULT NULL,
  `startDate` date DEFAULT NULL,
  `endDate` date DEFAULT NULL,
  `date` date DEFAULT NULL,
  PRIMARY KEY (`unique`),
  KEY `unique` (`unique`,`uniqueCategories`,`browser`,`os`,`country`,`url`,`bid`,`remain`,`rtoday`,`frequency`,`hours`,`block`,`valid`,`startDate`,`endDate`,`uniqueUser`    )
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我要做的是根据几个标准向每个访问者(基于IP)显示最合适的链接。我已经尝试了几个查询,但由于服务器仍然过载而失败。当pop_contor表获得大约200,000个条目时,它主要是hapens。表链接中有大约30行。

第一次尝试是做一个选择>其中>选择>其中>选择>其中我吃了午餐,包括我的午餐盒。

第二次尝试是(查询花了大约5秒钟完成):

SELECT l. * FROM pop_links AS l 
LEFT JOIN ( SELECT uniqueLink, SUM( ip = '".$ip."' ) AS ip_visits 
FROM pop_contor 
GROUP BY uniqueLink ) AS c 
ON c.uniqueLink = l.unique AND ip_visits <= frequency 
WHERE (`uniqueCategories` LIKE '%,".$cat.",%'OR `uniqueCategories` = '1') 
AND (`hours` LIKE '%,".date("H").",%' OR `hours` = 'all') 
AND (`browser` LIKE '%".$user_browser[name]."%' OR `browser` = '1') 
AND (`country` LIKE '%".$ccode."%' OR `country` = '1') 
AND (`os` LIKE '%".$user_browser[platform]."%' OR `os` = '1') 
AND (`remain` > '0') 
AND (`rtoday` > '0') 
AND `valid` = '1' 
AND (`block` NOT LIKE '%".$unique."%') 
ORDER BY `bid` DESC, `remain` DESC 
LIMIT 1

说明:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   PRIMARY     l   ALL     NULL    NULL    NULL    NULL    16  Using where; Using temporary; Using filesort
1   PRIMARY     <derived2>  ALL     NULL    NULL    NULL    NULL    16  
2   DERIVED     pop_contor  index   NULL    contor_IX1  141     NULL    299128  Using index

第三次尝试:

SELECT pop_links.unique, pop_links.uniqueUser, pop_links.uniqueCategories, pop_links.browser, pop_links.os, pop_links.country, pop_links.url, pop_links.bid, pop_links.remain, pop_links.rtoday, pop_links.frequency, pop_links.hours, pop_links.block, pop_links.valid, pop_links.startDate, pop_links.endDate, COUNT( IF( pop_contor.ip = '".$ip."', 1, NULL ) ) < pop_links.frequency AS toto 
FROM pop_links 
LEFT JOIN pop_contor 
ON pop_links.unique = pop_contor.uniqueLink 
WHERE (`uniqueCategories` LIKE '%,".$cat.",%' OR `uniqueCategories` = '1') 
AND (`hours` LIKE '%,".date("H").",%' OR `hours` = 'all') 
AND (pop_links.browser LIKE '%".$user_browser[name]."%' OR pop_links.browser = '1') 
AND (pop_links.country LIKE '%".$ccode."%' OR pop_links.country = '1')
AND (pop_links.os LIKE '%".$user_browser[platform]."%' OR pop_links.os = '1')
AND (`remain` > '0') 
AND `rtoday` > '0' 
AND `valid` = '1' 
AND (`block` NOT LIKE '%".$unique."%') 
GROUP BY pop_links.unique, pop_contor.uniqueLink 
ORDER BY `toto` DESC , pop_links.bid DESC , pop_links.remain DESC 
LIMIT 1

说明:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  pop_links   index   NULL    unique  2683    NULL    16  Using where; Using index; Using temporary; Using f...
1   SIMPLE  pop_contor  ref     contor_IX1  contor_IX1  93  admin_pops.pop_links.unique     13277   Using index

查询在大约0.3秒内完成,但服务器上的负载仍然很高。 SHOW PROCESSLIST向我展示了很多“复制到tmp表”的状态。

1 个答案:

答案 0 :(得分:0)

代替     hours LIKE '%,".date("H").",%' OR hours = 'all' 同     paused = 0(添加了一个暂停链接的列)。

负载从~4降至~0.20。我无法相信column LIKE %something可能对查询效果产生多大影响。