高效的MySQL查询,在A中查找与B中不匹配的条目
我有几个表(产品和供应商),想知道哪些项目不再列在供应商表中 表uc_products包含以下产品:。表uc_供应商_csv包含供应商库存。uc_products.model与uc_suppliers.sku合并 当我试图在products表中识别suppliers表中未提及的库存时,我看到了很长的查询。我只想提取匹配条目的nid;sid为空只是为了我可以识别哪些项目没有供应商 对于下面的第一个查询,DB服务器(4GB ram/2x 2.4GHz intel)需要一个小时才能得到结果(507行)。我没有等到第二个查询完成 如何使此查询更优化?是因为字符集不匹配吗 我认为以下是最有效的SQL:高效的MySQL查询,在A中查找与B中不匹配的条目,mysql,join,left-join,outer-join,ubercart,Mysql,Join,Left Join,Outer Join,Ubercart,我有几个表(产品和供应商),想知道哪些项目不再列在供应商表中 表uc_products包含以下产品:。表uc_供应商_csv包含供应商库存。uc_products.model与uc_suppliers.sku合并 当我试图在products表中识别suppliers表中未提及的库存时,我看到了很长的查询。我只想提取匹配条目的nid;sid为空只是为了我可以识别哪些项目没有供应商 对于下面的第一个查询,DB服务器(4GB ram/2x 2.4GHz intel)需要一个小时才能得到结果(507行)
SELECT nid, sid
FROM uc_products p
LEFT OUTER JOIN uc_supplier_csv c
ON p.model = c.sku
WHERE sid IS NULL ;
对于此查询,我得到以下解释结果:
mysql> EXPLAIN SELECT nid, sid FROM uc_products p LEFT OUTER JOIN uc_supplier_csv c ON p.model = c.sku WHERE sid IS NULL;
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------------------+
| 1 | SIMPLE | p | ALL | NULL | NULL | NULL | NULL | 6526 | |
| 1 | SIMPLE | c | ALL | NULL | NULL | NULL | NULL | 126639 | Using where; Not exists |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------------------+
2 rows in set (0.00 sec)
我本以为密钥idx_sku和idx_模型在这里是有效的,但它们不是。这是因为表的默认字符集不匹配吗?一个是UTF-8,一个是拉丁语1
我也考虑过这种形式:
SELECT nid
FROM uc_products
WHERE model
NOT IN (
SELECT DISTINCT sku FROM uc_supplier_csv
) ;
解释显示该查询的以下结果:
mysql> explain select nid from uc_products where model not in ( select sku from uc_supplier_csv ) ;
+----+--------------------+-----------------+-------+-----------------------+---------+---------+------+--------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-----------------+-------+-----------------------+---------+---------+------+--------+--------------------------+
| 1 | PRIMARY | uc_products | ALL | NULL | NULL | NULL | NULL | 6520 | Using where |
| 2 | DEPENDENT SUBQUERY | uc_supplier_csv | index | idx_sku,idx_sku_stock | idx_sku | 258 | NULL | 126639 | Using where; Using index |
+----+--------------------+-----------------+-------+-----------------------+---------+---------+------+--------+--------------------------+
2 rows in set (0.00 sec)
为了不遗漏任何内容,这里有一些更令人兴奋的细节:表的大小和统计数据,以及表的结构:)
及
编辑:为下面Martin的几个建议查询添加查询计划:
mysql> explain SELECT nid FROM uc_products p WHERE NOT EXISTS ( SELECT 1 FROM uc_supplier_csv c WHERE p.model = c.sku ) ;
+----+--------------------+-------+-------+---------------+---------+---------+------+--------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+-------+---------------+---------+---------+------+--------+--------------------------+
| 1 | PRIMARY | p | ALL | NULL | NULL | NULL | NULL | 6526 | Using where |
| 2 | DEPENDENT SUBQUERY | c | index | NULL | idx_sku | 258 | NULL | 126639 | Using where; Using index |
+----+--------------------+-------+-------+---------------+---------+---------+------+--------+--------------------------+
2 rows in set (0.00 sec)
mysql> explain SELECT nid FROM uc_products WHERE model NOT IN ( SELECT sku FROM uc_supplier_csv ) ;
+----+--------------------+-----------------+-------+-----------------------+---------+---------+------+--------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-----------------+-------+-----------------------+---------+---------+------+--------+--------------------------+
| 1 | PRIMARY | uc_products | ALL | NULL | NULL | NULL | NULL | 6526 | Using where |
| 2 | DEPENDENT SUBQUERY | uc_supplier_csv | index | idx_sku,idx_sku_stock | idx_sku | 258 | NULL | 126639 | Using where; Using index |
+----+--------------------+-----------------+-------+-----------------------+---------+---------+------+--------+--------------------------+
2 rows in set (0.00 sec)
也许尝试使用“不存在”而不是“计数”?例如:
SELECT nid
FROM uc_products p
WHERE NOT EXISTS (
SELECT 1
FROM uc_supplier_csv c
WHERE p.model = c.sku
)
因此,用户Quassnoi概述了一些测试,表明这可能也值得一试:
SELECT nid
FROM uc_products
WHERE model NOT IN (
SELECT sku
FROM uc_supplier_csv
)
基本上按照你原来的查询,没有区别
Chris,这是另一个为您准备的交叉编码连接帮助:
SELECT nid
FROM uc_products p
WHERE NOT EXISTS (
SELECT 1
FROM uc_supplier_csv c
WHERE CONVERT( p.model USING latin1 ) = c.sku
)
在第一个查询中使用have是不正确的——因为没有groupby,所以应该是一个简单的WHERE。我不知道为什么MySQL没有给你一条错误消息,但我想这就是为什么会打乱查询计划!我昨晚在我的笔记本电脑(MBP2.4GHz/4GB/OSX/MAMP MySQL)上测试了这个页面上的四个查询表单。*上面的左外部联接表单需要3526秒才能执行。*上面的子选择表单执行耗时1021秒。*Martin在下面的建议花了637秒执行。*James的略快于Martin的,但返回的结果与其他三个表单不同。此查询是返回正确结果的最快建议解决方案。执行耗时637秒。查询计划是什么样子的?添加到问题中(注释中的格式对我不起作用?)第三次幸运?看上面,哇。0.17秒而不是10分钟。美好的第三个示例(使用上面的WHERE CONVERT()几乎立即给出了正确答案。是关于你认为的皈依者吗?我已经将我的本地表更新为默认的字符集UTF8,但这样做并没有看到任何行为上的变化。
SELECT nid
FROM uc_products
WHERE model NOT IN (
SELECT sku
FROM uc_supplier_csv
)
SELECT nid
FROM uc_products p
WHERE NOT EXISTS (
SELECT 1
FROM uc_supplier_csv c
WHERE CONVERT( p.model USING latin1 ) = c.sku
)