자주 쿼리되는 100,000 개의 레코드가있는 MySQL 테이블


11

다양한 종류의 정보를 저장하기 위해 약 100 개의 테이블이있는 단일 데이터베이스가 있습니다.

가장 중요한 테이블은 고객 주문을 저장하는 데 사용되는 주문 테이블이며 현재 10 억 개가 넘는 레코드가 증가하고 있습니다.

이 테이블은 실시간 주문 대시 보드, 통계, 분석 등에서 필요한 다양한 정보를 위해 데이터베이스에서 가장 많이 쿼리 된 테이블입니다.

데이터베이스를 정기적으로 모니터링하고 데이터베이스에서 느린 쿼리를 사용하여 문제를 추적합니다.

나는 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

2
내가 잘못 읽었습니까, 아니면 평균 쿼리 시간이 1.7ms입니까? 왜 지구상에서 그 속도를 높이려고합니까?
Philᵀᴹ

느린 쿼리 로그에 왜 나타나는지 약간 혼란 스럽습니다.
쉘던

@RolandoMySQLDBA 내가 스키마 첨부
셀던

1
테이블에 인덱스가 있다고해서 쿼리에 적합한 인덱스라는 의미는 아닙니다. 느린 쿼리와 EXPLAIN 출력의 몇 가지 예를 게시 할 수 있습니까? 또한 orders 테이블은 얼마나 자주 업데이트됩니까?
bobwienholt

답변:


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 Database Design and Tuning 에서 72,73 페이지에서 그것을 배웠다 .

나는 과거에 이것에 대해 썼다 :


자세한 설명에 감사드립니다. 예, 테이블에 추가 된 인덱스는 시스템에서 사용되는 선택, 그룹 별 및 순서별 문에 사용 된 쿼리를 기반으로합니다. 인덱스 로그없이 쿼리를 모니터링하고 그에 따라 테이블을 업데이트했습니다.
쉘던
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.