1

这是我第一次尝试构建比仅使用 LIKE 功能更复杂的搜索功能。此搜索返回的结果非常完美,但运行速度非常慢。有什么我可以明智地改进代码以加快速度或我应该在数据库上查看的任何内容吗?还是我需要考虑更多的服务器功能?

非常感谢任何和所有的帮助。非常感谢!

function new_live_search($q){

    $title_score = 5;
    $tags_score = 10;
    $upvote_score = 1;

    $subdomain = $this->config->item('subdomain_name');

    $query = "SELECT DISTINCT results.*,
                ( 
                    ".$title_score."*(MATCH(title) AGAINST('$q' IN BOOLEAN MODE)) + 
                    ".$tags_score."*(MATCH(tags.name) AGAINST('$q' IN BOOLEAN MODE)) + 
                    ".$upvote_score."*usefulness
                ) AS score
                FROM results
                LEFT JOIN tags ON results.id = tags.result_id
                WHERE (scope = 'all' OR scope = '$subdomain') 
                        AND (published = 1)";

    $query .=  "
        HAVING score - usefulness > 0 
        ORDER BY score DESC, title";

    $query = $this->db->query($query);

    $results = array();


    foreach ($query->result() as $row){
        $results[] = $row;
    }

    return $results;

}
4

2 回答 2

1

来自 MySQL 文档

不幸的是,不可能将全文字段和普通(即整数)字段合并到一个索引中。由于每个查询只能使用一个索引,这似乎是一个问题

表布局:

id(integer primary key)|content(text fulltext indexed)|status(integer key)

请注意,执行以下查询,MySQL 将只使用一个索引。全文或状态(取决于实习生统计数据)。

查询一:

SELECT * FROM table WHERE MATCH(content) AGAINST('searchQuery') AND status = 1

但是,仍然可以在一个查询中使用两个索引。您将需要一个关于 id、status 对的新索引并使用 join。因此 MySQL 将能够为每个表使用一个索引。

查询 2:

SELECT t1.* FROM table t1
LEFT JOIN table t2 ON(t1.id=t2.id)
WHERE MATCH(t1.content) AGAINST('searchQuery') AND status=1

至少在我的情况下,查询 2 的运行速度将明显快于查询 1:) 请注意开销:您需要为每一行提供一个 id 和一个跨越以 id 开头的所需字段的键。

请参阅MySQL 文档上的全文搜索
希望对您有所帮助

于 2012-12-21T11:12:55.023 回答
0

如果您查看查询,则查询的全文部分实际上不会限制搜索。使用类似下面的东西应该会提高性能一点。

SELECT DISTINCT results.*, (
    $title_score * (MATCH(title) AGAINST('$q' IN BOOLEAN MODE)) + 
    $tags_score * (MATCH(tags.name) AGAINST('$q' IN BOOLEAN MODE)) + 
    $upvote_score * usefulness
) AS score
FROM results
LEFT JOIN tags ON results.id = tags.result_id
WHERE (scope = 'all' OR scope = '$subdomain') 
    AND (published = 1)
    AND (
        (MATCH(title) AGAINST('$q' IN BOOLEAN MODE)) OR
        (MATCH(tags.name) AGAINST('$q' IN BOOLEAN MODE)))
HAVING score - usefulness > 0 
ORDER BY score DESC, title
于 2012-12-21T12:20:15.657 回答