02.11 Day 23 - 如何选择索引

本文深入探讨MySQL优化器逻辑,包括最优执行方案的选择、索引基数的获取及统计信息的存储方式,分析索引选择异常的原因及处理策略,如使用forceindex强行指定索引、新建或删除索引来引导优化器做出正确选择。

大家好,我是 Snow Hide,作为《MySQL 实战》这个专栏的学员之一,这是我打卡的第 23 天,也是我第 81 次进行这种操作。

今天我温习了该专栏里一篇叫《MySQL 为什么有时候会选错索引?》的文章。

关键词总结:优化器逻辑(最优执行方案、综合判断、判断扫描行数、获得索引基数、两种存储索引统计的方式)、索引选择异常和处理(采用 force index 强行选择一个索引、引导 MySQL 使用我们期望的索引、新建一个更合适的索引,供优化器做选择,或删掉误用的索引)。

 

所学总结:

 

优化器逻辑

最优执行方案

优化器选择索引的目的是找到最有执行方案,并用最小的代价去执行语句。

综合判断

扫描行数并不是唯一的判断标准,优化器还会结合是否使用临时表、是否排序等因素进行综合判断。

判断扫描行数

MySQL 在真正开始执行语句之前,并不能精确地知道满足这个条件的记录有多少条,而只能根据统计信息来估算记录数。

获得索引基数

采样统计的时候,InnoDB 默认会选择 N 个数据页,统计这些页面上的不同值,得到一个平均值,然后乘以这个索引的页面数,就得到了这个索引的基数。

两种存储索引统计的方式

  • 设置为 on 的时候,表示统计信息会持久化存储。这时,默认的 N 是 20,M 是 10;
  • 设置为 off 的时候,表示统计信息只存储在内存中。这时,默认的 N 是 8,M 是 16。
     

索引选择异常和处理

采用 force index 强行选择一个索引

MySQL 会根据词法解析的结果分析出可能可以使用的索引作为后选项,然后在候选列表中依次判断每个索引需要扫描多少行。如果 force index 指定的索引在候选索引列表中,就直接选择该索引,不再评估其他索引的执行代价。

引导 MySQL 使用我们期望的索引

这种根据数据特征来诱导优化器的做法不具备通用性。

新建一个更合适的索引,供优化器做选择,或删掉误用的索引

找到一个更合适的索引一般比较难。删掉优化器错误选择的索引,使其重新选择正确的索引。

 

末了

重新总结了一下文中提到的内容:索引统计的更新机制、优化器存在选错索引的可能性、索引统计信息不准确导致的问题、在应用端用 force index 来强行指定索引。

有一个table变量,格式如下: time open high low close volume trading_day 2025-12-10 11:15:00 958.5400 958.5600 956.8000 956.8000 4879 2025-12-10 2025-12-10 11:30:00 956.8000 957.1000 956.3600 956.5200 4771 2025-12-10 2025-12-10 13:45:00 955.3600 957.1400 955.3600 957.0800 6269 2025-12-10 2025-12-10 14:00:00 957.0800 957.5600 956.4200 956.7200 4633 2025-12-10 2025-12-10 14:15:00 956.6800 956.7600 956.2400 956.4400 3780 2025-12-10 2025-12-10 14:30:00 956.4200 956.5800 955.5000 956.1400 6055 2025-12-10 2025-12-10 14:45:00 956.0800 956.1400 955.1000 955.9400 3806 2025-12-10 2025-12-10 15:00:00 956 956.4000 955.8000 956.4000 3559 2025-12-10 2025-12-10 21:15:00 954.4800 955.0600 953.4400 954.3400 11089 2025-12-11 2025-12-10 21:30:00 954.3400 954.8400 953.6600 954.4600 7730 2025-12-11 2025-12-10 21:45:00 954.4600 955.4600 953.9000 955.3600 7907 2025-12-11 2025-12-10 22:00:00 955.3800 955.8800 954.8000 954.8800 7102 2025-12-11 2025-12-10 22:15:00 954.9200 956.4200 954.5200 956.0200 7248 2025-12-11 2025-12-10 22:30:00 956.0200 956.1600 953.8400 954.2600 6987 2025-12-11 2025-12-10 22:45:00 954.2800 954.7600 953.2000 954.4800 11600 2025-12-11 2025-12-10 23:00:00 954.5200 955.5000 953.5800 953.6000 9411 2025-12-11 2025-12-10 23:15:00 953.5600 955.2000 953.5400 954.0400 8163 2025-12-11 2025-12-10 23:30:00 954.0400 954.7200 953.2600 954.7000 8797 2025-12-11 2025-12-10 23:45:00 954.6400 955.2800 954.2000 954.4200 4728 2025-12-11 2025-12-11 00:00:00 954.3800 954.5600 953.8600 954.3400 4699 2025-12-11 2025-12-11 00:15:00 954.3800 954.5600 954.1200 954.2000 2668 2025-12-11 2025-12-11 00:30:00 954.1800 955.4200 954.0200 955.3600 4030 2025-12-11 2025-12-11 00:45:00 955.3800 955.8400 955.0600 955.6600 3002 2025-12-11 2025-12-11 01:00:00 955.6200 956.4600 955.5000 956.2200 2898 2025-12-11 2025-12-11 01:15:00 956.1600 956.2000 955.1600 955.4000 1864 2025-12-11 2025-12-11 01:30:00 955.4200 956.5400 955.3600 955.8200 3369 2025-12-11 2025-12-11 01:45:00 955.8400 955.9600 955.3800 955.4400 1876 2025-12-11 2025-12-11 02:00:00 955.4400 956.0800 955.2000 955.7200 1919 2025-12-11 2025-12-11 02:15:00 955.7200 955.9600 955.5000 955.5600 1129 2025-12-11 2025-12-11 02:30:00 955.5200 955.6600 954.2000 954.7600 2118 2025-12-11 2025-12-11 09:15:00 962.3600 966.6000 962.3600 964.2000 30742 2025-12-11 2025-12-11 09:30:00 964.1800 964.3000 962.4200 962.7000 10074 2025-12-11 2025-12-11 09:45:00 962.7200 963.3400 962.0200 963.2200 7023 2025-12-11 2025-12-11 10:00:00 963.2600 963.8600 963.1200 963.5600 5282 2025-12-11 2025-12-11 10:15:00 963.6000 963.9400 961.7400 962.3200 6071 2025-12-11 2025-12-11 10:41:00 961.7600 961.7600 959.5200 959.8000 8973 2025-12-11 其中,时间格式都是datetime。我现在想对其time列进行操作,具体来说,就是编写一个函数,将输入的table变量的time列进行强制增加日期以修改日期: 1. 如果time列为周五,且时间大于等于21:00,那么强制修改其日期增加2天为周日,具体的时间则不变。比如,周五21:15则改为接下来的周日21:15。 2. 如果time列为周六(包括00:00点),且时间小于3:00,那么强制修改其日期增加2天为周一,具体的时间则不变。比如,周六00:15则改为接下来的周一3:00。
最新发布
12-12
将数据集进行分割,例如取2023年8月1日为分界点,使用这之前的数据,构建模型预测8月1日-8月7日某个区域每小时犯罪发生情况,可以开展哪些特征工程,请生成用于模型训练与验证的数据集 data = pd.read_csv('/kaggle/input/crime-data-from-2020-to-present/Crime_Data_from_2020_to_Present (1).csv') DR_NO Date Rptd DATE OCC TIME OCC AREA AREA NAME \ 0 10304468 2020-01-08 2020-01-08 2230 3 Southwest 1 190101086 2020-01-02 2020-01-01 330 1 Central 2 200110444 2020-04-14 2020-02-13 1200 1 Central 3 191501505 2020-01-01 2020-01-01 1730 15 N Hollywood 4 191921269 2020-01-01 2020-01-01 415 19 Mission ... ... ... ... ... ... ... 815877 231604807 2023-01-27 2023-01-26 1800 16 Foothill 815878 231606525 2023-03-22 2023-03-22 1000 16 Foothill 815879 231210064 2023-04-12 2023-04-12 1630 12 77th Street 815880 230115220 2023-07-02 2023-07-01 1 1 Central 815881 230906458 2023-03-05 2023-03-05 900 9 Van Nuys Rpt Dist No Part 1-2 Crm Cd \ 0 377 2 624 1 163 2 624 2 155 2 845 3 1543 2 745 4 1998 2 740 ... ... ... ... 815877 1663 2 740 815878 1602 1 230 815879 1239 1 230 815880 154 1 352 815881 914 2 745 Crm Cd Desc ... Cross Street \ 0 BATTERY - SIMPLE ASSAULT ... NaN 1 BATTERY - SIMPLE ASSAULT ... NaN 2 SEX OFFENDER REGISTRANT OUT OF COMPLIANCE ... NaN 3 VANDALISM - MISDEAMEANOR ($399 OR UNDER) ... NaN 4 VANDALISM - FELONY ($400 & OVER, ALL CHURCH VA... ... NaN ... ... ... ... 815877 VANDALISM - FELONY ($400 & OVER, ALL CHURCH VA... ... NaN 815878 ASSAULT WITH DEADLY WEAPON, AGGRAVATED ASSAULT ... NaN 815879 ASSAULT WITH DEADLY WEAPON, AGGRAVATED ASSAULT ... NaN 815880 PICKPOCKET ... NaN 815881 VANDALISM - MISDEAMEANOR ($399 OR UNDER) ... NaN LAT LON Date Is Holiday Year Month Day Hour \ 0 34.0141 -118.2978 2020-01-08 0 2020 1 8 22 1 34.0459 -118.2545 2020-01-01 1 2020 1 1 3 2 34.0448 -118.2474 2020-02-13 0 2020 2 13 12 3 34.1685 -118.4019 2020-01-01 1 2020 1 1 17 4 34.2198 -118.4468 2020-01-01 1 2020 1 1 4 ... ... ... ... ... ... ... .. ... 815877 34.2466 -118.4054 2023-01-26 0 2023 1 26 18 815878 34.2790 -118.4116 2023-03-22 0 2023 3 22 10 815879 33.9841 -118.2915 2023-04-12 0 2023 4 12 16 815880 34.0467 -118.2485 2023-07-01 0 2023 7 1 0 815881 34.1951 -118.4487 2023-03-05 0 2023 3 5 9 Time Period 0 22-23 1 3-4 2 12-13 3 17-18 4 4-5 ... ... 815877 18-19 815878 10-11 815879 16-17 815880 0-1 815881 9-10 [815882 rows x 35 columns]
06-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Snow Hide(雪诺海德)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值