大家好 我在dripal中有一个自定义查询,这个查询是:
select count(distinct B.src)
from node A, url_alias B
where concat('node/',A.nid)= B.src;
现在,节点中的nid是主键,我已将src作为url_alias表中的索引。 等了一分多钟后我得到了这个:
+-----------------------+
| count(distinct B.src) |
+-----------------------+
| 325715 |
+-----------------------+
1 row in set (1 min 24.37 sec)
通过检查“解释”我得到了这个:
******************* 1. row ***************************
id: 1
select_type: SIMPLE
table: A
type: index
possible_keys: NULL
key: PRIMARY
key_len: 4
ref: NULL
rows: 325716
Extra: Using index
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: B
type: ALL
possible_keys: src_language_pid,src
key: NULL
key_len: NULL
ref: NULL
rows: 325928
Extra: Range checked for each record (index map: 0xC)
2 rows in set (0.00 sec)
现在我的问题是:为什么这个查询没有使用src的索引,以及如何优化它?
感谢您的帮助
答案 0 :(得分:1)
性能问题与concat
的使用有关
如果nid是一个整数,那么会导致很多工作。
我认为你必须在url_alias中添加一个索引的nid列。
不幸的是,您的表格不再正常化。
答案 1 :(得分:1)
COUNT(DISTINCT something)
对于非平凡的查询,如果计算的表达式中不存在唯一索引,则强制查询在运行查询时在其上构建唯一索引。
这本来就很慢,在大多数情况下都是:
不是必需的 - 解决方案:重写查询以便不需要使用
如果真的有必要使用unique,那么通常会更快地将查询分成两个,一个将获得查询的有用结果,该结果将创建B.src
的重复项和另一个查询这不需要不同的
最后,学会使用EXPLAIN,这样您就可以开始了解如何执行查询以及如何优化它们。
答案 2 :(得分:0)
1)解释这个查询,用EXPLAIN SLECT count ....启动它。
2)尝试将连接条件(where)作为连接移动:
select count(distinct B.src) from node A inner join url_alias B ON concat('node/',A.nid)=B.src
3)快速索引的东西应该是节点表中的“concat('node /',nid)”。这里必须为每一行节点重新编译这个东西。根据您的MySQL版本,您可能无法使用表达式(只是列)构建索引。所以你可以有一个专用于存储“concat('node /',nid)”的列,你可以将其称为node_nid并将其编入索引。并检查你还没有得到它!