Заявката остава статистическо състояние за дълго време в Google Cloud SQL (MySQL 5.5)

Някои заявки остават в състояние „статистика“ за дълго време в моята база данни на Google Cloud SQL. (MySQL 5.5)

След тази публикация промених optimizer_search_depth на 0. Но някои заявки все още имат дълго време за статистика.

> select @@optimizer_search_depth;
+--------------------------+
| @@optimizer_search_depth |
+--------------------------+
|                        0 |
+--------------------------+

> show processlist;
+----+------+-----------+------+---------+------+------------+-----------------+
| Id | User | Host      | db   | Command | Time | State      | Info            |
+----+------+-----------+------+---------+------+------------+-----------------+
|  4 | root | localhost | mydb | Query   |   84 | statistics | SELECT * FROM ..|

Таблицата и броят са както по-долу.

> describe mytable;
+----------+---------------+------+-----+---------------------+-----------------------------+
| Field    | Type          | Null | Key | Default             | Extra                       |
+----------+---------------+------+-----+---------------------+-----------------------------+
| col1     | varchar(50)   | NO   | PRI | NULL                |                             |
| col2     | varchar(50)   | NO   | PRI | NULL                |                             |
| col3     | decimal(15,4) | NO   |     | NULL                |                             |
| col4     | decimal(15,4) | NO   |     | NULL                |                             |
| col5     | decimal(15,4) | NO   |     | NULL                |                             |
| col6     | decimal(15,4) | NO   |     | NULL                |                             |
| col7     | varchar(50)   | YES  |     | NULL                |                             |
| col8     | decimal(15,4) | NO   |     | NULL                |                             |
| col9     | decimal(15,4) | NO   |     | NULL                |                             |
| col10    | varchar(8)    | NO   |     | NULL                |                             |
| col11    | varchar(30)   | NO   |     | NULL                |                             |
| col12    | timestamp     | NO   |     | 0000-00-00 00:00:00 |                             |
| col13    | timestamp     | NO   |     | CURRENT_TIMESTAMP   | on update CURRENT_TIMESTAMP |
| col14    | int(11)       | NO   |     | NULL                |                             |
+----------+---------------+------+-----+---------------------+-----------------------------+

> select count(*) from mytable;
+----------+
| count(*) |
+----------+
|   852304 |
+----------+

Запитването е така.

SELECT * FROM mytable WHERE 
((col1 = 'FFP60003' AND col2 = '360' ) OR 
(col1 = 'FIU51001' AND col2 = '210' ) OR 
(col1 = 'FIU51003' AND col2 = '360' ) OR 
(col1 = 'FPC60001' AND col2 = '240' ) OR 
(col1 = 'SLU50006' AND col2 = '360' ) OR 
... (about 2000-3000 and/or) ...
(col1 = '89969' AND col2 = '270' ) ) AND col14 > 0

Както е показано по-горе, заявката е много дълга. Мисля, че това е причината за дълго състояние на статистиката, но приложението ми се нуждае от този тип заявка.

Как мога да избегна проблем с дълга статистика?

[Актуализация]

SHOW CREATE TABLE и SHOW VARIABLES LIKE '%buffer%' са както по-долу.

> show create table mytable\G
*************************** 1. row ***************************
       Table: mytable
Create Table: CREATE TABLE `mytable` (
  `col1` varchar(50) NOT NULL COMMENT 'col1',
  `col2` varchar(50) NOT NULL COMMENT 'col2',
  `col3` decimal(15,4) NOT NULL COMMENT 'col3',
  `col4` decimal(15,4) NOT NULL COMMENT 'col4',
  `col5` decimal(15,4) NOT NULL COMMENT 'col5',
  `col6` decimal(15,4) NOT NULL COMMENT 'col6',
  `col7` varchar(50) DEFAULT NULL COMMENT 'col7',
  `col8` decimal(15,4) NOT NULL COMMENT 'col8',
  `col9` decimal(15,4) NOT NULL COMMENT 'col9',
  `col10` varchar(8) NOT NULL COMMENT 'col10',
  `col11` varchar(30) NOT NULL COMMENT 'col11',
  `col12` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'col12',
  `col13` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'col13',
  `col14` int(11) NOT NULL COMMENT 'col14',
  PRIMARY KEY (`col1`,`col2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

 > SHOW VARIABLES LIKE '%buffer%';
+------------------------------+-----------+
| Variable_name                | Value     |
+------------------------------+-----------+
| bulk_insert_buffer_size      | 8388608   |
| innodb_buffer_pool_instances | 1         |
| innodb_buffer_pool_size      | 805306368 |
| innodb_change_buffering      | all       |
| innodb_log_buffer_size       | 8388608   |
| join_buffer_size             | 131072    |
| key_buffer_size              | 8388608   |
| myisam_sort_buffer_size      | 8388608   |
| net_buffer_length            | 16384     |
| preload_buffer_size          | 32768     |
| read_buffer_size             | 131072    |
| read_rnd_buffer_size         | 262144    |
| sort_buffer_size             | 2097152   |
| sql_buffer_result            | OFF       |
+------------------------------+-----------+

person N.F.    schedule 18.03.2015    source източник
comment
EXPLAIN SELECT ... вероятно ще каже, че е извършил сканиране на таблица, както е посочено от ALL. Това е така, защото OR е трудно да се оптимизира.   -  person Rick James    schedule 18.03.2015
comment
Ако col14 е достатъчно избирателен, тогава INDEX(col14) ще помогне. Моля, предоставете SHOW CREATE TABLE mytable -- трябва да видим точния индекс(и) плюс типа на двигателя. (Можете да скриете или премахнете повечето от колоните, ако е необходимо.) Също така SHOW VARIABLES LIKE '%buffer%'. Колко RAM имаш?   -  person Rick James    schedule 18.03.2015
comment
Актуализирах публикацията си. col14 не е избирателен. Повече от 850 000 записа имат стойност 1.   -  person N.F.    schedule 18.03.2015
comment
Типът екземпляр на Cloud SQL е D2. Това има 1GB RAM.   -  person N.F.    schedule 18.03.2015


Отговори (1)


В 1GB сървър не разполагайте с innodb_buffer_pool_size повече от около 200M. Задаването му на 800M ще доведе до размяна. MySQL очаква неговите кешове да останат в RAM; когато се разменят на диск, производителността страда ужасно.

Таблицата ви вероятно е твърде голяма, за да бъде изцяло кеширана. Така че "сканирането на таблица" ще издуха кеша, правейки кеша безполезен и заявката ще се изпълнява със скорост на диска. Или намерете начин да избегнете подобни заявки, или вземете повече RAM.

person Rick James    schedule 18.03.2015
comment
Промених тип екземпляр на Cloud SQL D8, който има 4 GB RAM. Това има известен ефект, но все още има състояние на статистика от 50 секунди. След като надстроих типа на екземпляра до D8, innodb_buffer_pool_size става 3221225472. Google автоматично задава тази стойност и не позволява промяна на тази стойност. - person N.F.; 18.03.2015
comment
3G/4G е стегнат; не оставя много място за операционната система и за други буфери, кешове и т.н. Има ли показатели, за да видите дали екземплярът се разменя? - person Rick James; 18.03.2015
comment
Настройката на облачната услуга 800M ли беше на 1G VM? Трябваше ли 1G да включва ОС и т.н.? Ако е така, смени доставчика, те не знаят какво правят. - person Rick James; 18.03.2015