您的位置:首页 > 数据库 > MySQL

MySQL物理优化---调整优化器代价参数进行优化

2017-03-13 19:05 309 查看
自MySQL 5.6版本之后,MySQL的优化器开始在物理优化方面,进行了改进,现在发布的版本,已经允许对估算代价的参数进行动态调整,以便于优化SQL使得其能适应不同的存储引擎和存储介质.

如下使用实例来介绍这样的功能. 一 创建表
 CREATE TABLE t1 (
  pk INTEGER PRIMARY KEY,
  a INTEGER,
  b INTEGER,
  c CHAR(255),
  UNIQUE KEY k1 (a)
);
INSERT INTO t1 VALUES (1, 1, NULL, "Abc"), (2, 2, NULL, "Abc"),
                      (3, 3, NULL, "Abc"), (4, 4, NULL, "Abc");
INSERT INTO t1 SELECT a + 4, a + 4, b, c FROM t1;
INSERT INTO t1 SELECT a + 8, a + 8, b, c FROM t1;
INSERT INTO t1 SELECT a + 16, a + 16, b, c FROM t1;
INSERT INTO t1 SELECT a + 32, a + 32, b, c FROM t1;
INSERT INTO t1 SELECT a + 64, a + 64, b, c FROM t1;
INSERT INTO t1 SELECT a + 128, a + 128, b, c FROM t1;
CREATE TABLE t2 (
  d INTEGER PRIMARY KEY,
  e INTEGER
);
INSERT INTO t2 SELECT a, b FROM t1;
ANALYZE TABLE t1, t2;
二 查询MySQL服务器默认情况下可调整的代价估算值
注意所查找的mysql.engine_cost和mysql.server_cost,其表中各"cost_name"的具体含义,可以参考官方手册.
MySQL官方手册解释说:
As of MySQL 5.7.5, the optimizer has in addition a database of cost estimates to use during execution plan construction. These estimates are stored in the server_cost and engine_cost tables in the mysql system database and are configurable at any time. The intent of these tables is that it should be possible to easily adjust the cost estimates that the optimizer uses when it attempts to arrive at query execution plans.
mysql> SELECT cost_name, cost_value FROM mysql.engine_cost;
+--------------------+------------+
| cost_name          | cost_value |
+--------------------+------------+
| io_block_read_cost |       NULL |
+--------------------+------------+
mysql> select * from mysql.server_cost;
+------------------------------+------------+---------------------+---------+
| cost_name                    | cost_value | last_update         | comment |
+------------------------------+------------+---------------------+---------+
| disk_temptable_create_cost   |       NULL | 2015-05-14 17:05:01 | NULL    |
| disk_temptable_row_cost      |       NULL | 2015-05-14 17:05:01 | NULL    |
| key_compare_cost             |       NULL | 2015-05-14 17:05:01 | NULL    |
| memory_temptable_create_cost |       NULL | 2015-05-14 17:05:01 | NULL    |
| memory_temptable_row_cost    |       NULL | 2015-05-14 17:05:01 | NULL    |
| row_evaluate_cost            |       NULL | 2015-05-14 17:05:01 | NULL    |
+------------------------------+------------+---------------------+---------+
三 执行查询,观察结果,与第五步对比
EXPLAIN FORMAT=JSON SELECT * FROM t1 JOIN t2 ON b=d ORDER BY a LIMIT 4;
| {
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": ""
    },
    "ordering_operation": {
      "using_filesort": false,
      "nested_loop": [
        {
          "table": {
            "table_name": "t1",
            "access_type": "index",
            "key": "k1",
            "used_key_parts": [
              "a"
            ],
            "key_length": "5",
            "rows_examined_per_scan": 4,
            "rows_produced_per_join": 256,
            "filtered": "100.00",
            "cost_info": {
              "read_cost": "7.00",
              "eval_cost": "51.20",
              "prefix_cost": "58.20",
              "data_read_per_join": "68K"
            },
            "used_columns": [
              "pk",
              "a",
              "b",
              "c"
            ],
            "attached_condition": "(`d`.`t1`.`b` is not null)"
          }
        },
        {
          "table": {
            "table_name": "t2",
            "access_type": "eq_ref",
            "possible_keys": [
              "PRIMARY"
            ],
            "key": "PRIMARY",
            "used_key_parts": [
              "d"
            ],
            "key_length": "4",
            "ref": [
              "d.t1.b"
            ],
            "rows_examined_per_scan": 1,
            "rows_produced_per_join": 256,
            "filtered": "100.00",
            "cost_info": {
              "read_cost": "256.00",
              "eval_cost": "51.20",
              "prefix_cost": "365.40",
              "data_read_per_join": "4K"
            },
            "used_columns": [
              "d",
              "e"
            ]

四 修改代价参数值,并刷出修改后的值,使之生效
SET cost_value=0.2
WHERE cost_name="row_evaluate_cost";
UPDATE mysql.server_cost
SET cost_value=0.1
WHERE cost_name="key_compare_cost";
UPDATE mysql.server_cost
SET cost_value=2.0
WHERE cost_name="memory_temptable_create_cost";
UPDATE mysql.server_cost
SET cost_value=0.2
WHERE cost_name="memory_temptable_row_cost";
UPDATE mysql.server_cost
SET cost_value=40
WHERE cost_name="disk_temptable_create_cost";
UPDATE mysql.server_cost
SET cost_value=1.0
WHERE cost_name="disk_temptable_row_cost";
UPDATE mysql.engine_cost
SET cost_value=1.0
WHERE cost_name="io_block_read_cost";
UPDATE mysql.server_cost
SET cost_value = 0.5 * cost_value;
UPDATE mysql.engine_cost
SET cost_value = 0.5 * cost_value;
FLUSH OPTIMIZER_COSTS;
五 新启动一个客户端,然后执行与第三步相同的查询,观察输出结果与第三步的不同之处
EXPLAIN FORMAT=JSON SELECT * FROM t1 JOIN t2 ON b=d ORDER BY a LIMIT 4;
| {
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": ""
    },
    "ordering_operation": {
      "using_filesort": false,
      "nested_loop": [
        {
          "table": {
            "table_name": "t1",
            "access_type": "index",
            "key": "k1",
            "used_key_parts": [
              "a"
            ],
            "key_length": "5",
            "rows_examined_per_scan": 4,
            "rows_produced_per_join": 256,
            "filtered": "100.00",
            "cost_info": {
              "read_cost": "3.50",
              "eval_cost": "51.20",
              "prefix_cost": "54.70",
              "data_read_per_join": "68K"
            },
            "used_columns": [
              "pk",
              "a",
              "b",
              "c"
            ],
            "attached_condition": "(`d`.`t1`.`b` is not null)"
          }
        },
        {
          "table": {
            "table_name": "t2",
            "access_type": "eq_ref",
            "possible_keys": [
              "PRIMARY"
            ],
            "key": "PRIMARY",
            "used_key_parts": [
              "d"
            ],
            "key_length": "4",
            "ref": [
              "d.t1.b"
            ],
            "rows_examined_per_scan": 1,
            "rows_produced_per_join": 256,
            "filtered": "100.00",
            "cost_info": {
              "read_cost": "128.00",
              "eval_cost": "51.20",
              "prefix_cost": "233.90",
              "data_read_per_join": "4K"
            },
            "used_columns": [
              "d",
              "e"
            ]
六 总结
通过第四步的设置,我们可以改变代价估算的值,然后在新的连接中,就可以使用这项功能。当你的存储设备更换,当临时表需要优化(磁盘临时表,内存临时表)等等,MySQL的优化手段是不是更丰富更灵活了?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: