C# 计算未出现在其他表中的元素数的最佳方法

C# 计算未出现在其他表中的元素数的最佳方法,c#,mysql,query-performance,C#,Mysql,Query Performance,考虑以下情况 TableA TableB +------------+----------+----------+----------+ +---------+ |Column1 | Column2 | Column3 | Column4 | | entB | +-----------------------+----------+---------

考虑以下情况

TableA                                                 TableB
+------------+----------+----------+----------+        +---------+  
|Column1     | Column2  | Column3  | Column4  |        | entB    |
+-----------------------+----------+----------+        +---------+
| zzzxxxx    | NULL     | NULL     | zzzyyyy  |        | zzzxxxx | 
+------------+----------+----------+----------+        +---------+
| zzzqqqq    | NULL     | SomeText | NULL     |        | zzzyyyy |
+------------+----------+----------+----------+        +---------+
| NULL       | zzzxxxx  | zzzxxx   | NULL     |        | zzzwwww |
+------------+----------+----------+----------+        +---------+
| zzzyyyy    | zzzyyyy  | zzzwwww  | SomeText |
+------------+----------+----------+----------+
其中z,y,x=1-9,某些文本可以包含任何数字或字母-表B的ent B列中不能有空值

我需要找到表A中不在表B中的值的总数。表A中的列不包含唯一(不同)值,并且可能为空

我的第一次尝试是以下和查询

$"select count(1) from " +
$"(" +
$"  select distinct Column1 from {TableA} where Column1 not in (select entB from {TableB})" +
$" union" +
$"  select distinct Column2 from {TableA} where Column2 not in (select entB from {TableB})" +
$" union" +
$"  select distinct Column3 from {TableA} where Column3 not in (select entB from {TableB})" +
$" union" +
$"  select distinct Column4 from {TableA} where Column4 not in (select entB from {TableB})" +
$") as t"
这很好,直到我不得不在一个有7000000行和100000行的TableB表上进行测试,而TableB的查询需要很长时间才能执行。我正在寻找减少时间的方法

我读到使用
Distinct
Union
是一种降低性能的简单方法,所以我想试试这样的方法

SELECT Column1
FROM TableA a
WHERE NOT EXISTS (SELECT 1 FROM TableB b WHERE a.Column1 = b.entB and a.Column1 is not null ) 
and Column1 is not null)
获取结果,将其保存在DataTable中,然后对其他3列重复相同的查询,并合并检查内存中重复项的结果

你知道有没有更好的解决办法吗


编辑:我编辑了表格,以便更好地显示我的数据。在这个例子中,我希望结果是值“2”,因为有两个值(SomeText和zzzqqq)不存在于表B中

一旦我们克服了所有关于
表A
如何未规范化的抱怨,这并不难做到

我猜您需要统计表a中与表B不匹配的四列的值。如果你想要更复杂的东西,恕我直言,花点时间想清楚如何准确地描述它

从一个子查询开始,该子查询提供要比较的
表a
中的值。因为我们使用
UNION
而不是
UNION ALL
,所以我们可以免费获得
SELECT DISTINCT
。(SQL操作集合。)

然后,使用
左连接。。。。为空
模式以获取不匹配的项

SELECT COUNT(*) number_of_unmatched_items
    FROM (        SELECT Column1 AS ent FROM TableA
                  UNION
                  SELECT Column2 AS ent FROM TableA
                  UNION
                  SELECT Column3 AS ent FROM TableA
                  UNION
                  SELECT Column4 AS ent FROM TableA
         ) a
    LEFT JOIN TableB b ON a.ent = b.entB
   WHERE b.entB IS NULL
WHERE…为NULL
从子查询中拾取在左联接中未满足
ON
条件的行

为了使这个过程非常快,我认为您需要在涉及到的
TableA
中的每一列上分别建立索引,以及在
TableB
中的
entB
上建立索引。但是您需要尝试一下,如果它仍然不能满足您的性能需求,请进行
解释

除非运行MySQL的机器真的缺少RAM,否则MySQL应该合理有效地处理这些事情


专业提示:您已经知道这一点。像
TableA
这样的非规范化表确实会扰乱查询性能。

一旦我们克服了所有关于
TableA
如何未规范化的抱怨,这并不难做到

我猜您需要统计表a中与表B不匹配的四列的值。如果你想要更复杂的东西,恕我直言,花点时间想清楚如何准确地描述它

从一个子查询开始,该子查询提供要比较的
表a
中的值。因为我们使用
UNION
而不是
UNION ALL
,所以我们可以免费获得
SELECT DISTINCT
。(SQL操作集合。)

然后,使用
左连接。。。。为空
模式以获取不匹配的项

SELECT COUNT(*) number_of_unmatched_items
    FROM (        SELECT Column1 AS ent FROM TableA
                  UNION
                  SELECT Column2 AS ent FROM TableA
                  UNION
                  SELECT Column3 AS ent FROM TableA
                  UNION
                  SELECT Column4 AS ent FROM TableA
         ) a
    LEFT JOIN TableB b ON a.ent = b.entB
   WHERE b.entB IS NULL
WHERE…为NULL
从子查询中拾取在左联接中未满足
ON
条件的行

为了使这个过程非常快,我认为您需要在涉及到的
TableA
中的每一列上分别建立索引,以及在
TableB
中的
entB
上建立索引。但是您需要尝试一下,如果它仍然不能满足您的性能需求,请进行
解释

除非运行MySQL的机器真的缺少RAM,否则MySQL应该合理有效地处理这些事情


专业提示:您已经知道这一点。像
TableA
这样的非规范化表确实会影响查询性能。

您似乎有几个column2。因此,这个问题是无法理解的。请看:@草莓这是一个明显的打字错误,而试图格式化的问题。。。现在已经解决了这类问题,这是糟糕的模式设计的严重症状。考虑是否有修改的范围。使用左外部连接。项目数默认为空。请参阅:@jdweng DefaultEmpty应该在我执行了4个查询后在我的代码中使用?您似乎有几个column2。因此,这个问题是无法理解的。请看:@草莓这是一个明显的打字错误,而试图格式化的问题。。。现在已经解决了这类问题,这是糟糕的模式设计的严重症状。考虑是否有修改的范围。使用左外部连接。项目数默认为空。请参阅:@jdweng DefaultEmpty应该在我执行了4个查询后在我的代码中使用?
endB
最好是
表b
中某个索引的开头。不过,查询可能需要几个小时,因为它需要对7000万行进行4次表扫描;再加上对较小的表进行4*70M的查找。我想让您知道,您的解决方案,至少在我的环境中是最慢的。我提出的第一个查询需要约5分钟才能执行,而不存在的版本需要约2分钟半。您的查询需要27分钟才能完成。建议将
UNION
更改为
UNION DISTINCT
,因为查询中包含的算法依赖于重复数据。
endB
最好是
表b
中某些索引的开始。不过,查询可能需要几个小时,因为它需要对7000万行进行4次表扫描;再加上对较小的表进行4*70M的查找。我想让您知道,您的解决方案,至少在我的环境中是最慢的。我提出的第一个查询需要约5分钟才能执行,而不存在的版本需要约2分钟半。您的查询需要27分钟才能完成。建议将
UNION
更改为
UNION DISTINCT
,因为