asmile1993 最近的时间轴更新
asmile1993

asmile1993

V2EX 第 574002 号会员,加入于 2022-03-01 15:22:58 +08:00
asmile1993 最近回复了
单行大小限制:每一行的数据大小最多不能超过 65,535 字节。utf8mb4 字符集在存储时,每个字符可能占用 1 到 4 个字节,因此如果你的表中有多个 utf8mb4 字符集的字段,那么它们会占用较多的存储空间,可能会影响你能够添加的有效字段数。
120 天前
回复了 leejinhong 创建的主题 MySQL 关于在业务中 MYSQL 事务查询的一个疑惑
@leejinhong 明白你的意思了,我记得流水表只记录差值,变更前后的值要靠当前值和差值构建出来。你要想记录,只能用悲观锁,变更前用 select ... for update/share 来读出最新值。
122 天前
回复了 leejinhong 创建的主题 MySQL 关于在业务中 MYSQL 事务查询的一个疑惑
@leejinhong 你为什么要以 select 出来的结果来做变更呢?上面已经有人提过了,你先用 select 查出来数据,判断是否能变更,如果不能,直接返回;如果能,那么就以 update t set value = value - 变化量 where ...,这样不就是当前读了吗?读的就是最新的数据啊,然后根据更新的行数来判断是否更新成功,0 则表示没有满足条件的记录,非 0 表示更新成功。
125 天前
回复了 leejinhong 创建的主题 MySQL 关于在业务中 MYSQL 事务查询的一个疑惑
@leejinhong 如果只是简单的 select ,在 RR 隔离级别下看到的的确是事务开始时的值,但当对记录进行修改操作时,用的是当前读—读最新的已提交记录,而不是一开始 select 得到的结果,想要了解更深的话,搜索下快照读和当前读。
196 天前
回复了 Grayan 创建的主题 MySQL 来个大佬帮看看 MYSQL 中查询关系树的问题
版本:mysql 8.0.33 ,我能查到结果,楼主什么数据都查不出来吗?

mysql> WITH RECURSIVE company_tree AS (
-> SELECT id, companyname, parent
-> FROM tb_company_info
-> WHERE companyname = 'top'
-> UNION ALL
-> SELECT c.id, c.companyname, c.parent
-> FROM tb_company_info c
-> INNER JOIN company_tree ct ON ct.companyname = c.parent
-> )
-> SELECT *
-> FROM company_tree;
+------+---------------+----------+
| id | companyname | parent |
+------+---------------+----------+
| 513 | top | |
| 490 | MR98C-B1 | top |
| 491 | MR98E-B1 | top |
| 492 | MR98E-B1-V101 | MR98E-B1 |
+------+---------------+----------+
原来的操作逻辑有问题,你第一步是查询用户积分总额,然后更新积分总额,最后再将积分余额插入到积分记录表中,第一步只读查询并没有加锁,因此是可以并发的,这可能导致并发的线程读取到的余额是不一致的,又因为你积分总表的更新逻辑是正确的,这会造成积分记录表中记录的积分余额错乱,而积分总表中的余额又是正确的。

-- 步骤一:先变更,这样会锁住 `uid`='22' 这条记录,别的会话只能查询,不能变更
UPDATE `api_credits` SET `credits1`=`credits1`-'100' WHERE `uid`='22' AND `credits1`>='100'
-- 步骤二:拿到变更后的最新的积分余额
SELECT * FROM `api_credits` WHERE `uid`='22' LIMIT 1
-- 将步骤二中获取到的积分余额插入到积分记录表中
INSERT INTO `api_credits_log` SET `uid`='22', `cid`='3', `credits`='100', `balance`='79900', `time`='1701001020'

将这三步放入到同一个事务中
从哪本书截的图?看这文字描述,我觉得这本书质量不是很高。

1) 假设 Q2 能利用上索引 (a, b),那么由于 a 是范围查询,根据高性能 MySQL 中的知识,可以知道“如果查询中有某个列的范围查询,则其右边所有列都无法使用索引优化查找”, 这里说的无法使用索引优化查找,是指“不能用索引快速定位”,但"快速过滤"是可以做的。

2) 由 1 可知,索引(a, b) 中,只有列 a 能用作索引快速定位,而列 b 不能用来快速定位,但 MySQL 有索引下推优化,因此对于列 b 来说,可以利用 ICP 来达到在索引遍历中快速过滤,从而减少回表次数。

有点没看懂你这个例子的回答,一直说索引有序是什么意思,虽然有关系,但有点答不对题,让人疑惑。
我估计楼主在 create_time 字段上建立了单列索引,查询具有 ORDER BY 或 GROUP BY 和 LIMIT 子句的情况下,控制优化器是否尝试使用有序索引而不是无序索引、文件排序或其他优化。 每当优化器确定使用它可以更快地执行查询时,默认情况下都会执行此优化。
因为这种算法不能处理所有可能的情况(部分原因是假设数据的分布总大体是均匀的),所以在某些情况下,这种优化可能是不可取的。 在 MySQL 5.7.33 之前,无法禁用此优化,但在 MySQL 5.7.33 及更高版本中,虽然它仍然是默认行为,但可以通过将 prefer_ordering_index 标志设置为 off 来禁用它。可以参考下文档 https://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html

解决方案 1:禁用 prefer_ordering_index 优化(不推荐),可能导致 pt 工具或其他根据 order by 的查询耗时过长(无法利用最优索引)
解决方案 2:order by create_time, 其他字段(推荐),加上除主键外的其他列,来达到禁用 create_time 上索引的效果
解决方案 3:使用 ignore index idx_name 来禁用掉 create_time 上的索引
解决方案 4:使用联合索引(推荐)
2022-11-17 19:33:40 +08:00
回复了 qiyong 创建的主题 程序员 面试中遇到的一道 sql 题
with goods_sales as(
-- 获取每种商品的总销售额
select distinct
g.id as goods_id,
g.name as goods_name,
g.group_id,
gg.name as group_name,
sum(gsr.sales_volume) over(partition by g.id, g.name, g.group_id, gg.name) sum_goods_sales_volume,
sum(gsr.sales_volume) over(partition by g.group_id, gg.name) sum_group_sales_volume
from goods g
inner join goods_group gg on g.group_id= gg.id
inner join goods_sales_record gsr on g.id= gsr.goods_id
order by sum_goods_sales_volume desc -- 以商品的总销售倒序排列,并取前三名
limit 3
)
select goods_id,
goods_name,
group_id,
group_name,
sum_goods_sales_volume, -- 每种商品的总销售额
sum_group_sales_volume -- 每种分类的总销售额
from goods_sales
order by sum_group_sales_volume desc, sum_goods_sales_volume desc -- 以每种分类的总销售额、商品的总销售倒序排列
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2461 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 13ms · UTC 15:57 · PVG 23:57 · LAX 07:57 · JFK 10:57
Developed with CodeLauncher
♥ Do have faith in what you're doing.