Mysql 我对多个表的联接查询非常慢
我目前对高级搜索的查询大约需要60秒才能完成。有什么改进的建议吗? 数据库:MySQL Web服务器:Apache-PHP(PDO) 当前代码结构:Mysql 我对多个表的联接查询非常慢,mysql,sql,Mysql,Sql,我目前对高级搜索的查询大约需要60秒才能完成。有什么改进的建议吗? 数据库:MySQL Web服务器:Apache-PHP(PDO) 当前代码结构: SELECT B.title, COUNT(*) AS NUM FROM library.PhysicalInfo A LEFT JOIN library.BibliographicInfo B ON A.BookID = B.BibliographicInfoID LEFT JOIN library.authors C
SELECT B.title, COUNT(*) AS NUM
FROM library.PhysicalInfo A
LEFT JOIN library.BibliographicInfo B
ON A.BookID = B.BibliographicInfoID
LEFT JOIN library.authors C
ON B.BibliographicInfoID = C.BookID
LEFT JOIN library.BookAuthors D
ON C.BookAuthorID = D.PersonID
LEFT JOIN library.series E
ON B.BibliographicInfoID = E.BookID
LEFT JOIN library.BooksLocation F
ON A.location = F.BookLocationID
LEFT JOIN library.PublishStatement G
ON B.BibliographicInfoId=G.BookID
LEFT JOIN library.publisher H
ON G.PublisherID = H.PublisherID
WHERE ( B.title LIKE '%سلام%' OR
D.name LIKE '%سلام%' OR
F.location LIKE '%سلام%' OR
G.place LIKE '%سلام%' OR
G.year LIKE '%سلام%' OR
H.name LIKE '%سلام%' )
LIMIT 0, 30
我已经为联接比较和WHERE
语句中使用的所有字段创建了索引:
CREATE INDEX PersonID ON library.BookAuthors(PersonID);
....
我的表格结构是:
mysql> DESCRIBE PhysicalInfo;
+----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+----------------+
| PhysicalInfoID | int(11) | NO | PRI | NULL | auto_increment |
| volume | varchar(10) | YES | | NULL | |
| section | varchar(100) | YES | | NULL | |
| year | varchar(10) | YES | | NULL | |
| RegisterNo | varchar(20) | YES | | NULL | |
| barcode | varchar(45) | YES | MUL | NULL | |
| location | int(11) | YES | MUL | NULL | |
| BookID | int(11) | YES | MUL | NULL | |
| version | varchar(10) | YES | | NULL | |
+----------------+--------------+------+-----+---------+----------------+
mysql> DESCRIBE BibliographicInfo;
+------------------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+---------------+------+-----+---------+----------------+
| BibliographicInfoID | int(11) | NO | PRI | NULL | auto_increment |
| LCNO | varchar(45) | YES | | NULL | |
| DeviNo | varchar(45) | YES | | NULL | |
| title | varchar(200) | YES | MUL | NULL | |
| ISBN | varchar(20) | YES | MUL | NULL | |
| language | int(11) | YES | | NULL | |
| IsReference | smallint(6) | YES | | NULL | |
+------------------------+---------------+------+-----+---------+----------------+
解释扩展的
结果:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: A
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 348390
filtered: 100.00
Extra: NULL
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: B
type: eq_ref
possible_keys: PRIMARY,BibliographicInfoID
key: PRIMARY
key_len: 4
ref: library.A.BookID
rows: 1
filtered: 100.00
Extra: NULL
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: C
type: ref
possible_keys: BookID_idx,BookID
key: BookID_idx
key_len: 5
ref: library.B.BibliographicInfoID
rows: 1
filtered: 100.00
Extra: NULL
*************************** 4. row ***************************
id: 1
select_type: SIMPLE
table: D
type: eq_ref
possible_keys: PRIMARY,PersonID
key: PRIMARY
key_len: 4
ref: library.C.BookAuthorID
rows: 1
filtered: 100.00
Extra: NULL
*************************** 5. row ***************************
id: 1
select_type: SIMPLE
table: E
type: ref
possible_keys: BookID
key: BookID
key_len: 5
ref: library.B.BibliographicInfoID
rows: 2
filtered: 100.00
Extra: Using index
*************************** 6. row ***************************
id: 1
select_type: SIMPLE
table: F
type: eq_ref
possible_keys: PRIMARY,BookLocationID
key: PRIMARY
key_len: 4
ref: library.A.location
rows: 1
filtered: 100.00
Extra: NULL
*************************** 7. row ***************************
id: 1
select_type: SIMPLE
table: G
type: ref
possible_keys: book_idx,BookID
key: book_idx
key_len: 5
ref: library.B.BibliographicInfoID
rows: 1
filtered: 100.00
Extra: NULL
*************************** 8. row ***************************
id: 1
select_type: SIMPLE
table: H
type: eq_ref
possible_keys: PRIMARY,PublisherID
key: PRIMARY
key_len: 4
ref: library.G.PublisherID
rows: 1
filtered: 100.00
Extra: Using where
8 rows in set, 1 warning (0.00 sec)
我目前的查询(大约500万条记录)需要60秒!所以我的问题是:
EXPLAIN EXTENDED
中的第一行总是有type=All
?据我所知,这是最差的类型
,不应该存在,因为我已经为该表的BookID
和主键
创建了索引如果需要从多个表中选择数据,则除了在查询中联接它们之外别无选择 具有多个嵌套级别的查询听起来可能过于复杂,但我建议您是为业务创建解决方案的人,如果您创建了一个数据中心管理员不认可的复杂查询,那么您应该能够将其提交给他们,并讨论更好的方法。您可能会发现,没有比您提供的解决方案更好的方法了 底线是,我不认为有人能够在不提供帮助以满足这些限制的情况下将这些限制强加给你。
- 我首先想到的是索引。如果您明智地选择它们,可以显著提高性能。看李> 有时候你应该考虑把桌子变平。这样可以打破一些关系数据库规范化规则,但可以通过执行较少的“连接”来提高速度李>
- 我有时使用的另一种方法是:如果其中一个表的值不多,您可以在单独的查询中获取它,将“JOIN”字段移动到键(缓存数组),并在查询执行后在php(或其他语言)代码中获取记录时执行JOIN
- 另一种方法是按时执行一些工作,准备好数据并将其插入到另一个表中,以备抓取(由于延迟,在许多用例中不可能)
而且您始终可以将值存储在缓存中。+1。。。有了正确的索引,
JOIN
操作可以非常快。在MySQL的最新版本之前,它们几乎可以保证比相关子查询更快。@lvil:您能提供更多信息或关于第三个建议(键…)的链接吗?不有用的示例:您有一个students表(id、name、degreeID)和degreeTable(degreeID、degreeName)。首先从degreeTable获取所有数据,然后将其转换为数组(degreeID=>degreeName)。如果你想显示一个学生列表,每个学生都可以进入数组[degreeID]。“你通过执行较少的[sic]“加入”来提高速度”。我仍然持怀疑态度。不幸的是,他们确实强制这样的限制!:(但是我现在的查询在服务器上运行大约需要63秒,这真是太可怕了!我建议您的查询可以以不同的方式更有效,而不是尝试删除连接。我首先检查您是否有适当的索引,然后您需要考虑更改查询,但您需要发布。如果您需要帮助,请访问并解释一下数据库。我不敢相信这个问题仍然没有解决!我不知道如何更具体地回答我的问题?这是一个社区,而不是军事基地……%x“无法使用索引,因此它将一直处于挣扎状态。如果有帮助,请访问“x%”可以使用索引,所以速度要快得多。也许可以看看全文搜索。@草莓:谢谢,我知道在关键字前使用通配符会导致优化器忽略索引,但它仍然不应该返回EXPLAIN EXTENDED第一行上的那么多行。我已经为BookID、PhysicalInfo等列创建了索引不适用于varchar列(在LIKE%%中使用的列)。好的,但是您提到您已经“为[…]WHERE语句中使用的所有字段创建了索引”,所以我想我应该指出这些是多余的。@草莓:是的,我已经创建了一个关于书籍标题的索引,但它将在分组操作中使用,而不是%%。不过,感谢您注意到:)