经常查询100,000条记录的MySQL表


11

我有一个大约100个表的数据库,用于存储各种信息。

最重要的表是我们的订单表,该表用于存储客户的订单,截止到现在并且正在不断增长,已超过100000条记录。

该表是我们数据库中查询最多的表,用于实时订单仪表板,统计信息,分析等所需的信息的各个部分。

我会定期监视数据库,并在数据库上启用慢速查询以跟踪问题。

我每天都使用mysqltuner之类的脚本来执行查询。

我还使用mysqlsla收集有关数据库中最慢的10个查询的信息。

sample stat
Count         : 11.48k  (30.66%)
Time          : 19.623758 s total, 1.709 ms avg, 239 µs to 2.475017 s max  (18.64%)
  95% of Time : 5.246833 s total, 481 µs avg, 239 µs to 1.095 ms max
Lock Time (s) : 14.460071 s total, 1.259 ms avg, 53 µs to 2.462555 s max  (41.38%)
  95% of Lock : 806.43 ms total, 74 µs avg, 53 µs to 137 µs max
Rows sent     : 1 avg, 0 to 9 max  (0.99%)
Rows examined : 6 avg, 1 to 28 max  (0.15%)

查询最慢的大多数都涉及上述订单表。我使用MyISAM作为存储引擎,因此可能的问题可能是:

  1. 表锁定
  2. 索引问题

我如何改善这些统计数据,为这些表建立了索引,并不断对其进行调整以改善读取查询。

表架构

`orderid` int(11) NOT NULL AUTO_INCREMENT,
`cityid` tinyint(3) unsigned NOT NULL DEFAULT '1',
 `model_type` tinyint(1) unsigned DEFAULT '1',
`userid` int(11) DEFAULT NULL,
`usertype` char(1) DEFAULT NULL,
`time` time DEFAULT NULL,
`ordercode` char(8) DEFAULT NULL,
`restid` smallint(3) unsigned NOT NULL,
`areaid` smallint(3) unsigned DEFAULT NULL,
`restname` varchar(50) DEFAULT NULL,
`date` date NOT NULL,
`del_time` time NOT NULL,
`status` tinyint(3) unsigned NOT NULL,
`amount` float NOT NULL,
`deliverycharge` smallint(4) unsigned DEFAULT '0',
`tax` float NOT NULL,
`total` float NOT NULL,
`extras` varchar(255) DEFAULT NULL,
`requests` varchar(255) DEFAULT NULL,
`discount` float DEFAULT NULL,
`rdiscount` float DEFAULT NULL,
`reason` varchar(255) DEFAULT NULL,
`rest_order` tinyint(1) unsigned DEFAULT NULL,
`admin_user` varchar(25) DEFAULT NULL,
`mode` char(1) NOT NULL,
`priority_order` tinyint(1) unsigned DEFAULT '0',
`payment_mode` tinyint(1) unsigned DEFAULT '0',
`km` tinyint(3) unsigned DEFAULT NULL,
`order_type` tinyint(1) NOT NULL DEFAULT '1',
`coupon_discount` smallint(3) DEFAULT '0',
`pickup_time` time NOT NULL,
PRIMARY KEY (`orderid`),
KEY `cityid` (`cityid`),
KEY `date_3` (`date`,`status`,`mode`),
KEY `orderid` (`orderid`),
KEY `time` (`time`),
KEY `userid` (`userid`,`usertype`),
KEY `restid` (`restid`,`date`,`status`)

慢日志查询

SELECT `a`.`orderid`, `a`.`date`, `a`.`status`, `a`.`restname`, `a`.`admin_user`, `a`.`model_type`, `b`.`name` as cityname
FROM `tk_order_queue` AS a
INNER JOIN `tk_cities` AS b ON `a`.`cityid` = `b`.`id`
WHERE `a`.`date` =  '2012-06-30'
AND `a`.`status` =  0
AND `a`.`mode` =  1
ORDER BY `a`.`orderid` desc;

请运行SHOW CREATE TABLE orders\G并在问题中发布该内容
RolandoMySQLDBA 2012年

2
我读错了吗,还是平均查询时间是1.7ms?您到底想为什么加快速度?
–Philᵀᴹ2012年

我对为什么它出现在缓慢的查询日志中感到有些困惑。
谢尔顿2012年

@RolandoMySQLDBA我已经附加了架构
sheldon

1
仅仅因为您在表上有索引并不意味着它们是您查询的正确索引。您能否发布一些慢速查询及其EXPLAIN输出的示例?另外,订单表多久更新一次?
bobwienholt 2012年

Answers:


8

您将必须比较所有查询的WHERE子句以及GROUP BY和ORDER BY语句,以确保当前索引可以在其EXPLAIN计划中支持它们。

昨天,我回答了这个问题:InnoDB vs MyISAM有很多索引

在这个问题中,我建议对MyISAM表做一些您也可以做的事情

ALTER TABLE orders ROW_FORMAT=Fixed;

这会将所有VARCHAR视为CHAR。每行的长度将完全相同。这将增加磁盘空间80%-100%。您的表格会膨胀到行布局的最大大小乘以行数。您的表的大小可以增加一倍或两倍。

好处在哪里?然后,您的MyISAM表将以20%-30%的速度读取/写入,而无需进行任何其他更改。

我从MySQL数据库设计和调整的第72,73页中学到了这一点。

我过去曾写过:


谢谢您的详细说明,是的,添加到表中的索引基于我们系统中使用的用于selects,group by和order by语句的查询。一直在监视没有索引日志的查询,并正在相应地更新表。
谢尔顿2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.