2

我有以下程序:

CREATE PROCEDURE getProjectTeams(IN p_idProject INTEGER)
BEGIN
 SELECT idTeam, name, workersCount, confirmersCount, isConfirm 
 FROM Teams JOIN team_project USING (idTeam)
 WHERE idProject = p_idProject;
END $$

这里是CREATE TABLE表格Teams和脚本team_project

CREATE TABLE Teams (
 idTeam INT PRIMARY KEY auto_increment,
 name CHAR(20) NOT NULL UNIQUE,
 isConfirm BOOL DEFAULT 0,
 workersCount SMALLINT DEFAULT 0,
 confirmersCount SMALLINT DEFAULT 0 
) engine = innodb DEFAULT CHARACTER SET=utf8 COLLATE=utf8_polish_ci;

CREATE TABLE team_project (
idTeam INT NOT NULL,
idProject INT NOT NULL,
FOREIGN KEY(idTeam) REFERENCES Teams(idTeam)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
FOREIGN KEY (idProject) REFERENCES Projects(idProject)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
PRIMARY KEY(idTeam, idProject)
) engine = innodb DEFAULT CHARACTER SET=utf8 COLLATE=utf8_polish_ci;

我在服务器上几乎没有具有相同架构的数据库,但只有当它被一个数据库调用时才会记录此过程。那些其他数据库完成的调用没有被记录。这不是查询慢或慢的问题(它总是需要大约 0.0001 秒)。这就是为什么它被记录为不使用索引。这怎么可能?

正如 Zagor23 建议EXPLAIN的那样,我运行它,这是结果。a) 在记录过程的数据库中:

| id | select_type | table        | type | possible_keys     | key       | key_len | ref   | rows | Extra                          |
|  1 | SIMPLE      | team_project | ref  | PRIMARY,idProject | idProject | 4       | const |    3 | Using index                    |
|  1 | SIMPLE      | Teams        | ALL  | PRIMARY           | NULL      | NULL    | NULL  |    4 | Using where; Using join buffer |

b) 数据库,其中未记录过程:

| id | select_type | table        | type   | possible_keys     | key       | key_len | ref                              | rows | Extra       |
|  1 | SIMPLE      | team_project | ref    | PRIMARY,idProject | idProject | 4       | const                            |    1 | Using index |
|  1 | SIMPLE      | Teams        | eq_ref | PRIMARY           | PRIMARY   | 4       | ecovbase.team_project.idTeam |    1 |             |

事实是 - 数据有点不同,但差别不大。GoodDB(不记录 proc)在 Teams 中有 11 行,在 team_project 中有 420 行,BadDB - 在 Teams 中有 4 行,在 team_project 中有大约 800 行。看起来不像是出价差异。有没有办法避免记录该过程?

4

2 回答 2

2

也许它没有被记录,因为它在这些情况下使用索引。尝试运行

EXPLAIN SELECT idTeam, name, workersCount, confirmersCount, isConfirm 
FROM Teams JOIN team_project USING (idTeam)
WHERE idProject = p_idProject;

在你觉得它不应该使用索引的数据库上,看看它是否真的这样做。如果有一个可用且适合查询的索引,并且返回的结果集达到整个结果集的 7-8% 左右,MySql 将使用索引。

你说那information_schema是相同的,但如果数据不是,那可能是不同行为的原因。

于 2012-07-05T14:17:36.837 回答
2

@Zago23 解释了为什么会发生这种情况。您的表在此数据库中可能要大得多,并且您没有适当的索引。

我的建议是UNIQUE在表上添加一个索引team_project,在(idProject, idTeam)


在添加EXPLAIN输出之后,似乎在记录的情况下,MySQL 优化器选择了一个不需要使用Team表中任何索引的计划,只扫描整个(4 行!)表。这很可能更快,因为该表只有 4 行。

现在,slow-log 有一些默认设置,如果我没记错的话,它会在日志中添加任何不使用索引的查询,即使查询需要 0.0001 秒才能完成。

您可以简单地忽略此日志记录或更改慢日志设置以忽略不使用索引的查询。请参阅 MySQL 文档:慢查询日志

于 2012-07-05T14:25:43.087 回答