我有一个相当静态的(InnoDB)表T
,其中有四列:A
,B
,C
和D
。
我首先希望确定A
的给定值,B
在所有记录中产生唯一C
的值。我的尝试如下:
CREATE PROCEDURE P(x int) BEGIN
SELECT B
FROM T
WHERE A = x
GROUP BY B
HAVING COUNT(DISTINCT C) = COUNT(C);
END
但是,尽管列GROUP BY
上有索引,但引入B
会大大降低此查询的性能。有没有更有效的方法,或者我可以以某种方式提高此查询的性能?
为了回应下面的Daan评论,该表格创建时带有以下内容:
CREATE TABLE T (
A int(11) NOT NULL,
B varchar(45) NOT NULL,
C varchar(255) DEFAULT NULL,
D int(11) NOT NULL,
PRIMARY KEY (A,B,D),
KEY iA (A),
KEY iB (B),
KEY iC (C)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
在回应下面的tombom评论时,查询解释如下:
+----+-------------+-------+------+---------------+---------+---------+-------+---------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+---------+---------+-------+---------+-----------------------------+
| 1 | SIMPLE | T | ref | PRIMARY,iA | PRIMARY | 4 | const | 2603472 | Using where; Using filesort |
+----+-------------+-------+------+---------------+---------+---------+-------+---------+-----------------------------+
答案 0 :(得分:2)
您可以尝试各种方法:
1。)像这样
创建A,B和C的索引CREATE INDEX iABC ON T(A,B,C);
由于问题很可能是HAVING
子句(C列为varchar(255)在这种情况下不是很好):
2。)创建(临时或非临时)表,然后加入它。这可能会加快速度。以下非临时性可能更快,因为您可以在其上创建索引。
CREATE TABLE foo AS
SELECT
B,
COUNT(DISTINCT C) AS distinctC,
COUNT(C) AS countC
FROM T
GROUP BY B;
CREATE INDEX idx_b ON foo(B);
CREATE INDEX idx_cc ON foo(distinctC, countC);
SELECT T.B
FROM T
INNER JOIN foo ON T.B = foo.B
WHERE A = x
AND foo.distinctC = foo.countC
GROUP BY B
ORDER BY NULL; /*see Daan's comment*/
3.。)将C列放在一个单独的表中,其中实际内容由INT
标识。
CREATE TABLE T (
A int(11) NOT NULL,
B varchar(45) NOT NULL,
C int(11) DEFAULT NULL,
PRIMARY KEY (A,B),
KEY iB (B),
KEY iC (C)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE C (
id int(11) NOT NULL,
Ccontent varchar(255) DEFAULT NULL
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
然后像往常一样做所有事情,稍后在将结果输出到表C时加入,用实际的varchar值转换id。
我更喜欢选项2.顺便说一句,你的索引iA可能没用。
答案 1 :(得分:0)
为什么不改为COUNT(DISTINCT C)=1
?