Tabela MySQL com 100.000 registros consultados frequentemente

11

Eu tenho um único banco de dados de cerca de 100 tabelas para armazenar vários tipos de informações.

A tabela mais importante é a nossa tabela de pedidos, que é usada para armazenar pedidos de clientes e tem mais de 100.000 registros a partir de agora e em crescimento.

Esta tabela é a tabela mais consultada em nosso banco de dados, para várias partes de informações necessárias em painéis de pedidos em tempo real, estatísticas, análises, etc.

Monitoro o banco de dados regularmente e tenho consultas lentas ativadas no banco de dados para rastrear problemas.

Eu uso scripts como o mysqltuner para cuspir consultas diariamente.

Eu também uso o mysqlsla para reunir informações sobre as 10 consultas mais lentas do nosso banco de dados.

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%)

A maioria das consultas mais lentas envolve a tabela de pedidos mencionada acima. Eu uso o MyISAM como meu mecanismo de armazenamento para que possíveis problemas possam ser:

  1. Travamento da mesa
  2. Problemas de indexação

Como eu poderia melhorar essas estatísticas, tenho a indexação em vigor para essas tabelas e as aprimorei para melhorar as consultas de leitura.

Esquema de tabela

`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`)

consulta de log lenta

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;
Sheldon
fonte
Por favor, executar SHOW CREATE TABLE orders\Ge postar que na questão
RolandoMySQLDBA
2
Estou lendo isso incorretamente ou o tempo médio de consulta é de 1,7 ms? Por que diabos você procuraria acelerar isso?
Philᵀᴹ
Estou um pouco confuso sobre por que isso aparece nos logs de consulta lenta.
sheldon
@RolandoMySQLDBA Anexei o esquema
Sheldon
1
Só porque você tem índices na tabela não significa que eles são os índices certos para suas consultas. Você poderia postar alguns exemplos de consultas lentas e sua saída EXPLAIN? Além disso, com que frequência a tabela de pedidos é atualizada?
22712 bobbienholt

Respostas:

8

Você precisará comparar as cláusulas WHERE e as instruções GROUP BY e ORDER BY de todas as suas consultas para garantir que seus índices atuais possam suportá-las em seus planos EXPLAIN.

Ontem, eu respondi esta pergunta: InnoDB vs MyISAM com muitos índices

Nessa pergunta, sugeri fazer algo na tabela MyISAM que você também pode fazer

ALTER TABLE orders ROW_FORMAT=Fixed;

Isso tratará todos os VARCHARs como CHARs. Cada linha terá exatamente o mesmo comprimento. Isso aumentará o espaço em disco de 80% a 100%. Sua tabela aumentará para o tamanho máximo do layout da linha vezes o número de linhas. Sua mesa pode dobrar ou triplicar de tamanho.

Onde está o benefício? Sua tabela MyISAM será então lida / gravada para algo entre 20% e 30% mais rápido sem alterar mais nada.

Aprendi isso nas páginas 72,73 do MySQL Database Design and Tuning .

Eu escrevi sobre isso no passado:

RolandoMySQLDBA
fonte
Obrigado pela explicação detalhada, sim, os índices adicionados à tabela são baseados nas consultas usadas para as seleções, agrupar por e ordenar por instruções usadas em nosso sistema. Estão monitorando as consultas sem logs de índices e atualizando as tabelas de acordo.
sheldon