在表格中搜索并获取结果和结果数量的最佳方法(MySQL)
我有一个"项目"表和一个" itemkeywords"表。
当用户搜索关键字时,我想给他一页结果,再加上结果总数。
我目前正在做的是(对于搜索" a b c"的用户:
SELECT DISTINCT {fields I want} FROM itemkeywords JOIN items WHERE (keyword = 'a' or keyword='b' or keyword='c' ORDER BY "my magic criteria" LIMIT 20.10
然后我用一个计数做相同的查询
SELECT COUNT(*) FROM itemkeywords JOIN items WHERE (keyword = 'a' or keyword='b' or keyword='c'
这可能会得到一个相当大的表,我认为这种解决方案非常麻烦...
但是我想不出更好的办法了。
避免两次访问MySQL的明显替代方法是只执行第一个查询,不带LIMIT子句,然后导航到正确的记录以显示相应的页面,然后导航到记录集的末尾以计算结果甚至更糟...
有任何想法吗?
注意:我使用的是ASP.Net和MySQL,而不是PHP
解决方案
在受限选择中的选择之后添加SQL_CALC_FOUND_ROWS,然后在第一个选择完成后执行" SELECT FOUND_ROWS()"。
例子:
mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name -> WHERE id > 100 LIMIT 10; mysql> SELECT FOUND_ROWS();
我们有2个选择:
MySQL API应该具有一个返回行数的函数。使用较旧的API,其mysql_num_rows()。如果我们使用的是无缓冲查询,则此方法将无效。
一种更简单的方法可能是合并两个查询:
SELECT DISTINCT {fields I want}, count(*) as results FROM itemkeywords JOIN items WHERE (keyword = 'a' or keyword='b' or keyword='c' ORDER BY "my magic criteria" LIMIT 20.10
我做了一些测试,并且count(*)函数不受limit子句的影响。我将首先使用DESCRIBE
进行测试。我不知道它将对查询速度产生多大的影响。仅需要给出前10个结果的查询应该比必须查找所有结果的查询短,然后是前10个查询,但是在这里我可能是错的。
我们可能会在第一条语句中查看MySQL" SQL_CALC_FOUND_ROWS",然后在第二条语句" SELECT FOUND_ROWS()"中查看,这至少可以防止我们执行2个数据查询,但仍然倾向于对整个表进行一次扫描。
参见http://dev.mysql.com/doc/refman/5.0/en/select.html和
http://dev.mysql.com/doc/refman/5.0/zh-CN/information-functions.html
最好考虑一下:我们真的需要此功能吗?
如果我们真的担心性能,并且最终需要进行两个查询,则可能要考虑缓存匹配的总数,因为在用户浏览结果页面时,匹配的总数不会改变。