考虑下面的Schema::create('adverts', function (Blueprint $table) {
$table->increments('id'); //PRIMARY KEY
$table->string('name', 150); //VARCHAR
$table->text('description'); //TEXT
$table->integer('city_id')->nullable();
$table->foreign('city_id')->references('id')->on('cities');
$table->timestamps();
});
表(使用Laravel创建,但代码非常自我解释):
adverts
FULLTEXT
表有更多列,但这些是现在必需的。我希望用户能够找到带有文本搜索功能的广告,因此我添加了以下ALTER TABLE posts ADD FULLTEXT search(name, description)
索引:
city_id
正如您所看到的,每个广告还有一个adverts
外键,用户可以在city
以及给定半径范围内的城市中搜索radius
。为此,我有一个| city_A | city_B |distance|
----------------------------------
| 1 | 2 | 30 |
| 2 | 1 | 30 |
表,其中包含城市对的记录以及彼此之间的距离:
radius
adverts
表包含大约7 000 000条记录,并且所有列都已编制索引。我在Advert::whereRaw('MATCH(name, description) AGAINST(? IN BOOLEAN MODE)', [$term])
->join('radius', function ($join) use ($radius, $id){
$join->on('radius.secondary_id','=', 'posts.city_id');
})->where('radius.primary_id', $id)
->whereBetween('radius.radius', [0,$radius]);
表播种了大约10万个假记录(描述大约是700个字符)。搜索广告时,我执行以下Laravel查询:
SLECT * FROM `adverts`
INNER JOIN `radius` on `radius`.`city_B` = `posts`.`city_id`
WHERE MATCH(name, description) AGAINST(? IN BOOLEAN MODE)
AND `radius`.`city_A` = ?
AND `radius`.`radius` between ? and ?
ORDER BY `created_at` desc
LIMIT 20
在SQL中,这转换为:
adverts
好的,因为我说FULLTEXT
表有更多列,但在执行搜索查询时似乎没有造成重大问题。然而,一旦我将MATCH
术语搜索与城市邻近搜索结合起来,查询在我的本地主机上执行需要相当长的时间 - 大约10-15秒。似乎在整个adverts
表上执行radius
工作正常,CPU: Intel Core i5 3450 @ 3.10GHz Quad
RAM: 8,00GB Dual-Channel DDR3 @ 665MHz
HDD: Seagate ST3320613AS ATA Device (SATA) 7200RPM 16MB Cache
搜索工作正常但是这样组合会导致响应相当慢。
我是否可以采取一些措施来改进表格或查询语句,或者这是MySQL无法跟上的情况?
我的记录规范:
+----+-------------+-------+------+---------------+-----+---------+-----+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+-----+---------+--------+---+--+
| 1 | SIMPLE |adverts|fulltxt|adverts_city_id_foreign,| search | 0 | | 1 | Using where; Using filesort |
| | | | | search | | |
------------------------------------------------------------------------------------------
| 1 | SIMPLE | radius | ref | city_A_index,| city_A_index| 5 | test_db.adverts.city_id | 1417 | Using where |
| | | | | city_B_index,| | |
| | | | | distances_ind| | |
+----+------------+--------+------+--------------+-------------+---+---+---+---+
编辑:MySQL解释内连接查询:
UPDATE STATEMENT