PHP加速MySql查询

5 php mysql performance laravel laravel-5

我正在使用Laravel PHP框架.

说我有这样的问题:

public function order($orderby){
        \DB::connection()->disableQueryLog();

        if($orderby == "level"){
            $clan = Clans::orderBy('level', 'DESC')
            ->orderBy('exp', 'DESC')
            ->paginate(100,['id', 'clanid', 'name', 'level', 'exp', 'warwinpercent', 'warswon', 'playercount', 'score']);
        }elseif($orderby == "score"){
            $clan = Clans::orderBy('score', 'DESC')
            ->paginate(100,['id', 'clanid', 'name', 'level', 'exp', 'warwinpercent', 'warswon', 'playercount', 'score']);
        }elseif($orderby == "warwinpercent"){
            $clan = Clans::orderBy('warwinpercent', 'DESC')
            ->where('warswon', '>=', '100')
            ->paginate(100,['id', 'clanid', 'name', 'level', 'exp', 'warwinpercent', 'warswon', 'playercount', 'score']);
        }else
            $clan = Clans::paginate(100,['id', 'clanid', 'name', 'level', 'exp', 'warwinpercent', 'warswon', 'playercount', 'score']);

        \DB::connection()->enableQueryLog();

        return view('clans.index')->with('clan', $clan);
    }
Run Code Online (Sandbox Code Playgroud)

这些大约需要10-15秒才能运行.

我有一个这样的:

public function index(){

        $clan = Clans::orderBy('clanid', 'ASC')
            ->paginate(100,['id', 'clanid', 'name', 'level', 'exp', 'warwinpercent', 'warswon', 'playercount', 'score']);

        return view('clans.index')->with('clan', $clan);
    }
Run Code Online (Sandbox Code Playgroud)

几乎立即加载.

为什么前三个比前一个花费的时间长得多?我为我需要在表格中搜索的所有变量添加了一个索引,但它仍然需要很长时间才能工作.我是否需要在MySql端做任何事情才能重建索引?我已经尝试过优化表,我也多次重启MySql服务..

如果无法加速它们,那么有一种简单的方法可以在加载页面时向用户显示加载动画吗?

谢谢!

UPDATE

以下是快速查询的Explain结果:

explain extended select `id`, `clanid`, `name`, `level`, `exp`, `warwinpercent`, `warswon`, `playercount`, `score` from `clans` order by `clanid` asc limit 100 offset 0
Run Code Online (Sandbox Code Playgroud)

这是orderBy level查询的Explain结果.

explain extended select `id`, `clanid`, `name`, `level`, `exp`, `warwinpercent`, `warswon`, `playercount`, `score` from `clans` order by `level` desc, `exp` desc limit 100 offset 0
Run Code Online (Sandbox Code Playgroud)

这是SHOW INDEX FROM clans结果.

更新2

我也有这个代码在列中搜索字符串 name

public function clans(){
        if((isset($_GET['search'])) && $_GET['search'] != ""){

            $search = $_GET['search'];
            $result = Clans::where('name', 'LIKE', '%'.$search.'%')->paginate(100,['id', 'clanid', 'name', 'level', 'exp', 'warwinpercent', 'warswon', 'playercount', 'score']);
            $data = array(
                'result'  => $result,
                'search'   => $search
            );

            return view('search.clans')->with($data);

        }else
            return view('errors.1')->with('message', 'You entered an invalid search term');
    }
Run Code Online (Sandbox Code Playgroud)

这可能需要几秒钟才能加载..

解释查询:

explain extended select `id`, `clanid`, `name`, `level`, `exp`, `warwinpercent`, `warswon`, `playercount`, `score` from `clans` where `name` LIKE '%lol%' limit 100 offset 0
Run Code Online (Sandbox Code Playgroud)

Dre*_*rew 0

查询 2 的问题(查询 1 看起来不错)。但是对于两个,虽然你有一个级别的索引,但是基数太高以至于mysql放弃它。行数 170K,基数 159k

\n\n

从标题为MySQL 如何使用索引的手册页中:

\n\n
\n

对于小表或报表查询处理大部分或全部行的大表的查询,索引不太重要。当查询需要访问大多数行时,按顺序读取比通过索引工作要快。即使查询不需要所有行,顺序读取也会最大限度地减少磁盘寻道。有关详细信息,请参阅第 8.2.1.16 节\n \xe2\x80\x9c如何避免全表扫描\xe2\x80\x9d。

\n
\n\n

综合指数

\n\n

复合(多列)索引是 2 个或更多列作为组合的索引。可以是唯一的,也可以不是。

\n\n
CREATE UNIQUE INDEX `thing_my_composite` ON thing (position,email,dob); -- forbid dupes hereafter\n
Run Code Online (Sandbox Code Playgroud)\n\n

覆盖指数

\n\n

覆盖索引是一种可以通过快速浏览索引 B 树来解决查询的索引,而不需要查找实际的表数据页。这些是速度的终极必杀技。Percona关于它的快速文章。

\n\n

全文搜索(基于 OP 评论)

\n\n

以下是关于全文搜索功能的手册页的摘录:

\n\n
\n

MySQL 支持全文索引和搜索:

\n\n

MySQL中的全文索引是FULLTEXT类型的索引。

\n\n

全文索引只能与 MyISAM 表一起使用。(在 MySQL 5.6\n 及更高版本中,它们还可以与 InnoDB 表一起使用。)只能为 CHAR、VARCHAR 或 TEXT 列创建全文索引\n。

\n\n

创建表时,可以在 CREATE TABLE 语句中给出 FULLTEXT 索引定义,或者稍后使用 ALTER TABLE 或 CREATE INDEX 添加。

\n\n

对于大型数据集,将数据加载到没有 FULLTEXT 索引的表中然后创建索引比将数据加载到具有现有 FULLTEXT 索引的表要快得多。

\n
\n