Производительность AWS RDS очень низкая
Есть две базы данных, AWS RDS и Digitalocean 5 VPS. Я импортировал один и тот же файл.sql в обе базы, разница в производительности между ними почти 66000%
select count(special_cargo_id) from special_cargos;
Прошедшее время AWS RDS = 35,681 секунды
DO 5$ VPS на Mysql прошедшее время = 0,086 секунды
Детали:
Длина стола
1,85 ГБ строк ~260 КБ
MySQL версии 8
Таблица Engine InnoDB
ВЫХОД RDS
CREATE TABLE `special_cargos` (
`special_cargo_id` int(11) NOT NULL AUTO_INCREMENT,
`barcode` varchar(20) DEFAULT '',
`salesCode` varchar(15) NOT NULL,
`price` varchar(15) NOT NULL,
`para` varchar(3) DEFAULT NULL,
`postaceki` varchar(25) DEFAULT '',
`iban` varchar(30) DEFAULT NULL,
`send_type` tinyint(1) unsigned NOT NULL,
`customer_id` int(11) NOT NULL,
`address_id` int(11) NOT NULL,
`height` varchar(5) DEFAULT '',
`weight` varchar(5) DEFAULT '',
`width` varchar(5) NOT NULL DEFAULT '',
`desi` varchar(5) DEFAULT '',
`length` varchar(255) DEFAULT '',
`customer_firstname` varchar(32) NOT NULL,
`customer_lastname` varchar(32) NOT NULL,
`customer_company` varchar(40) NOT NULL,
`customer_address` varchar(255) NOT NULL,
`customer_city` int(11) NOT NULL DEFAULT '0',
`customer_city_name` varchar(55) DEFAULT '',
`customer_zone_id` int(11) NOT NULL DEFAULT '0',
`customer_zone_name` varchar(55) DEFAULT '',
`customer_postcode` varchar(10) NOT NULL,
`firstname` varchar(32) NOT NULL,
`lastname` varchar(32) NOT NULL,
`company` varchar(40) DEFAULT '',
`address` varchar(255) NOT NULL,
`country_id` int(5) DEFAULT NULL,
`country_name` varchar(64) DEFAULT NULL,
`city_id` int(11) NOT NULL,
`city_name` varchar(55) NOT NULL,
`district_id` int(11) NOT NULL,
`district_name` varchar(64) NOT NULL,
`email` varchar(96) NOT NULL,
`phone` varchar(55) NOT NULL,
`postcode` varchar(10) DEFAULT '',
`product` text,
`sendText` text,
`returnText` text,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`deleted_at` datetime DEFAULT NULL,
`cargo_firm` tinyint(1) NOT NULL DEFAULT '0',
`ups_barcode_link` text,
`status` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`special_cargo_id`),
KEY `customer_id` (`customer_id`),
KEY `special_cargo_id` (`special_cargo_id`),
KEY `barcode` (`barcode`),
KEY `salesCode` (`salesCode`),
KEY `price` (`price`),
KEY `postaceki` (`postaceki`),
KEY `customer_firstname` (`customer_firstname`),
KEY `customer_lastname` (`customer_lastname`),
KEY `firstname` (`firstname`),
KEY `lastname` (`lastname`),
KEY `customer_company` (`customer_company`),
KEY `customer_address` (`customer_address`),
KEY `customer_city_name` (`customer_city_name`),
KEY `customer_zone_name` (`customer_zone_name`),
KEY `company` (`company`),
KEY `address` (`address`),
KEY `city_name` (`city_name`),
KEY `district_name` (`district_name`),
KEY `email` (`email`),
KEY `phone` (`phone`),
KEY `postcode` (`postcode`),
KEY `index_special_cargos` (`special_cargo_id`)
) ENGINE=InnoDB AUTO_INCREMENT=497539 DEFAULT CHARSET=utf8
+-----------------------+----------+
|Variable_name |Value |
+-----------------------+----------+
|innodb_buffer_pool_size|1073741824|
+-----------------------+----------+
+--+-----------+--------------+----------+-----+-------------+-----------+-------+----+------+--------+-----------+
|id|select_type|table |partitions|type |possible_keys|key |key_len|ref |rows |filtered|Extra |
+--+-----------+--------------+----------+-----+-------------+-----------+-------+----+------+--------+-----------+
|1 |SIMPLE |special_cargos|NULL |index|NULL |customer_id|4 |NULL|146973|100 |Using index|
+--+-----------+--------------+----------+-----+-------------+-----------+-------+----+------+--------+-----------+
ПРОСТОЙ VPS НА ВЫХОДЕ MYSQL
CREATE TABLE `special_cargos` (
`special_cargo_id` int(11) NOT NULL AUTO_INCREMENT,
`barcode` varchar(20) NOT NULL,
`salesCode` varchar(15) NOT NULL,
`price` varchar(15) NOT NULL,
`para` varchar(3) DEFAULT NULL,
`postaceki` varchar(25) NOT NULL,
`iban` varchar(30) DEFAULT NULL,
`send_type` tinyint(1) unsigned NOT NULL,
`customer_id` int(11) NOT NULL,
`address_id` int(11) NOT NULL,
`height` varchar(5) NOT NULL,
`weight` varchar(5) NOT NULL,
`width` varchar(5) NOT NULL,
`desi` varchar(5) NOT NULL,
`length` varchar(255) NOT NULL,
`customer_firstname` varchar(32) NOT NULL,
`customer_lastname` varchar(32) NOT NULL,
`customer_company` varchar(40) NOT NULL,
`customer_address` varchar(255) NOT NULL,
`customer_city` int(11) NOT NULL,
`customer_city_name` varchar(55) NOT NULL,
`customer_zone_id` int(11) NOT NULL,
`customer_zone_name` varchar(55) NOT NULL,
`customer_postcode` varchar(10) NOT NULL,
`firstname` varchar(32) NOT NULL,
`lastname` varchar(32) NOT NULL,
`company` varchar(40) NOT NULL,
`address` varchar(255) NOT NULL,
`country_id` int(5) DEFAULT NULL,
`country_name` varchar(64) DEFAULT NULL,
`city_id` int(11) NOT NULL,
`city_name` varchar(55) NOT NULL,
`district_id` int(11) NOT NULL,
`district_name` varchar(64) NOT NULL,
`email` varchar(96) NOT NULL,
`phone` varchar(55) NOT NULL,
`postcode` varchar(10) NOT NULL,
`product` text,
`sendText` text NOT NULL,
`returnText` text NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
`deleted_at` datetime DEFAULT NULL,
`cargo_firm` int(1) NOT NULL DEFAULT '0',
`ups_barcode_link` text,
`status` int(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`special_cargo_id`),
KEY `customer_id` (`customer_id`),
KEY `special_cargo_id` (`special_cargo_id`),
KEY `barcode` (`barcode`),
KEY `salesCode` (`salesCode`),
KEY `price` (`price`),
KEY `postaceki` (`postaceki`),
KEY `customer_firstname` (`customer_firstname`),
KEY `customer_lastname` (`customer_lastname`),
KEY `firstname` (`firstname`),
KEY `lastname` (`lastname`),
KEY `customer_company` (`customer_company`),
KEY `customer_address` (`customer_address`),
KEY `customer_city_name` (`customer_city_name`),
KEY `customer_zone_name` (`customer_zone_name`),
KEY `company` (`company`),
KEY `address` (`address`),
KEY `city_name` (`city_name`),
KEY `district_name` (`district_name`),
KEY `email` (`email`),
KEY `phone` (`phone`),
KEY `postcode` (`postcode`)
) ENGINE=InnoDB AUTO_INCREMENT=497037 DEFAULT CHARSET=utf8
+-----------------------+---------+
|Variable_name |Value |
+-----------------------+---------+
|innodb_buffer_pool_size|134217728|
+-----------------------+---------+
+--+-----------+--------------+----------+-----+-------------+-----------+-------+----+------+--------+-----------+
|id|select_type|table |partitions|type |possible_keys|key |key_len|ref |rows |filtered|Extra |
+--+-----------+--------------+----------+-----+-------------+-----------+-------+----+------+--------+-----------+
|1 |SIMPLE |special_cargos|NULL |index|NULL |customer_id|4 |NULL|133967|100 |Using index|
+--+-----------+--------------+----------+-----+-------------+-----------+-------+----+------+--------+-----------+
3 ответа
Здесь есть два аспекта проблемы. Один и более важный аспект ИМО - это запрос - это плохо. Он выполняет полное сканирование индекса (да, PRIMARY также является индексом). Его производительность линейно масштабируется по сравнению с лучшими и желаемыми nlog(n) дерева B +.
Аспект второй. Почему разница во времени исполнения. Это может быть связано с кешированием (в случае DO запрос обслуживался из пула буферов, а в RDS с диска (=EBS)). Это может быть связано с оптимизатором MySQL (DO и RDS могут выбирать разные индексы для обслуживания ПЕРВИЧНОГО запроса по сравнению с меньшим вторичным индексом). Но все это не имеет большого значения из-за проблем с самим запросом.
Можете ли вы предоставить результат:
SHOW CREATE TABLE special_cargos;
SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size';
EXPLAIN select count(special_cargo_id) from special_cargos;
и на RDS, и на вашем экземпляре без RDS?
Предполагая на мгновение, что special_cargo_id
является первичным ключом, и он помещается в ОЗУ, и innodb_buffer_pool_size настроен разумно (на сервере с 2 ГБ ОЗУ 1 ГБ является разумным объемом, хотя RDS должен быть предварительно настроен на разумное значение), он должен работать аналогично на оба узла.
На ум приходят два возможных объяснения:
1) На RDS у вас нет special_cargo_id
определяется как ПК.
2) RDS по какой-то причине предпочитает не использовать индекс (сравнение EXPLAIN
вывод подтвердит, происходит ли это).
Редактировать:
На самом деле - вы уверены, что ваш VPS за 5 долларов использует InnoDB? Если вы получаете ответ через 0,08 секунды, это звучит так, как будто на самом деле он не сканирует даже индекс. Есть большая вероятность, что на VPS вы используете MyISAM, который обновляет количество строк в заголовке таблицы после каждой записи, особенно для того, чтобыSELECT COUNT(*) FROM table_name;
запросы возвращаются мгновенно - как вы заметили.
Изменить 2:
Вау - значит, VPS настроен только на 128 МБ innodb_buffer_pool_size и ВСЕГДА работает быстрее, чем RDS, настроенный с 1 ГБ innodb_buffer_pool_size, и план выполнения для обоих одинаковый?
ОК, попробуйте это:
select count(1) from special_cargos FORCE INDEX (PRIMARY);
1 ГБ для buffer_pool - это опасно, когда у вас всего 2 ГБ ОЗУ. Наверное, та система яростно меняла местами.
Опустите его до 200M и посмотрите, как быстро он работает.
Посмотрите, есть ли у них какой-либо способ мониторинга использования свопа.