我想在一个大的mysql(5.6版)表中添加8个新列,其中innodb有数百万条记录。我试图以最优化的方式实现这一目标。
使用单个查询添加所有列而不是在8个不同查询中添加8列是否有任何优势。如果是这样想知道原因。
指定 ALGORITHM = INPLACE,LOCK = NONE 时,我需要注意的一切是什么,以免造成任何数据损坏或应用程序失败!
我正在使用查询测试ALGORITHM = INPLACE,LOCK = NONE。
ALTER TABLE table_test ADD COLUMN test_column TINYINT UNSIGNED DEFAULT 0 ALGORITHM=INPLACE LOCK = NONE;
但它与ALGORITHM = DEFAULT运行查询的时间相同。可能是什么原因。
改变的表只有主键索引而没有其他索引。从应用程序到此表的查询是:
insert into table;
select * from table where user_id=uid;
select sum(column) from table where user_id=id and date<NOW();
答案 0 :(得分:2)
通过&#34;优化&#34;,你的意思是&#34;最快&#34;?或者&#34;对其他查询的影响最小&#34;?
在旧版本中,最佳方式(不使用加载项)是将所有ADD COLUMNs
放在一个ALTER TABLE
中;然后等到它完成。
在任何版本中,pt-online-schema-change
都会在短时间内添加所有列。
既然你提到ALGORITHM=INPLACE, LOCK=NONE
,我假设你使用的是更新的版本?所以,可能是8 ALTERs
是最优的。会有一些干扰,但可能不会太多&#34;。
ALGORITHM=DEFAULT
让服务器选择最好的&#34;。这几乎总是最好的&#34;。也就是说,除了DEFAULT
之外,很少需要说出任何其他内容。
您永远不会受到数据损坏。在最坏的情况下,由于ALTER(s)
的干扰导致某种超时,查询可能会失败。您应该始终检查错误(包括超时),并在您的应用程序中处理它。
讨论查询...
insert into table;
一次一行?还是分批? (批量效率更高 - 可能提高10倍。)
select * from table;
当然不是!这将为您提供数百万行的所有列。你为什么要这样做?
select count(column) from table where pk=id and date<NOW();
COUNT(col)
检查col
是NOT NULL
- 您需要吗?如果没有,那么只需COUNT(*)
。
WHERE pk=id
只给你一行;那么为什么还有资格date<NOW()
? PRIMARY KEY
使查询尽可能快。
唯一的索引是PRIMARY KEY
?对于百万行表来说,这似乎不寻常。它是一个&#34;事实&#34;数据仓库中的表格#34;应用?
<强>塔内强>
(警告:对内部构件的大部分讨论是间接得出的,可能是不正确的。)
对于某些ALTERs
,工作基本上只是在架构中。例如:在ENUM
的末尾添加选项; 增加 VARCHAR
的大小。
对于某些ALTERs
INPLACE
,处理基本上是修改数据 - 无需复制。例如:最后添加一列。
PRIMARY KEY
更改(在InnoDB中)必然涉及重建包含数据的BTree;他们无法完成INPLACE
。
可以在不触摸(除了读取)数据的情况下完成许多次要 INDEX
操作。 DROP INDEX
扔掉一个BTree并进行一些元更改。 ADD INDEX
读取整个表,在侧面构建索引BTree,然后宣布它的存在。 CHARACTER SET
和COLLATION
更改需要重建索引。
如果必须复制表,则表上存在重大锁定。任何需要读取所有数据的ALTER
都会产生间接影响,因为I / O和/或CPU和/或块/行等上的简短锁定。
目前还不清楚代码是否足够智能以最有效的方式处理多任务ALTER
。在一个INPLACE
传递中添加8列应该,但是如果它使代码太复杂,那么的操作可能会转换为 COPY
可能多任务ALTER
会做最差的事情。案件。例如,更改PRIMARY KEY
和扩充ENUM
只会在一个COPY
中执行。由于COPY
是完成所有ALTERs
的原始方式,因此现在已经过很好的调试和优化。 (但这是缓慢和侵入性的。)
COPY
实现起来非常简单,主要涉及现有原语:
real
所以没有人写信CREATE TABLE new LIKE real;
ALTER TABLE new ...
- 无论你要求什么real
的所有行复制到new
- 这是缓慢的部分RENAME TABLE real TO old, new TO real;
- 快速,原子等DROP TABLE old;
INPLACE
更复杂,因为它必须决定许多不同的算法和锁定级别。 DEFAULT
如果无法COPY
,则INPLACE
必须向import cfscrape, re, os, time
from bs4 import BeautifulSoup
cc = open('cookie.txt').read()
mybbuser, sid = cc.split(':')
MainScrapper = cfscrape.create_scraper()
def substring_after(string, delim,back):
return string.partition(delim)[back]
suspect = raw_input('User ID: ')
def reputationCheck(userid):
reputationlist = []
r = MainScrapper.get('https://v3rmillion.net/reputation.php?uid={}&show=positive'.format(userid), cookies={'mybbuser': mybbuser,'sid': sid})
soup = BeautifulSoup(r.text, 'html.parser')
reputations = soup.find_all('a', href=re.compile("member\.php\?action=profile\&uid=(\d+)"))
for reputation in reputations:
reputationlist = reputationlist + [substring_after(reputation['href'],'uid=', 2)]
if soup.find('span', {'class' : 'pages'}):
pages = soup.find('span', {'class' : 'pages'}).text
pages = substring_after(pages, '(', 2)
pages = substring_after(pages, '):', 0)
soup = BeautifulSoup(r.text, 'html.parser')
for x in range(1, (int(pages))):
r = MainScrapper.get('https://v3rmillion.net/reputation.php?uid={}'.format(userid) + '&show=positive&page={}'.format(x + 1), cookies={'mybbuser': mybbuser,'sid': sid})
soup = BeautifulSoup(r.text, 'html.parser')
reputations = soup.find_all('a', href=re.compile("member\.php\?action=profile\&uid=(\d+)"))
for reputation in reputations:
if not reputation == suspect:
reputationlist = reputationlist + [substring_after(reputation['href'],'uid=', 2)]
for userids in reputationlist:
if not str(userids) == str(suspect):
victim = []
r = MainScrapper.get('https://v3rmillion.net/reputation.php?uid={}'.format(userids) + '&show=positive', cookies={'mybbuser': mybbuser,'sid': sid})
soup = BeautifulSoup(r.text, 'html.parser')
reputations = soup.find_all('a', href=re.compile("member\.php\?action=profile\&uid=(\d+)"))
for reputation in reputations:
if substring_after(reputation['href'],'uid=', 2) == str(suspect):
print(str(userids) + 'exchanged reputation with ' + str(suspect))
else:
pass
发送。