CREATE TABLE `a` (
`id` varchar(30) NOT NULL,
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `b` (
`id` varchar(30) NOT NULL,
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SELECT a.id FROM a INNER join b on a.id = b.id;
|  |      1uiosun      2023-02-09 13:09:14 +08:00  1 必须要一句 SQL 搞定吗?一句话搞定的话,感觉超难…… | 
|      2lovelylain      2023-02-09 13:09:47 +08:00 via Android  1 字符串也可以排序比较大小的,你这里是主键,也不用考虑重复和索引问题,按你那个 id > xxx limit 做就行。 | 
|      3foolishcrab      2023-02-09 13:10:23 +08:00 via iPhone  1 Sql server 试试 interset, mysql 全拿出来在内存里算吧还是 | 
|      6ccagml OP @moqizhengz 没权限换数据库😂, MySQl 怎么做也不清楚,就是 io 满了,也没有加配置的空间 | 
|      7xsonglive491      2023-02-09 13:58:45 +08:00  1 你应该先 explain 下你的查询语句看是什么问题 | 
|      8thinkershare      2023-02-09 14:05:08 +08:00  1 没啥原因,MySQL 数据库过亿了就是慢。直接用子程序算了。先分别独立查询,看看独立查询费事多久。你这个过滤后大概会命中多少数据嘛?另外就像楼上说的,先 explain 一下,看看命中的索引信息。字符串肯定一样可以比较大小,为啥会不能比较大小呢?另外看看你字符串上使用的 collate 信息。 | 
|  |      9LeegoYih      2023-02-09 14:15:37 +08:00  1 求交集有过滤条件吗?如果有过滤条件且数量少直接 join 是没问题的。 如果是全量匹配,那只用代码一批一批查,没办法做到实时。 | 
|  |      10F281M6Dh8DXpD1g2      2023-02-09 14:18:14 +08:00 取出来之后要干啥? 要是只要其中一张表的数据可以用 exists | 
|  |      11opengps      2023-02-09 14:40:38 +08:00 首先,硬盘慢。你用的云服务器,自带的硬盘,这个硬盘是虚拟化之后的,本身 io 就严重打折。 其次,索引大。你的 id 本身 30 字节,结合 1 亿,8000 万,这意味着这两个主键索引就得 54 亿字节(约 3GB ) 结论是:可以考虑下,分别把两个 id 拷贝到 2 个内存表,然后对两个内存表进行 INNER join 。看看效率提升多少 | 
|  |      13starrys      2023-02-09 15:23:24 +08:00 via Android  1 观察一下两表的 id 的分布规律,分割成 10~50 次查询,再将结果 union 起来。 | 
|  |      14weidaizi      2023-02-09 16:30:17 +08:00  1 别用数据库来做这种偏计算类的工作,用个 python 查一下两张表的 id 字段回来,在程序里做对比就好了 | 
|      15ccagml OP | 
|  |      18F281M6Dh8DXpD1g2      2023-02-09 16:58:14 +08:00 @ccagml 忍着吧,mysql 就这性能 | 
|      21thinkershare      2023-02-09 17:09:09 +08:00 @ccagml 你这属于在 A 表上做全表扫描,怎么会块,慢是理所当然的。 | 
|      23thinkershare      2023-02-09 17:12:05 +08:00  1 A 表的主键还是 varchar(30)这种,主键一般不是用 char(30)这种就能搞定了吗,难道还要处理中文和可变长度。你这个 2 张表数据都差不多了,至少需要扫描 A 表 /或者 B 表一次,因为 a/b 表没用其它外键关联索引。 | 
|  |      24Maboroshii      2023-02-09 17:19:49 +08:00  1 写脚本, 循环从 a 查所有的 id , 然后 select id from b where id in (...)   放在后台跑就行了 | 
|      25dusu      2023-02-09 19:00:02 +08:00 via iPhone  1 既然内存够 把 id 都存 redis 用 sinter | 
|      26ccagml OP @dusu 长见识了,看着 sinter 的实现是 取最小集合 然后 检查其他集合是否有相同的 key,感觉一个 8000W 的循环是避免不了的, 还涉及到搭建 redis 环境问题,感觉可能不如自己写脚本去重 | 
|      27ccagml OP @Maboroshii 确实后台跑批可以解决 | 
|      28ccagml OP @thinkershare 感觉就是 2 个表检查相同值,一个 O(n)是避免不了的 | 
|  |      29encro      2023-02-09 20:06:02 +08:00  1 你看的不是我这个吧: https://c4ys.com/archives/2349 你这个必须临时表,而且查询集是 n*m 而不是 n+m. 你这个需求有点奇怪,没有 where ,所以没法缩小结果集,只能都跑全表。 | 
|  |      30my3157      2023-02-09 20:07:09 +08:00 试试 exsits | 
|  |      31encro      2023-02-09 20:11:22 +08:00 多表关联查询重要的就两条: 1, 先查结果集少的表,再查大的;(通常先查索引稀疏且分布均匀的) 2 , 索引必须用上,且尽量用主键关联; 优化也是三板斧: 1,show processlist 2,explain 3,slow query | 
|      32ccagml OP @encro 哈,不是看到那个,想要做的一开始已经写了,数据有问题,想看看有哪些数据错了,所以没有查询范围 也已经是主键关联了,你看 explain | 
|  |      33encro      2023-02-09 20:23:51 +08:00 没看备注: | 1 | SIMPLE | b | index | PRIMARY,b_id_index | id2 | 4 | NULL | 88343401 | Using index | 关键就在这里,用了 id2 全表扫描了。 你试一下用 exist 是不是更快。 | 
|  |      34xuelu520      2023-02-10 10:09:39 +08:00  1 id 都取出来扔 redis ,然后一个个去查呗 | 
|      35ccagml OP @xuelu520 这种一次性的小需求,感觉搭一套 redis 环境,加导出数据,感觉并不是很好的选择 | 
|      36xsonglive491      2023-02-10 12:51:01 +08:00 @ccagml 要是一次性需求你还是写脚本计算吧 | 
|      37512357301      2023-02-12 13:40:35 +08:00 via Android 本地跑个 clickhouse ,然后把关键的字段同步到本地,在本地分析,速度会快很多,clickhouse 是列式数据库,速度比 mysql 快多了 |