这个问题很好,不过我感觉是问产品的,不是问测试的。
如果测试能有这种视野当然更好,属于锦上添花的事情,但也就更好仅此而已。
现在整体行业,想要拿到高工资,懂技术是必备的。
也许大家都很不爽,测试为啥需要懂那么多技术,甚至还要刷算法,我点点点需要啥玩意算法。
但事实就如此,个人力量是无法改变行业趋势,懂技术就是比纯点点点的工资更高。
这一切的前提都是工作就是为了搞钱,如果纯为了乐趣,点点点也很快乐,那就另说。
这三个用途都完全不一样啊,先搞清楚需求。
另外,没必要买最新款的,买二手,官翻的性价比高很多,特别适合预算不足的情况
整体上来说,员工薪水是市场决定的。
当然,也会存在很多和市场不匹配的个例。
这是因为市场价格和当前员工薪是不同步,或者企业故意为之
转行做啥哦
确实,怎么发现好多人结婚好难呀
婚纱照是跟老婆挑了一家私人定制来拍,大概 7k 左右
没有订婚,没有定亲
彩礼是我妈直接跟丈母娘沟通的,我至今都不知道具体数字,只知道大概是 3w 多
3 金是老婆家拿彩礼买的
婚礼的酒席是我爸安排的,在广东三线城市的老家 40 桌不到,12w 左右
婚礼流程,舞台这些是我们请人设计,主持司仪是老婆的好朋友
这一套下来,整体花费跟部分省份的彩礼起步价差不多
结婚整体还是蛮顺利的,唯一的遗憾就是因为口罩,导致老婆很多朋友闺蜜不能来
可以说甲方就是牛批:我可以不用,但你得有
也可以换个角度:
哈哈哈,符合阿里高管的作风。
其实都一样,新高管入职都会搞类似的动作。。
通勤方面说一下个人的感受:
如果单身的话,可以考虑在公司附近的小区合租,不要住城中村。缩短通勤幸福感提升超级明显!!!
我在福田市中心合租 2k 多点就行,电梯老小区。很多城中村也差不多这个价格,甚至更贵。
住得近,通勤骑小电驴 10min 不到,比起 1h 的地铁要好太多了!
本来下班血槽就差不多空了,但是还要快 1h 通勤,要命啊。
早上又要一大早起来挤地铁,太难受了。
多出来的时间,大概率也不会用来学习,但身体感受会很爽,整个人都开心多了。
正 hao,是正浩对吧,之前练手面过,有被恶心到
实践出真知,那就跑起来吧。
先说结论
耗时绝对值都是比较小的。
INNER JOIN 执行时间: 0.0093 秒
LEFT JOIN 执行时间: 0.0078 秒
性能差异: LEFT JOIN 比 INNER JOIN 慢 0.84 倍
无索引 INNER JOIN 执行时间: 0.2907 秒
无索引 LEFT JOIN 执行时间: 24.5531 秒
无索引性能差异: LEFT JOIN 比 INNER JOIN 慢 84.47 倍
$ python test_inner_join_left_join.py
数据库创建成功
表结构创建成功
正在生成左表数据...
左表已插入 0 行
...
左表数据生成完成:1000行
正在生成右表数据...
右表已插入 10000 行
....
右表已插入 980000 行
右表已插入 990000 行
右表已插入 1000000 行
右表数据生成完成:1,000,000行
为右表的join_key添加索引...
索引添加成功
测试 INNER JOIN:
执行计划分析:
(1, 'SIMPLE', 'l', 'ALL', 'join_key', None, None, None, '1000', 'Using where')
(1, 'SIMPLE', 'r', 'ref', 'idx_join_key', 'idx_join_key', '5', 'test_inner_join_left_join.l.join_key', '50', '')
INNER JOIN 匹配记录数: 100051
INNER JOIN 执行时间: 0.0093 秒
测试 LEFT JOIN:
执行计划分析:
(1, 'SIMPLE', 'l', 'ALL', None, None, None, None, '1000', '')
(1, 'SIMPLE', 'r', 'ref', 'idx_join_key', 'idx_join_key', '5', 'test_inner_join_left_join.l.join_key', '50', 'Using where')
LEFT JOIN 匹配记录数: 100051
LEFT JOIN 执行时间: 0.0078 秒
性能差异: LEFT JOIN 比 INNER JOIN 慢 0.84 倍
测试移除索引后的性能:
已移除右表索引
测试无索引的 INNER JOIN:
执行计划分析:
(1, 'SIMPLE', 'r', 'ALL', None, None, None, None, '997003', 'Using where')
(1, 'SIMPLE', 'l', 'ref', 'join_key', 'join_key', '5', 'test_inner_join_left_join.r.join_key', '1', '')
无索引 INNER JOIN 匹配记录数: 100051
无索引 INNER JOIN 执行时间: 0.2907 秒
测试无索引的 LEFT JOIN:
执行计划分析:
(1, 'SIMPLE', 'l', 'ALL', None, None, None, None, '1000', '')
(1, 'SIMPLE', 'r', 'ALL', None, None, None, None, '997003', 'Using where; Using join buffer (flat, BNL join)')
无索引 LEFT JOIN 匹配记录数: 100051
无索引 LEFT JOIN 执行时间: 24.5531 秒
无索引性能差异: LEFT JOIN 比 INNER JOIN 慢 84.47 倍
使用 Cursor + sonnet3.7 模型
在mysql中,请帮我写程序来验证下面的的结论:
连接信息是:
"HOST": "127.0.0.1",
"PORT": 3306,
"USER": "root",
"PASSWORD": "root",
db重新创建一个,名为test_inner_join_left_join
优先选 INNER JOIN:若只需匹配数据,效率通常更高。
谨慎用 LEFT JOIN:仅在需要保留左表所有行时使用,并确保右表连接键有索引。
实际验证:通过 EXPLAIN 分析执行计划,观察是否触发全表扫描或低效操作。
import pymysql
import time
import random
# 数据库连接信息
DB_CONFIG = {
"host": "127.0.0.1",
"port": 3306,
"user": "root",
"password": "root",
}
def create_database():
"""创建新数据库"""
conn = pymysql.connect(**DB_CONFIG)
cursor = conn.cursor()
try:
# 删除已存在的数据库(如果有)
cursor.execute("DROP DATABASE IF EXISTS test_inner_join_left_join")
# 创建新数据库
cursor.execute("CREATE DATABASE test_inner_join_left_join")
print("数据库创建成功")
except Exception as e:
print(f"创建数据库失败: {e}")
finally:
cursor.close()
conn.close()
def setup_tables():
"""创建表结构"""
# 连接到新创建的数据库
conn = pymysql.connect(
**DB_CONFIG,
database="test_inner_join_left_join"
)
cursor = conn.cursor()
try:
# 创建左表 - 较小的表 (1000行)
cursor.execute("""
CREATE TABLE left_table (
id INT AUTO_INCREMENT PRIMARY KEY,
join_key INT,
data VARCHAR(100),
INDEX (join_key)
)
""")
# 创建右表 - 较大的表 (100万行)
cursor.execute("""
CREATE TABLE right_table (
id INT AUTO_INCREMENT PRIMARY KEY,
join_key INT,
data VARCHAR(100)
)
""")
print("表结构创建成功")
conn.commit()
except Exception as e:
print(f"创建表结构失败: {e}")
conn.rollback()
finally:
cursor.close()
conn.close()
def generate_data():
"""生成测试数据"""
conn = pymysql.connect(
**DB_CONFIG,
database="test_inner_join_left_join"
)
cursor = conn.cursor()
try:
# 为左表生成1000行数据
print("正在生成左表数据...")
for i in range(1000):
join_key = random.randint(1, 2000) # 随机生成连接键
data = f"Left data {i}"
cursor.execute(
"INSERT INTO left_table (join_key, data) VALUES (%s, %s)",
(join_key, data)
)
if i % 200 == 0:
conn.commit()
print(f"左表已插入 {i} 行")
conn.commit()
print("左表数据生成完成:1000行")
# 为右表生成100万行数据
print("正在生成右表数据...")
batch_size = 10000
for i in range(1, 1000001):
join_key = random.randint(1, 10000) # 随机生成连接键
data = f"Right data {i}"
cursor.execute(
"INSERT INTO right_table (join_key, data) VALUES (%s, %s)",
(join_key, data)
)
if i % batch_size == 0:
conn.commit()
print(f"右表已插入 {i} 行")
conn.commit()
print("右表数据生成完成:1,000,000行")
except Exception as e:
print(f"生成数据失败: {e}")
conn.rollback()
finally:
cursor.close()
conn.close()
def add_index_to_right_table():
"""为右表的连接键添加索引"""
conn = pymysql.connect(
**DB_CONFIG,
database="test_inner_join_left_join"
)
cursor = conn.cursor()
try:
print("为右表的join_key添加索引...")
cursor.execute("CREATE INDEX idx_join_key ON right_table(join_key)")
conn.commit()
print("索引添加成功")
except Exception as e:
print(f"添加索引失败: {e}")
conn.rollback()
finally:
cursor.close()
conn.close()
def test_join_performance():
"""测试两种连接方式的性能差异"""
conn = pymysql.connect(
**DB_CONFIG,
database="test_inner_join_left_join"
)
cursor = conn.cursor()
try:
# 测试INNER JOIN
print("\n测试 INNER JOIN:")
print("执行计划分析:")
cursor.execute("""
EXPLAIN SELECT l.id, l.data, r.data
FROM left_table l
INNER JOIN right_table r ON l.join_key = r.join_key
""")
explain_result = cursor.fetchall()
for row in explain_result:
print(row)
# 测量INNER JOIN执行时间
start_time = time.time()
cursor.execute("""
SELECT COUNT(*)
FROM left_table l
INNER JOIN right_table r ON l.join_key = r.join_key
""")
inner_count = cursor.fetchone()[0]
inner_time = time.time() - start_time
print(f"INNER JOIN 匹配记录数: {inner_count}")
print(f"INNER JOIN 执行时间: {inner_time:.4f} 秒")
# 测试LEFT JOIN
print("\n测试 LEFT JOIN:")
print("执行计划分析:")
cursor.execute("""
EXPLAIN SELECT l.id, l.data, r.data
FROM left_table l
LEFT JOIN right_table r ON l.join_key = r.join_key
""")
explain_result = cursor.fetchall()
for row in explain_result:
print(row)
# 测量LEFT JOIN执行时间
start_time = time.time()
cursor.execute("""
SELECT COUNT(*)
FROM left_table l
LEFT JOIN right_table r ON l.join_key = r.join_key
""")
left_count = cursor.fetchone()[0]
left_time = time.time() - start_time
print(f"LEFT JOIN 匹配记录数: {left_count}")
print(f"LEFT JOIN 执行时间: {left_time:.4f} 秒")
# 计算性能差异
print(f"\n性能差异: LEFT JOIN 比 INNER JOIN 慢 {left_time/inner_time:.2f} 倍")
# 测试没有索引的情况
print("\n测试移除索引后的性能:")
cursor.execute("DROP INDEX idx_join_key ON right_table")
print("已移除右表索引")
# 再次测试INNER JOIN (无索引)
print("\n测试无索引的 INNER JOIN:")
print("执行计划分析:")
cursor.execute("""
EXPLAIN SELECT l.id, l.data, r.data
FROM left_table l
INNER JOIN right_table r ON l.join_key = r.join_key
""")
explain_result = cursor.fetchall()
for row in explain_result:
print(row)
# 测量无索引INNER JOIN执行时间
start_time = time.time()
cursor.execute("""
SELECT COUNT(*)
FROM left_table l
INNER JOIN right_table r ON l.join_key = r.join_key
""")
inner_count_no_idx = cursor.fetchone()[0]
inner_time_no_idx = time.time() - start_time
print(f"无索引 INNER JOIN 匹配记录数: {inner_count_no_idx}")
print(f"无索引 INNER JOIN 执行时间: {inner_time_no_idx:.4f} 秒")
# 测试无索引的LEFT JOIN
print("\n测试无索引的 LEFT JOIN:")
print("执行计划分析:")
cursor.execute("""
EXPLAIN SELECT l.id, l.data, r.data
FROM left_table l
LEFT JOIN right_table r ON l.join_key = r.join_key
""")
explain_result = cursor.fetchall()
for row in explain_result:
print(row)
# 测量无索引LEFT JOIN执行时间
start_time = time.time()
cursor.execute("""
SELECT COUNT(*)
FROM left_table l
LEFT JOIN right_table r ON l.join_key = r.join_key
""")
left_count_no_idx = cursor.fetchone()[0]
left_time_no_idx = time.time() - start_time
print(f"无索引 LEFT JOIN 匹配记录数: {left_count_no_idx}")
print(f"无索引 LEFT JOIN 执行时间: {left_time_no_idx:.4f} 秒")
# 计算无索引情况下的性能差异
print(f"\n无索引性能差异: LEFT JOIN 比 INNER JOIN 慢 {left_time_no_idx/inner_time_no_idx:.2f} 倍")
except Exception as e:
print(f"测试连接性能失败: {e}")
finally:
cursor.close()
conn.close()
def run_test():
"""运行完整测试流程"""
create_database()
setup_tables()
generate_data()
add_index_to_right_table()
test_join_performance()
if __name__ == "__main__":
run_test()
首先,没有任何抬杠的意思;因为回答中说了问 AI,我就顺手问 AI。
仅仅是复制了原文给 gpt,让它来判断。因为我确实不知道这两者的区别,也不知道这个结论的正确性。
另外,我不确定你说得抬杠是我抬杠,还是 gpt 抬杠。
GPT o1 模型给出的答案,似乎不是很认可总结中的示例
在 mysql 中,这个说法有道理吗
示例:若左表有 1000 行,右表有 100 万行且无索引:
INNER JOIN 可能通过索引快速过滤,仅匹配少量数据。
LEFT JOIN 可能需扫描右表全部 100 万行,导致性能骤降。
简短回答:
那种 “一旦用 LEFT JOIN,MySQL 就会被迫扫右表全部数据,而用 INNER JOIN 就能快速过滤只读少量数据” 的说法往往是过度简化甚至不准确的。具体是否要扫右表所有行,取决于是否有可用索引、连接条件、以及优化器能否调整执行计划等多重因素,而不只是句型(LEFT 还是 INNER)本身。
连接顺序受限
INNER JOIN
,MySQL 优化器通常可以自由地对多表进行 重排(reorder),选择最优的连接顺序(也就是决定谁先作为驱动表、谁后作为被驱动表)。LEFT JOIN
,逻辑上要求 “左表中的每一行都必须出现在结果集中”,所以 MySQL 不能随意重排,必须先读取左表,再去匹配右表。INNER JOIN
,有时优化器能把 “大表” 放在前面过滤掉大部分无关行(或用其他执行策略),从而减少总的扫描量。没有索引时的 Nested Loop Join
LEFT JOIN
限制了连接顺序,可能导致大表总是放在后面被 “一行一行” 地嵌套查找,性能糟糕。INNER JOIN
还是 LEFT JOIN
,都可能导致大量扫描,不见得一定是谁就一定更快。是否能用到索引才是关键
LEFT JOIN
还是 INNER JOIN
中被当作 “被驱动” 一方)上的连接字段上建有索引,通常就能利用该索引快速定位匹配行,而不会傻傻地扫整个大表。INNER JOIN
,也有可能被优化器选成 “左表” 的角色——然后对另一张表做多次的全表扫描,同样卡得飞起。优化器对 INNER JOIN
和 LEFT JOIN
的选择空间不同
INNER JOIN
时,MySQL 通常可以根据代价估算,动态调整表的读取顺序以及连接方式,因此有时可以 “先扫大表并过滤掉无效行” 或 “先扫小表做索引查找” 等等。LEFT JOIN
时,原则上必须保证左表所有行都会输出(包括右表匹配不到时的 NULL
),因此 MySQL 在决定执行计划时,不能把右表排到前面 去先做过滤。INNER JOIN
相对更快,而 LEFT JOIN
可能会慢。有没有外部过滤条件、统计信息等
WHERE
条件,或者联结字段有不同的选择性,优化器就可能采取完全不同的执行策略。给连接列加上合适的索引
LEFT
还是 INNER
,都比较容易走到比较高效的执行路径。尽量用能表达业务需求的 JOIN 类型
LEFT JOIN
。INNER JOIN
就可以。不要为了 “也许会快一点” 而改动语义。分析执行计划(EXPLAIN)
EXPLAIN
看实际的 “各表的读取顺序”“是否用到索引”“预估的扫描行数” 等。注意 MySQL 版本
LEFT JOIN
,MySQL 也能做得不错。LEFT JOIN
很慢、INNER JOIN
快不少” 的情况,但它更多是执行计划和索引缺失的问题,而不只是字面上的 “左连接一定会扫右表”。EXPLAIN
确认优化器是否走到了正确的索引访问路径。https://chatgpt.com/share/67f29f7e-38a8-800b-91bf-dda853d03fe0
说吧,cursor 快速请求用了多少次
牛,精英 od!
不是国企但是有着国企的人情世故
这个就挺难受的
WLB, so cool.
年轻人,以后天下是你的,真棒
标准中年人,太难啦
可以的,毕竟考公才是打工的尽头,加油~~~
副业之所以没告诉大家,只是这个东西没什么可复制性,且风险非常高。
那其实也还好?跟成年人的费用差不多了,每年 5 万,一个月 4k 左右
流利说
哇,你也一直在学习英语哦
哈哈哈,远程对 i 人挺好的。
奖金的话,我感觉差不多,可能是猪场太坑了
这个不太方便多说