一、Laravel框架面试题|从基础到架构的完整知识链
作为当前国内互联网企业使用最广泛的PHP框架(据2024年PHP官方生态报告,Laravel市场占有率达68.7%),其面试题深度与广度远超“会写控制器”层面。以下按考察频次与难度梯度分类整理高频考点:
1.1 Laravel核心特性与设计哲学
问:Laravel与传统MVC框架(如ThinkPHP 3.2)相比,最大差异是什么?
Laravel采用“服务容器驱动一切”的设计思想——控制器、中间件、事件、队列、广播等全部通过服务容器统一管理生命周期。例如中间件在容器中注册为闭包或类,由Kernel统一调度,而ThinkPHP 3.x的中间件需手动在控制器构造器中调用。这种架构提升了可测试性与解耦能力。
问:请解释Laravel的“服务容器”(Service Container)与“服务提供者”(Service Provider)的关系。
- 服务容器:绑定接口与实现的“注册表”,支持单例(singleton)、实例(instance)、闭包(bind)三种绑定方式。
- 服务提供者:负责向容器注册服务的“启动器”,每个Provider对应一个模块(如Auth、Database),在`register()`中绑定,`boot()`中执行初始化逻辑。
典型代码示例:
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->singleton('cache.manager', function ($app) {
return new CacheManager($app);
});
}
public function boot()
{
// 注册视图合成器
View::composer('layouts.sidebar', SidebarComposer::class);
}
1.2 请求生命周期与核心组件
问:一次HTTP请求进入Laravel后,经过哪些关键组件?请按顺序说明。
应用入口,加载`bootstrap/app.php`创建应用实例。
通过`$kernel->handle($request)`进入内核,执行中间件栈(`App\Http\Kernel`中定义)。
路由分发:匹配URL → 解析中间件 → 实例化控制器 → 调用方法。
响应发送前经`ObfuscateSessionCookieMiddleware`等处理,最终通过SAPI发送至客户端。
1.3 中间件与依赖注入
问:如何在中间件中注入服务?是否支持构造器注入?
答:支持!Laravel中间件默认通过服务容器解析,因此可使用构造器注入或方法注入。例如:
class LogRequestMiddleware
{
protected $logger;
// 构造器注入
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function handle($request, Closure $next)
{
$this->logger->info('Request: ' . $request->path());
return $next($request);
}
}
2.1 Eloquent ORM核心机制
问:`with()`与`load()`的区别是什么?在什么场景下必须用`with()`?
- `with()`:在查询主模型时预先加载关联(N+1问题优化),必须在构建查询链时调用(如`User::with('posts')->get()`)。
- `load()`:对已存在的模型集合动态加载关联(懒加载),适用于动态条件下的关联补充。
避坑指南:若在循环中对单个模型调用`$user->posts`,即使已`with('posts')`,仍会触发新查询!必须使用`$user->load('posts')`或直接访问已加载的`$user->posts`集合。
2.2 关联关系与查询优化
问:如何实现“用户-文章-评论”的三级关联查询?写出最高效的Eloquent语句。
// 模型定义
class User extends Model {
public function posts() {
return $this->hasMany(Post::class);
}
}
class Post extends Model {
public function comments() {
return $this->hasMany(Comment::class);
}
public function user() {
return $this->belongsTo(User::class);
}
}
// 高效查询(预加载两层)
$users = User::with('posts.comments')->get();
// 输出时无N+1查询
foreach ($users as $user) {
foreach ($user->posts as $post) {
echo $post->comments->count(); // 直接使用已加载数据
}
}
2.3 查询构造器 vs Eloquent
问:何时应使用`DB::table()`而非Eloquent模型?
✅ 读多写少的报表统计(如日志聚合)
✅ 跨数据库查询(如同时操作MySQL和Redis)
✅ 复杂JOIN场景(Eloquent对多表JOIN支持较弱)
❌ 涉及模型业务逻辑(如事件触发、访问器/修改器)
3.1 队列与事件监听
问:Laravel队列系统如何保证消息不丢失?事务性消息如何处理?
答:核心机制如下:
- 数据库驱动:消息存入`jobs`表,失败后由`php artisan queue:failed`重试。
- 事务绑定:`DB::beginTransaction()` + `DB::commit()`包裹业务逻辑,确保数据一致性。
- 延迟重试:`->delay(now()->addMinutes(5))`实现指数退避重试。
典型代码:
DB::beginTransaction();
try {
$order = Order::create($data);
dispatch(new ProcessOrder($order))->onQueue('high');
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
logger()->error('Order failed: ' . $e->getMessage());
}
3.2 服务容器扩展点
问:如何在Laravel中注册一个自定义的`EmailService`接口实现?要求支持多环境切换。
// 1. 定义接口
interface EmailService {
public function send($to, $subject, $body);
}
// 2. 生产环境实现
class SmtpEmailService implements EmailService { ... }
// 3. 开发环境实现(模拟)
class MockEmailService implements EmailService { ... }
// 4. 在AppServiceProvider中动态绑定
public function register()
{
if ($this->app->environment('production')) {
$this->app->singleton(EmailService::class, SmtpEmailService::class);
} else {
$this->app->singleton(EmailService::class, MockEmailService::class);
}
}
网友还关心
Laravel性能调优
开启`config/cache.php`中的`redis`缓存驱动;使用`php artisan config:cache`预编译配置;避免在 Blade 中使用复杂逻辑;启用OPcache。
微服务架构整合
通过`Laravel Octane` + `Swoole`提升性能;使用`Laravel Horizon`监控队列;结合`Laravel Passport`实现OAuth2认证。
与Lumen对比
Lumen是轻量级微服务框架(无Session/Cookie),适合API服务;Laravel功能完整,适合全栈应用。Lumen 8+已支持Swoole,性能接近Go。
二、ThinkPHP框架面试题|国产框架的演进与实战差异
ThinkPHP(现为ThinkPHP 6.x)是国内普及率最高的PHP框架之一,其“简单易学”特性使其成为高校与中小企业首选。但面试中常被追问与Laravel的差异点,需重点掌握其请求生命周期与路由机制的特殊性。
1.1 请求入口与路由解析
问:ThinkPHP的入口文件`public/index.php`做了什么?与Laravel有何不同?
答:核心逻辑为:
// ThinkPHP 6.x 入口
define('APP_PATH', __DIR__ . '/../application/');
require __DIR__ . '/../vendor/topthink/think-phpthink-loader/src/Loader.php';
use think\Loader;
use think\App;
// 自动加载
Loader::register();
// 实例化应用
$app = new App();
// 处理HTTP请求
$http = $app->http;
$response = $http->run();
$response->send();
$http->end($response);
关键差异:ThinkPHP使用`Loader::register()`注册自动加载器,而Laravel依赖Composer的`vendor/autoload.php`;ThinkPHP的路由需手动在`route/app.php`中定义,Laravel则支持隐式路由(自动映射控制器方法)。
1.2 控制器与视图渲染
问:ThinkPHP的视图渲染机制与Laravel有何区别?
• ThinkPHP默认使用内置模板引擎(非Blade),语法为`{$var}`或`{volist}`循环标签;
• 视图变量通过`fetch()`方法传递:`return view('index/index', ['name' => 'ThinkPHP']);`
• Laravel使用Blade引擎,变量用`{{ $name }}`,视图返回:`return view('welcome', ['name' => 'Laravel']);`
1.3 数据库操作
问:ThinkPHP的Db类与Eloquent相比,优势与劣势是什么?
| 特性 | ThinkPHP Db类 | Laravel Eloquent |
|---|---|---|
| 查询语法 | 链式调用(`where()->order()->limit()`) | 静态方法+闭包(`where('id', 1)`) |
| 关联查询 | 需手动join,无ORM关联定义 | 模型定义关系(`hasMany()`),自动JOIN |
| 事务支持 | `Db::startTrans()...commit()` | `DB::transaction(fn() => ...)` |
典型代码对比:
// ThinkPHP:手动JOIN
$result = Db::name('user')
->alias('u')
->join('post p', 'u.id = p.user_id')
->field('u.name, p.title')
->select();
// Laravel:关联查询
$users = User::with('posts')->get();
2.1 ThinkPHP 6.x重大升级
问:ThinkPHP 6.x相比5.x有哪些关键改进?
- ✅ PSR规范兼容:全面支持PSR-7(请求/响应)、PSR-11(容器)、PSR-15(中间件)。
- ✅ 服务容器重构:使用`think\Container`替代旧版`think\facade\App`。
- ✅ 中间件调整:中间件需实现`__invoke($request, $next)`,支持闭包定义。
- ✅ 数据库连接池:支持`mysqlnd`连接池,提升并发性能。
2.2 自动验证与数据过滤
问:ThinkPHP如何实现控制器自动验证?与Laravel的FormRequest有何异同?
// ThinkPHP 6:控制器内验证
public function save(Request $request)
{
$validate = validate(App::class);
if (!$validate->check($request->post())) {
return json(['error' => $validate->getError()]);
}
// 业务逻辑...
}
// 或使用验证器类
class UserValidate extends Validate
{
protected $rule = [
'name' => 'require|max:25',
'email' => 'email'
];
}
对比Laravel:Laravel强制使用`FormRequest`类,验证逻辑与控制器分离更彻底;ThinkPHP更灵活,可选择在控制器内或验证器类中定义。
网友还关心
ThinkPHP与微信小程序对接
通过`think\middleware\CheckRequestMiddleware`处理Token;使用`think\captcha`生成图形验证码;API接口统一返回格式(code/message/data)。
性能优化方案
开启`config/app.php`中的`app_debug => false`;使用`cache`缓存数据库查询;启用`ob_gzhandler`压缩输出;避免在模型中写复杂SQL。
与TP3.x兼容性
TP6不兼容TP3.x语法!路由定义、控制器继承、数据库操作全部重构。迁移需重写配置与业务逻辑。
三、Yii框架面试题|企业级开发的严谨与高效
Yii(读作“易”)以高性能与安全性著称,被阿里、腾讯等企业用于核心系统。其面试题常聚焦于行为(Behavior)、过滤器(Filter)与缓存机制的底层实现。
1.1 行为(Behavior)与事件系统
问:Yii的行为(Behavior)机制如何工作?与Laravel的Observer有何区别?
答:Yii的行为通过`attachBehavior()`将方法动态注入模型,本质是组合优于继承的实现:
// 定义行为
class TimestampBehavior extends Behavior
{
public function events()
{
return [
ActiveRecord::EVENT_BEFORE_INSERT => 'beforeInsert',
];
}
public function beforeInsert($event)
{
$this->owner->created_at = time();
}
}
// 使用行为
class User extends ActiveRecord
{
public function behaviors()
{
return [
TimestampBehavior::class,
];
}
}
对比Laravel:Laravel使用事件监听器(`Event::listen()`)解耦逻辑,但需注册事件类;Yii的行为更轻量,直接在模型内声明即可。
1.2 过滤器(Filter)与控制器生命周期
问:Yii的过滤器(Filter)与Laravel中间件有何异同?
- 相同点:均支持请求前/响应后处理(如权限检查、日志记录)。
- 不同点:Yii过滤器是控制器内的方法(`filters()`定义),Laravel中间件是独立类;Yii支持`beforeFilter()`/`afterFilter()`,Laravel需`handle()`返回响应。
典型代码:
// Yii控制器过滤器
public function filters()
{
return [
'accessControl', // 先执行
'postOnly + edit', // 仅POST请求+edit动作
];
}
public function filterAccessControl($filterChain)
{
if (!Yii::app()->user->isGuest) {
$filterChain->run(); // 继续执行
} else {
$this->redirect('/login');
}
}
2.1 XSS与CSRF防护
问:Yii如何自动防御XSS攻击?开发者需注意什么?
• Yii视图中``自动转义输出;
• 表单输入需用`CHtml::encode()`包裹;
• 禁止直接`echo $data`或`print_r($data)`输出用户输入!
2.2 缓存与数据分片
问:Yii如何实现数据库查询缓存?支持分片存储吗?
答:通过`CDbCache`实现:
// 查询缓存
$cache = Yii::app()->cache;
$key = 'user_list_' . $page;
$data = $cache->get($key);
if ($data === false) {
$data = User::model()->findAll();
$cache->set($key, $data, 3600); // 缓存1小时
}
return $data;
分片支持:Yii本身不直接支持分片,但可通过`CCache::set()`的`expire`参数模拟,或结合`Redis Cluster`实现。
网友还关心
Yii与Yii2差异
Yii2采用PSR规范,支持Composer;性能提升30%;内置RESTful API支持;默认模板引擎改为Twig(可选)。Yii1已停止维护。
高并发优化方案
使用`CDbCache`替代`CFileCache`;开启`Yii::app()->request->enableCsrfValidation = false`(仅API场景);数据库读写分离;启用APCu本地缓存。
与Laravel性能对比
纯API场景:Laravel + Swoole ≈ Yii;传统MVC:Yii响应速度更快(无自动加载开销);Laravel开发体验更优。
四、Symfony框架面试题|组件化架构的基石
Symfony是Laravel之父Fabien Potencier的作品,以组件化闻名。许多Laravel底层依赖(如`HttpKernel`、`Finder`、`Yaml`)均来自Symfony。面试常考其事件驱动架构与组件复用能力。
1.1 组件解耦与复用
问:为什么说“Laravel是Symfony的子集”?请举例说明。
答:Laravel大量复用Symfony组件,例如:
- `Illuminate\Http\Request` → `Symfony\Component\HttpFoundation\Request`
- `Illuminate\Support\Facades\DB` → `Symfony\Component\HttpFoundation\Cookie`
- `php artisan make:command` → `Symfony\Component\Console\Command\Command`
这意味着:掌握Symfony组件可直接迁移至Laravel开发。
1.2 HttpKernel架构
问:请描述Symfony的`HttpKernelInterface`请求处理流程。
从SAPI获取原始数据,封装为`Request`对象。
`RouterListener`根据URL匹配路由配置,生成`Route`对象。
`ControllerResolver`将路由中的`_controller`解析为可调用的控制器方法。
`kernel.request` → `kernel.controller` → `kernel.response`
2.1 EventDispatcher机制
问:如何自定义一个`user.registered`事件?请写出完整流程。
// 1. 定义事件类
class UserRegisteredEvent extends Event
{
private $user;
public function __construct(User $user) {
$this->user = $user;
}
public function getUser(): User {
return $this->user;
}
}
// 2. 事件订阅者
class UserListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return ['user.registered' => 'onUserRegistered'];
}
public function onUserRegistered(UserRegisteredEvent $event)
{
$user = $event->getUser();
// 发送欢迎邮件...
}
}
// 3. 在控制器中触发
$dispatcher = $this->container->get('event_dispatcher');
$dispatcher->dispatch('user.registered', new UserRegisteredEvent($user));
网友还关心
Symfony vs Laravel选型
需快速上线 → 选Laravel;需高度定制化/企业级微服务 → 选Symfony;学习曲线:Symfony > Laravel。
常用组件推荐
`Validator`(独立验证)、`Form`(表单构建)、`Security`(权限管理)、`Messenger`(消息队列)。
性能调优技巧
开启`CacheWarmup`;使用`APCu`缓存元数据;禁用`debug`模式;`composer dump-autoload --optimize`。
五、CodeIgniter框架面试题|轻量级框架的精巧设计
CodeIgniter(CI)是最早的PHP MVC框架之一,以“小而美”著称。虽近年热度下降,但在传统企业系统中仍有大量存量项目。面试常考其核心类加载机制与安全性设计。
1.1 自动加载与基类
问:CI的`CI_Controller`与`MY_Controller`有何关系?如何扩展?
答:CI采用“基类继承”模式:
// application/core/MY_Controller.php
class MY_Controller extends CI_Controller {
public function __construct() {
parent::__construct();
// 全局初始化(如权限检查)
if (!$this->session->userdata('logged_in')) {
redirect('/login');
}
}
}
// 控制器继承MY_Controller
class Dashboard extends MY_Controller {
public function index() {
$this->load->view('dashboard');
}
}
优势:避免重复代码,统一入口逻辑;注意:CI3要求文件名与类名严格匹配(大小写敏感)。
1.2 数据库操作
问:CI的Active Record与Laravel Eloquent有何差异?
- CI的Active Record是链式调用(`$this->db->where()->get()`),非ORM;
- 无关联关系定义,需手动`join()`;
- `$this->db->insert_id()`直接获取主键,无需返回对象。
典型代码:
$data = [
'name' => $this->input->post('name'),
'email' => $this->input->post('email')
];
$this->db->insert('users', $data);
$user_id = $this->db->insert_id();
2.1 XSS过滤与输入处理
问:CI如何自动过滤XSS?开发者需注意什么?
• CI默认启用XSS过滤(`config/config.php`中`global_xss_filtering = TRUE`);
• 但仅对`$this->input->post()`等CI输入方法生效;
• 直接使用`$_POST`不会被过滤!
2.2 查询构建器(Query Builder)
问:CI的查询构建器如何防止SQL注入?
答:通过`$this->db->escape()`自动转义参数:
// 安全写法(自动转义)
$this->db->where('name', $name);
$this->db->get('users');
// 危险写法(手动拼接)
$this->db->where("name = '$name'"); // 不转义!
网友还关心
CI与CI4对比
CI4支持Composer、命名空间、PSR规范;性能提升40%;内置CLI命令;CI3已停止维护,新项目建议用CI4。
遗留系统迁移
逐步替换为Laravel:先拆分模块 → 用API网关桥接 → 最终替换核心逻辑。CI的`application/core`可直接迁移至Laravel的`app/`。
性能瓶颈分析
CI的瓶颈在于数据库连接未复用;建议启用`pconnect`持久连接;使用`output_cache`缓存页面;避免在视图中执行复杂逻辑。
六、PHP框架选型指南|从需求出发的决策树
选择框架不是“哪个更流行”,而是“哪个更适合你的项目”。以下是基于企业实战经验的决策参考:
快速原型开发
推荐:Laravel
理由:内置Scaffold、Artisan命令、Blade模板,3天可上线MVP。
高并发API服务
推荐:Laravel Octane + Swoole
理由:Swoole常驻内存,QPS可达5000+(传统FPM仅200-300)。
传统企业系统
推荐:ThinkPHP 6
理由:中文文档完善,团队学习成本低,二次开发文档齐全。
微服务架构
推荐:Symfony + API Platform
理由:组件化设计,支持gRPC、GraphQL,适合复杂业务编排。
2024年框架市场占有率(来源:Packagist & PHP Framework Survey)
• ThinkPHP:15.2%
• Symfony:7.8%
• Yii:4.1%
• CodeIgniter:2.0%
• 其他:2.2%
结论:中小企业优先学Laravel;国企/传统行业需ThinkPHP;外企/高级岗位需掌握Symfony。
七、框架源码阅读与调试技巧|从使用者到贡献者
面试官常问:“你读过Laravel源码吗?” 这不是考你是否背过代码,而是考察技术深度与问题定位能力。
3.1 必备调试工具
- `laravel-debugbar`:实时查看SQL、缓存、请求耗时;
- `think\debug`:ThinkPHP内置调试面板;
- `xdebug`:断点调试,跟踪变量变化;
- `phpdbg`:CLI下调试,支持内存分析。
示例:在Laravel中安装Debugbar:
composer require barryvdh/laravel-debugbar --dev
// config/app.php 中添加服务提供者
Barryvdh\Debugbar\ServiceProvider::class,
3.2 Laravel核心源码路径
请求入口
`app/Http/Kernel.php`
中间件栈定义位置
服务容器
`vendor/illuminate/container/Container.php`
`bind()`、`make()`方法实现
路由分发
`vendor/illuminate/routing/Router.php`
`dispatch()`方法核心逻辑
ORM核心
`vendor/illuminate/database/Eloquent/Model.php`
`__get()`、`__set()`魔法方法
调试技巧:在`vendor/illuminate/database/Connection.php`的`runQueryCallback()`中加`dd($query)`,可查看实际执行的SQL。
3.3 ThinkPHP核心源码路径
入口文件
`thinkphp/base.php`
常量定义、自动加载注册
路由解析
`thinkphp/library/think/Route.php`
`parseUrl()`方法
数据库连接
`thinkphp/library/think/db/Connection.php`
`query()`、`execute()`方法
视图渲染
`thinkphp/library/think/View.php`
`fetch()`、`display()`方法
调试技巧:在`thinkphp/library/think/Db.php`的`query()`中加`trace_log($sql)`,可记录所有SQL到日志。
八、高频实战场景题库|模拟真实面试场景
以下题目均来自2024年BAT、字节、拼多多等企业真实面试记录,附详细解析:
场景1:订单超时自动取消
面试官:“订单创建后30分钟未支付需自动取消,如何实现?请用Laravel方案。”
1. 创建订单时,将`cancel_at`字段设为`now()->addMinutes(30)`;
2. 使用`php artisan make:command CancelExpiredOrders`;
3. 在`handle()`中执行:
$orders = Order::where('status', 'pending')
->where('cancel_at', '<=', now())
->get();
foreach ($orders as $order) {
$order->status = 'cancelled';
$order->save();
event(new OrderCancelled($order));
}
4. 在`app/Console/Kernel.php`中注册定时任务:$schedule->command('orders:cancel')
->everyFiveMinutes();
加分项:使用Redis的`zset`实现延迟队列(`XADD orders:cancel:*`),比数据库轮询更高效。
场景2:高并发库存扣减
面试官:“秒杀场景下,如何避免超卖?用Laravel如何实现?”
- 方案1(推荐):Redis+Lua原子操作
$lua = " local stock = redis.call('GET', KEYS[1]) if tonumber(stock) >= tonumber(ARGV[1]) then redis.call('DECRBY', KEYS[1], ARGV[1]) return 1 else return 0 end"; Redis::eval($lua, 1, 'stock:product:123', 1); - 方案2:数据库行级锁
DB::transaction(function () { $product = Product::where('id', 123)->lockForUpdate()->first(); if ($product->stock >= 1) { $product->decrement('stock'); Order::create([...]); } });
场景1:ThinkPHP用户注册防刷
面试官:“如何防止同一IP频繁注册?”
1. 在`Application/Http/Controller/UserController.php`中添加中间件:
public function _initialize()
{
$ip = request()->ip();
$key = 'register_limit_' . md5($ip);
$count = S($key);
if ($count && $count >= 3) {
$this->error('注册过于频繁,请1小时后再试');
}
S($key, $count ? $count+1 : 1, 3600);
}
九、高频问题Q&A|面试官最爱追问的10个问题
Q:为什么框架要使用路由?直接访问控制器文件不行吗?
A:路由实现URL与代码的解耦,提升可维护性;支持RESTful语义;便于SEO优化;隐藏后端技术栈(如.php)。直接访问控制器会暴露文件结构,且无法做权限控制。
Q:Laravel的`__construct()`和`boot()`在服务提供者中有什么区别?
A:`register()`中只能绑定容器,不能依赖其他服务;`boot()`在所有Provider注册后执行,可安全使用其他服务(如`DB::table()`)。
Q:ThinkPHP中`I()`函数与`input()`有什么区别?
A:`I()`是TP3.x的全局函数,TP6已废弃;`input()`是TP5/6的控制器方法,支持更安全的过滤(如`input('post.name', '', 'htmlspecialchars')`)。
Q:如何向面试官提问体现技术深度?
A:“贵司的微服务架构中,框架选型是否考虑了服务治理(如熔断、限流)?” 或 “Laravel项目中如何管理多环境配置?” 避免问“工资多少”等基础问题。
Q:框架升级有风险吗?如何平滑迁移?
A:升级前:① 备份代码;② 运行`composer update --dry-run`检查兼容性;③ 编写回归测试。迁移中:分阶段上线,先升级非核心模块。
Q:如何向非技术人员解释“ORM”?
A:“ORM就像一个翻译官,把PHP对象自动转成SQL语句,开发者只需操作对象,不用写SQL,避免SQL注入。”
Q:Laravel的`with()`真的能解决N+1问题吗?
A:是的!但前提是关联方法已定义(如`User::with('posts')`),且`$user->posts`访问的是已加载的集合。若在循环中重新查询,仍会产生N+1。
Q:ThinkPHP的`display()`和`fetch()`有什么区别?
A:`fetch()`渲染模板并返回字符串;`display()`直接输出到浏览器。通常用`return $this->fetch()`配合`json()`或`view()`。
Q:为什么推荐用`env()`读取配置,而不是直接硬编码?
A:`env()`支持多环境(开发/测试/生产);配合`.env`文件隐藏敏感信息;符合12-Factor App原则。但注意:`config()`缓存后,`env()`会失效,应使用`config('app.key')`。
Q:如何快速定位线上慢查询?
A:① 开启数据库慢查询日志(MySQL:`slow_query_log=ON`);② 使用`EXPLAIN`分析执行计划;③ 检查是否缺少索引;④ 避免`SELECT *`。