简体   繁体   English

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

[英]Redesign query/database because of high load

I need help with query or redesigning my db.我需要有关查询或重新设计数据库的帮助。 I'm not a DB admin, nor am I some MySQL wiz.我不是数据库管理员,也不是 MySQL 专家。

I have the following tables:我有以下表格:

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;

and:和:

   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;

What I'm trying to do is to show each visitor (based on ip) the best fit link based on several criteria.我想要做的是根据几个标准向每个访问者(基于 ip)显示最合适的链接。 I've tried several queries but failed as server still gets overloaded.我已经尝试了几个查询,但由于服务器仍然超载而失败。 It hapens mostly when table pop_contor gets around 200k entries.它主要发生在表 pop_contor 获得大约 20 万个条目时。 Table links has ~30 rows in it.表链接中有 ~30 行。

First attempt was doing a select>where>select>where>select>where but it ate my lunch including my lunchbox.第一次尝试是做一个选择>哪里>选择>哪里>选择>哪里但它吃了我的午餐,包括我的午餐盒。

Second attempt was (query took about 5 seconds to complete):第二次尝试是(查询需要大约 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

Explain:解释:

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

Third atempt:第三次尝试:

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

Explain:解释:

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

Query completes in about 0.3 seconds but the load on the server is still high.查询在大约 0.3 秒内完成,但服务器上的负载仍然很高。 SHOW PROCESSLIST shows me a lot of "Copying to tmp table" statuses. SHOW PROCESSLIST向我展示了很多“复制到 tmp 表”状态。

Replaced hours LIKE '%,".date("H").",%' OR hours = 'all' with paused = 0 (added a column paused to links).hours LIKE '%,".date("H").",%' OR hours = 'all'替换为paused = 0 (向链接添加了暂停的列)。

Load dropped from ~4 to ~0.20.负载从 ~4 下降到 ~0.20。 I can't believe how much impact column LIKE %something could have on the query performance.我无法相信column LIKE %something会对查询性能产生多大影响。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM