mysql - 列出 MySQL 表外键的高效方法?

标签 mysql performance

是否有一种高效的方法来获取分配给 MySQL 表的外键列表?

查询信息模式
SELECT
    `column_name`, 
    `referenced_table_schema` AS foreign_db, 
    `referenced_table_name` AS foreign_table, 
    `referenced_column_name`  AS foreign_column 
FROM
    `information_schema`.`KEY_COLUMN_USAGE`
WHERE
    `constraint_schema` = SCHEMA()
AND
    `table_name` = 'your-table-name-here'
AND
    `referenced_column_name` IS NOT NULL
ORDER BY
    `column_name`;

有效,但在我尝试过的 MySQL 版本上运行缓慢。一些研究出现了 this bug ,这似乎表明这是一个没有明确解决方案的持续问题。暗示的解决方案需要使用补丁重新配置或重新编译 mysql,这不适用于我正在处理的项目。

我意识到可以发布以下内容

SHOW CREATE TABLE table_name;

并获取 CREATE TABLE 语句的字符串表示形式,其中将包含外键约束。然而,解析这个字符串似乎很脆弱,而且我没有大量的 CREATE TABLE 语句来测试。 (如果有一些标准的解析代码,我会喜欢一些链接)

我也意识到我可以用以下列出索引

SHOW CREATE TABLE table_name;

索引列表将包括外键,但似乎没有办法确定哪些索引是外键,哪些是“常规”MySQL 索引。同样,与 SHOW CREATE 表信息的一些交叉引用在这里可能有所帮助,但这使我们回到了脆弱的字符串解析。

任何帮助,甚至链接到有关该问题的其他智能讨论,我们都将不胜感激。

最佳答案

SequelPro 和 Magento 都使用 SHOW CREATE TABLE 查询来加载外键信息。 Magento 的实现是我要引用的一个,因为它既是一个基于 PHP 的系统,也是我们都非常熟悉的系统。但是,以下代码片段可以应用于任何基于 PHP 的系统。

解析是在 Varien_Db_Adapter_Pdo_Mysql::getForeignKeys() 方法 ( the code for this class can be found here ) 中使用相对简单的 RegEx 完成的:


    $createSql = $this->getCreateTable($tableName, $schemaName);

    // collect CONSTRAINT
    $regExp  = '#,\s+CONSTRAINT `([^`]*)` FOREIGN KEY \(`([^`]*)`\) '
        . 'REFERENCES (`[^`]*\.)?`([^`]*)` \(`([^`]*)`\)'
        . '( ON DELETE (RESTRICT|CASCADE|SET NULL|NO ACTION))?'
        . '( ON UPDATE (RESTRICT|CASCADE|SET NULL|NO ACTION))?#';
    $matches = array();
    preg_match_all($regExp, $createSql, $matches, PREG_SET_ORDER);
    foreach ($matches as $match) {
        $ddl[strtoupper($match[1])] = array(
            'FK_NAME'           => $match[1],
            'SCHEMA_NAME'       => $schemaName,
            'TABLE_NAME'        => $tableName,
            'COLUMN_NAME'       => $match[2],
            'REF_SHEMA_NAME'    => isset($match[3]) ? $match[3] : $schemaName,
            'REF_TABLE_NAME'    => $match[4],
            'REF_COLUMN_NAME'   => $match[5],
            'ON_DELETE'         => isset($match[6]) ? $match[7] : '',
            'ON_UPDATE'         => isset($match[8]) ? $match[9] : ''
        );
    }

在文档 block 中,它描述了结果数组如下:


    /**
     * The return value is an associative array keyed by the UPPERCASE foreign key,
     * as returned by the RDBMS.
     *
     * The value of each array element is an associative array
     * with the following keys:
     *
     * FK_NAME          => string; original foreign key name
     * SCHEMA_NAME      => string; name of database or schema
     * TABLE_NAME       => string;
     * COLUMN_NAME      => string; column name
     * REF_SCHEMA_NAME  => string; name of reference database or schema
     * REF_TABLE_NAME   => string; reference table name
     * REF_COLUMN_NAME  => string; reference column name
     * ON_DELETE        => string; action type on delete row
     * ON_UPDATE        => string; action type on update row
     */

我知道这不是完全您所要求的,因为它使用的是 SHOW CREATE TABLE 输出,但根据我的发现,这似乎是普遍接受的做事方式。

关于mysql - 列出 MySQL 表外键的高效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7451054/

相关文章:

php - Mysql-如何从表中选择最后100条记录

mysql - AWS RDS 迁移

MySQL 键约束

sql - 如何使用MYSQL中同一行中的列中的数据更新列?

javascript - jQuery html() 表现真的很慢

performance - numpy:评估矩阵中的函数,使用前一个数组作为计算下一个数组的参数

java - 二维 ArrayList 不断添加新值

mysql - 如何防止从 LAN 上的任何计算机(服务器除外)使用 Web 浏览器访问 phpmyadmin(MySQL 数据库)

performance - HubConnection 的 SignalR 性能问题(服务器中有很多线程,交付之间的延迟很长)

mysql - MariaDB Galera 集群服务器以 100% CPU 运行并且负载不断上升