我在表上添加新列时遇到问题。
我尝试运行了几次,但是运行了 10 多分钟后,由于锁定时间,我决定取消查询。
ALTER TABLE mytable ADD mycolumn VARCHAR(50);
Run Code Online (Sandbox Code Playgroud)
有用的信息:
我发现了有关 PostgreSQL 管理可空列的方式的有趣信息(通过 HeapTupleHeader)。
我的第一个猜测是,因为这个表已经有 32 个 8 位的可空列MAXALIGN, HeapTupleHeader 是 4 字节长度(未验证,我不知道如何这样做)。
因此,添加新的可为空的列可能需要在每一行上更新 HeapTupleHeader 以添加新的 8-bits MAXALIGN,这可能会导致性能问题。
因此,我尝试更改可空列之一(实际上并不是真正可以为空的),以便将可空列的数量减少到 31,以检查我的猜测是否属实。
ALTER TABLE mytable ALTER myothercolumn SET NOT NULL;
Run Code Online (Sandbox Code Playgroud)
不幸的是,这个改动也需要很长时间,超过5分钟,所以我也中止了。
您知道是什么导致了这种性能成本吗?
我发现了几个声明 ALTER TABLE ... DROP COLUMN 是仅元数据操作的来源。
怎么会这样?DROP COLUMN 期间的数据是否不需要从底层非聚集索引和聚集索引/堆中清除?
此外,为什么Microsoft Docs暗示它是一个完整记录的操作?
对表所做的修改会被记录下来并且完全可以恢复。影响大表中所有行的更改(例如删除列或在某些版本的 SQL Server 上添加具有默认值的 NOT NULL 列)可能需要很长时间才能完成并生成许多日志记录。以与影响多行的任何 INSERT、UPDATE 或 DELETE 语句相同的方式运行这些 ALTER TABLE 语句。
作为次要问题:如果数据没有从底层页面中删除,引擎如何跟踪删除的列?
我不得不将 MYSQL 中的一列更改为 NULL 到 NOT NULL,但是我得到了语法错误。我只想更改最后一列,已经进行了一些研究,但还没有找到解决方案,这可能很简单,但我是数据库新手,直到现在才意识到这一点。有谁能够帮助我?
ALTER TABLE glpi_ticketsatisfactions ALTER COLUMN comment BIGINT NOT NULL;
Run Code Online (Sandbox Code Playgroud)
错误:
[42000][1064] 你的 SQL 语法有错误;检查与您的 MariaDB 服务器版本相对应的手册,在第 1 行的“BIGINT NOT NULL”附近使用正确的语法
CREATE TABLE:
CREATE TABLE glpi_ticketsatisfactions
( id int(11) NOT NULL AUTO_INCREMENT,
tickets_id int(11) NOT NULL DEFAULT '0',
type int(11) NOT NULL DEFAULT '1',
ate_begin datetime DEFAULT NULL,
date_answered datetime DEFAULT NULL,
satisfaction int(11) DEFAULT NULL,
comment text COLLATE utf8_unicode_ci,
PRIMARY KEY (id),
UNIQUE KEY tickets_id …Run Code Online (Sandbox Code Playgroud) 我有一个包含 45M 行(45 GB 数据空间和 2GB 索引空间)的表。我添加了一个新列,它立即完成。
alter table T add C char(25)
Run Code Online (Sandbox Code Playgroud)
然后我发现尺寸太小,所以我运行以下查询。
alter table T alter column C varchar(2500)
Run Code Online (Sandbox Code Playgroud)
它运行了一个小时,并且仍在运行。sp_whoisactive 显示(目前,仍在运行)
reads: 48,000,000
writes: 5,000,000
physical reads: 3,900,000
Run Code Online (Sandbox Code Playgroud)
不是应该很快吗?
我有一个非常大的表,让我们调用它example,然后我尝试在该表上执行一些更改命令:
ALTER TABLE `example` ADD `example_column` TINYINT(1) NOT NULL DEFAULT 0;
Run Code Online (Sandbox Code Playgroud)
检查alter命令的进度:
mysql -e 'show engine innodb status \G' | grep 'undo \| log \| entries'
Run Code Online (Sandbox Code Playgroud)
给我很好的信息,关于时间 - 或多或少需要 17 天才能完成......
更改阻塞表,因此阻塞生产表 17 天不是一个好的选择。;)
我尝试在网上调查一些很棒的工具,例如:
我还阅读了文档和上述工具的限制部分:
触发器的使用意味着如果表上已经定义了任何触发器,则该工具将无法工作。
不提供任何改变包含外键的表的好方法
我的示例表有触发器和外键...
你能给我一些建议,如何处理这个改变?
我有 MySQL 5.6。我使用 GTID(基于行)复制。
我将非常感谢您的建议!
我正在阅读有关新的Postgres 10 标识列的信息,并了解了如何使用它SERIAL在CREATE TABLE.
是否也可以向现有表添加标识列?
例如,使用旧SERIAL列,我可以执行以下操作:
ALTER TABLE sourceTable ADD COLUMN ogc_fid SERIAL;
Run Code Online (Sandbox Code Playgroud)
对于标识列,是否有与上述相同的内容?我试过:
ALTER TABLE sourceTable ADD COLUMN ogc_fid GENERATED BY DEFAULT AS IDENTITY;
Run Code Online (Sandbox Code Playgroud)
但是得到了一个错误:
错误:“BY”第 1 行或附近的语法错误:...R TABLE sourceTable ADD COLUMN ogc_fid GENERATED BY DEFAULT
我正在考虑用我的脚本中的SERIAL列替换列IDENTITY,只是想检查这是否可行。
我有一个关于ALTER TABLE ... ADD COLUMNDDL 语句的问题。
在使用 MariaDB v10.2 的 Amazon RDS 实例上,我注意到INSERT语句完成并且行在表上完成SELECT之前正确插入表中(通过 验证)ALTER TABLE ... ADD COLUMN。
在ALTER TABLE操作完成之前,不应该将任何执行写入的 DML 语句排队吗?
我发布这个问题是因为我被要求执行一些测试来验证是否可以ALTER TABLE ... ADD COLUMN在工作时间内在实时生产数据库上运行,在频繁使用的数据库上,在有几百万行的表上运行——我觉得很不明智。即使ALTER TABLE没有在表上放置锁,它也必须等到任何连接不再使用该表(由于连接放置了元数据锁),这可能会在很久以后发生。
编辑:显然这个评估过于悲观。我一直在做几个测试,mysqlslap在表上执行繁重的操作 ( INSERT, UPDATE,DELETE语句和SELECT语句LIKE避免在ALTER TABLE ... ADD COLUMN运行时在 150 个模拟并发连接上使用索引;分析显示元数据锁定,但等待时间很短(每个 1 秒),表更改在大约 30 分钟内完成,而没有运行 SQL 语句时则需要 10 分钟。虽然这很令人满意,但另一方面,我想知道假设 DDL 语句是非阻塞的是否安全。
(可能值得注意的是InnoDB …
许多 PostgreSQLALTER TABLE命令(例如添加具有默认值的新列)在最新版本的 PostgreSQL 中进行了巧妙的优化,一旦 Postgres 短暂获取了表上的锁,即使在大型表上,它们也能基本上立即执行。
不幸的是,最后的警告很重要。链接博客文章中类似这样的命令
ALTER TABLE users ADD COLUMN credits bigint NOT NULL DEFAULT 0;
Run Code Online (Sandbox Code Playgroud)
仍然需要等待表上的独占锁users才能运行,尽管一旦获取锁就会立即执行。更糟糕的是,当它等待该锁时,它会阻止涉及该表的所有写入和读取。
重现此问题的一些简单步骤(在 Postgres 13.3 中测试):
在一个psqlshell 中,创建一个表,然后启动一个事务,从表中进行读取,但不提交:
CREATE TABLE users (id SERIAL, name TEXT);
INSERT INTO users (name) VALUES ('bob'), ('fred');
START TRANSACTION;
SELECT * FROM users WHERE id = 1;
Run Code Online (Sandbox Code Playgroud)
让第一个 shell 打开,然后打开第二个 shell 并尝试更改表:
ALTER TABLE users ADD COLUMN credits bigint NOT NULL DEFAULT 0;
Run Code Online (Sandbox Code Playgroud)
请注意,此查询挂起,等待第一个 shell …
在一个表中删除多个 KEYS 是首选还是一个一个的首选?
“按键A,按键B,按键C”
表中有 9 亿多条记录。
它在内部如何运作?
我想将所有表从架构移动xyz到默认架构public。
我可以移动单个表
ALTER TABLE table_name
SET SCHEMA public;
Run Code Online (Sandbox Code Playgroud)
我可以得到所有的桌子
SELECT table_name FROM information_schema.tables WHERE table_schema='xyz'
Run Code Online (Sandbox Code Playgroud)
有没有办法将这两者结合在一起?
alter-table ×10
postgresql ×4
mysql ×3
sql-server ×2
amazon-rds ×1
identity ×1
index ×1
innodb ×1
locking ×1
mariadb ×1
mysql-5.6 ×1
schema ×1