我有这个问题:
SELECT stringa FROM table WHERE stringb = 'x' OR stringb = 'y' OR stringb = 'z'
这只是一个缩短版本,实际查询在一个查询中有超过1,000个“OR”子句。
执行需要几分钟,这是不行的。
我尝试过这样的一次查询:
SELECT stringa FROM table WHERE stringb = 'x'
SELECT stringa FROM table WHERE stringb = 'y'
SELECT stringa FROM table WHERE stringb = 'z'
但这需要更长的时间。我也试过这样一个大问题:
SELECT stringa FROM table WHERE stringb = 'x'
UNION
SELECT stringa FROM table WHERE stringb = 'y'
UNION
SELECT stringa FROM table WHERE stringb = 'z'
但这又花了更长时间。
如果有人有任何提高性能的建议,我们将不胜感激。我的桌子是MyISAM,如果它很重要的话。
编辑:
这是表格的结构:
列:
key (CHAR PRIMARY), stringa (CHAR), stringb (CHAR)
行如下所示:( key - stringa - stringb)
key - a - b
key - a - c
key - a - d
key - a - e
key - a - f
key - b - b
key - b - c
key - b - d
key - c - c
key - c - d
key - c - f
key - d - f
等。等等。有近百万行。
我需要选择所有'stringa',其中'stringb'等于OR b OR c等。
当然stringa和stringb不仅仅是'a'和'b',它们包含长度在3到80个字符之间的CHAR。
我希望以某种方式有所帮助
答案 0 :(得分:2)
首先,将列数据类型更改为varchar
。尽管您可能已经听说char
据说速度更快,但权衡的是为I / O的大量增加(非常糟糕的交易)节省一点CPU。
其次,如果列stringb
上没有索引,则需要索引。索引不必是唯一的。
第三,许多DBMS对数千个OR条件没有问题,但通常这样的事情表示为WHERE stringb IN ('a', 'b', 'c', 'd', 'e' ...)
。
最后,在许多情况下,如果不提供卓越的性能(尽管在某些DBMS或情况下可能),JOIN至少会提供更高的清晰度和重用性。例如,许多人做的一件事是创建一个字符串拆分函数,当以'a,b,c,d,e'
格式传递字符串时,返回一个包含单独行中每个项目的行集。然后加入到这个行集很简单,只要客户端可以构造要拆分的字符串,就可以动态地驱动查询。
这是一种可能的联接方式:
CREATE TEMPORARY TABLE Keys (
Value varchar(30)
);
INSERT Keys VALUES ('x');
INSERT Keys VALUES ('y');
INSERT Keys VALUES ('z');
SELECT T.SomeColumns
FROM
YourTable T
INNER JOIN Keys K
ON T.stringb = K.Value
答案 1 :(得分:1)
您需要在stringb列上创建索引。
您的问题更多的是您正在进行全表扫描,而不是“或”的效率。传统的方法是在“in”语句中路由值列表。但是,在某些数据库中,这对性能没有影响。
另外,您的字段是在char或varchar中声明的吗?如果它们是char,那么这可能是性能问题的根源。这些将用空格填充,大大增加了存储空间并延长了比较。
答案 2 :(得分:1)
首先,正如其他人所建议的,VARCHAR是比CHAR更好的选择。 CHAR不会更快。
考虑通过KEY(stringb)PARTITIONS 8(这是任意的)对表进行分区,并在(stringb,stringa)上添加索引。这将减少IO,覆盖索引将使返回数据更快。
运行等式查找IN PARALLEL。运行:
SELECT stringa FROM table WHERE stringb in('x',...)
SELECT stringa FROM table WHERE stringb in('y',...)
SELECT stringa FROM table WHERE stringb in('z',...)
三个线程将导致显着的性能提升。
您只需将结果重新组合在一起并不困难。如果要查看,Shard-Query可用于自动将查询与IN()列表并行化:
答案 3 :(得分:0)
尝试
SELECT stringa FROM table WHERE stringb = 'x'
UNION ALL
SELECT stringa FROM table WHERE stringb = 'y'
UNION ALL
SELECT stringa FROM table WHERE stringb = 'z'
或
SELECT stringa FROM table WHERE stringb in ( 'x', 'y', 'z')
或@ ErikE的解决方案,如果你真的有一千个OR条件。
UNION ALL应该比UNON快得多,因为你的选择是互斥的,你不需要让查询删除表达联合的方式。
答案 4 :(得分:0)
虽然我认为@HLGEM的第二个答案是最好的,但您也可以尝试在查询中使用正则表达式来表示列stringb。