15.8.2 Оператор EXPLAIN
{EXPLAIN | DESCRIBE | DESC}
tbl_name [col_name | wild]
{EXPLAIN | DESCRIBE | DESC}
[explain_type] [INTO variable]
{[schema_spec] explainable_stmt | FOR CONNECTION connection_id}
{EXPLAIN | DESCRIBE | DESC} ANALYZE [FORMAT = TREE] [schema_spec] select_statement
explain_type: {
FORMAT = format_name
}
format_name: {
TRADITIONAL
| JSON
| TREE
}
explainable_stmt: {
SELECT statement
| TABLE statement
| DELETE statement
| INSERT statement
| REPLACE statement
| UPDATE statement
}
schema_spec:
FOR {SCHEMA | DATABASE} schema_name
Операторы DESCRIBE и EXPLAIN являются синонимами. На практике, ключевое слово DESCRIBE чаще используется для получения информации о структуре таблицы, в то время как EXPLAIN используется для получения плана выполнения запроса (т.е., объяснения того, как MySQL выполнит запрос).
В последующем обсуждении используются ключевые слова DESCRIBE и EXPLAIN в соответствии с этими случаями использования, но анализатор MySQL рассматривает их как полные синонимы.
Получение информации о структуре таблицы
DESCRIBE предоставляет информацию о столбцах в таблице:
mysql> DESCRIBE City;
+------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+----------------+
| Id | int(11) | NO | PRI | NULL | auto_increment |
| Name | char(35) | NO | | | |
| Country | char(3) | NO | UNI | | |
| District | char(20) | YES | MUL | | |
| Population | int(11) | NO | | 0 | |
+------------+----------+------+-----+---------+----------------+
DESCRIBE является сокращением для SHOW COLUMNS. Эти операторы также отображают информацию для представлений. Описание для SHOW COLUMNS содержит более подробную информацию о столбцах вывода. См. Раздел 15.7.7.6, «Оператор SHOW COLUMNS».
По умолчанию, DESCRIBE отображает информацию обо всех столбцах в таблице. col_name, если указано, является именем столбца в таблице. В этом случае оператор отображает информацию только для указанного столбца. wild, если указано, является строкой-шаблоном. Она может содержать символы-подстановки SQL % и _. В этом случае оператор отображает вывод только для столбцов с именами, соответствующими строке. Нет необходимости заключать строку в кавычки, если она не содержит пробелов или других специальных символов.
Оператор DESCRIBE предоставляется для совместимости с Oracle.
Операторы SHOW CREATE TABLE, SHOW TABLE STATUS и SHOW INDEX также предоставляют информацию о таблицах. См. Раздел 15.7.7, «Операторы SHOW».
Переменная системы explain_format не влияет на вывод EXPLAIN при использовании для получения информации о столбцах таблицы.
Получение информации о плане выполнения запроса
Оператор EXPLAIN предоставляет информацию о том, как MySQL выполняет запросы:
Оператор
EXPLAINработает с операторамиSELECT,DELETE,INSERT,REPLACE,UPDATEиTABLE.Когда оператор
EXPLAINиспользуется с оператором, для которого можно получить план выполнения, MySQL отображает информацию из оптимизатора о плане выполнения запроса. То есть, MySQL объясняет, как он бы обработал запрос, включая информацию о том, как таблицы соединяются и в каком порядке. Для получения информации об использованииEXPLAINдля получения информации о плане выполнения см. Раздел 10.8.2, «Формат вывода EXPLAIN».Когда оператор
EXPLAINиспользуется сFOR CONNECTIONвместо оператора, для которого можно получить план выполнения, он отображает план выполнения для запроса, выполняемого в указанном соединении. См. Раздел 10.8.4, «Получение информации о плане выполнения для указанного соединения».connection_idДля операторов, для которых можно получить план выполнения, оператор
EXPLAINгенерирует дополнительную информацию о плане выполнения, которую можно отобразить с помощью оператораSHOW WARNINGS. См. Раздел 10.8.3, «Расширенный формат вывода EXPLAIN».Оператор
EXPLAINполезен для анализа запросов, включающих разнесенные таблицы. См. Раздел 26.3.5, «Получение информации о разбиениях».-
Опция
FORMATможет использоваться для выбора формата вывода.TRADITIONALотображает вывод в табличном формате. Это значение по умолчанию, если опцияFORMATне указана.JSONотображает информацию в формате JSON.TREEпредоставляет вывод в виде дерева с более точными описаниями обработки запросов, чем форматTRADITIONAL; это единственный формат, который показывает использование хэш-соединений (см. Раздел 10.2.1.4, «Оптимизация хэш-соединений») и всегда используется дляEXPLAIN ANALYZE.В MySQL 8.4 формат вывода по умолчанию, используемый оператором
EXPLAIN(то есть, когда у него нет опцииFORMAT), определяется значением системной переменнойexplain_format. Точные эффекты этой переменной описаны позже в этом разделе.MySQL 8.4 поддерживает дополнительную опцию
INTOсEXPLAIN FORMAT=JSON, которая позволяет сохранить вывод в формате JSON в переменную пользователя, например:mysql>
EXPLAIN FORMAT=JSON INTO @myselect->SELECT name FROM a WHERE id = 2;Query OK, 0 rows affected (0.00 sec) mysql>SELECT @myselect\G*************************** 1. row *************************** @myex: { "query_block": { "select_id": 1, "cost_info": { "query_cost": "1.00" }, "table": { "table_name": "a", "access_type": "const", "possible_keys": [ "PRIMARY" ], "key": "PRIMARY", "used_key_parts": [ "id" ], "key_length": "4", "ref": [ "const" ], "rows_examined_per_scan": 1, "rows_produced_per_join": 1, "filtered": "100.00", "cost_info": { "read_cost": "0.00", "eval_cost": "0.10", "prefix_cost": "0.00", "data_read_per_join": "408" }, "used_columns": [ "id", "name" ] } } } 1 row in set (0.00 sec)Это работает с любым оператором, для которого можно получить план выполнения (
SELECT,TABLE,INSERT,UPDATE,REPLACEилиDELETE). Примеры использования операторовUPDATEиDELETEпоказаны здесь:mysql>
EXPLAIN FORMAT=JSON INTO @myupdate->UPDATE a SET name2 = "garcia" WHERE id = 3;Query OK, 0 rows affected (0.00 sec) mysql>EXPLAIN FORMAT=JSON INTO @mydelete->DELETE FROM a WHERE name1 LIKE '%e%';Query OK, 0 rows affected (0.00 sec) mysql>SELECT @myupdate, @mydelete\G*************************** 1. row *************************** @myupdate: { "query_block": { "select_id": 1, "table": { "update": true, "table_name": "a", "access_type": "range", "possible_keys": [ "PRIMARY" ], "key": "PRIMARY", "used_key_parts": [ "id" ], "key_length": "4", "ref": [ "const" ], "rows_examined_per_scan": 1, "filtered": "100.00", "attached_condition": "(`db`.`a`.`id` = 3)" } } } @mydelete: { "query_block": { "select_id": 1, "table": { "delete": true, "table_name": "a", "access_type": "ALL", "rows_examined_per_scan": 2, "filtered": "100.00", "attached_condition": "(`db`.`a`.`name1` like '%e%')" } } } 1 row in set (0.00 sec)Вы можете работать с этим значением с помощью функций MySQL JSON так же, как и с любым другим значением JSON, как в этих примерах с использованием
JSON_EXTRACT():mysql>
SELECT JSON_EXTRACT(@myselect, "$.query_block.table.key");+----------------------------------------------------+ | JSON_EXTRACT(@myselect, "$.query_block.table.key") | +----------------------------------------------------+ | "PRIMARY" | +----------------------------------------------------+ 1 row in set (0.01 sec) mysql>SELECT JSON_EXTRACT(@myupdate, "$.query_block.table.access_type") AS U_acc,->JSON_EXTRACT(@mydelete, "$.query_block.table.access_type") AS D_acc;+---------+-------+ | U_acc | D_acc | +---------+-------+ | "range" | "ALL" | +---------+-------+ 1 row in set (0.00 sec)Для сложных операторов вывод в формате JSON может быть достаточно большим; в частности, при чтении его может быть сложно сопоставить закрывающую скобку и открывающую скобку; для того, чтобы ключ структуры JSON, если он есть, повторялся рядом с закрывающей скобкой, установите
end_markers_in_json=ON. Следует иметь в виду, что хотя это делает вывод более читабельным, это также делает JSON недействительным, что приводит к ошибке функций JSON.См. также Раздел 14.17, «Функции JSON».
Попытка использовать предложение
INTOбез явного включенияFORMAT=JSONприводит к отклонениюEXPLAIN. Это верно независимо от текущего значения системной переменнойexplain_format.Предложение
INTOне поддерживается сFOR CONNECTION.INTOтакже не поддерживается сEXPLAIN ANALYZE, когдаexplain_json_format_version=1.ВажноЕсли по какой-либо причине запрос для анализа отклоняется, переменная пользователя не обновляется.
-
MySQL 8.4 поддерживает предложение
FOR SCHEMA, которое заставляетEXPLAINвести себя так, как если бы запрос для анализа был выполнен в указанной базе данных;FOR DATABASEподдерживается как синоним. Простой пример использования показан здесь:mysql>
USE b;Database changed mysql>CREATE SCHEMA s1;Query OK, 1 row affected (0.01 sec) mysql>CREATE SCHEMA s2;Query OK, 1 row affected (0.01 sec) mysql>USE s1;Database changed mysql>CREATE TABLE t (c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, c2 INT NOT NULL);Query OK, 0 rows affected (0.04 sec) mysql>USE s2;Database changed mysql>CREATE TABLE t (c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, c2 INT NOT NULL, KEY i1 (c2));Query OK, 0 rows affected (0.04 sec) mysql>USE b;Database changed mysql>EXPLAIN FORMAT=TREE FOR SCHEMA s1 SELECT * FROM t WHERE c2 > 50\G*************************** 1. row *************************** EXPLAIN: -> Filter: (t.c2 > 50) (cost=0.35 rows=1) -> Table scan on t (cost=0.35 rows=1) 1 row in set (0.00 sec) mysql>EXPLAIN FORMAT=TREE FOR SCHEMA s2 SELECT * FROM t WHERE c2 > 50\G*************************** 1. row *************************** EXPLAIN: -> Filter: (t.c2 > 50) (cost=0.35 rows=1) -> Covering index scan on t using i1 (cost=0.35 rows=1) 1 row in set (0.00 sec)Если базы данных не существует, запрос отклоняется с сообщением об ошибке. Если у пользователя нет необходимых привилегий для выполнения запроса, запрос отклоняется с сообщением об ошибке.
FOR SCHEMAнесовместимо сFOR CONNECTION.
EXPLAIN требует тех же привилегий, что и для выполнения запроса. Кроме того, EXPLAIN также требует привилегии SHOW VIEW для любых представлений. EXPLAIN ... FOR
CONNECTION также требует привилегии PROCESS, если указанное соединение принадлежит другому пользователю.
Системная переменная explain_format определяет формат вывода от EXPLAIN при отображении плана выполнения запроса. Эта переменная может принимать любые значения, используемые с опцией FORMAT, с добавлением DEFAULT как синонима для TRADITIONAL. В следующем примере используется таблица country из базы данных world, которую можно получить с MySQL: Other Downloads:
mysql> USE world; # Make world the current database
Database changed
Проверка значения explain_format показывает, что оно имеет значение по умолчанию, и что EXPLAIN (без опции FORMAT) поэтому использует традиционный табличный вывод:
mysql> SELECT @@explain_format;
+------------------+
| @@explain_format |
+------------------+
| TRADITIONAL |
+------------------+
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT Name FROM country WHERE Code Like 'A%';
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| 1 | SIMPLE | country | NULL | range | PRIMARY | PRIMARY | 12 | NULL | 17 | 100.00 | Using where |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
Если мы установим значение explain_format на TREE, а затем повторно выполним тот же оператор EXPLAIN, вывод будет использовать древовидный формат:
mysql> SET @@explain_format=TREE;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @@explain_format;
+------------------+
| @@explain_format |
+------------------+
| TREE |
+------------------+
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT Name FROM country WHERE Code LIKE 'A%';
+--------------------------------------------------------------------------------------------------------------+
| EXPLAIN |
+--------------------------------------------------------------------------------------------------------------+
| -> Filter: (country.`Code` like 'A%') (cost=3.67 rows=17)
-> Index range scan on country using PRIMARY over ('A' <= Code <= 'A????????') (cost=3.67 rows=17) |
+--------------------------------------------------------------------------------------------------------------+
1 row in set, 1 warning (0.00 sec)
Как уже отмечалось, опция FORMAT переопределяет это значение. Выполнение того же оператора EXPLAIN с FORMAT=JSON вместо FORMAT=TREE демонстрирует это:
mysql> EXPLAIN FORMAT=JSON SELECT Name FROM country WHERE Code LIKE 'A%';
+------------------------------------------------------------------------------+
| EXPLAIN |
+------------------------------------------------------------------------------+
| {
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "3.67"
},
"table": {
"table_name": "country",
"access_type": "range",
"possible_keys": [
"PRIMARY"
],
"key": "PRIMARY",
"used_key_parts": [
"Code"
],
"key_length": "12",
"rows_examined_per_scan": 17,
"rows_produced_per_join": 17,
"filtered": "100.00",
"cost_info": {
"read_cost": "1.97",
"eval_cost": "1.70",
"prefix_cost": "3.67",
"data_read_per_join": "16K"
},
"used_columns": [
"Code",
"Name"
],
"attached_condition": "(`world`.`country`.`Code` like 'A%')"
}
}
} |
+------------------------------------------------------------------------------+
1 row in set, 1 warning (0.00 sec)
Для возврата к формату вывода EXPLAIN в табличный вид, установите значение explain_format на TRADITIONAL. В качестве альтернативы, вы можете установить его на DEFAULT, что имеет тот же эффект, как показано здесь:
mysql> SET @@explain_format=DEFAULT;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @@explain_format;
+------------------+
| @@explain_format |
+------------------+
| TRADITIONAL |
+------------------+
1 row in set (0.00 sec)
MySQL 8.4 поддерживает два варианта формата вывода JSON. Версия 1 — линейный формат, всегда используемый в MySQL 8.2 и более ранних версиях; это по-прежнему значение по умолчанию в MySQL 8.4 и используется в примерах, уже показанных в этом разделе. Версия 2 формата вывода JSON основана на путях доступа и предназначена для обеспечения совместимости с будущими версиями оптимизатора MySQL. Вы можете переключиться на формат версии 2, установив значение системной переменной сервера explain_json_format_version на 2, как показано здесь для того же оператора EXPLAIN, используемого в предыдущем примере:
mysql> SELECT @@explain_json_format_version;
+-------------------------------+
| @@explain_json_format_version |
+-------------------------------+
| 1 |
+-------------------------------+
1 row in set (0.00 sec)
mysql> SET @@explain_json_format_version = 2;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @@explain_json_format_version;
+-------------------------------+
| @@explain_json_format_version |
+-------------------------------+
| 2 |
+-------------------------------+
1 row in set (0.00 sec)
mysql> EXPLAIN FORMAT=JSON SELECT Name FROM country WHERE Code LIKE 'A%';
+------------------------------------------------------------------------------+
| EXPLAIN |
+------------------------------------------------------------------------------+
| {
"query": "/* select#1 */ select `world`.`country`.`Name` AS `Name` from `world`.`country` where (`world`.`country`.`Code` like 'A%')",
"inputs": [
{
"ranges": [
"('A' <= Code <= 'A????????')"
],
"covering": false,
"operation": "Index range scan on country using PRIMARY over ('A' <= Code < 'A????????')",
"index_name": "PRIMARY",
"table_name": "country",
"access_type": "index",
"estimated_rows": 17.0,
"index_access_type": "index_range_scan",
"estimated_total_cost": 3.668778400708174
}
],
"condition": "(country.`Code` like 'A%')",
"operation": "Filter: (country.`Code` like 'A%')",
"access_type": "filter",
"estimated_rows": 17.0,
"estimated_total_cost": 3.668778400708174
} |
+------------------------------------------------------------------------------+
После использования формата версии 2 вы можете вернуть вывод JSON от всех последующих операторов EXPLAIN FORMAT=JSON к формату версии 1, установив значение explain_json_format_version обратно на значение по умолчанию 1.
Значение explain_json_format_version определяет версию формата вывода JSON, используемого всеми операторами EXPLAIN, которые его используют, независимо от того, используется ли формат JSON из-за того, что данный оператор EXPLAIN включает явную опцию FORMAT=JSON, или потому, что формат JSON используется автоматически из-за того, что системная переменная explain_format установлена на JSON.
С помощью EXPLAIN вы можете увидеть, где следует добавить индексы в таблицы, чтобы оператор выполнялся быстрее, используя индексы для поиска строк. Вы также можете использовать EXPLAIN, чтобы проверить, объединяет ли оптимизатор таблицы в оптимальном порядке. Чтобы дать подсказку оптимизатору использовать порядок объединения, соответствующий порядку указания таблиц в операторе SELECT, начните оператор с SELECT STRAIGHT_JOIN, а не просто с SELECT. (См. Раздел 15.2.13, «Оператор SELECT».)
Иногда трассировка оптимизатора может предоставить дополнительную информацию по сравнению с EXPLAIN. Однако формат и содержимое трассировки оптимизатора могут меняться между версиями. Для получения подробностей см. Раздел 10.15, «Отслеживание оптимизатора».
Если у вас возникла проблема с тем, что индексы не используются, хотя, по вашему мнению, они должны использоваться, запустите ANALYZE
TABLE, чтобы обновить статистику таблицы, такую как мощность ключей, которая может повлиять на выбор оптимизатора. См. Раздел 15.7.3.1, «Оператор ANALYZE TABLE».
MySQL Workbench имеет функцию визуального объяснения, которая предоставляет визуальное представление выходных данных EXPLAIN. См. .
Получение информации с помощью EXPLAIN ANALYZE
EXPLAIN ANALYZE выполняет оператор и выводит EXPLAIN вывод вместе со временем и дополнительной информацией, основанной на итераторах, о том, как ожидания оптимизатора соответствовали фактическому выполнению. Для каждого итератора предоставляется следующая информация:
-
Ожидаемая стоимость выполнения
(Некоторые итераторы не учитываются моделью стоимости, поэтому не включаются в оценку.)
Ожидаемое количество возвращаемых строк
Время возврата первой строки
-
Время, затраченное на выполнение этого итератора (включая дочерние итераторы, но не родительские), в миллисекундах.
(При наличии нескольких циклов эта цифра показывает среднее время за цикл.)
Количество строк, возвращенных итератором
Количество циклов
Информация о выполнении запроса отображается в формате вывода TREE, в котором узлы представляют итераторы. EXPLAIN ANALYZE всегда использует формат вывода TREE. Это можно необязательно явно указать, используя FORMAT=TREE; форматы, отличные от TREE, остаются неподдерживаемыми.
EXPLAIN ANALYZE может использоваться с операторами SELECT, многотабличными операторами UPDATE и DELETE, а также операторами TABLE.
Вы можете завершить этот оператор, используя KILL QUERY или CTRL-C.
EXPLAIN ANALYZE не может использоваться с FOR CONNECTION.
Пример вывода:
mysql> EXPLAIN ANALYZE SELECT * FROM t1 JOIN t2 ON (t1.c1 = t2.c2)\G
*************************** 1. row ***************************
EXPLAIN: -> Inner hash join (t2.c2 = t1.c1) (cost=3.5 rows=5)
(actual time=0.121..0.131 rows=1 loops=1)
-> Table scan on t2 (cost=0.07 rows=5)
(actual time=0.0126..0.0221 rows=5 loops=1)
-> Hash
-> Table scan on t1 (cost=0.75 rows=5)
(actual time=0.0372..0.0534 rows=5 loops=1)
mysql> EXPLAIN ANALYZE SELECT * FROM t3 WHERE i > 8\G
*************************** 1. row ***************************
EXPLAIN: -> Filter: (t3.i > 8) (cost=0.75 rows=1.67)
(actual time=0.0168..0.0182 rows=1 loops=1)
-> Table scan on t3 (cost=0.75 rows=5)
(actual time=0.015..0.0167 rows=5 loops=1)
mysql> EXPLAIN ANALYZE FORMAT=TREE SELECT * FROM t3 WHERE pk > 17\G
*************************** 1. row ***************************
EXPLAIN: -> Filter: (t3.pk > 17) (cost=0.91 rows=2)
(actual time=0.0334..0.042 rows=2 loops=1)
-> Index range scan on t3 using PRIMARY over (17 < pk)
(cost=0.91 rows=2) (actual time=0.0306..0.0384 rows=2 loops=1)
Таблицы, используемые в примере вывода, были созданы операторами, показанными здесь:
CREATE TABLE t1 (
c1 INTEGER DEFAULT NULL,
c2 INTEGER DEFAULT NULL
);
CREATE TABLE t2 (
c1 INTEGER DEFAULT NULL,
c2 INTEGER DEFAULT NULL
);
CREATE TABLE t3 (
pk INTEGER NOT NULL PRIMARY KEY,
i INTEGER DEFAULT NULL
);
Значения, отображаемые для actual time в выходных данных этого оператора, выражены в миллисекундах.
explain_format оказывает следующее влияние на EXPLAIN ANALYZE:
Если значение этой переменной равно
TRADITIONALилиTREE(или синонимуDEFAULT),EXPLAIN ANALYZEиспользует форматTREE. Это гарантирует, что этот оператор по-прежнему использует форматTREEпо умолчанию, как это было до появленияexplain_format.Если значение
explain_formatравноJSON,EXPLAIN ANALYZEвозвращает ошибку, еслиFORMAT=TREEне указан как часть оператора. Это связано с тем, чтоEXPLAIN ANALYZEподдерживает только формат выводаTREE.
Мы иллюстрируем поведение, описанное во втором пункте, повторно используя последний оператор EXPLAIN ANALYZE из предыдущего примера:
mysql> SET @@explain_format=JSON;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @@explain_format;
+------------------+
| @@explain_format |
+------------------+
| JSON |
+------------------+
1 row in set (0.00 sec)
mysql> EXPLAIN ANALYZE SELECT * FROM t3 WHERE pk > 17\G
ERROR 1235 (42000): This version of MySQL doesn't yet support 'EXPLAIN ANALYZE with JSON format'
mysql> EXPLAIN ANALYZE FORMAT=TRADITIONAL SELECT * FROM t3 WHERE pk > 17\G
ERROR 1235 (42000): This version of MySQL doesn't yet support 'EXPLAIN ANALYZE with TRADITIONAL format'
mysql> EXPLAIN ANALYZE FORMAT=TREE SELECT * FROM t3 WHERE pk > 17\G
*************************** 1. row ***************************
EXPLAIN: -> Filter: (t3.pk > 17) (cost=1.26 rows=5)
(actual time=0.013..0.016 rows=5 loops=1)
-> Index range scan on t3 using PRIMARY (cost=1.26 rows=5)
(actual time=0.012..0.014 rows=5 loops=1)
Использование FORMAT=TRADITIONAL или FORMAT=JSON с EXPLAIN
ANALYZE всегда вызывает ошибку, независимо от значения explain_format.
В MySQL 8.4 числа в выходных данных EXPLAIN ANALYZE и EXPLAIN
FORMAT=TREE форматируются по следующим правилам:
-
Числа в диапазоне 0,001-999999,5 выводятся как десятичные числа.
Десятичные числа меньше 1000 имеют три значащие цифры; остальные имеют четыре, пять или шесть.
Числа за пределами диапазона 0,001-999999,5 выводятся в инженерном формате. Примерами таких значений являются
1.23e+9и934e-6.Не выводится trailing ноль. Например, мы выводим
2.3, а не2.30, и1.2e+6, а не1.20e+6.Числа меньше
1e-12выводятся как0.
© 2025 Oracle
Licensed under the GPLv2 License.