【GreatSQL优化器-17】DYNAMIC RANGE

echarts实现3D地图——map3D 【代码】echarts实现3D地图——map3D。 阅读详情

【GreatSQL优化器-17】DYNAMIC RANGE

一、DYNAMIC RANGE介绍

GreatSQL 的优化器有一种扫描方式是动态范围扫描方式,类似于“已读乱回”模式,这种模式是在表有多个索引的情况下,对驱动表连接的时候部分选择索引的情况。优化器没有找到好的索引可以使用,但发现在知道前面表的列值后,可能会使用某些索引。对于前面表中的每个行组合,优化器检查是否可以使用 range 或 index merge 访问方法来检索行。虽然这不是很快,但比执行完全没有索引的连接要快。

下面用一个简单的例子来说明直方图怎么应用在优化器。

CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT,date1 DATETIME);
INSERT INTO t1 VALUES (1,10,'2021-03-25 16:44:00.123456'),(2,1,'2022-03-26 16:44:00.123456'),(3,4,'2023-03-27 16:44:00.123456'),(5,5,'2024-03-25 16:44:00.123456'),(7,null,'2020-03-25 16:44:00.123456'),(8,10,'2020-10-25 16:44:00.123456'),(11,16,'2023-03-25 16:44:00.123456');
CREATE TABLE t2 (cc1 INT PRIMARY KEY, cc2 INT);
INSERT INTO t2 VALUES (1,3),(2,1),(3,2),(4,3),(5,15);
CREATE TABLE t3 (ccc1 INT, ccc2 varchar(100));
INSERT INTO t3 VALUES (1,'aa1'),(2,'bb1'),(3,'cc1'),(4,'dd1'),(null,'ee');
CREATE INDEX idx1 ON t1(c2);
CREATE INDEX idx2 ON t1(c2,date1);
CREATE INDEX idx2_1 ON t2(cc2);
CREATE INDEX idx3_1 ON t3(ccc1);

greatsql> EXPLAIN SELECT * FROM t1 join t3 ON t1.c1=t3.ccc1 or t1.c2<5;
+----+-------------+-------+------------+------+-------------------+------+---------+------+------+----------+------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys     | key  | key_len | ref  | rows | filtered | Extra                                          |
+----+-------------+-------+------------+------+-------------------+------+---------+------+------+----------+------------------------------------------------+
|  1 | SIMPLE      | t3    | NULL       | ALL  | idx3_1            | NULL | NULL    | NULL |    5 |   100.00 | NULL                                           |
|  1 | SIMPLE      | t1    | NULL       | ALL  | PRIMARY,idx1,idx2 | NULL | NULL    | NULL |    7 |    43.67 | Range checked for each record (index map: 0x7) |
-- 这里的结果出现了Range checked,说明进行了DYNAMIC_RANGE
+----+-------------+-------+------------+------+-------------------+------+---------+------+------+----------+------------------------------------------------+

greatsql> SELECT * FROM t1 join t3 ON t1.c1=t3.ccc1 or t1.c2<5;
+----+------+---------------------+------+------+
| c1 | c2   | date1               | ccc1 | ccc2 |
+----+------+---------------------+------+------+
|  1 |   10 | 2021-03-25 16:44:00 |    1 | aa1  |
|  2 |    1 | 2022-03-26 16:44:00 |    1 | aa1  |
|  3 |    4 | 2023-03-27 16:44:00 |    1 | aa1  |
|  2 |    1 | 2022-03-26 16:44:00 |    2 | bb1  |
|  3 |    4 | 2023-03-27 16:44:00 |    2 | bb1  |
|  2 |    1 | 2022-03-26 16:44:00 |    3 | cc1  |
|  3 |    4 | 2023-03-27 16:44:00 |    3 | cc1  |
|  2 |    1 | 2022-03-26 16:44:00 |    4 | dd1  |
|  3 |    4 | 2023-03-27 16:44:00 |    4 | dd1  |
|  2 |    1 | 2022-03-26 16:44:00 | NULL | ee   |
|  3 |    4 | 2023-03-27 16:44:00 | NULL | ee   |
+----+------+---------------------+------+------+

greatsql> SELECT * FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
             "attaching_conditions_to_tables": {
              "original_condition": "((`t1`.`c1` = `t3`.`ccc1`) or (`t1`.`c2` < 5))",
              "attached_conditions_computation": [
                {
                  "table": "`t1`",
                  "rechecking_index_usage": { -- 这里对t1进行了recheck
                    "recheck_reason": "not_first_table",
                    "range_analysis": {
                      "table_scan": {
                        "rows": 7,
                        "cost": 3.05
                      },
                      "potential_range_indexes": [
                        {
                          "index": "PRIMARY",
                          "usable": true,
                          "key_parts": [
                            "c1"
                          ]
                        },
                        {
                          "index": "idx1",
                          "usable": true,
                          "key_parts": [
                            "c2",
                            "c1"
                          ]
                        },
                        {
                          "index": "idx2",
                          "usable": true,
                          "key_parts": [
                            "c2",
                            "date1",
                            "c1"
                          ]
                        }
                      ],
                      "best_covering_index_scan": {
                        "index": "idx2",
                        "cost": 0.952742,
                        "chosen": true
                      },
                      "setup_range_conditions": [
                      ],
                      "group_index_range": {
                        "chosen": false,
                        "cause": "not_single_table"
                      },
                      "skip_scan_range": {
                        "chosen": false,
                        "cause": "not_single_table"
                      },
                      "analyzing_range_alternatives": {
                        "range_scan_alternatives": [
                        ],
                        "analyzing_roworder_intersect": {
                          "usable": false,
                          "cause": "too_few_roworder_scans"
                        }
                      },
                      "analyzing_index_merge_union": [
                        {
                          "indexes_to_merge": [
                            {
                              "range_scan_alternatives": [
                                {
                                  "index": "PRIMARY",
                                  "chosen": false,
                                  "cause": "depends_on_unread_values"
                                }
                              ],
                              "chosen": false,
                              "cause": "cost"
                            },
                            {
                              "range_scan_alternatives": [
                                {
                                  "index": "idx1",
                                  "ranges": [
                                    "NULL < c2 < 5"
                                  ],
                                  "index_dives_for_eq_ranges": true,
                                  "rowid_ordered": false,
                                  "using_mrr": false,
                                  "index_only": true,
                                  "in_memory": 1,
                                  "rows": 2,
                                  "cost": 0.460274,
                                  "chosen": true
                                },
                                {
                                  "index": "idx2",
                                  "ranges": [
                                    "NULL < c2 < 5"
                                  ],
                                  "index_dives_for_eq_ranges": true,
                                  "rowid_ordered": false,
                                  "using_mrr": false,
                                  "index_only": true,
                                  "in_memory": 1,
                                  "rows": 2,
                                  "cost": 0.460457,
                                  "chosen": false,
                                  "cause": "cost"
                                }
                              ],
                              "chosen": false,
                              "cause": "cost"
                            }
                          ],
                          "cost_of_reading_ranges": 0,
                          "chosen": false,
                          "cause": "cost"
                        }
                      ]
                    }
                  }
                }
              ],
              "attached_conditions_summary": [
                {
                  "table": "`t3`",
                  "attached": null
                },
                {
                  "table": "`t1`",
                  "attached": "((`t1`.`c1` = `t3`.`ccc1`) or (`t1`.`c2` < 5))"
                }
              ]
            }
     "join_execution": {
        "select#": 1,
        "steps": [
          {
            "rows_estimation_per_outer_row": { -- 这里只截取t3读第一行时候t1的索引选择
              "table": "`t1`",
              "range_analysis": {
                "table_scan": {
                  "rows": 7,
                  "cost": 3.05
                },
                "potential_range_indexes": [
                  {
                    "index": "PRIMARY",
                    "usable": true,
                    "key_parts": [
                      "c1"
                    ]
                  },
                  {
                    "index": "idx1",
                    "usable": true,
                    "key_parts": [
                      "c2",
                      "c1"
                    ]
                  },
                  {
                    "index": "idx2",
                    "usable": true,
                    "key_parts": [
                      "c2",
                      "date1",
                      "c1"
                    ]
                  }
                ],
                "best_covering_index_scan": {
                  "index": "idx2",
                  "cost": 0.952742,
                  "chosen": true
                },
                "setup_range_conditions": [
                ],
                "group_index_range": {
                  "chosen": false,
                  "cause": "not_single_table"
                },
                "skip_scan_range": {
                  "chosen": false,
                  "cause": "not_single_table"
                },
                "analyzing_range_alternatives": {
                  "range_scan_alternatives": [
                  ],
                  "analyzing_roworder_intersect": {
                    "usable": false,
                    "cause": "too_few_roworder_scans"
                  }
                },
                "analyzing_index_merge_union": [
                  {
                    "indexes_to_merge": [
                      {
                        "range_scan_alternatives": [
                          {
                            "index": "PRIMARY",
                            "ranges": [
                              "c1 = 1"
                            ],
                            "index_dives_for_eq_ranges": true,
                            "rowid_ordered": true,
                            "using_mrr": false,
                            "index_only": true,
                            "in_memory": 1,
                            "rows": 1,
                            "cost": 0.36,
                            "chosen": true
                          }
                        ],
                        "index_to_merge": "PRIMARY",
                        "cumulated_cost": 0.36
                      },
                      {
                        "range_scan_alternatives": [
                          {
                            "index": "idx1",
                            "ranges": [
                              "NULL < c2 < 5"
                            ],
                            "index_dives_for_eq_ranges": true,
                            "rowid_ordered": false,
                            "using_mrr": false,
                            "index_only": true,
                            "in_memory": 1,
                            "rows": 2,
                            "cost": 0.460274,
                            "chosen": true
                          },
                          {
                            "index": "idx2",
                            "ranges": [
                              "NULL < c2 < 5"
                            ],
                            "index_dives_for_eq_ranges": true,
                            "rowid_ordered": false,
                            "using_mrr": false,
                            "index_only": true,
                            "in_memory": 1,
                            "rows": 2,
                            "cost": 0.460457,
                            "chosen": false,
                            "cause": "cost"
                          }
                        ],
                        "index_to_merge": "idx1",
                        "cumulated_cost": 0.820274
                      }
                    ],
                    "cost_of_reading_ranges": 0.820274,
                    "cost_of_mapping_rowid_in_non_clustered_pk_scan": 0.1,
                    "cost_sort_rowid_and_read_disk": 0.4375,
                    "use_roworder_index_merge": true, -- 根据上面结果选择了主键合并idx1的结果
                    "cause": "cost"
                  }
                ]
              }
            }
          },

greatsql> EXPLAIN SELECT * FROM t1 join t3 ON t1.c1=t3.ccc1 or t1.c2<5;
+----+-------------+-------+------------+------+-------------------+------+---------+------+------+----------+------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys     | key  | key_len | ref  | rows | filtered | Extra                                          |
+----+-------------+-------+------------+------+-------------------+------+---------+------+------+----------+------------------------------------------------+
|  1 | SIMPLE      | t3    | NULL       | ALL  | idx3_1            | NULL | NULL    | NULL |    5 |   100.00 | NULL                                           |
|  1 | SIMPLE      | t1    | NULL       | ALL  | PRIMARY,idx1,idx2 | NULL | NULL    | NULL |    7 |    42.85 | Range checked for each record (index map: 0x7) | -- 这里0x7指的是t1表的3条索引
+----+-------------+-------+------------+------+-------------------+------+---------+------+------+----------+------------------------------------------------+

-- 驱动表t3一共5条数据,每行记录都进行了一次test_quick_select()来查找t1是否有可用的更优索引

详细DYNAMIC RANGE执行过程如下表所示

t3.ccc1t1全表扫描costt1索引uniont1索引sort-union的costt1联合索引idx2t1范围扫描结果
13.8排序[PRIMARY,idx1,idx2], idx2加进去的cost太大放弃1.580271.71097无PRIMARY,idx1索引合并
23.8排序[PRIMARY,idx1,idx2], idx2的cost太大放弃1.580271.71097无PRIMARY,idx1索引合并
33.8排序[PRIMARY,idx1,idx2], idx2的cost太大放弃1.580271.71097无PRIMARY,idx1索引合并
43.8排序[PRIMARY,idx1,idx2], idx2的cost太大放弃1.580271.71097无PRIMARY,idx1索引合并
null3.8排序[idx1,idx2],cost太大, 不用合并idx1的cost太大,不用合并1.71097idx2 1.21183索引idx2
二、相关代码解释

DYNAMIC_RANGE 的判断在对表join排序以后执行make_join_query_block的时候,这时候要对非 join 第一张表做 recheck,recheck 以后有可能让表变为 DYNAMIC_RANGE 扫描方式。

static bool make_join_query_block(JOIN *join, Item *cond) {
        // 满足以下条件的需要进行RECHECK,要么是非第一张表要么是有limit语句
        if ((tab->type() == JT_ALL || tab->type() == JT_RANGE ||
             tab->type() == JT_INDEX_MERGE || tab->type() == JT_INDEX_SCAN) &&
            tab->use_quick != QS_RANGE) {
          if (cond &&                              // 1a
              (tab->keys() != tab->const_keys) &&  // 1b
              (i > 0 ||                            // 1c
               (join->query_block->master_query_expression()->item &&
                cond->is_outer_reference())))
            recheck_reason = NOT_FIRST_TABLE;
          else if (!tab->const_keys.is_clear_all() &&  // 2a
                   i == join->const_tables &&          // 2b
                   (join->query_expression()->select_limit_cnt <
                    (tab->position()->rows_fetched *
                     tab->position()->filter_effect)) &&  // 2c
                   !join->calc_found_rows)                // 2d
            recheck_reason = LOW_LIMIT;

        // 满足这个if条件的执行QS_DYNAMIC_RANGE,详情见下面几张表
          if (!tab->table()->quick_keys.is_subset(tab->checked_keys) ||
              !tab->needed_reg.is_subset(tab->checked_keys)) {
            tab->keys().merge(tab->table()->quick_keys);
            tab->keys().merge(tab->needed_reg);
            if (!tab->needed_reg.is_clear_all() &&
                (tab->table()->quick_keys.is_clear_all() ||
                 (tab->range_scan() &&
                  (tab->range_scan()->num_output_rows() >= 100.0)))) {
              tab->use_quick = QS_DYNAMIC_RANGE;
              tab->set_type(JT_ALL);
            } else
              tab->use_quick = QS_RANGE;
          }
        }
}
// 实际使用代码
bool DynamicRangeIterator::Init() {
  // 每次迭代器开始的时候先获取最佳索引组合和AccessPath
  AccessPath *range_scan;
  int rc = test_quick_select(&range_scan);
}

表一:需要进行 recheck 的原因

场景条件
非join表连接的第一张表存在针对这张表的条件
连接的第一张表没有第一张表的列与常量值的比较,limit值小于预估的满足条件的行数

表二:quick_type 类型

类型说明
QS_NONE不使用快速扫描
QS_RANGE使用范围扫描
QS_DYNAMIC_RANGE使用动态范围

表三:表用 QS_DYNAMIC_RANGE 的场合

条件(以下必须全部满足)说明
条件列存在索引有机会生成mm tree
keyuse_array数组没有值有值的话执行REF扫描,一般有OR条件时候导致该数组没有值
表没有对应的mm tree无法生成mm tree的条件
这张表不是join连接的第一张表
对表执行recheckrecheck的原因见表一
recheck以后生成AccessPath但是找到的范围内行数大于等于100行
三、实际例子说明

接下来看几个例子来说明上面的代码:

greatsql> EXPLAIN SELECT * FROM t1 join t3 ON t1.c1=t3.ccc1 or t1.c2<5;
+----+-------------+-------+------------+------+-------------------+------+---------+------+------+----------+------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys     | key  | key_len | ref  | rows | filtered | Extra                                          |
+----+-------------+-------+------------+------+-------------------+------+---------+------+------+----------+------------------------------------------------+
|  1 | SIMPLE      | t3    | NULL       | ALL  | idx3_1            | NULL | NULL    | NULL |    5 |   100.00 | NULL                                           |
|  1 | SIMPLE      | t1    | NULL       | ALL  | PRIMARY,idx1,idx2 | NULL | NULL    | NULL |    7 |    43.67 | Range checked for each record (index map: 0x7) |
+----+-------------+-------+------------+------+-------------------+------+---------+------+------+----------+------------------------------------------------+
-- 第一次对单表进行估计的时候t1.c1=t3.ccc1条件没有加入到mm tree,只对t1.c1打了一个标记MAYBE_KEY表示后面可能可以用到这个索引,因此最后没有生成mm tree,在make_join_query_block因为已经确定表连接顺序可以使用t1.c1=t3.ccc1条件,这时候可以把两个条件结合起来对t1执行mm tree,因此这个时候才生成mm tree,而这个时候才能考虑range scan和索引合并等操作。

t1 的 JOIN_TAB 的两个相关 key 变量,因此 keys() != const_keys

keyidx2(c2,date1)idx1(c2)primary(c1)说明
keys()111用来存放所有条件列涉及的key,这里指t1所有索引
const_keys110用来存放所有列与常量对比的key,这里指t1.c2<5

下面删除t1的一些数据,让join方式变为t1在前t3在后,这样的话对t1就不需要执行recheck,并且最后t1也通过索引进行扫描。

greatsql> DELETE FROM t1 WHERE c1 IN (7,8,11);
greatsql> EXPLAIN SELECT * FROM t1 JOIN t3 ON t1.c1=t3.ccc1 OR t1.c2<5;
+----+-------------+-------+------------+-------+-------------------+------+---------+------+------+----------+--------------------------------------------+
| id | select_type | table | partitions | type  | possible_keys     | key  | key_len | ref  | rows | filtered | Extra                                      |
+----+-------------+-------+------------+-------+-------------------+------+---------+------+------+----------+--------------------------------------------+
|  1 | SIMPLE      | t1    | NULL       | index | PRIMARY,idx1,idx2 | idx2 | 11      | NULL |    3 |   100.00 | Using index                                |
|  1 | SIMPLE      | t3    | NULL       | ALL   | idx3_1            | NULL | NULL    | NULL |   10 |   100.00 | Using where; Using join buffer (hash join) |
+----+-------------+-------+------------+-------+-------------------+------+---------+------+------+----------+--------------------------------------------+

下面执行一下三张表的连接,看到因为t1不是第一张表,最后用到了DYNAMIC RANGE

greatsql> INSERT INTO t1 VALUES (7,null,'2020-03-25 16:44:00.123456'),(8,10,'2020-10-25 16:44:00.123456'),(11,16,'2023-03-25 16:44:00.123456');
greatsql> EXPLAIN SELECT * FROM t1 join t3 join t2 ON t1.c1=t3.ccc1 and t1.c1=t2.cc1 or t1.c2<5 ;
+----+-------------+-------+------------+-------+-------------------+--------+---------+------+------+----------+------------------------------------------------+
| id | select_type | table | partitions | type  | possible_keys     | key    | key_len | ref  | rows | filtered | Extra                                          |
+----+-------------+-------+------------+-------+-------------------+--------+---------+------+------+----------+------------------------------------------------+
|  1 | SIMPLE      | t2    | NULL       | index | PRIMARY           | idx2_1 | 5       | NULL |    5 |   100.00 | Using index                                    |
|  1 | SIMPLE      | t1    | NULL       | ALL   | PRIMARY,idx1,idx2 | NULL   | NULL    | NULL |    7 |    42.85 | Range checked for each record (index map: 0x7) |
|  1 | SIMPLE      | t3    | NULL       | ALL   | idx3_1            | NULL   | NULL    | NULL |    5 |   100.00 | Using where; Using join buffer (hash join)     |
+----+-------------+-------+------------+-------+-------------------+--------+---------+------+------+----------+------------------------------------------------+

如果遇到 DYNAMIC RANGE 的情况,每行进行索引判断肯定比一开始就决定单纯走索引浪费时间,为了避免这种情况,可以采取以下的方法来避免。

1、强制让 DYNAMIC RANGE 的表作为驱动表

greatsql> EXPLAIN SELECT /*+ qb_name(qb1) JOIN_ORDER(@qb1 t1,t2,t3) */ * FROM t1 join t3 join t2 ON t1.c1=t3.ccc1 and t1.c1=t2.cc1 or t1.c2<5 ;
+----+-------------+-------+------------+-------+-------------------+--------+---------+------+------+----------+---------------------------------------------------------+
| id | select_type | table | partitions | type  | possible_keys     | key    | key_len | ref  | rows | filtered | Extra                                                   |
+----+-------------+-------+------------+-------+-------------------+--------+---------+------+------+----------+---------------------------------------------------------+
|  1 | SIMPLE      | t1    | NULL       | index | PRIMARY,idx1,idx2 | idx2   | 11      | NULL |    7 |   100.00 | Using index                                             |
|  1 | SIMPLE      | t2    | NULL       | index | PRIMARY           | idx2_1 | 5       | NULL |    5 |   100.00 | Using where; Using index; Using join buffer (hash join) |
|  1 | SIMPLE      | t3    | NULL       | ALL   | idx3_1            | NULL   | NULL    | NULL |    5 |   100.00 | Using where; Using join buffer (hash join)              |
+----+-------------+-------+------------+-------+-------------------+--------+---------+------+------+----------+---------------------------------------------------------+

2、给 DYNAMIC RANGE 的表强制指定索引

greatsql> EXPLAIN SELECT * FROM t1 FORCE INDEX(idx1,idx2) join t3 join t2 ON t1.c1=t3.ccc1 and t1.c1=t2.cc1 or t1.c2<5 ;
+----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+---------------------------------------------------------+
| id | select_type | table | partitions | type  | possible_keys | key    | key_len | ref  | rows | filtered | Extra                                                   |
+----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+---------------------------------------------------------+
|  1 | SIMPLE      | t2    | NULL       | index | PRIMARY       | idx2_1 | 5       | NULL |    5 |   100.00 | Using index                                             |
|  1 | SIMPLE      | t1    | NULL       | index | idx1,idx2     | idx2   | 11      | NULL |    7 |    42.85 | Using where; Using index; Using join buffer (hash join) |
|  1 | SIMPLE      | t3    | NULL       | ALL   | idx3_1        | NULL   | NULL    | NULL |    5 |   100.00 | Using where; Using join buffer (hash join)              |
+----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+---------------------------------------------------------+

3、改变条件,删除or条件,使用 keyuse_array 数组来选择路径。

greatsql> EXPLAIN SELECT * FROM t1 join t3 join t2 ON t1.c1=t3.ccc1 and t1.c1=t2.cc1;
+----+-------------+-------+------------+--------+---------------+---------+---------+------------+------+----------+-------------+
| id | select_type | table | partitions | type   | possible_keys | key     | key_len | ref        | rows | filtered | Extra       |
+----+-------------+-------+------------+--------+---------------+---------+---------+------------+------+----------+-------------+
|  1 | SIMPLE      | t2    | NULL       | index  | PRIMARY       | idx2_1  | 5       | NULL       |    5 |   100.00 | Using index |
|  1 | SIMPLE      | t3    | NULL       | ref    | idx3_1        | idx3_1  | 5       | db1.t2.cc1 |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t1    | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | db1.t2.cc1 |    1 |   100.00 | NULL        |
+----+-------------+-------+------------+--------+---------------+---------+---------+------------+------+----------+-------------+
四、总结

从上面关于 DYNAMIC RANGE 的解释我们知道这个状态需要经过一系列判断,并且只在特定条件才有可能出现,但是每行进行一次索引判断还是很消耗资源的,最好还是直接走索引,所以要尽量避免这种情况,适当的时候可以进行 SQL 命令干预。

2021-09-29 每天几个LCEDA小知识——如何交叉选择并阵列放置元器件 立创EDA专业版之交叉选择并阵列放置元器件????交叉选择????阵列放置 ????交叉选择 在原理图界面,先框选需要交叉选择的元器件对象,右键,选择交叉选择(如果熟练之后,直接选择元器件,快捷键Shift+X)。 完成上述操作之后,可以看到自动跳转到PCB绘图界面,并自动选定PCB中相关的元器件,接下来不要取消选择的状态,在相关元器件被选中的情况下,即可开展阵列放置,将这些元器件都放在一个区域,方便PCB画线前的布局工作。 ????阵列放置 在布局菜单栏中,选择分布,选择阵列分布, 在弹出的对话框 阅读详情

相关推荐

多目标进化算法——NSGA-II(python实现)

NSGA-II(python实现)--最全注释,痴呆能懂--

no___good的博客 5279

SQL调优之字符集-Range checked for each record (index map: 0x2)

目录 一、背景 二、复盘 三、参考文献 一、背景 项目中有些业务涉及到多个表的关联查询,每个表都有大量数据,因此查询起来很慢,需要对其进行优化。通过explain进行分析过程中发现,有个关联查询增加索引的字段居然没有起作用,并且有提示信息:Range checked for each record (index map: 0x2)。通过查询相关资料,发现是两个数据表字符集不匹配的问题。复盘如下: 二、复盘 测试环境准备: -- ---------------------------- -.

无痕之剑的书橱 7007

linux 4.19在龙芯平台上编译出错解决方法

OS: Loongnix server 1.7 工具链为:系统自带的gcc-4.8.5 和 gcc-7.3 平台:3A3000/3A4000 源码:kernel: 4.19 编译步骤 ··· make loongson3_defconfig make -j4 ··· 出错信息: HOSTCC arch/mips/boot/compressed/calc_vmlinuz_load_addr arch/mips/boot/compressed/head.S: Assembler messages: arch/m

sense的专栏 1125

SQL优化——Range checked for each record

百度了一下,这个原因是因为关联表的字符集不一致,导致索引失效,改为相同字符集之后效率大大增加。

Keep on moving! 1301

VS Code+ESP-IDF开发避坑指南:头文件标红报错的5种解决方法(附CMakeLists.txt配置)

本文详细解析了在VS Code中使用ESP-IDF开发ESP32时头文件标红报错的5种解决方法,包括环境配置检查、CMakeLists.txt规范配置、路径解析策略、缓存清理技巧和高级调试手段。特别提供了CMakeLists.txt的实战配置示例,帮助开发者彻底解决头文件路径问题,提升开发效率。

weixin_33670786的博客 560

保姆级教程:用海思PQTool搞定ISP图像调试,从参数读取到固件烧录全流程

本文提供海思PQTool的ISP图像调试全流程指南,从参数读取、实时调试到固件烧录,涵盖环境配置、核心功能解析、参数固化及生产部署。通过实战案例和避坑指南,帮助开发者高效提升图像质量,适用于海思开发板的ISP调试与优化。

weixin_30872337的博客 280

MySQL排序规则导致无法命中索引问题

MySQL 没有找到好的索引可以使用,但发现在知道前面表的列值后,可能会使用某些索引。在SQL的关联条件中,关联字段类型相同,并不是隐式类型转换问题导致无法命中索引,那么我们开始排查两表的字符集、排序规则是否一致。,不会出现因字符集不同导致隐式转换的问题,那么对比排序规则发现两表的排序规则是不同的,排序规则不一致时,但在key项中,却没有展示执行过程中命中的索引,而是扫描了全表,在Extra信息中,出现了。方案二:将原表重命名备份, 修改原建表语句为正确的排序规则,执行建表语句,而后使用。

FirstMrRight的博客 1800

Claude Code 完整学习笔记

Claude Code 学习笔记摘要 Claude Code是Anthropic推出的智能编码工具,基于Claude Opus 4.5模型构建,提供跨平台支持(终端/VS Code/JetBrains/Web等)。核心功能包括: 代码库理解与多文件编辑 命令执行与开发工具集成 智能体协作开发流程 安装要求Node.js≥18,提供原生/Homebrew/npm等多种安装方式,支持环境变量配置API访问。基础交互模式包括会话管理、文件操作和代码审查等功能,可自动读写文件并执行精确修改。 (149字)

虚心若愚 812

SQL调优—Range checked for each record (index map: 0x1)

问题 使用explain查看sql语句的执行计划,发现Extra给出了Range checked for each record (index map: 0x1)这个提示。 我写的sql语句是一个left join关联查询,关联其他表效率都正常,唯独关联其中一张表,就查询的特别慢,经过查找资料,终于发现,原来是关联查询的连接条件使用的字段,在mysql数据库中的排序方式设置的不一致: 统一两个关联字段的排序方式后,效率大幅提高。 ...

Keep on moving! 5904

抽象代数学习笔记(抽象代数的历史、运算)

1. 抽象代数历史 对于五次及以上的代数方程是否存在根式解这个问题,欧拉、拉格朗日、高斯等数学家都没得到答案,但是他们得出五次及以上的代数方程组不存在根式解的结论。19世纪初,阿贝尔提出五次及以上的代数方程不存在根式解,并找出一类特殊的五次及以上的代数方程可以用根式解表示出来。另外一个年轻的数学家伽罗华...

huangzhpei的博客 3668

捷联惯导,其实没有你想象的那么复杂!(附:惯导嵌入式应用中需要的一些C代码)

摘要:捷联惯导系统将惯性测量单元固连于运动载体,通过核心算法实现导航解算。系统首先进行传感器误差补偿和初始对准,然后利用陀螺和加速度计数据,通过姿态更新算法(如四元数法)计算载体相对于地理系的姿态。加速度数据经比力方程转换后积分得到速度和位置,过程中需补偿圆锥误差和划船效应。捷联惯导通过数字平台替代物理平台,实现了载体坐标系与导航坐标系的实时转换,是当前惯性导航系统的主流方案。

victoryqian528的博客 270

Range checked for each record (index map: 0x8)

sql优化

gdssgxf的博客 1014

2024年11月架构设计师案例分析真题回顾,附参考答案、解析及所涉知识点(二)

软考高级系统架构设计师考试包含三个科目:信息系统综合知识、案例分析和系统架构设计论文。考试形式为机考。本文主要回顾2024年下半年(2024-11-10)系统架构设计师考试上午第二科案例分析的题目,同时附带参考解答、解析和所涉知识点。

一几文的编程学习笔记。 1661

mysql 排序键导致不走索引Range checked for each record (index map: 0x80)

这两个字段字符集一样,但排序规则不一样,关联时候就会出现此时不走任何索引,每次关联都要全表扫描14440行,所以速度特别慢。

zjy9951的博客 609

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

MySQL技巧-EXPLAIN输出格式

MySQL技巧-EXPLAIN输出格式 如需转载请标明出处:http://blog.youkuaiyun.com/itas109 QQ技术交流群:12951803 环境: MySQL版本:5.5.15 操作系统:windows EXPLAIN语句提供了一个SELECT语句的执行计划信息。 EXPLAIN返回的一行信息在SELECT语句中使用的每个表。它列出的表中的顺序是,MySQL会读他们

itas109的专栏 1888

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Range checked for each record(index map: 0×2)

Range checked for each record(index map: 0×2)

baidu_38794249的博客 1411

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

mysql表关联的索引命中失败 range checked for each record

mysql表关联的索引命中失败和由此带来的思考 ###问题描述 最近翻了慢查询日志,大多数都是备份,夜晚的临时查询表生成,但是偶尔有几句是早年间留下的legend code留下的错误.有几个显示的问题 目前看来对于关联大表都要小心谨慎,尤其是关联条件的使用,本次出现的问题就在于join的on条件下过长导致的 虽然使用慢查询在生产环境中可以看到 LEFT JOIN orders o ON u.user_id = o.user_id and o.chain_id = ‘158’ and o.create_dat

南浦 3025

Mysql的性能优化问题

Using where; Using join buffer (Block Nested Loop) 建了索引却没有走索引,问题出在left join身上,left join改为 join既能解决问题。

weixin_46106438的博客 753

MySQL 优化 —— EXPLAIN 执行计划详解

引言 本博客总结自MySQL 官网Understanding the Query Execution Plan专题。 根据我们的表、字段、索引、以及 where 子句中的条件等信息,MySQL 优化器会考虑各种技术来更高效地执行查找。一个大表中的查找不一定要读取所有记录;多表连接也不一定需要比较每条联合记录。优化器选择的执行最优查询的操作集,称为“查询执行计划”,也可以说是 EXPLAIN...

Morty的技术乐园 4654

sql很慢,Range checked for each record (index map: 0x2)。最大数据表5000多条数据

生产问题: 问题列表 突然变慢了,首先检查 表关联 字段 都已经加上索引了(外键加了,主键没有重复加索引)。 执行计划: =====》去掉 多余的c2即可。 第二次这种问题了。加上多余关联表的初衷(去掉可能的脏数据:其实生产很少会有脏数据)。 还是性能要紧啊。 ...

anyway, life must全力以赴 7948

关于mysql中explain的那些事儿

explain语法 有两种用法: 1.EXPLAIN tbl_name 2.EXPLAIN [EXTENDED] SELECT select_options 为了更好的说明它,我们需要建两张表,下面的语句用于创建一张测试用的订单表: CREATETABLE`t_order`(`order_id`int(10)...

weixin_33901641的博客 244

MySQL中explain执行计划中额外信息字段(Extra)详解

SQL执行计划是经过优化器决策,产生的SQL在数据库内部执行的访问路径计划; 由如下语法得到:explain select col1,col2 from t1..; desc select col1,col2 from t1..;理解输出各个列的含义 id:每个select子句的标识id select_type:select语句的类型 table:当前表名 显示查询将访问的分区,如果你的查询是基于

poxiaonie的博客 6万+

MySQL EXPLAIN Output Format

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34146410的博客 226

mysql优化--explain--结果参数--02

一、数据准备 DROP TABLE IF EXISTS `course`; CREATE TABLE `course` ( `id` int(0) NOT NULL AUTO_INCREMENT COMMENT '主键id,自增涨', `name` varchar(20) DEFAULT NULL COMMENT '课程名称', `teacher_id` int(0) NULL DEFAULT NULL COMMENT '教师ID', PRIMARY KEY (`id`) USIN

zhou920786312的博客 602

Explain分析sql语句的性能

EXPLAIN语法(获取SELECT相关信息) EXPLAIN tbl_name 或: EXPLAIN [EXTENDED] SELECT select_options EXPLAIN 语句可以用作DESCRIBE 的一个同义词,或获得关于MySQL 如何执行SELECT 语句的信息: · EXPLAIN tbl_name 是DESCRIBE tbl_name

xubo_zhang的专栏 3539

五、MySql索引基本介绍

上篇文章介绍了查询命令中过慢的语句,总结原因如下: 查询命令过慢的原因: 在执行时需要对所有的数据来进行排序 在执行时需要对表中所有数据进行遍历 通过I/O流加载表文件次数 索引介绍: 【定义】: 索引存在于对应的索引文件中,索引本质就是排好了顺序的一组数据 【作用】: 在索引数据中进行排序时,避免再次排序 在索引数据中对数据行进行定位时,可以避免全表扫面 【索引文件位置】: 如果当前的表依赖于innodb存储引擎,索引存在于FRM文件中 如果当前的表依赖于myisam存储引擎,所以.

Jian Sun_的博客 1323
上一篇: 优化GreatSQL日志文件空间占用
下一篇: GreatSQL 为何选择全表扫描而不选索引
GreatSQL社区
博客等级 码龄5年 1210粉丝 390原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值