假设我有以下基本 MySQL 数据:
CREATE TABLE my_words (my_word VARCHAR(255));
INSERT INTO my_words VALUES ('dog');
INSERT INTO my_words VALUES ('cat');
INSERT INTO my_words VALUES ('tree');
INSERT INTO my_words VALUES ('ball');
INSERT INTO my_words VALUES ('life');
INSERT INTO my_words VALUES ('complex');
INSERT INTO my_words VALUES ('digeridoo');
INSERT INTO my_words VALUES ('hamster');
INSERT INTO my_words VALUES ('it');
INSERT INTO my_words VALUES ('house');
INSERT INTO my_words VALUES ('love');
INSERT INTO my_words VALUES ('zealous');
INSERT INTO my_words VALUES ('nevis');
INSERT INTO my_words VALUES ('mountain');
INSERT INTO my_words VALUES ('call');
INSERT INTO my_words VALUES ('nail');
INSERT INTO my_words VALUES ('rat');
INSERT INTO my_words VALUES ('hat');
SELECT CONCAT(w1.my_word, w2.my_word) joined
FROM my_words w1, my_words w2
WHERE LENGTH(CONCAT(w1.my_word, w2.my_word)) = 8
ORDER BY RAND() LIMIT 5;
我可以在最后编写 SQL 语句来生成由 2 个单词组成的 5 个随机连接字符串的列表,其中字符串的总长度为 8 个字符。
这对于像我在示例中得到的简单数据表来说效果很好。
然而,我正在使用的“真实”表包含大约 6,200 行。
如果我尝试相同类型的语句,则需要 10 秒才能生成 5 个字符串。
我猜想 SQL 效率非常低,因为它每次都会搜索表两次,并且这些表没有以任何方式连接。
我想知道是否有一种更简单的方法来从表中提取由 2 个单词组成的单词字符串,其中连接字符串的长度为 8 个字符长(尽管这可以改变 - 我只是使用 8 作为示例)。
Thanks
Update 1
解释计划:
EXPLAIN
SELECT CONCAT(w1.fld_un, w2.fld_un) joined
FROM j_un w1
JOIN j_un w2 ON w1.fld_len = 8 - w2.fld_len
WHERE w2.fld_len < 8
ORDER BY RAND()
LIMIT 5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE w2 range un_len un_len 5 \N 2694 Using where; Using temporary; Using filesort
1 SIMPLE w1 ref un_len un_len 5 func 527 Using where
Update 2
我不确定它是否相关,但“fld_un”表大约有 6,200 行。
“word”保存在“fld_un”列中。
表的结构是:
Field Type Null Key Default Extra
fld_id int(11) NO PRI NULL auto_increment
fld_un varchar(255) YES NULL
fld_cat_id int(11) YES MUL NULL
fld_len int(2) NO MUL NULL
表中存在这些索引:
Keyname Type Cardinality Field
PRIMARY PRIMARY 6318 fld_id
cat INDEX 15 fld_cat_id
bob INDEX 11 fld_len
表上已经有主索引有关系吗?我认为从技术上讲我不需要这个。
陈述:
SELECT CONCAT(word1, word2) joined
FROM (
SELECT w1.fld_un word1, w2.fld_un word2
FROM j_un2 w1
JOIN j_un2 w2 ON w1.fld_len = 8 - w2.fld_len
WHERE w2.fld_len < 8
ORDER BY RAND()
LIMIT 5) x;
查询花费了 23.6805 秒
解释计划:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
2 DERIVED w2 range bob bob 4 NULL 4627 Using where; Using temporary; Using filesort
2 DERIVED w1 ref bob bob 4 func 527 Using where
当我按照 Thorsten Kettner 的建议修改“bob”索引以包含 2 列时:
Keyname Type Cardinality Field
bob INDEX 11 fld_len, fld_un
并重新测试:
SELECT CONCAT(word1, word2) joined
FROM (
SELECT w1.fld_un word1, w2.fld_un word2
FROM j_un2 w1
JOIN j_un2 w2 ON w1.fld_len = 8 - w2.fld_len
WHERE w2.fld_len < 8
ORDER BY RAND()
LIMIT 5) x;
该查询花了 30.3394 秒返回 5 行。
解释计划:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
2 DERIVED w2 range bob bob 4 NULL 4211 Using where; Using temporary; Using filesort
2 DERIVED w1 ref bob bob 4 func 527 Using where
Update 3
在没有“order by rand()”的情况下运行,它在 0.0011 秒内运行!