cost量化分析

Caddy2 vs Nginx:HTTP基础认证配置对比及性能实测(附避坑指南) 本文详细对比了Caddy2与Nginx在HTTP基础认证(Basic Authentication)配置上的差异及性能表现。通过实战配置示例和性能测试数据,帮助开发者选择适合的Web服务器,并提供了安全优化和常见问题排查的实用指南。 阅读详情
  • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
  • GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。
  • 作者: xryz
  • 文章来源:GreatSQL社区原创

前言:

我们在日常维护数据库的时候,经常会遇到查询慢的语句,这时候一般会通过执行EXPLAIN去查看它的执行计划,但是执行计划往往只给我们带来了最基础的分析信息,比如是否有使用索引,还有一些其他供我们分析的信息,比如使用了临时表、排序等等,却无法展示为什么一些其他的执行计划未被选择,比如说明明有索引,或者好几个索引,但是为什么查询时未使用到期望的索引等

explain select * from basic_person_info t1 join basic_person_info2 t2 on t1.id_num=t2.id_num where t1.age >10 and t2.age<20;
+----+-------------+-------+------------+--------+--------------------------------------+---------------+---------+----------------+------+----------+-----------------------+
| id | select_type | table | partitions | type   | possible_keys                        | key           | key_len | ref            | rows | filtered | Extra                 |
+----+-------------+-------+------------+--------+--------------------------------------+---------------+---------+----------------+------+----------+-----------------------+
|  1 | SIMPLE      | t2    | NULL       | range  | id_num_unique,idx_age,idx_age_id_num | idx_age       | 1       | NULL           | 9594 |   100.00 | Using index condition |
|  1 | SIMPLE      | t1    | NULL       | eq_ref | id_num_unique,idx_age                | id_num_unique | 60      | test.t2.id_num |    1 |    50.00 | Using where           |
+----+-------------+-------+------------+--------+--------------------------------------+---------------+---------+----------------+------+----------+-----------------------+
2 rows in set, 1 warning (0.01 sec)

如上面这个例子,为什么t2表上列出了多个可能使用的索引,却选择了idx_age,优化器为什么选择了指定的索引,这时候并不能直观的看出问题,这时候我们就可以开启optimizer_trace跟踪分析MySQL具体是怎么选择出最优的执行计划的。

OPTIMIZER_TRACE:

optimizer_trace是什么:

optimizer_trace是一个具有跟踪功能的工具,可以跟踪执行的语句的解析优化执行过程,并将跟踪到的信息记录到INFORMATION_SCHEMA.OPTIMIZER_TRACE表中,但是每个会话都只能跟踪它自己执行的语句,并且表中默认只记录最后一个查询的跟踪结果

使用方法:

# 打开optimizer trace功能 (默认情况下它是关闭的):
set optimizer_trace="enabled=on";
select ...; # 这里输入你自己的查询语句
SELECT * FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
# 当你停止查看语句的优化过程时,把optimizer trace功能关闭
set optimizer_trace="enabled=off";

相关参数:

mysql>  show variables like '%optimizer_trace%';
+------------------------------+----------------------------------------------------------------------------+
| Variable_name                | Value                                                                      |
+------------------------------+----------------------------------------------------------------------------+
| optimizer_trace              | enabled=on,one_line=off                                                    |
| optimizer_trace_features     | greedy_search=on,range_optimizer=on,dynamic_range=on,repeated_subselect=on |
| optimizer_trace_limit        | 1                                                                          |
| optimizer_trace_max_mem_size | 1048576                                                                    |
| optimizer_trace_offset       | -1                                                                         |
+------------------------------+----------------------------------------------------------------------------+
  • optimizer_trace: enabled 开启/关闭optimizer_trace,one_line 是否单行显示,关闭为json模式,一般不开启
  • optimizer_trace_features:跟踪信息中可打印的项,一般不调整默认打印所有项
  • optimizer_trace_limit:存储的跟踪sql条数
  • optimizer_trace_offset:开始记录的sql语句的偏移量,负数表示从最近执行倒数第几条开始记录
  • optimizer_trace_max_mem_size:optimizer_trace内存的大小,如果跟踪信息超过这个大小,信息将会被截断

optimizer_trace表信息:

该表总共有4个字段

  • QUERY 表示我们的查询语句。
  • TRACE 表示优化过程的JSON格式文本。(重点关注)
  • MISSING_BYTES_BEYOND_MAX_MEM_SIZE 由于优化过程可能会输出很多,如果超过某个限制时,多余的文本将不会被显示,这个字段展示了被忽略的文本字节数。
  • INSUFFICIENT_PRIVILEGES 表示是否没有权限查看优化过程,默认值是0,只有某些特殊情况下才会是 1,我们暂时不关心这个字段的值。

信息解读:

通过 optimizer_trace表的query字段可以看到,一条语句的执行过程主要分为三个步骤:

"join_preparation": {},(准备阶段)
"join_optimization": {},(优化阶段)
"join_execution": {},(执行阶段)

各个步骤的详细内容解读:

  • preparation:
expanded_query :将语句进行格式化,补充隐藏的列名和表名等
transformations_to_nested_joins :查询重写,比如join的on改为where语句
  • optimization:
condition_processing{ :条件句处理。
    transformation{:转换类型句。这三次的转换分别是
        equality_propagation(等值条件句转换),如:a = b and b = c and c = 5
        constant_propagation(常量条件句转换),如:a = 1 AND b > a
        trivial_condition_removal(无效条件移除的转换),如:1 = 1
    }
}
substitute_generated_columns :替换虚拟生成列,测试了很多sql,这一列都没有看到有用的信息
table_dependencies :梳理表之间的依赖关系。
ref_optimizer_key_uses :如果优化器认为查询可以使用ref的话,在这里列出可以使用的索引。
rows_estimation{ :估算表行数和扫描的代价。如果查询中存在range扫描的话,对range扫描进行计划分析及代价估算。
  table_scan:全表扫描的行数(rows)以及所需要的代价(cost)。
  potential_range_indexes:该阶段会列出表中所有的索引并分析其是否可用,并且还会列出索引中可用的列字段。
  analyzing_range_alternatives :分析可选方案的代价。
}
considered_execution_plans{ :对比各可行计划的代价,选择相对最优的执行计划。
  plan_prefix:前置的执行计划。
  best_access_path:当前最优的执行顺序信息结果集。
  access_type表示使用索引的方式,可参照为explain中的type字段。
  condition_filtering_pct:类似于explain中的filtered列,这是一个估算值。
  rows_for_plan:该执行计划最终的扫描行数,这里的行数其实也是估算值,是由considered_access_paths的resulting_rows相乘之后再乘以condition_filtering_pct获得。
  cost_for_plan:该执行计划的执行代价,由considered_access_paths的cost相加而得。
  chosen:是否选择了该执行计划。
}
attaching_conditions_to_tables :添加附加条件,使得条件尽可能筛选单表数据。
refine_plan :优化后的执行计划。

trace信息中的json信息很长,因为我们关心的是不同执行计划的cost区别,所以只需要重点关注两个部分rows_estimation 和considered_execution_plans

代价模型计算:

统计信息和cost计算参数:

计算cost会涉及到表的主键索引数据页(聚簇索引)数量和表中的记录数,两个信息都可以通过innodb的表统计信息mysql.innodb_table_stats查到,n_rows是记录数,clustered_index_size是聚簇索引页数。

mysql> select * from mysql.innodb_table_stats where table_name='basic_person_info';
+---------------+-------------------+---------------------+--------+----------------------+--------------------------+
| database_name | table_name        | last_update         | n_rows | clustered_index_size | sum_of_other_index_sizes |
+---------------+-------------------+---------------------+--------+----------------------+--------------------------+
| test          | basic_person_info | 2022-12-23 18:27:24 |  86632 |                  737 |                     1401 |
+---------------+-------------------+---------------------+--------+----------------------+--------------------------+
1 row in set (0.01 sec)

代价模型将操作分为Server层和Engine(存储引擎)层两类,Server层主要是CPU代价,Engine层主要是IO代价,比如MySQL从磁盘读取一个数据页的代价io_block_read_cost为1,从buffer pool读取的代价memory_block_read_cost为0.25,计算符合条件的行代价为row_evaluate_cost为0.1,除此之外还有:

  • memory_temptable_create_cost (default 1.0) 内存临时表的创建代价。
  • memory_temptable_row_cost (default 0.1) 内存临时表的行代价。
  • key_compare_cost (default 0.1) 键比较的代价,例如排序。
  • disk_temptable_create_cost (default 20.0) 内部myisam或innodb临时表的创建代价。
  • disk_temptable_row_cost (default 0.5) 内部myisam或innodb临时表的行代价。

这些都可以通过mysql.server_cost、mysql.engine_cost查看defalt值和设置值

mysql> select * from mysql.server_cost;
+------------------------------+------------+---------------------+---------+---------------+
| cost_name                    | cost_value | last_update         | comment | default_value |
+------------------------------+------------+---------------------+---------+---------------+
| disk_temptable_create_cost   |       NULL | 2022-05-11 16:09:37 | NULL    |            20 |
| disk_temptable_row_cost      |       NULL | 2022-05-11 16:09:37 | NULL    |           0.5 |
| key_compare_cost             |       NULL | 2022-05-11 16:09:37 | NULL    |          0.05 |
| memory_temptable_create_cost |       NULL | 2022-05-11 16:09:37 | NULL    |             1 |
| memory_temptable_row_cost    |       NULL | 2022-05-11 16:09:37 | NULL    |           0.1 |
| row_evaluate_cost            |       NULL | 2022-05-11 16:09:37 | NULL    |           0.1 |
+------------------------------+------------+---------------------+---------+---------------+
mysql> select * from mysql.engine_cost;
+-------------+-------------+------------------------+------------+---------------------+---------+---------------+
| engine_name | device_type | cost_name              | cost_value | last_update         | comment | default_value |
+-------------+-------------+------------------------+------------+---------------------+---------+---------------+
| default     |           0 | io_block_read_cost     |       NULL | 2022-05-11 16:09:37 | NULL    |             1 |
| default     |           0 | memory_block_read_cost |       NULL | 2023-01-09 11:17:39 | NULL    |          0.25 |
+-------------+-------------+------------------------+------------+---------------------+---------+---------------+
计算公式:

如上面介绍的一样,代价模型将操作分为两类io_cost和cpu_cost,io_cost+cpu_cost就是总的cost,下面是具体的计算方法:

全表扫描:

全表扫描成本 = io_cost + 1.1 + cpu_cost + 1 (io_cost +1.1和cpu_cost +1在代码里是直接硬加上的,不知道为什么,计算的时候直接加上)

io_cost = clustered_index_size (统计信息中的主键页数) * avg_single_page_cost(读取一个页的平均成本)

avg_single_page_cost = pages_in_memory_percent * 0.25(memory_block_read_cost) + pages_on_disk_percent * 1.0(io_block_read_cost)

pages_in_memory_percent 表示已经加载到 Buffer Pool 中的叶结点占所有叶结点的比例 pages_on_disk_percent 表示没有加载到 Buffer Pool 中的叶结点占所有叶结点的比例

所以当数据已经全部读取到buffer pool中的时候:

io_cost=clustered_index_size * 0.25

都没有读取到buffer pool中的时候:

io_cost=clustered_index_size * 1.0

当部分数据在buffer pool中,部分数据需要从磁盘读取时,这时的系数介于0.25到1之间

cpu_cost = n_rows(统计信息中记录数) * 0.1(row_evaluate_cost)

走索引的成本:

和全表扫描的计算方法类似,其中io_cost与搜索的区间数有关,比如扫描三个区间where a between 1 and 10 or a between 20 and 30 or a between 40 and 50,此时:

io_cost=3 * avg_single_page_cost

cpu_cost=记录数 * 0.1(row_evaluate_cost)+0.01(代码中的微调参数)

针对二级索引还会有回表的操作:

MySQL认为每次回表都相当于是访问一个页面,所以每次回表都会进行一次IO,这部分成本:

io_cost=rows(记录数)*avg_single_page_cost

对回表查询的数据还需要进行一次计算:

cpu_cost=rows(记录数) * 0.1(row_evaluate_cost)(需要注意的是当索引需要回表扫描时,在rows_estimation阶段并不会计算这个值,在considered_execution_plans阶段会重新加上这部分成本)

所以针对需要回表的查询:

io_cost=查询区间 * avg_single_page_cost + rows(记录数) * avg_single_page_cost

cpu_cost=记录数 * 0.1(row_evaluate_cost) + 0.01(代码中的微调参数) + rows(记录数) * 0.1(row_evaluate_cost)

例子:

mysql> set optimizer_trace='enabled=on';
Query OK, 0 rows affected (0.00 sec)

mysql>explain select * from basic_person_info t1 join basic_person_info2 t2 on t1.id_num=t2.id_num where t1.age >10 and t2.age<20;
+----+-------------+-------+------------+--------+--------------------------------------+---------------+---------+----------------+------+----------+-----------------------+
| id | select_type | table | partitions | type   | possible_keys                        | key           | key_len | ref            | rows | filtered | Extra                 |
+----+-------------+-------+------------+--------+--------------------------------------+---------------+---------+----------------+------+----------+-----------------------+
|  1 | SIMPLE      | t2    | NULL       | range  | id_num_unique,idx_age,idx_age_id_num | idx_age       | 1       | NULL           | 9594 |   100.00 | Using index condition |
|  1 | SIMPLE      | t1    | NULL       | eq_ref | id_num_unique,idx_age                | id_num_unique | 60      | test.t2.id_num |    1 |    50.00 | Using where           |
+----+-------------+-------+------------+--------+--------------------------------------+---------------+---------+----------------+------+----------+-----------------------+
2 rows in set, 1 warning (0.04 sec)
查看optimizer_trace的内容
select * from basic_person_info t1 join basic_person_info2 t2 on t1.id_num=t2.id_num where t1.age >10 and t2.age<20 | {
  "steps": [
    {
      "join_preparation": {
        "select#": 1,
        "steps": [
          {
            "expanded_query": "/* select#1 */ select `t1`.`id` AS `id`,`t1`.`id_num` AS `id_num`,`t1`.`lastname` AS `lastname`,`t1`.`firstname` AS `firstname`,`t1`.`mobile` AS `mobile`,`t1`.`sex` AS `sex`,`t1`.`birthday` AS `birthday`,`t1`.`age` AS `age`,`t1`.`top_education` AS `top_education`,`t1`.`address` AS `address`,`t1`.`income_by_year` AS `income_by_year`,`t1`.`create_time` AS `create_time`,`t1`.`update_time` AS `update_time`,`t2`.`id` AS `id`,`t2`.`id_num` AS `id_num`,`t2`.`lastname` AS `lastname`,`t2`.`firstname` AS `firstname`,`t2`.`mobile` AS `mobile`,`t2`.`sex` AS `sex`,`t2`.`birthday` AS `birthday`,`t2`.`age` AS `age`,`t2`.`top_education` AS `top_education`,`t2`.`address` AS `address`,`t2`.`income_by_year` AS `income_by_year`,`t2`.`create_time` AS `create_time`,`t2`.`update_time` AS `update_time` from (`basic_person_info` `t1` join `basic_person_info2` `t2` on((`t1`.`id_num` = `t2`.`id_num`))) where ((`t1`.`age` > 10) and (`t2`.`age` < 20))"
          },
          {
            "transformations_to_nested_joins": {
              "transformations": [
                "JOIN_condition_to_WHERE",
                "parenthesis_removal"
              ],
              "expanded_query": "/* select#1 */ select `t1`.`id` AS `id`,`t1`.`id_num` AS `id_num`,`t1`.`lastname` AS `lastname`,`t1`.`firstname` AS `firstname`,`t1`.`mobile` AS `mobile`,`t1`.`sex` AS `sex`,`t1`.`birthday` AS `birthday`,`t1`.`age` AS `age`,`t1`.`top_education` AS `top_education`,`t1`.`address` AS `address`,`t1`.`income_by_year` AS `income_by_year`,`t1`.`create_time` AS `create_time`,`t1`.`update_time` AS `update_time`,`t2`.`id` AS `id`,`t2`.`id_num` AS `id_num`,`t2`.`lastname` AS `lastname`,`t2`.`firstname` AS `firstname`,`t2`.`mobile` AS `mobile`,`t2`.`sex` AS `sex`,`t2`.`birthday` AS `birthday`,`t2`.`age` AS `age`,`t2`.`top_education` AS `top_education`,`t2`.`address` AS `address`,`t2`.`income_by_year` AS `income_by_year`,`t2`.`create_time` AS `create_time`,`t2`.`update_time` AS `update_time` from `basic_person_info` `t1` join `basic_person_info2` `t2` where ((`t1`.`age` > 10) and (`t2`.`age` < 20) and (`t1`.`id_num` = `t2`.`id_num`))"
            }
          }
        ]
      }
    },
    {
      "join_optimization": {
        "select#": 1,
        "steps": [
          {
            "condition_processing": {
              "condition": "WHERE",
              "original_condition": "((`t1`.`age` > 10) and (`t2`.`age` < 20) and (`t1`.`id_num` = `t2`.`id_num`))",
              "steps": [
                {
                  "transformation": "equality_propagation",
                  "resulting_condition": "((`t1`.`age` > 10) and (`t2`.`age` < 20) and multiple equal(`t1`.`id_num`, `t2`.`id_num`))"
                },
                {
                  "transformation": "constant_propagation",
                  "resulting_condition": "((`t1`.`age` > 10) and (`t2`.`age` < 20) and multiple equal(`t1`.`id_num`, `t2`.`id_num`))"
                },
                {
                  "transformation": "trivial_condition_removal",
                  "resulting_condition": "((`t1`.`age` > 10) and (`t2`.`age` < 20) and multiple equal(`t1`.`id_num`, `t2`.`id_num`))"
                }
              ]
            }
          },
          {
            "substitute_generated_columns": {
            }
          },
          {
            "table_dependencies": [
              {
                "table": "`basic_person_info` `t1`",
                "row_may_be_null": false,
                "map_bit": 0,
                "depends_on_map_bits": [
                ]
              },
              {
                "table": "`basic_person_info2` `t2`",
                "row_may_be_null": false,
                "map_bit": 1,
                "depends_on_map_bits": [
                ]
              }
            ]
          },
          {
            "ref_optimizer_key_uses": [
              {
                "table": "`basic_person_info` `t1`",
                "field": "id_num",
                "equals": "`t2`.`id_num`",
                "null_rejecting": true
              },
              {
                "table": "`basic_person_info2` `t2`",
                "field": "id_num",
                "equals": "`t1`.`id_num`",
                "null_rejecting": true
              }
            ]
          },
          {
            "rows_estimation": [
              {
                "table": "`basic_person_info` `t1`",
                "range_analysis": {
                  "table_scan": {
                    "rows": 86734,
                    "cost": 8859.75

                    t1表的scan成本=聚簇索引页数*0.25 + 行数 * 0.1 +1.1+1
                    737*0.25+1.1+86734*0.1+1=8859.75

                  },
                  "potential_range_indexes": [
                    {
                      "index": "PRIMARY",
                      "usable": false,
                      "cause": "not_applicable"
                    },
                    {
                      "index": "id_num_unique",
                      "usable": false,
                      "cause": "not_applicable"
                    },
                    {
                      "index": "mobile_unique",
                      "usable": false,
                      "cause": "not_applicable"
                    },
                    {
                      "index": "idx_basic_person_info_name",
                      "usable": false,
                      "cause": "not_applicable"
                    },
                    {
                      "index": "idx_basic_person_info_top_education",
                      "usable": false,
                      "cause": "not_applicable"
                    },
                    {
                      "index": "idx_basic_person_info_create_time",
                      "usable": false,
                      "cause": "not_applicable"
                    },
                    {
                      "index": "idx_basic_person_info_mobile",
                      "usable": false,
                      "cause": "not_applicable"
                    },
                    {
                      "index": "idx_age",
                      "usable": true,
                      "key_parts": [
                        "age",
                        "id"
                      ]
                    }
                  ],
                  "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": [
                      {
                        "index": "idx_age",
                        "ranges": [
                          "10 < age"
                        ],
                        "index_dives_for_eq_ranges": true,
                        "rowid_ordered": false,
                        "using_mrr": false,
                        "index_only": false,
                        "rows": 43367,
                        "cost": 15178.7,

                        通过索引idx_age读取数据:
                        io_cost=区间数* 0.25 +记录数* 0.25
                        io_cost=1*0.25+43367*0.25=10,842  
                        cpu_cost=记录数* 0.1 (没有回表的cost)
                        cpu_cost=43367*0.1=4,336.7 
                        cost=10842+4,336.7=15178.7

                        "chosen": false,
                        "cause": "cost"
                      }
                    ],
                    "analyzing_roworder_intersect": {
                      "usable": false,
                      "cause": "too_few_roworder_scans"
                    }
                  }
                }
              },
              {
                "table": "`basic_person_info2` `t2`",
                "range_analysis": {
                  "table_scan": {
                    "rows": 73845,
                    "cost": 7538.85

                    t2表的scan成本=聚簇索引页数*0.25 + 行数 * 0.1 +1.1+1
                    609*0.25+1+73845*0.1+1.1=7538.85

                  },
                  "potential_range_indexes": [
                    {
                      "index": "PRIMARY",
                      "usable": false,
                      "cause": "not_applicable"
                    },
                    {
                      "index": "id_num_unique",
                      "usable": false,
                      "cause": "not_applicable"
                    },
                    {
                      "index": "mobile_unique",
                      "usable": false,
                      "cause": "not_applicable"
                    },
                    {
                      "index": "idx_basic_person_info_name",
                      "usable": false,
                      "cause": "not_applicable"
                    },
                    {
                      "index": "idx_basic_person_info_top_education",
                      "usable": false,
                      "cause": "not_applicable"
                    },
                    {
                      "index": "idx_basic_person_info_create_time",
                      "usable": false,
                      "cause": "not_applicable"
                    },
                    {
                      "index": "idx_basic_person_info_mobile",
                      "usable": false,
                      "cause": "not_applicable"
                    },
                    {
                      "index": "idx_age",
                      "usable": true,
                      "key_parts": [
                        "age",
                        "id"
                      ]
                    },
                    {
                      "index": "idx_age_id_num",
                      "usable": true,
                      "key_parts": [
                        "age",
                        "id_num",
                        "id"
                      ]
                    }
                  ],
                  "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": [
                      {
                        "index": "idx_age",
                        "ranges": [
                          "age < 20"
                        ],
                        "index_dives_for_eq_ranges": true,
                        "rowid_ordered": false,
                        "using_mrr": false,
                        "index_only": false,
                        "rows": 9594,
                        "cost": 3358.16,

                        通过索引idx_age读取数据:
                        io_cost=区间数* 0.25 +记录数* 0.25
                        io_cost=1*0.25+9594*0.25=2,398.75        
                        cpu_cost=记录数* 0.1   (没有回表的cost) 
                        cpu_cost=9594*0.1959.4  
                        cost=2,398.75+959.4=3,358.15

                        "chosen": true
                      },
                      {
                        "index": "idx_age_id_num",
                        "ranges": [
                          "age < 20"
                        ],
                        "index_dives_for_eq_ranges": true,
                        "rowid_ordered": false,
                        "using_mrr": false,
                        "index_only": false,
                        "rows": 19086,
                        "cost": 6680.36,

                        通过索引idx_age_id_num读取数据:
                        io_cost=区间数* 0.25 +记录数* 0.25
                        io_cost=1*0.25+19086*0.25=4,771.75           
                        cpu_cost=记录数* 0.1  (没有回表的cost)  
                        cpu_cost=19086*0.1=1908.6
                        cost=4,771.75+1908.6=6,680.35

                        "chosen": false,
                        "cause": "cost"
                      }
                    ],
                    "analyzing_roworder_intersect": {
                      "usable": false,
                      "cause": "too_few_roworder_scans"
                    }
                  },
                  "chosen_range_access_summary": {
                    "range_access_plan": {
                      "type": "range_scan",
                      "index": "idx_age",
                      "rows": 9594,
                      "ranges": [
                        "age < 20"
                      ]
                    },
                    "rows_for_plan": 9594,
                    "cost_for_plan": 3358.16,
                    "chosen": true
                  }
                }
              }
            ]
          },
          {
            "considered_execution_plans": [
              {
                "plan_prefix": [
                ],
                "table": "`basic_person_info2` `t2`",
                "best_access_path": {
                  "considered_access_paths": [
                    {
                      "access_type": "ref",
                      "index": "id_num_unique",
                      "usable": false,
                      "chosen": false
                    },
                    {
                      "rows_to_scan": 9594,
                      "filtering_effect": [
                      ],
                      "final_filtering_effect": 1,
                      "access_type": "range",
                      "range_details": {
                        "used_index": "idx_age"
                      },
                      "resulting_rows": 9594,
                      "cost": 4317.56,

                        通过索引idx_age读取数据:
                        io_cost=区间数* 0.25 +记录数* 0.25
                        io_cost=1*0.25+9594*0.25=2,398.75        
                        cpu_cost=记录数* 0.1 + 记录数* 0.1   
                        cpu_cost=9594*0.1*2=1,918.8  
                        cost=2,398.75+1,918.8=4317.56

                      "chosen": true
                    }
                  ]
                },
                "condition_filtering_pct": 100,
                "rows_for_plan": 9594,
                "cost_for_plan": 4317.56,
                "rest_of_plan": [
                  {
                    "plan_prefix": [
                      "`basic_person_info2` `t2`"
                    ],
                    "table": "`basic_person_info` `t1`",
                    "best_access_path": {
                      "considered_access_paths": [
                        {
                          "access_type": "eq_ref",
                          "index": "id_num_unique",
                          "rows": 1,
                          "cost": 3357.9,

                          io_cost=t2表记录数*0.25=9594*0.25=2398.5
                          cpu_cost=记录数*0.1=9594*0.1=959.4
                          cost=2398.5+959.4=3357.9

                          "chosen": true
                        },
                        {
                          "rows_to_scan": 86734,
                          "filtering_effect": [
                          ],
                          "final_filtering_effect": 0.5,
                          "access_type": "scan",
                          "using_join_cache": true,
                          "buffers_needed": 14,
                          "resulting_rows": 43367,
                          "cost": 4.16701e+07,
                          "chosen": false
                        }
                      ]
                    },
                    "condition_filtering_pct": 100,
                    "rows_for_plan": 9594,
                    "cost_for_plan": 7675.46,

                   总cost=4,317.56+3,357.9=7,675.46

                    "chosen": true
                  }
                ]
              },
              {
                "plan_prefix": [
                ],
                "table": "`basic_person_info` `t1`",
                "best_access_path": {
                  "considered_access_paths": [
                    {
                      "access_type": "ref",
                      "index": "id_num_unique",
                      "usable": false,
                      "chosen": false
                    },
                    {
                      "rows_to_scan": 86734,
                      "filtering_effect": [
                      ],
                      "final_filtering_effect": 0.5,
                      "access_type": "scan",
                      "resulting_rows": 43367,
                      "cost": 8857.65,

                      t1的scan成本

                      "chosen": true
                    }
                  ]
                },
                "condition_filtering_pct": 100,
                "rows_for_plan": 43367,
                "cost_for_plan": 8857.65,
                "pruned_by_cost": true

                放弃后续的计算

              }
            ]
          },
          {
            "attaching_conditions_to_tables": {
              "original_condition": "((`t1`.`id_num` = `t2`.`id_num`) and (`t1`.`age` > 10) and (`t2`.`age` < 20))",
              "attached_conditions_computation": [
              ],
              "attached_conditions_summary": [
                {
                  "table": "`basic_person_info2` `t2`",
                  "attached": "(`t2`.`age` < 20)"
                },
                {
                  "table": "`basic_person_info` `t1`",
                  "attached": "((`t1`.`id_num` = `t2`.`id_num`) and (`t1`.`age` > 10))"
                }
              ]
            }
          },
          {
            "finalizing_table_conditions": [
              {
                "table": "`basic_person_info2` `t2`",
                "original_table_condition": "(`t2`.`age` < 20)",
                "final_table_condition   ": "(`t2`.`age` < 20)"
              },
              {
                "table": "`basic_person_info` `t1`",
                "original_table_condition": "((`t1`.`id_num` = `t2`.`id_num`) and (`t1`.`age` > 10))",
                "final_table_condition   ": "(`t1`.`age` > 10)"
              }
            ]
          },
          {
            "refine_plan": [
              {
                "table": "`basic_person_info2` `t2`",
                "pushed_index_condition": "(`t2`.`age` < 20)",
                "table_condition_attached": null
              },
              {
                "table": "`basic_person_info` `t1`"
              }
            ]
          }
        ]
      }
    },
    {
      "join_execution": {
        "select#": 1,
        "steps": [
        ]
      }
    }
  ]
}
成本常数修改:

前面已经介绍了成本常量值实际上存放在MySQL自带的系统库MySQL中的server_cost和engine_cost表中,其中server_cost表存放server层的成本常量,engine_cost表存放engine层成本常量

mysql> select * from mysql.server_cost;
+------------------------------+------------+---------------------+---------+---------------+
| cost_name                    | cost_value | last_update         | comment | default_value |
+------------------------------+------------+---------------------+---------+---------------+
| disk_temptable_create_cost   |       NULL | 2022-05-11 16:09:37 | NULL    |            20 |
| disk_temptable_row_cost      |       NULL | 2022-05-11 16:09:37 | NULL    |           0.5 |
| key_compare_cost             |       NULL | 2022-05-11 16:09:37 | NULL    |          0.05 |
| memory_temptable_create_cost |       NULL | 2022-05-11 16:09:37 | NULL    |             1 |
| memory_temptable_row_cost    |       NULL | 2022-05-11 16:09:37 | NULL    |           0.1 |
| row_evaluate_cost            |       NULL | 2022-05-11 16:09:37 | NULL    |           0.1 |
+------------------------------+------------+---------------------+---------+---------------+

mysql> select * from mysql.engine_cost;
+-------------+-------------+------------------------+------------+---------------------+---------+---------------+
| engine_name | device_type | cost_name              | cost_value | last_update         | comment | default_value |
+-------------+-------------+------------------------+------------+---------------------+---------+---------------+
| default     |           0 | io_block_read_cost     |       NULL | 2022-05-11 16:09:37 | NULL    |             1 |
| default     |           0 | memory_block_read_cost |       NULL | 2023-01-09 11:17:39 | NULL    |          0.25 |
+-------------+-------------+------------------------+------------+---------------------+---------+---------------+

其中 default_value的值是系统默认的,不能修改,cost_value列的值我们可以修改,如果cost_value列的值不为空系统将用该值覆盖默认值,我们可以通过update语句来修改

mysql> update mysql.engine_cost set cost_value=10 where cost_name='memory_block_read_cost';
Query OK, 0 rows affected (0.00 sec)
mysql> update mysql.engine_cost set cost_value=10 where cost_name='io_block_read_cost';
Query OK, 0 rows affected (0.00 sec)

很多资料都说执行flush optimizer_costs就可以生效,不过我在修改完后并执行flush optimizer_costs并不能马上生效,最后是通过重启数据库实例才生效,这个可能是数据库版本的差异,大家可以自行验证。

mysql> explain select * from basic_person_info t1 join basic_person_info2 t2 on t1.id_num=t2.id_num where t1.age >10 and t2.age<20;
+----+-------------+-------+------------+--------+--------------------------------------+---------------+---------+----------------+-------+----------+-------------+
| id | select_type | table | partitions | type   | possible_keys                        | key           | key_len | ref            | rows  | filtered | Extra       |
+----+-------------+-------+------------+--------+--------------------------------------+---------------+---------+----------------+-------+----------+-------------+
|  1 | SIMPLE      | t2    | NULL       | ALL    | id_num_unique,idx_age,idx_age_id_num | NULL          | NULL    | NULL           | 73990 |    12.97 | Using where |
|  1 | SIMPLE      | t1    | NULL       | eq_ref | id_num_unique,idx_age                | id_num_unique | 60      | test.t2.id_num |     1 |    50.00 | Using where |
+----+-------------+-------+------------+--------+--------------------------------------+---------------+---------+----------------+-------+----------+-------------+

"table": "`basic_person_info2` `t2`",
                "range_analysis": {
                  "table_scan": {
                    "rows": 73990,
                    "cost": 13491.1

                   全表扫描cost=609*10+73990*0.1+1.1+1= 13491.1

                  },
"index": "idx_age",
                        "ranges": [
                          "age < 20"
                        ],
                        "index_dives_for_eq_ranges": true,
                        "rowid_ordered": false,
                        "using_mrr": false,
                        "index_only": false,
                        "rows": 9594,
                        "cost": 96909.4,

                        idx_age索引扫描cost=1*10+9594*10+9594*0.1=96,909.4

                        "chosen": false,
                        "cause": "cost"
                      },

修改后的执行计划,发现t2表走了全表扫描了而没有走idx_age索引,分别查看一下t2表走全表扫描和idx_age索引的cost发现全表扫描的cost为13491.1,而走索引的cost为96,909.4,因为全表扫描的cost比走索引低,所以优化器没有选择idx_age索引。

从这个例子可以看出,更改成本常量值会直接影响优化器的方案选择,所以一定要慎重,没有特殊原因建议不要修改。

explain format=json

虽然通过optimizer_trace可以看到很多详细的优化器选择过程,但是使用起来起来还是比较麻烦,需要过滤的信息很多,这时explain format=json输出json格式的分析数据也是一个不错的选择,它也包含语句将要执行的成本信息,如下:

query_cost  总查询成本
read_cost   IO成本+除 eval_cost以外cpu成本
eval_cost   检测rows * filter条记录的成本
prefix_cost 单次查询的成本,等于read_cost+eval_cost
mysql> explain format=json select * from basic_person_info t1 join basic_person_info2 t2 on t1.id_num=t2.id_num where t1.age >10 and t2.age<20;
{
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": "7675.46"
    },
    "nested_loop": [
      {
        "table": {
          "table_name": "t2",
          "access_type": "range",
          "possible_keys": [
            "id_num_unique",
            "idx_age",
            "idx_age_id_num"
          ],
          "key": "idx_age",
          "used_key_parts": [
            "age"
          ],
          "key_length": "1",
          "rows_examined_per_scan": 9594,
          "rows_produced_per_join": 9594,
          "filtered": "100.00",
          "index_condition": "(`test`.`t2`.`age` < 20)",
          "cost_info": {
            "read_cost": "3358.16",
            包含所有io成本+(cpu成本-eval_cost)
            "eval_cost": "959.40",
            计算扇出的cpu成本,优化器利用启发式规则估算出满足所有条件的的比例(filtered)
            =rows_examined_per_scan*filtered*0.1
            "prefix_cost": "4317.56",
            单表查询的总成本

            "data_read_per_join": "3M"
          },
          "used_columns": [
            "id",
            "id_num",
            "lastname",
            "firstname",
            "mobile",
            "sex",
            "birthday",
            "age",
            "top_education",
            "address",
            "income_by_year",
            "create_time",
            "update_time"
          ]
        }
      },
      {
        "table": {
          "table_name": "t1",
          "access_type": "eq_ref",
          "possible_keys": [
            "id_num_unique",
            "idx_age"
          ],
          "key": "id_num_unique",
          "used_key_parts": [
            "id_num"
          ],
          "key_length": "60",
          "ref": [
            "test.t2.id_num"
          ],
          "rows_examined_per_scan": 1,
          "rows_produced_per_join": 4797,
          "filtered": "50.00",
          "cost_info": {
            "read_cost": "2398.50",
            包含所有io成本+(cpu成本-eval_cost)
            "eval_cost": "479.70",
            计算扇出的cpu成本,优化器利用启发式规则估算出满足所有条件的的比例(filtered)
            =rows_examined_per_scan*filtered*0.1
            "prefix_cost": "7675.46",
            两表查询的总cost
            "data_read_per_join": "1M"
          },
          "used_columns": [
            "id",
            "id_num",
            "lastname",
            "firstname",
            "mobile",
            "sex",
            "birthday",
            "age",
            "top_education",
            "address",
            "income_by_year",
            "create_time",
            "update_time"
          ],
          "attached_condition": "(`test`.`t1`.`age` > 10)"
        }
      }
    ]
  }
}

另外,explain结合show warnings语句一起使用还可以得知优化器改写后的语句

mysql> show warnings;
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`id_num` AS `id_num`,`test`.`t1`.`lastname` AS `lastname`,`test`.`t1`.`firstname` AS `firstname`,`test`.`t1`.`mobile` AS `mobile`,`test`.`t1`.`sex` AS `sex`,`test`.`t1`.`birthday` AS `birthday`,`test`.`t1`.`age` AS `age`,`test`.`t1`.`top_education` AS `top_education`,`test`.`t1`.`address` AS `address`,`test`.`t1`.`income_by_year` AS `income_by_year`,`test`.`t1`.`create_time` AS `create_time`,`test`.`t1`.`update_time` AS `update_time`,`test`.`t2`.`id` AS `id`,`test`.`t2`.`id_num` AS `id_num`,`test`.`t2`.`lastname` AS `lastname`,`test`.`t2`.`firstname` AS `firstname`,`test`.`t2`.`mobile` AS `mobile`,`test`.`t2`.`sex` AS `sex`,`test`.`t2`.`birthday` AS `birthday`,`test`.`t2`.`age` AS `age`,`test`.`t2`.`top_education` AS `top_education`,`test`.`t2`.`address` AS `address`,`test`.`t2`.`income_by_year` AS `income_by_year`,`test`.`t2`.`create_time` AS `create_time`,`test`.`t2`.`update_time` AS `update_time` from `test`.`basic_person_info` `t1` join `test`.`basic_person_info2` `t2` where ((`test`.`t1`.`id_num` = `test`.`t2`.`id_num`) and (`test`.`t1`.`age` > 10) and (`test`.`t2`.`age` < 20)) |
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

总结:

  • MySQL的优化器是基于成本来选择最优执行方案的,哪个成本最少就选哪个,所以重点在于计算出各个执行计划的cost
  • 成本由CPU成本和IO成本组成,每个成本常数值可以自己调整,非必要的情况下不要调整,以免影响整个数据库的执行计划选择
  • 通过开启optimizer_trace可以跟踪优化器的各个环节的分析步骤,可以判断有时候为什么没有走索引而走了全表扫描
  • explain加上format=json选项后可以查看成本信息分为read_cost和eval_cost,但只能看到当前已经选择的执行计划,另外通过show warnings可以看到优化器改写后的语句

Enjoy GreatSQL :)

\

Enjoy GreatSQL :)

关于 GreatSQL

GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。

相关链接: GreatSQL社区 Gitee GitHub Bilibili

GreatSQL社区:

image

社区有奖建议反馈: https://greatsql.cn/thread-54-1-1.html

社区博客有奖征稿详情: https://greatsql.cn/thread-100-1-1.html

社区2022年度勋章获奖名单: https://greatsql.cn/thread-184-1-1.html

(对文章有疑问或者有独到见解都可以去社区官网提出或分享哦~)

技术交流群:

微信&QQ群:

QQ群:533341697

微信群:添加GreatSQL社区助手(微信号:wanlidbc )好友,待社区助手拉您进群。

通达信COST与WINNER的Python高效实现:fengwo模块加速筹码分布计算 在量化选股中,筹码分布是判断支撑压力与主力成本的关键技术,其核心指标COST和WINNER通过换手率衰减递推计算历史筹码。传统Python循环实现速度慢,难以满足全市场批量选股需求。fengwo模块基于通达信算法,利用底层语言优化,实现高速计算,结果与通达信高度一致,速度提升百倍。适用于量化选股、指标复现及筹码分析等场景,助力高效处理通达信数据。 阅读详情

相关推荐

Python量化:用fengwo模块高效计算通达信WINNER和COST筹码指标

在量化分析中,筹码分布是判断市场成本结构的重要工具,通达信的WINNER和COST函数常用于计算获利盘比例和成本分位数。其原理基于换手率衰减和价格区间分配,通过迭代更新每日筹码。Python实现时,利用numba加速和增量计算可大幅提升性能,适用于批量股票因子计算、择时信号构建等场景。fengwo模块将这一算法封装为高效Python库,支持快速计算获利盘和成本区间,帮助开发者节省造轮子时间。

weixin_33507732的博客 274

机器人控制成本量化分析工具:OpenClaw-Cost-Diff 原理与应用

在机器人控制与强化学习领域,成本函数是衡量系统性能的核心数学工具,它量化了控制策略在执行任务过程中的各项“代价”,如能耗、时间与动作平滑度。其原理在于通过定义加权求和的目标函数,将跟踪误差、控制力等状态量转化为可优化的标量指标,从而引导算法学习更高效的行为。这一技术的工程价值在于实现了从定性“能否完成任务”到定量“以多高质量完成任务”的跃迁,为算法迭代与硬件选型提供了客观依据。在机器人仿真、自动化测试等应用场景中,成本差异分析工具通过后处理对比不同控制器的轨迹数据,帮助开发者精准定位性能瓶颈。本文聚焦的 `

weixin_42523907的博客 353

同花顺公式语法与量化分析实战指南

量化分析是金融科技领域的核心技术之一,通过数学模型和计算机算法对市场数据进行系统性分析。其核心原理是将交易策略转化为可执行的程序逻辑,同花顺公式语法正是为此设计的专用语言。相比传统编程语言,它采用更接近自然语言的表达方式,如用CLOSE>MA(CLOSE,5)表示收盘价突破5日均线,大幅降低了量化交易的门槛。该语法体系包含数据引用、函数计算和逻辑运算三大组件,支持MACD、均线系统等技术指标的快速实现。在工程实践中,合理的参数优化和公式调试能显著提升策略性能,而模块化开发则便于复用代码。典型应用场景包括条件

weixin_29235525的博客 486

MySQL optimizer_trace cost量化分析

前言:我们在日常维护数据库的时候,经常会遇到查询慢的语句,这时候一般会通过执行EXPLAIN去查看它的执行计划,但是执行计划往往只给我们带来了最基础的分析信息,比如是否有使用索引,还有一些其他供我们分析的信息,比如使用了临时表、排序等等,却无法展示为什么一些其他的执行计划未被选择,比如说明明有索引,或者好几个索引,但是为什么查询时未使用到期望的索引等explainselect*fromba...

老叶茶馆 399

通达信筹码获利比例指标公式源码与Python复算解析

筹码分布与获利盘比例是股票技术分析中的基础概念,通达信通过WINNER、COST等函数把成本地图压缩为0—100的读数。其原理并非简单均线,而是基于日线成交量按三角形分布近似叠加,并以换手率衰减历史筹码,再计算某价格以下的筹码占比。技术价值在于识别潜在抛压存量、成本区与支撑压力,适合中周期择时、顶部风险预警和低位钝化过滤。工程实践中,常用Python按OHLCV与流通股本复算,再与通达信WINNER对拍校准误差,也可结合量能饱和度判断高位风险是否兑现。围绕通达信筹码获利比例指标公式源码、成本带主副图写法及P

weixin_29229055的博客 301

通达信跟庄筹码副图源码拆解:从EMA到筹码盈亏度

指数移动平均线(EMA)通过加权最新价格,能更灵敏地反映成本变化,常用于构建多周期均价线。筹码分布则基于成本分布函数(COST),量化不同价格区间的持仓集中度,是判断支撑阻力的重要依据。将EMA与COST结合,可构造出跟庄筹码指标,通过筹码盈亏度柱状信号辅助识别主力动向。该指标适用于通达信副图,无未来函数,适合短线与中线看盘。本文深入拆解其计算链与绘图逻辑,并给出参数调优方法。

weixin_29081101的博客 280

文华财经软件指标公式期货量化分析软件

B31:=HB-B3;

QQ209427943的博客 290

Springboot项目中使用邮箱验证码注册登录的代码实现

本文介绍了在Spring Boot应用中实现邮箱验证码注册和登录功能的完整方案。文章首先概述了三种用户认证方式(邮箱验证码注册/登录和传统密码登录),然后详细说明了实现所需的技术栈(Spring Boot、Spring Security、JWT等)。重点阐述了邮件服务配置、验证码生成与存储的核心实现,包括QQ邮箱授权码获取、Thymeleaf邮件模板处理以及验证码缓存管理。最后展示了发送验证码和用户注册的API实现,为开发者提供了完整的参考方案。该方案兼顾安全性和用户体验,适合现代Web应用的用户认证需求。

BXCQ_xuan的技术专栏 | 实战干货·实践教程·学习笔记 1340

各方筹码三分天下通达信指标筹码三分法含1主图2副图1选股工具

七十成本集中度:=(LIJIN_85-LIJIN_15)/HHV(HIGH,9999)*100,COLORGRAY,DOTLINE,NODRAW;七十成本集中度:(LIJIN_85-LIJIN_15)/HHV(HIGH,9999)*100,COLORGRAY,DOTLINE,NODRAW;九十集中:=(COST(95)-COST(5))/CONST(HHV(HIGH,0))*100,NODRAW;九十集中:(COST(95)-COST(5))/CONST(HHV(HIGH,0))*100,NODRAW;

qq_20993549的博客 583

静态时序分析(Static Timing Analysis, STA):简介及内容导航

静态时序分析(简称STA)是用来验证数字设计时序的技术之一,另外一种验证时序的方法是时序仿真,时序仿真可以同时验证功能和时序。“时序分析”这个术语就是用来指代“静态时序分析“或”时序仿真“这两种方法之一,简单来说,时序分析的目的就是为了解决设计中的各种时序问题。STA被称为静态的原因是其对于设计的分析是静态地执行的,并不依赖于施加在输入端口上的激励。相比之下,时序仿真则可以被视作动态地执行对设计的分析,具体过程描述如下:施加一组激励,观察在这组激励下电路行为是否符合要求,然后换一组激。

Starry__的博客 1992

速腾16线激光雷达(RS-16)在ubuntu18.04系统下跑SC-A-LOAM算法

说明: 简要记录一下速腾16线激光雷达即RS-16在ubuntu18.04系统下跑SC-A-LOAM算法的过程,因为SC-A-LOAM算法源码不支持RS雷达的数据,大致思想就是先将rs雷达发布的激光数据转换为velodyne类型的数据,考虑到接下来还要基于RS-16实时运行SC-A-LOAM算法,这里提前将RS_SDK驱动安装好。 1 搭建SC-A-LOAM算法运行环境 首先需要在电脑上搭建SC-A-LOAM算法的运行环境,见文章《ubuntu18.04搭建SC-A-LOAM环境并运行》 本文所使用的系统架

超爱吃小蛋糕的66的博客 2373

通达信主力趋势动向指标公式源码副图

STICKLINE(主力动向,主力动向,SCR,3,0),COLORYELLOW;1、股价下降+主力线上升=主力建仓;主力派发:=HHV(主力动向,21),COLORGREEN;主力收集:=LLV(主力动向,21),COLORRED;5、股价下降+主力线横盘=主力洗盘;2、股价上升+主力线上升=主力拉升;3、股价下降+主力线下降=主力出货;4、股价上升+主力线下降=主力出货;主力动向:SCR,COLORRED;

zhibiaogong的博客 45

在 Windows 10 中通过 WSL2 安装 vLLM 部署本地大模型的方法和步骤

通过 WSL2 在 Windows 10 中部署 vLLM 的核心优势是兼顾 Windows 生态与 Linux 环境的 GPU 加速能力,适合需要在 Windows 下开发但依赖 vLLM 高性能推理的场景。相比原生 Windows 部署(Ollama 等工具),该方案性能更优(接近原生 Ubuntu),且支持更大模型和量化优化。若追求极致性能,建议直接使用 Ubuntu 系统;若必须依赖 Windows 工具链,WSL2 + vLLM 是当前最优选择。

当 AI 开始写文章、绘星空,甚至预测未来,您还在旁观吗?这里将剖开人工智能的思考逻辑,拆解 AI 创作的底层密码,也聊聊人工智能里的人文温度。每篇都有让你拍案的细节,快来解锁 AI 时代的神奇世界! 3754

LinkSwift 网盘直链下载:8大网盘免费接入,5分钟快速跑通

LinkSwift 是一款免费开源的网盘直链浏览器插件,一个基于 JavaScript 编写的用户脚本,在【网盘直链下载助手】基础上改造而来。它能在百度网盘、阿里云盘等 8 大网盘页面里取回文件直链,再把链接交给你自己挑的 IDM、Aria2 或浏览器自带下载,省去盯浏览器进度条的工夫。 ## 为什么需要网盘直链下载 浏览器自带下载面对大文件很慢,页面一关传输就断;非会员账号还会被限带宽,只能

gitblog_00039的博客 336

[3D检测系列-PV-RCNN] PV-RCNN实战指南:从论文解析到代码调试全流程

本文提供了PV-RCNN在3D目标检测领域的实战全流程指南。文章深入解析了其Point-Voxel融合的核心思想,并详细演示了从环境搭建、数据准备、代码复现到模型训练与调试的具体步骤,特别针对常见的报错问题给出了解决方案,帮助开发者高效掌握这一经典算法。

weixin_29189381的博客 480

Jupyter Lab 无法启动 Kernel 问题排查与解决总结

使用 curl,telnet,或 Python websocket-client 库可以本地模拟 WebSocket 握手行为,帮助分析服务端响应状态。避免使用 http:// + ws:// 组合方式部署 Jupyter Lab,特别是在远程或跨域访问场景。建议统一采用 https:// + wss:// 方式部署,确保浏览器信任并兼容。确认 WebSocket 已升级为 wss://,内核可正常启动。但在远程访问时,浏览器出于安全策略,默认拒绝 ws:// 协议。

weixin_43866043的博客 1858

通达信庄家筹码成本主图指标公式

主力成本:(COST(50)+COST(50)+COST(55)+COST(60)+COST(65)+COST(70)+COST(75)+COST(80))/8,COLORYELLOW;壹线:=SMA(SMA(SMA(MA1,2,1),2,1),2,1),COLORGREEN;牛股起步1:=((上涨=1 AND REF(上涨,1)=0 AND C>压力) OR (CROSS(C,三线) AND CROSS(C,平均成本) AND CROSS(C,主力成本)));

zhibiaogong的博客 177

STM32F103(二十三)通用同步异步收发器(USART)

学习板:STM32F103ZET6 往期博客: STM32F103五分钟入门系列(一)跑马灯(库函数+寄存器)+加编程模板+GPIO总结 STM32F103五分钟入门系列(二)GPIO的七大寄存器+GPIOx_LCKR作用和配置 STM32F103五分钟入门系列(三)GPIO的常用库函数使用方法总结+一个网络上的误区 STM32F103五分钟入门系列(四)蜂鸣器实验(库函数+寄存器) STM32F103五分钟入门系列(五)按键实验(库函数+寄存器) STM32F103五分钟入门系列(六)时钟框图+相关寄存器

Curnane0_0的博客 1019

通达信机构之星 源码

神偷出现:=IF((COUNT((股海神偷>REF(股海神偷,1)),1)=1) AND (REF(股海神偷,1)<REF(REF(股海神偷,1),1)) AND (股海神偷<跟踪),50,0),Colorred;股海:=(((DD-LLV(DD,21))/(HHV(DD,21)-LLV(DD,21)))*(4))*(25);STICKLINE(控盘<REF(控盘,1) AND 控盘>0,控盘,0,4,0),color00ff00;STICKLINE(控盘<0,控盘,0,4,0),colorwhite;

gpzb7的博客 659

【企业智能体开发】优化模型成本、延迟与失败降级

小林的培训快开始时,服务台花很久“思考最优回答”,体验并不会更好。反过来,为了省钱而始终选最轻的模型,若连房间、连接方式和任务状态都识别不稳,后续错误检索和重复建单会造成更大代价。企业 Agent 的优化对象不是单次模型调用价格,而是任务在可接受时间内、安全地推进到正确结果的总成本。

Mr数据杨 893

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

通达信十九波段副图指标

预警:(IF((((V7 >= 200) AND (V6 >= 150)) OR CROSS(65,多方)),15,IF(((V7 <= (0 - 200)) AND (V6 <= (0 - 150))),(0 - 15),V9)) + 50),COLORFFFF00;注意:IF(((VAR2A >= 3) AND (PWINNER(5,CLOSE) < 2)),10,0),LINETHICK1,COLORFFCC99;高位:IF(CROSS(80,MM),60,100),COLORFFCC66;

zhibiaogong的博客 190

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

学习笔记------Collaborative Spatioitemporal Feature Learning for Video Action Recognition

Collaborative Spatioitemporal Feature Learning for Video Action Recognition keywords:时空特征的联合学习 和现有神经网网络的区别 现有神经网络: 现有神经网络要么分别学习时间特征和空间特征,要么不加控制的联合学习时间和空间特征 本文的神经网络:提出了一个对于神经网络新颖的操作,通过在可学习的参数上添加权重共享...

lord0555的博客 1005

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

传统观念:亏损就死扛总能回本,编程回测深度套牢个股持有5年回本概率,量化死扛亏损的时间成本。

print(f" 回本次数:{summary['recovered_count']} / {summary['total_years']}")print(f" 机会成本:{opp_cost['opportunity_cost_pct']}%")print(f" 个股收益:{opp_cost['stock_profit_pct']}%")print(f" 指数收益:{opp_cost['index_profit_pct']}%")f"价格:{r['year_end_price']:.2f} | "

2301_82202864的博客 189

【MCP采样接口成本控制权威指南】:20年SRE亲授Sampling调用流优化的7大黄金法则

解决MCP采样接口高成本难题,20年SRE提炼Sampling调用流优化的7大黄金法则。覆盖高频调用场景、动态采样率调整、错误率熔断等成本控制策略,显著降低可观测性开销。方法经生产环境验证,兼顾精度与性价比,值得收藏。

VarIsle的博客 251

图像生成评估新指标:VAR提出的相对成本(rel.cost)详解

你还在仅用FID评估图像生成模型吗?在实际应用中,模型的生成质量与计算成本往往需要权衡。Visual Autoregressive Modeling(VAR)项目创新性地提出了**相对成本(rel.cost)** 指标,解决了不同模型间效率对比的难题。本文将深入解析这一指标的定义、计算方法及其在模型选型中的应用,帮助你全面理解如何在生成质量与计算资源间找到最佳平衡点。 读完本文你将获得: - 相...

gitblog_01091的博客 1112

贾子公理体系(Kucius Axiomatic System v1.0)深度剖析:从底层逻辑到跨域统治力

摘要: 本文深度剖析贾子公理体系(KAS v1.0),这是一套由三大母公理(规律先于价值、认知决定命运、清算不可逃逸)构成的非规范性元规则系统。它跳出价值判断,在“零层前提”上揭示了支配认知、权力、战争、文明与AI演化的结构必然性。体系通过形式化表达,实现了从哲学思辨到可推导、可验证的学术升级,其跨域同构性为历史周期、组织崩溃、AI治理等复杂系统问题提供了统一的“约束性”解释框架与生存指南。

首席技术执行官CTO(Chief Technology Officer)|技术总监--邓斌博客 732
上一篇: MySQL 8.0数据字典有什么变化
下一篇: GreatSQL 8.0.25-17今日发布
GreatSQL社区
博客等级 码龄5年 1210粉丝 390原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值