එන්ජින් දෙක අතර යාන්ත්රික වෙනස්කම් ආවරණය වන පරිදි මෙහි පුළුල් ප්රතිචාර වලට එකතු කිරීම සඳහා, මම ආනුභවික වේග සංසන්දනය අධ්යයනයක් ඉදිරිපත් කරමි.
පිරිසිදු වේගය සම්බන්ධයෙන් ගත් කල, මයිසෑම් ඉනෝ ඩීබී වලට වඩා වේගවත් බව සැමවිටම නොවේ, නමුත් මගේ අත්දැකීම් අනුව එය පිරිසිදු පරිසරය සඳහා 2.0-2.5 ගුණයක සාධකයකින් වේගවත් වේ. පැහැදිලිවම මෙය සියලු පරිසරයන්ට සුදුසු නොවේ - අනෙක් අය ලියා ඇති පරිදි, ගනුදෙනු සහ විදේශීය යතුරු වැනි දේ MyISAM හි නොමැත.
මම පහතින් මිණුම් සලකුණු කිරීමක් කර ඇත - මම ලූප් කිරීම සඳහා පයිතන් සහ කාල සැසඳීම් සඳහා කාල පුස්තකාලය භාවිතා කර ඇත්තෙමි. උනන්දුව සඳහා මම මතක එන්ජිමද ඇතුළත් කර ඇති අතර, මෙය කුඩා වගු සඳහා පමණක් සුදුසු වුවද පුවරුව හරහා හොඳම කාර්ය සාධනය ලබා දෙයි (ඔබ The table 'tbl' is full
MySQL මතක සීමාව ඉක්මවා යන විට ඔබට නිරන්තරයෙන් හමු වේ ). මා බලන තෝරාගත් වර්ග හතර නම්:
- වැනිලා තේරීම්
- ගණන්
- කොන්දේසි සහිත තේරීම්
- සුචිගත කළ සහ සුචිගත නොකළ උප තේරීම්
පළමුව, මම පහත SQL භාවිතා කරමින් වගු තුනක් නිර්මාණය කළෙමි
CREATE TABLE
data_interrogation.test_table_myisam
(
index_col BIGINT NOT NULL AUTO_INCREMENT,
value1 DOUBLE,
value2 DOUBLE,
value3 DOUBLE,
value4 DOUBLE,
PRIMARY KEY (index_col)
)
ENGINE=MyISAM DEFAULT CHARSET=utf8
දෙවන හා තෙවන වගු වල 'InnoDB' සහ 'මතකය' සඳහා ආදේශ කර ඇති 'MyISAM' සමඟ.
1) වැනිලා තෝරා ගනී
විමසුම: SELECT * FROM tbl WHERE index_col = xx
ප්රති ult ලය: අදින්න
මේ සියල්ලේ වේගය පුළුල් ලෙස සමාන වන අතර අපේක්ෂිත පරිදි තෝරා ගත යුතු තීරු ගණනෙහි රේඛීය වේ. InnoDB MyISAM ට වඩා තරමක් වේගවත් බව පෙනේ, නමුත් මෙය සැබවින්ම ආන්තිකය.
කේතය:
import timeit
import MySQLdb
import MySQLdb.cursors
import random
from random import randint
db = MySQLdb.connect(host="...", user="...", passwd="...", db="...", cursorclass=MySQLdb.cursors.DictCursor)
cur = db.cursor()
lengthOfTable = 100000
# Fill up the tables with random data
for x in xrange(lengthOfTable):
rand1 = random.random()
rand2 = random.random()
rand3 = random.random()
rand4 = random.random()
insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
cur.execute(insertString)
cur.execute(insertString2)
cur.execute(insertString3)
db.commit()
# Define a function to pull a certain number of records from these tables
def selectRandomRecords(testTable,numberOfRecords):
for x in xrange(numberOfRecords):
rand1 = randint(0,lengthOfTable)
selectString = "SELECT * FROM " + testTable + " WHERE index_col = " + str(rand1)
cur.execute(selectString)
setupString = "from __main__ import selectRandomRecords"
# Test time taken using timeit
myisam_times = []
innodb_times = []
memory_times = []
for theLength in [3,10,30,100,300,1000,3000,10000]:
innodb_times.append( timeit.timeit('selectRandomRecords("test_table_innodb",' + str(theLength) + ')', number=100, setup=setupString) )
myisam_times.append( timeit.timeit('selectRandomRecords("test_table_myisam",' + str(theLength) + ')', number=100, setup=setupString) )
memory_times.append( timeit.timeit('selectRandomRecords("test_table_memory",' + str(theLength) + ')', number=100, setup=setupString) )
2) ගණන්
විමසුම: SELECT count(*) FROM tbl
ප්රති ult ලය : MyISAM ජය ගනී
මෙය MyISAM සහ InnoDB අතර විශාල වෙනසක් පෙන්නුම් කරයි - MyISAM (සහ මතකය) වගුවේ ඇති වාර්තා ගණන නිරීක්ෂණය කරයි, එබැවින් මෙම ගනුදෙනුව වේගවත් වන අතර O (1) වේ. InnoDB ගණනය කිරීම සඳහා ගතවන කාලය මා විමර්ශනය කළ පරාසය තුළ වගු ප්රමාණය සමඟ සුපිරි රේඛීයව වැඩි වේ. ප්රායෝගිකව නිරීක්ෂණය කරන ලද MyISAM විමසුම් වල වේගවත් කිරීම් බොහෝමයක් සමාන බලපෑම් නිසා ඇති වූවක් යැයි මම සැක කරමි.
කේතය:
myisam_times = []
innodb_times = []
memory_times = []
# Define a function to count the records
def countRecords(testTable):
selectString = "SELECT count(*) FROM " + testTable
cur.execute(selectString)
setupString = "from __main__ import countRecords"
# Truncate the tables and re-fill with a set amount of data
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:
truncateString = "TRUNCATE test_table_innodb"
truncateString2 = "TRUNCATE test_table_myisam"
truncateString3 = "TRUNCATE test_table_memory"
cur.execute(truncateString)
cur.execute(truncateString2)
cur.execute(truncateString3)
for x in xrange(theLength):
rand1 = random.random()
rand2 = random.random()
rand3 = random.random()
rand4 = random.random()
insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
cur.execute(insertString)
cur.execute(insertString2)
cur.execute(insertString3)
db.commit()
# Count and time the query
innodb_times.append( timeit.timeit('countRecords("test_table_innodb")', number=100, setup=setupString) )
myisam_times.append( timeit.timeit('countRecords("test_table_myisam")', number=100, setup=setupString) )
memory_times.append( timeit.timeit('countRecords("test_table_memory")', number=100, setup=setupString) )
3) කොන්දේසි සහිත තේරීම්
විමසුම: SELECT * FROM tbl WHERE value1<0.5 AND value2<0.5 AND value3<0.5 AND value4<0.5
ප්රති ult ලය : MyISAM ජය ගනී
මෙන්න, MyISAM සහ මතකය දළ වශයෙන් එක හා සමාන වන අතර විශාල වගු සඳහා InnoDB 50% කින් පරාජය කරන්න. MyISAM හි ප්රතිලාභ උපරිම ලෙස පෙනෙන ආකාරයේ විමසුම මෙයයි.
කේතය:
myisam_times = []
innodb_times = []
memory_times = []
# Define a function to perform conditional selects
def conditionalSelect(testTable):
selectString = "SELECT * FROM " + testTable + " WHERE value1 < 0.5 AND value2 < 0.5 AND value3 < 0.5 AND value4 < 0.5"
cur.execute(selectString)
setupString = "from __main__ import conditionalSelect"
# Truncate the tables and re-fill with a set amount of data
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:
truncateString = "TRUNCATE test_table_innodb"
truncateString2 = "TRUNCATE test_table_myisam"
truncateString3 = "TRUNCATE test_table_memory"
cur.execute(truncateString)
cur.execute(truncateString2)
cur.execute(truncateString3)
for x in xrange(theLength):
rand1 = random.random()
rand2 = random.random()
rand3 = random.random()
rand4 = random.random()
insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
cur.execute(insertString)
cur.execute(insertString2)
cur.execute(insertString3)
db.commit()
# Count and time the query
innodb_times.append( timeit.timeit('conditionalSelect("test_table_innodb")', number=100, setup=setupString) )
myisam_times.append( timeit.timeit('conditionalSelect("test_table_myisam")', number=100, setup=setupString) )
memory_times.append( timeit.timeit('conditionalSelect("test_table_memory")', number=100, setup=setupString) )
4) උප තේරීම්
ප්රති ult ලය : InnoDB ජය ගනී
මෙම විමසුම සඳහා, මම උප තේරීම සඳහා අතිරේක වගු මාලාවක් නිර්මාණය කළෙමි. සෑම එකක්ම BIGINT තීරු දෙකකි, එකක් ප්රාථමික යතුරු දර්ශකයක් සහ එකක් දර්ශකයක් නොමැතිව. විශාල වගු ප්රමාණය නිසා, මම මතක එන්ජිම පරීක්ෂා කළේ නැත. SQL වගු නිර්මාණය කිරීමේ විධානය විය
CREATE TABLE
subselect_myisam
(
index_col bigint NOT NULL,
non_index_col bigint,
PRIMARY KEY (index_col)
)
ENGINE=MyISAM DEFAULT CHARSET=utf8;
එහිදී නැවත වරක්, දෙවන වගුවේ 'InnoDB' සඳහා 'MyISAM' ආදේශ කරනු ලැබේ.
මෙම විමසුමේදී, මම තේරීම් වගුවේ ප්රමාණය 1000000 ට තබන අතර ඒ වෙනුවට උප-තෝරාගත් තීරුවල ප්රමාණය වෙනස් වේ.
මෙන්න InnoDB පහසුවෙන් ජය ගනී. අපි සාධාරණ ප්රමාණයේ වගුවකට ගිය පසු එන්ජින් දෙකම උප තේරීමේ ප්රමාණය සමඟ රේඛීයව පරිමාණය කරයි. දර්ශකය MyISAM විධානය වේගවත් කරන නමුත් සිත්ගන්නා කරුණ නම් InnoDB වේගයට එතරම් බලපෑමක් නැත. subSelect.png
කේතය:
myisam_times = []
innodb_times = []
myisam_times_2 = []
innodb_times_2 = []
def subSelectRecordsIndexed(testTable,testSubSelect):
selectString = "SELECT * FROM " + testTable + " WHERE index_col in ( SELECT index_col FROM " + testSubSelect + " )"
cur.execute(selectString)
setupString = "from __main__ import subSelectRecordsIndexed"
def subSelectRecordsNotIndexed(testTable,testSubSelect):
selectString = "SELECT * FROM " + testTable + " WHERE index_col in ( SELECT non_index_col FROM " + testSubSelect + " )"
cur.execute(selectString)
setupString2 = "from __main__ import subSelectRecordsNotIndexed"
# Truncate the old tables, and re-fill with 1000000 records
truncateString = "TRUNCATE test_table_innodb"
truncateString2 = "TRUNCATE test_table_myisam"
cur.execute(truncateString)
cur.execute(truncateString2)
lengthOfTable = 1000000
# Fill up the tables with random data
for x in xrange(lengthOfTable):
rand1 = random.random()
rand2 = random.random()
rand3 = random.random()
rand4 = random.random()
insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
cur.execute(insertString)
cur.execute(insertString2)
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:
truncateString = "TRUNCATE subselect_innodb"
truncateString2 = "TRUNCATE subselect_myisam"
cur.execute(truncateString)
cur.execute(truncateString2)
# For each length, empty the table and re-fill it with random data
rand_sample = sorted(random.sample(xrange(lengthOfTable), theLength))
rand_sample_2 = random.sample(xrange(lengthOfTable), theLength)
for (the_value_1,the_value_2) in zip(rand_sample,rand_sample_2):
insertString = "INSERT INTO subselect_innodb (index_col,non_index_col) VALUES (" + str(the_value_1) + "," + str(the_value_2) + ")"
insertString2 = "INSERT INTO subselect_myisam (index_col,non_index_col) VALUES (" + str(the_value_1) + "," + str(the_value_2) + ")"
cur.execute(insertString)
cur.execute(insertString2)
db.commit()
# Finally, time the queries
innodb_times.append( timeit.timeit('subSelectRecordsIndexed("test_table_innodb","subselect_innodb")', number=100, setup=setupString) )
myisam_times.append( timeit.timeit('subSelectRecordsIndexed("test_table_myisam","subselect_myisam")', number=100, setup=setupString) )
innodb_times_2.append( timeit.timeit('subSelectRecordsNotIndexed("test_table_innodb","subselect_innodb")', number=100, setup=setupString2) )
myisam_times_2.append( timeit.timeit('subSelectRecordsNotIndexed("test_table_myisam","subselect_myisam")', number=100, setup=setupString2) )
මම හිතන්නේ මේ සියල්ලේ ගෙදර ගෙන යාමේ පණිවිඩය නම් ඔබ වේගය ගැන සැබවින්ම සැලකිලිමත් වන්නේ නම් , කුමන එන්ජිම වඩාත් සුදුසු වනු ඇත්දැයි උපකල්පන කරනවාට වඩා ඔබ කරන විමසුම් මිණුම් සලකුණු කළ යුතුය.