为什么在导入CSV之后,数据库表中的数据会按字母顺序存储?

后端开发 2026-07-11

为什么我的CSV文件导入数据库时,第一列 product_key 的字母序被排序?不是按行逐行,从CSV的第一行到最后一行导入吗?

我的CSV并非按 product_key 排序,但导入后,行在 my_table 中按字母顺序排列,如在PHPMyAdmin中所见。表为 InnoDB

我在INSERT语句中没有使用ASC或 DESC

我想弄清楚这个原因,因为在一个页面上,我在CSV文件上传表单下方显示表中的数据,我希望数据的显示顺序与上传的文件保持一致。

编辑3/26/26:

SHOW CREATE TABLE显示如下:

vw_star_ratings CREATE TABLE `vw_star_ratings` (
  `product_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `ID_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL,
  UNIQUE KEY `key_index` (`product_key`,`ID_key`,`value`),
  KEY `product_key` (`product_key`),
  KEY `ID_key` (`ID_key`),
  KEY `value` (`value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci

有什么想法吗?

            $file = fopen($fileTmpPath, "r");
            // Start transaction
            $pdo->beginTransaction();

            $stmt = $pdo->prepare("
                INSERT INTO my_table (product_key, ID_key, value) 
                VALUES (?, ?, ?)
            ");

            // Skip header
            fgetcsv($file);

            while (($row = fgetcsv($file, 1000, ",")) !== FALSE) {
                if (count($row) < 3) continue;
                $stmt->execute([$row[0], $row[1], $row[2]]);
            }

            fclose($file);
            $pdo->commit();

解决方案

上述评论的要点:

  • 你的表有这个索引:UNIQUE KEY key_index (product_key,ID_key,value)。由于这三列都是 NOT NULL,并且表使用InnoDB存储引擎,这意味着这三列构成了表的聚簇索引。有关此的文档,请参阅 https://dev.mysql.com/doc/refman/en/innodb-index-types.html
  • InnoDB会根据这三列对聚簇索引中的行进行排序存储,product_key位于第一位。
  • 当你对InnoDB表进行查询且未指定 ORDER BY 子句时,数据库会按照优化器选择的任意索引的顺序读取行,若未使用其他索引,则按聚簇索引的顺序读取。这就是在你导入数据后,默认排序会按 product_key 的原因。

至少这是当前InnoDB实现中的行为,但没有文档化,你不应该依赖它。 * 强制按你插入的顺序存储行的一种解决方法是添加一个自增列:

ALTER TABLE vw_star_ratings ADD COLUMN id INT AUTO_INCREMENT PRIMARY KEY;

这会添加一个列和一个主键。然后按之前的方式导入你的CSV数据。由于你的 INSERT 指定了列,省略新列后,这使得自增 id 能够自动生成值,按你插入数据的顺序。 * 当你想要特定排序时,最佳做法是在查询中显式使用 ORDER BY。任何出现的默认排序都不可靠,可能会改变,例如InnoDB选择了不同的索引。

SELECT ... FROM vw_star_ratings ORDER BY id;

如果优化器无论如何都会按这个顺序读取行,那么 ORDER BY 就是一个无操作,对性能没有影响。至少你的代码对阅读它的其他人来说更能体现意图。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章