èæ ̄
å¨ MySQL ä¸ï¼å½æ们为表å建äºä¸ä¸ªæå¤ä¸ªç´¢å¼åï¼é常éè¦å¨ç´¢å¼å®ä¹å®æåï¼æ ¹æ®å ·ä½çæ°æ®æ åµæ§è¡ EXPLAIN å½ä»¤ï¼æè½è§å¯å°æ°æ®åºå®é 使ç¨åªä¸ªç´¢å¼ãæ¯å¦ä½¿ç¨ç´¢å¼ãè¿ä½¿å¾æ们å¨æ·» å æ°ç´¢å¼ä¹åï¼æ æ³æåé¢ç¥æ°æ®åºæ¯å¦è½ä½¿ç¨ææçç´¢å¼ãæ´ä¸ºç³ç³çæ¯ï¼ææ¶çè³å¨æ·» å æ°çç´¢å¼åï¼æ°æ®åºå¨æäºæ¥è¯¢ä¸ä¼ä½¿ç¨å®ï¼èå¨å ¶ä»æ¥è¯¢ä¸åä¸ä¼ä½¿ç¨ï¼è¿ç§æ åµä¸ï¼æ们æ æ³ç¡®å®ç´¢å¼æ¯å¦åæ¥äºé¢æçä½ç¨ï¼è®©äººæå°é常è¦æ¼ãè¿ç§æ åµåºæ¬ä¸æå³ç MySQL 并没æ为æ们éæ©æä¼çç´¢å¼ï¼èæ们ä¸å¾ä¸å¨è«è«æ°æ®ä¸æ¸ç´¢ï¼è¯å¾æ¾å°é®é¢ççç»æå¨ãæ们å¯è½ä¼å°è¯è°æ´ç´¢å¼ï¼çè³å é¤ç´¢å¼ï¼ç¶åéæ°æ·» å ï¼å¸æ MySQL è½ä»ä¸æ¾å°æä¼çç´¢å¼éæ©ãç¶èï¼è¿æ ·çè¿ç¨æ¢èæ¶åè´¹åï¼èä¸å¾å¾æ¶æçå¾®ã
å¦æå ̈æ·» å ç ́¢å1/4ä¹åï1/4æ们è1/2å¤é¢ç¥ç ́¢å1/4çä1/2¿ç ̈æ åμï1/4é£ä¹å ̄¹äºè¡ ̈è®3/4计å°å¤§æè£ ̈çãæ们å ̄以¥ å ̈è®3/4è®¡è¡ ̈ç»ææ¶ï1/4æ ́å æç¡®å°ç¥éåºè ̄¥éæ©åªäºç ́¢å1/4ï1/4å¦ä1/2ä1/4åç ́¢å1/4ï1/4以æé«æ¥è ̄¢æçãæ们ä ̧åéè¦ä3/4èμç²ç®å°è ̄åçæμï1/4èæ ̄å ̄以åºäºå®é çæ°æ®åæ¥è ̄¢æ åμï1/4ååºæ ́å ææºçå �³çãå æ¤ï1/4å ̄¹äº MySQL ç ̈æ·æ¥è ̄ ́ï1/4è1/2å¤é¢ç¥ç ́¢å1/4èμ°å¿çéæ±éå ̧ ̧è¿«åãæ们å ̧æè1/2æä ̧ç榹æ³ï1/4è1/2å¤è®©æ们å ̈æ·» å ç ́¢å1/4ä¹åï1/4å°±æ ̧ æ¥å°äºè§£ MySQL å°å¦ä1/2ä1/2¿ç ̈ç ́¢å1/4ï1/4以ä3/4¿æ们è1/2å¤æ ́å¥1/2å°ä1/4åè¡ ̈Èå �»æï1/4æé«æ¥è ̄¢æçãè¿å°æ大å°åè1/2»æ们çå·¥ä1/2è ́æ ï1/4æé«æ们çå·¥ä1/2æçï1/4让æ们è1/2å¤æ ́å ä ̧æ³ ̈äºä ̧å¡é»è3/4çå¤çï1/4èä ̧æ ̄å ̈ç ́¢å1/4çæμ·æ ́ä ̧æ£æã
ä ̧ºäºè§£å³è¿ä ̧ªé®é¢ï1/4æ们å ̄ä»¥æ·±å ¥ç 究 MySQL çç ́¢å1/4éæ©æºå¶ãå®é ä ̧ï1/4è¿ä ̧ªæºå¶çæ ̧å¿å° ±æ ̄代»·æ ̈¡åï1/4å®éè¿ä ̧ä ̧ªå ¬å1/4æ¥åóå®ç ́¢å1/4çéæ©çç¥ãç ̧å ̄¹äº MySQL å ¶ä»å¤æçæ¦å¿μï1/4代价æ ̈¡åå®ç°èμ·æ¥è¦ç®åå3/4å¤ãçæ代价æ ̈¡åä¹åï1/4æ们å ̄以é¢å äºè§£ MySQL å ̈æ§è¡æ¥è ̄¢âå �¶ä1/4å¦ä1/2éæ©ç ́¢å1/4ï1/4ä»èæ ́ææå°è¿è¡ç ́¢å1/4ä1/4åãå ̈æ¥ä ̧æ¥çæ« ä ̧ï1/4æå°ç»åè¿æè¿è¡ç ́¢å1/4ä1/4åçå ·ä1/2æ¡ä3/4ï1/4æ¥è ̄¦ç»è§£éå¦ä1/2è¿ç ̈»£»·æ ̈¡åæ¥ä1/4åç ́¢å1/4ã
MySQL »£»·æ ̈¡åæμ æ æ

MySQLæ°æ®åºä¸»è¦ç±4å±ç»æï¼
1.è¿æ¥å±ï1/4客æ·ç« ̄åè¿æ¥æå¡ï1/4ä ̧»è¦å®æä ̧äºç±»ä1/41/4äºè¿æ¥å¤çãæ管çã以åç ̧å ³çå®å ̈æ¹æ¡ã
2.æå¡å±ï1/4ä ̧»è¦å®æ大å¤æ°çæ ̧å¿æå¡åè1/2ï1/4å¦SQLæ¥å£ï1/4并å®æç1/4åçæ¥è ̄¢ï1/4SQLçåååä1/4å以åå é ̈å1/2æ°çæ§è¡ã
3.å1/4æå±ï1/4è ́è ́£MySQLä ̧æ°æ®çåå ̈ååï1/4æå¡å ̈éè¿AP1ä ̧åå ̈å1/4æè¿è¡éä¿¡ã
4.åå¨å±ï¼å°æ°æ®åå¨æ件系ç»ä¸ï¼å¹¶å®æä¸åå¨å¼æç交äºã
ç ́¢å1/4çç¥éæ©å ̈SQLä1/4åå ̈è¿è¡ç
SQL ä1/4åå ̈ä1/4åæææå ̄è1/2çæ§è¡åï1®/4éæ©ææææä1/2çæ§è¡ï1/4è¿ç§ä1/4åå ̈称ä¹ä ̧ºï1/4CBOï1/4Cost-based Optimizerï1/4åºúúææ¹çä1/4åå ̈ï1/4ã
Cost = Server Cost + Engine Cost = CPU Cost + IO Cost
å ¶ä ̧ï1/4CPU Cost è¡ ̈示计ç®çå1/4éï1/4æ ̄å¦ç ́¢å1/4é®å1/4çæ ̄è3/4ãè®°å1/2å1/4çæ ̄è3/4ãç»æéçæåº ...... è¿äºæä1/2é1/2å ̈ Server å±å®æï1/4
IO Cost is¡ ̈示å1/4æå± IO çå1/4éï1/4MySQL å ̄以éè¿åºåä ̧å1/4 è¡ ̈çæ°æ®æ ̄å¦å ̈å åä ̧ï1/4åå«® è¡ç®è ̄»åå å IO å1/4é以åè ̄»åç£ç IO çå1/4éã
æºç ç®è ̄»
MySQLçæ°æ®æºä»£ç éç ̈äº5.7.22çæ¬ï1/4åç»ç代»·è®¡ç®å ¬å1/4å°åºäºæ¤çæ¬è¿è¡åèã

opt_costconstants.cc㻣»·æ ̈¡åâ计ç®æé代»·è®¡ç®ç³»æ°ã
/*
å¨Server_cost_constantsç±»ä¸å®ä¹ä¸ºéæ常éåéçææ¬å¸¸éçå¼ãå¦ææå¡å¨ç®¡çå没æå¨server_cost表ä¸æ·»å æ°å¼ï¼åå°ä½¿ç¨è¿äºé»è®¤ææ¬å¸¸æ°å¼ã
5.7çæ¬å¼å§å¯ç¨ä»æ°æ®åºå 载常éå¼ï¼è¯¥çæ¬å使ç¨ä»£ç ä¸åç常éå¼
*/
// 计ç®ç¬¦åæ¡ä»¶çâ¾ç代价ï¼â¾æ°è¶å¤ï¼æ¤é¡¹ä»£ä»·è¶â¼¤
const double Server_cost_constants::ROW_EVALUATE_COST= 0.2;
// é®â½è¾ç代价ï¼ä¾å¦æåº
const double Server_cost_constants::KEY_COMPARE_COST= 0.1;
/*
å
å临æ¶è¡¨çå建代价
éè¿åºåæµè¯ï¼å建Memory临æ¶è¡¨çææ¬ä¸å表ä¸åå
¥10è¡çææ¬ä¸æ ·é«ã
*/
const double Server_cost_constants::MEMORY_TEMPTABLE_CREATE_COST= 2.0;
// å
å临æ¶è¡¨çâ¾ä»£ä»·
const double Server_cost_constants::MEMORY_TEMPTABLE_ROW_COST= 0.2;
/*
å
é¨myisamæinnodb临æ¶è¡¨çå建代价
å建MyISAM表çé度æ¯å建Memory表ç20åã
*/
const double Server_cost_constants::DISK_TEMPTABLE_CREATE_COST= 40.0;
/*
å
é¨myisamæinnodb临æ¶è¡¨çâ¾ä»£ä»·
å½è¡æ°å¤§äº1000æ¶ï¼æ顺åºçæMyISAMè¡æ¯çæMemoryè¡æ
¢2åãç¶èï¼æ²¡æé常大ç表çåºåï¼å æ¤ä¿å®å°å°æ¤ç³»æ°è®¾ç½®ä¸ºæ
¢5åï¼å³ææ¬ä¸º1.0ï¼ã
*/
const double Server_cost_constants::DISK_TEMPTABLE_ROW_COST= 1.0;
/*
å¨SE_cost_constantsç±»ä¸å®ä¹ä¸ºéæ常éåéçææ¬å¸¸éçå¼ãå¦ææå¡å¨ç®¡çå没æå¨engine_cost表ä¸æ·»å æ°å¼ï¼åå°ä½¿ç¨è¿äºé»è®¤ææ¬å¸¸æ°å¼ã
*/
// ä»ä¸»å
åç¼å²æ± 读ååçææ¬
const double SE_cost_constants::MEMORY_BLOCK_READ_COST= 1.0;
// ä»IO设å¤ï¼ç£çï¼è¯»ååçææ¬
const double SE_cost_constants::IO_BLOCK_READ_COST= 1.0;
opt_costmodel.cc㻣»·æ ̈¡åââé ̈åæ¶åæ¹æ³ã
double Cost_model_table::page_read_cost(double pages) const
{
DBUG_ASSERT(m_initialized);
DBUG_ASSERT(pages >= 0.0);
// ä¼°ç®èéç´¢å¼å
åä¸é¡µé¢æ°å å
¶ææ页é¢æ°çæ¯ç
const double in_mem= m_table->file->table_in_memory_estimate();
const double pages_in_mem= pages * in_mem;
const double pages_on_disk= pages - pages_in_mem;
DBUG_ASSERT(pages_on_disk >= 0.0);
const double cost= buffer_block_read_cost(pages_in_mem) +
io_block_read_cost(pages_on_disk);
return cost;
}
double Cost_model_table::page_read_cost_index(uint index, double pages) const
{
DBUG_ASSERT(m_initialized);
DBUG_ASSERT(pages >= 0.0);
double in_mem= m_table->file->index_in_memory_estimate(index);
const double pages_in_mem= pages * in_mem;
const double pages_on_disk= pages - pages_in_mem;
const double cost= buffer_block_read_cost(pages_in_mem) +
io_block_read_cost(pages_on_disk);
return cost;
}
handler.ccã代价æ ̈¡åââé ̈åæ¶åæ¹æ³ã
// èéç´¢å¼æ«æIO代价计ç®å
¬å¼
Cost_estimate handler::read_cost(uint index, double ranges, double rows)
{
DBUG_ASSERT(ranges >= 0.0);
DBUG_ASSERT(rows >= 0.0);
const double io_cost= read_time(index, static_cast<uint>(ranges),
static_cast<ha_rows>(rows)) *
table->cost_model()->page_read_cost(1.0);
Cost_estimate cost;
cost.add_io(io_cost);
return cost;
}
// 表å
¨éæ«æ代价ç¸å
³è®¡ç®ï¼IO-costï¼
Cost_estimate handler::table_scan_cost()
{
const double io_cost= scan_time() * table->cost_model()->page_read_cost(1.0);
Cost_estimate cost;
cost.add_io(io_cost);
return cost;
}
// è¦çç´¢å¼æ«æ代价ç¸å
³è®¡ç®
Cost_estimate handler::index_scan_cost(uint index, double ranges, double rows)
{
DBUG_ASSERT(ranges >= 0.0);
DBUG_ASSERT(rows >= 0.0);
const double io_cost= index_only_read_time(index, rows) *
table->cost_model()->page_read_cost_index(index, 1.0);
Cost_estimate cost;
cost.add_io(io_cost);
return cost;
}
/**
ä¼°ç®å¨æå® keynrç´¢å¼è¿è¡è¦çæ«æï¼ä¸éè¦å表ï¼ï¼æ«æ recordsæ¡è®°å½ï¼éè¦è¯»åçç´¢å¼é¡µé¢æ°
@param keynr Index number
@param records Estimated number of records to be retrieved
@return
Estimated cost of 'index only' scan
*/
double handler::index_only_read_time(uint keynr, double records)
{
double read_time;
uint keys_per_block= (stats.block_size/2/
(table_share->key_info[keynr].key_length + ref_length) +
1);
read_time=((double) (records + keys_per_block-1) /
(double) keys_per_block);
return read_time;
}
sql_planner.ccãç ̈äºref访é®ç±»åç ́¢å1/4è ́¹ç ̈计ç®ã
double tmp_fanout= 0.0;
if (table->quick_keys.is_set(key) && !table_deps && //(C1)
table->quick_key_parts[key] == cur_used_keyparts && //(C2)
table->quick_n_ranges[key] == 1+MY_TEST(ref_or_null_part)) //(C3)
{
tmp_fanout= cur_fanout= (double) table->quick_rows[key];
}
else
{
// Check if we have statistic about the distribution
if (keyinfo->has_records_per_key(cur_used_keyparts - 1))
{
cur_fanout= keyinfo->records_per_key(cur_used_keyparts - 1);
if (!table_deps && table->quick_keys.is_set(key) && // (1)
table->quick_key_parts[key] > cur_used_keyparts) // (2)
{
trace_access_idx.add("chosen", false)
.add_alnum("cause", "range_uses_more_keyparts");
is_dodgy= true;
continue;
}
tmp_fanout= cur_fanout;
}
else
{
rec_per_key_t rec_per_key;
if (keyinfo->has_records_per_key(
keyinfo->user_defined_key_parts - 1))
rec_per_key=
keyinfo->records_per_key(keyinfo->user_defined_key_parts - 1);
else
rec_per_key=
rec_per_key_t(tab->records()) / distinct_keys_est + 1;
if (tab->records() == 0)
tmp_fanout= 0.0;
else if (rec_per_key / tab->records() >= 0.01)
tmp_fanout= rec_per_key;
else
{
const double a= tab->records() * 0.01;
if (keyinfo->user_defined_key_parts > 1)
tmp_fanout=
(cur_used_keyparts * (rec_per_key - a) +
a * keyinfo->user_defined_key_parts - rec_per_key) /
(keyinfo->user_defined_key_parts - 1);
else
tmp_fanout= a;
set_if_bigger(tmp_fanout, 1.0);
}
cur_fanout= (ulong) tmp_fanout;
}
if (ref_or_null_part)
{
// We need to do two key searches to find key
tmp_fanout*= 2.0;
cur_fanout*= 2.0;
}
if (table->quick_keys.is_set(key) &&
table->quick_key_parts[key] <= cur_used_keyparts &&
const_part &
((key_part_map)1 << table->quick_key_parts[key]) &&
table->quick_n_ranges[key] == 1 + MY_TEST(ref_or_null_part &
const_part) &&
cur_fanout > (double) table->quick_rows[key])
{
tmp_fanout= cur_fanout= (double) table->quick_rows[key];
}
}
······
······
// Limit the number of matched rows
const double tmp_fanout=
min(cur_fanout, (double) thd->variables.max_seeks_for_key);
if (table->covering_keys.is_set(key)
|| (table->file->index_flags(key, 0, 0) & HA_CLUSTERED_INDEX))
{
// We can use only index tree
const Cost_estimate index_read_cost=
table->file->index_scan_cost(key, 1, tmp_fanout);
cur_read_cost= prefix_rowcount * index_read_cost.total_cost();
}
else if (key == table->s->primary_key &&
table->file->primary_key_is_clustered())
{
const Cost_estimate table_read_cost=
table->file->read_cost(key, 1, tmp_fanout);
cur_read_cost= prefix_rowcount * table_read_cost.total_cost();
}
else
cur_read_cost= prefix_rowcount *
min(table->cost_model()->page_read_cost(tmp_fanout),
tab->worst_seeks);
handler.ccãç ̈äºrange访é®ç±»åç ́¢å1/4è ́¹ç ̈计ç®ã
handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
void *seq_init_param, uint n_ranges_arg,
uint *bufsz, uint *flags,
Cost_estimate *cost)
{
KEY_MULTI_RANGE range;
range_seq_t seq_it;
ha_rows rows, total_rows= 0;
uint n_ranges=0;
THD *thd= current_thd;
/* Default MRR implementation doesn't need buffer */
*bufsz= 0;
DBUG_EXECUTE_IF("bug13822652_2", thd->killed= THD::KILL_QUERY;);
seq_it= seq->init(seq_init_param, n_ranges, *flags);
while (!seq->next(seq_it, &range))
{
if (unlikely(thd->killed != 0))
return HA_POS_ERROR;
n_ranges++;
key_range *min_endp, *max_endp;
if (range.range_flag & GEOM_FLAG)
{
min_endp= &range.start_key;
max_endp= NULL;
}
else
{
min_endp= range.start_key.length? &range.start_key : NULL;
max_endp= range.end_key.length? &range.end_key : NULL;
}
int keyparts_used= 0;
if ((range.range_flag & UNIQUE_RANGE) && // 1)
!(range.range_flag & NULL_RANGE))
rows= 1; /* there can be at most one row */
else if ((range.range_flag & EQ_RANGE) && // 2a)
(range.range_flag & USE_INDEX_STATISTICS) && // 2b)
(keyparts_used= my_count_bits(range.start_key.keypart_map)) &&
table->
key_info[keyno].has_records_per_key(keyparts_used-1) && // 2c)
!(range.range_flag & NULL_RANGE))
{
rows= static_cast<ha_rows>(
table->key_info[keyno].records_per_key(keyparts_used - 1));
}
else
{
DBUG_EXECUTE_IF("crash_records_in_range", DBUG_SUICIDE(););
DBUG_ASSERT(min_endp || max_endp);
if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
max_endp)))
{
/* Can't scan one range => can't do MRR scan at all */
total_rows= HA_POS_ERROR;
break;
}
}
total_rows += rows;
}
if (total_rows != HA_POS_ERROR)
{
const Cost_model_table *const cost_model= table->cost_model();
/* The following calculation is the same as in multi_range_read_info(): */
*flags|= HA_MRR_USE_DEFAULT_IMPL;
*flags|= HA_MRR_SUPPORT_SORTED;
DBUG_ASSERT(cost->is_zero());
if (*flags & HA_MRR_INDEX_ONLY)
*cost= index_scan_cost(keyno, static_cast<double>(n_ranges),
static_cast<double>(total_rows));
else
*cost= read_cost(keyno, static_cast<double>(n_ranges),
static_cast<double>(total_rows));
cost->add_cpu(cost_model->row_evaluate_cost(
static_cast<double>(total_rows)) + 0.01);
}
return total_rows;
}
éªè ̄å ¬å1/4
å建éªè ̄éè¦çè¡ ̈
CREATE TABLE `store_goods_center`
(
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主é®id',
`sku_id` bigint(20) NOT NULL COMMENT 'ååskuid',
`station_no` varchar(20) NOT NULL COMMENT 'é¨åºç¼å·',
`org_code` bigint(20) NOT NULL COMMENT 'å家ç¼å·',
`extend_field` text COMMENT 'æ©å±å段',
`version` int(11) DEFAULT '0' COMMENT 'çæ¬å·',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´',
`create_pin` varchar(50) DEFAULT '' COMMENT 'å建人',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT 'æ´æ°æ¶é´',
`update_pin` varchar(50) DEFAULT '' COMMENT 'æ´æ°äºº',
`yn` tinyint(4) DEFAULT '0' COMMENT 'å é¤æ 示 0:æ£å¸¸ 1ï¼å é¤',
`ts` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'æ¶é´æ³',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_storegoods` (`station_no`, `sku_id`) USING BTREE,
KEY `idx_storegoods_org` (`org_code`, `sku_id`, `station_no`),
KEY `idx_sku_id` (`sku_id`),
KEY `idx_station_no_and_id` (`station_no`, `id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='é¨åºååå
³ç³»è¡¨';
éè¿åå ̈è¿ç ̈åå§åæμè ̄æ°æ®
DELIMITER //
CREATE PROCEDURE callback()
BEGIN
DECLARE num INT;
SET num = 1;
WHILE
num <= 100000 DO
INSERT INTO store_goods_center(sku_id, station_no, org_code) VALUES (num + 10000000, floor(50+rand()*(100-50+1)), num);
SET num = num + 1;
END WHILE;
END;
æ§è¡åå ̈è¿ç ̈çææ°æ®
CALL callback();
1.å ¨è¡¨æ«æ计ç®ä»£ä»·å ¬å¼
计ç®è¿ç¨ï¼
// ä¸åå¼æ计ç®æ¹å¼ææåºå«
// innodbå¼æå®ç°handler.h
// é¢ä¼°è®°å½æ°ï¼ha_innobase::info_low
// 页æ°éï¼ha_innobase::scan_timeãæ°æ®æ»å¤§å°(åè) / 页大å°ã
// æ¥è¯¢å
¨è¡¨æ°æ®å¤§å°ï¼7880704ï¼
SHOW TABLE STATUS LIKE 'store_goods_center';
// æ¥è¯¢æ°æ®åºé¡µå¤§å°ï¼é»è®¤ï¼16384ï¼
SHOW VARIABLES LIKE 'innodb_page_size';
// å
¨è¡¨æ«æ计ç®ä»£ä»·
// 页æ°é
page = æ°æ®æ»å¤§å°(åè) / é¡µå¤§å° = 7880704 / 16384 = 481;
// é¢ä¼°èå´è¡æ°ï¼æ»æ°æ®æ¡æ°ï¼10ä¸ï¼é¢ä¼°æ°æ®æ¡æ°ï¼99827ï¼æä¸å®è¯¯å·®ï¼
records = 99827;
// 计ç®æ»ä»£ä»·
// 481 * 1 ä¸çç³»æ°1 代表ä»ä¸»å
åç¼å²æ± 读ååçææ¬ï¼SE_cost_constants::IO_BLOCK_READ_COST= 1.0ï¼
// 99827 * 0.2 ä¸çç³»æ°0.2 代表计ç®ç¬¦åæ¡ä»¶çâ¾ç代价ï¼ROW_EVALUATE_COST= 0.2ï¼
cost = IO-cost + CPU-cost = (481 * 1) + (99827 * 0.2) = 481 + 19965.4 = 20446.4
éªè ̄ç»æï1/4
explain format = json
select * from store_goods_center;
"cost_info": {"query_cost": "20446.40"}
æ"ç»å ¬å1/4ï1/4
å
¨è¡¨æ«æ代价 = æ°æ®æ»å¤§å° / 16384 + é¢ä¼°èå´è¡æ° * 0.2
2.è¦çç´¢å¼æ«æ计ç®ä»£ä»·å ¬å¼
计ç®è¿ç¨ï¼
// æ¥è¯¢å
¨è¡¨æ°æ®å¤§å°ï¼7880704ï¼
SHOW TABLE STATUS LIKE 'store_goods_center';
// æ¥è¯¢æ°æ®åºé¡µå¤§å°ï¼é»è®¤ï¼16384ï¼
SHOW VARIABLES LIKE 'innodb_page_size';
// é¢ä¼°èå´è¡æ°ï¼æ»æ°æ®æ¡æ°ï¼1999ï¼é¢ä¼°æ°æ®æ¡æ°ï¼1999ï¼æä¸å®è¯¯å·®ï¼ 1999;
records = 1999
// keys_per_block计ç®
// block_sizeæ¯æ件çblock大å°ï¼mysqlé»è®¤ä¸º16Kï¼
// key_lenæ¯ç´¢å¼çé®é¿åº¦ï¼
// ref_lenæ¯ä¸»é®ç´¢å¼çé¿åº¦ï¼
keys_per_block = (stats.block_size / 2 / (table_share->key_info[keynr].key_length + ref_length) + 1);
// table_share->key_info[keynr].key_length 为èåç´¢å¼ï¼åå«æ¯station_noåsku_id
// station_no 为varchar(20)ä¸ä¸ºutf8mb4ï¼é¿åº¦ = 20 * 4 + 2 (å¯åé¿åº¦éè¦å 2) = 82
// sku_id bigintç±»åï¼é¿åº¦ä¸º8
// 主é®ç´¢å¼ä¸ºbigintç±»åï¼é¿åº¦ä¸º8
keys_per_block = 16384 / 2 / (82 + 8 + 8) + 1 â 84
// 计ç®æ»ä»£ä»·
read_time = ((double) (records + keys_per_block - 1) / (double) keys_per_block);
read_time = (1999 + 84 - 1) / 84 = 24.78;
// 计ç®æ»ä»£ä»·
// 24.78 * 1 ä¸çç³»æ°1 代表ä»ä¸»å
åç¼å²æ± 读ååçææ¬ï¼SE_cost_constants::IO_BLOCK_READ_COST= 1.0ï¼
// 1999 * 0.2 ä¸çç³»æ°0.2 代表计ç®ç¬¦åæ¡ä»¶çâ¾ç代价ï¼ROW_EVALUATE_COST= 0.2ï¼
cost = IO-cost + CPU-cost = (24.78 * 1) + (1999 * 0.2) = 24.78 + 399.8 = 424.58
éªè ̄ç»æï1/4
explain format = json
select station_no from store_goods_center where station_no = '53';
"cost_info": {"query_cost": "424.58"}
æ"ç»å ¬å1/4ï1/4
keys_per_block = 8192 / ç´¢å¼é¿åº¦ + 1
è¦çç´¢å¼æ«æ代价 = (records + keys_per_block - 1) / keys_per_block + é¢ä¼°èå´è¡æ° * 0.2
å
¬å¼ç®åï¼å»é¤å½±åè¾å°çå¤æ计ç®ï¼
è¦çç´¢å¼æ«æ代价 = (records * æ¶åç´¢å¼é¿åº¦) / 8192 + é¢ä¼°èå´è¡æ° * 0.2
3.refç´¢å¼æ«æ计ç®ä»£ä»·å ¬å¼
计ç®è¿ç¨ï¼
// cardinality = 49ï¼åºæ°ï¼å³æå¤å°ä¸ªä¸åkeyç»è®¡ãï¼
SHOW TABLE STATUS LIKE 'store_goods_center';
// 页æ°é
page = æ°æ®æ»å¤§å°(åè) / é¡µå¤§å° = 7880704 / 16384 = 481;
// 计ç®ä»£ä»·æä½ç´¢å¼(sql_planner.cc ä¸find_best_refå½æ°)
// IO COSTæåä¸ä¼è¶
è¿å
¨è¡¨æ«æIOæ¶èç3å(æè
æ»è®°å½æ°é¤ä»¥10)
// å
¶ä¸s->found_records表示表ä¸çè®°å½æ°ï¼s->read_timeå¨innodbå±è¡¨ç¤ºpageæ°
// s-> worst_seeks = min((double) s -> found_records / 10, (double) s -> read_time * 3);
// cur_read_cost= prefix_rowcount * min(table->cost_model() -> page_read_cost(tmp_fanout), tab -> worst_seeks);
// é¢ä¼°èå´è¡æ°ï¼æ»æ°æ®æ¡æ°ï¼10ä¸ï¼é¢ä¼°æ°æ®æ¡æ°ï¼99827ï¼æä¸å®è¯¯å·®ï¼
total_records = 99827;
// é¢ä¼°èå´è¡æ°ï¼æ»æ°æ®æ¡æ°ï¼1999ï¼é¢ä¼°æ°æ®æ¡æ°ï¼1999ï¼æä¸å®è¯¯å·®ï¼ 1999;
records = 1999
// 计ç®æ»ä»£ä»·
// 1999 * 0.2 ä¸çç³»æ°0.2 代表计ç®ç¬¦åæ¡ä»¶çâ¾ç代价ï¼ROW_EVALUATE_COST= 0.2ï¼
// s-> worst_seeks = min((double) s -> found_records / 10, (double) s -> read_time * 3) -> min(99827 / 10, 481 * 3) = 481 * 3
// min(table->cost_model() -> page_read_cost(tmp_fanout), tab -> worst_seeks) -> min(page_read_cost(1999), 481 * 3) = 481 * 3
cost = IO-cost + CPU-cost = 481 * 3 + (1999 * 0.2) = 1443 + 399.8 = 1842.80
éªè ̄ç»æï1/4
explain format = json
select * from store_goods_center where station_no = '53';
"cost_info": {"query_cost": "1842.80"}
æ"ç»å ¬å1/4ï1/4
ä¸é¢3个å
¬å¼ï¼åå¼æä½ç
1.(æ°æ®æ»å¤§å° / 16384) * 3 + é¢ä¼°èå´è¡æ° * 0.2
2.æ»è®°å½æ° / 10 + é¢ä¼°èå´è¡æ° * 0.2
3.æ«æåºè®°å½æ° + é¢ä¼°èå´è¡æ° * 0.2
4.rangeç´¢å¼æ«æ计ç®ä»£ä»·å ¬å¼
// é¢ä¼°èå´è¡æ°ï¼æ»æ°æ®æ¡æ°ï¼1299ï¼é¢ä¼°æ°æ®æ¡æ°ï¼1299ï¼æä¸å®è¯¯å·®ï¼ 1299;
records = 1299
// 计ç®ä»£ä»·æä½ç´¢å¼(handler.cc ä¸ multi_range_read_info_const å½æ°)
// 计ç®æ»ä»£ä»·
// 1299 * 0.2 计ç®å
¬å¼ï¼cost_model->row_evaluate_cost(static_cast<double>(total_rows))
// + 0.01 计ç®å
¬å¼ï¼cost->add_cpu(cost_model->row_evaluate_cost(static_cast<double>(total_rows)) + 0.01);
// 1299 + 1 ä¸ç +1 ï¼å个æ«æåºé´ï¼ id > 35018 ï¼
// 1299 + 1 计ç®å
¬å¼ï¼*cost= read_cost(keyno, static_cast<double>(n_ranges), static_cast<double>(total_rows));
// (1299 * 0.2 + 0.01 + 1299) * 1 ä¸çç³»æ°1 代表ä»ä¸»å
åç¼å²æ± 读ååçææ¬ï¼SE_cost_constants::IO_BLOCK_READ_COST= 1.0ï¼
// 1299 * 0.2 ä¸çç³»æ°0.2 代表计ç®ç¬¦åæ¡ä»¶çâ¾ç代价ï¼ROW_EVALUATE_COST= 0.2ï¼
cost = IO-cost + CPU-cost = ((1299 * 0.2 + 0.01 + 1299 + 1) * 1) + (1299 * 0.2) = 1559.81 + 259.8 = 1819.61
éªè ̄ç»æï1/4
explain format = json
select * from store_goods_center where station_no = '53' and id > 35018;
"cost_info": {"query_cost": "1819.61"}
æ"ç»å ¬å1/4ï1/4
rangeæ«æ代价 = é¢ä¼°èå´è¡æ° * 1.4 + 0.01 + èå´æ°
å
¬å¼ç®åï¼å»é¤å½±åè¾å°çå¤æ计ç®ï¼
rangeæ«æ代价 = é¢ä¼°èå´è¡æ° * 1.4
ç´¢å¼å²çªæ¡ä¾
é ̈åºååç³»ç»ä ̧ä ̧»è¦åå ̈é ̈åºä ̧ååçå ³èä¿¡æ ̄ï1/4并ä ̧ºBç« ̄æä3/4æ ¹æ®é ̈åºIDæ¥è ̄¢å ³èååçåè1/2ãç±äºé ̈åºå ³èçåå°æ®éè3/4大ï1/4éè¦åé¡μæ¥è ̄¢å ³èåå°æ®ãä ̧ºé¿å æ·±åé¡μé®é¢ï1/4æ们éæ©åºäºä ̧次ææ°ä ̧»é®è¿è¡æ¥è ̄¢ï1/4æ ̧å¿ææ³ï1/4éè¿ä ̧»é®ç ́¢å1/4ï1/4æ ̄次å®ä1/2å° IDæå ̈ä1/2ç1/2®ï1/4ç¶åå3/4åéåNä ̧ªæ°æ®ãè¿æ ·ï1/4æ 论æ°æ®éå¤å°ï1/4æ¥è ̄¢æ§è1/2é1/2è1/2ä¿æç ̈³å®ãæ们å°ææ°æ®æ ¹æ®ä ̧»é®IDè¿è¡æåºï1/4ç¶åå¹æ¬¡ååºï1/4å°å1/2åæ¹æ¬¡çæ大IDä1/2ä ̧ºä ̧次æ¥è ̄¢ççéæ¡ä»¶ï1/4ã
select å段1ï¼å段2 ... from store_goods_center where station_no = âé¨åºidâ and id > ä¸æ¬¡æ¥è¯¢æ大id order by id asc
为äºç¡®ä¿é¨åºä¸ååç»åçå¯ä¸æ§ï¼æ们å¨MySQL表ä¸ä¸ºé¨åºIDåååIDæ·» å äºç»åå¯ä¸ç´¢å¼ãUNIQUE KEY uniq_storegoods (station_no, sku_id) USING BTREEããç±äºè¯¥ç´¢å¼å å«é¨åºID并ä¸å¨èåç´¢å¼ç第ä¸ä¸ªä½ç½®ï¼æ¥è¯¢ä¼ä½¿ç¨è¯¥ç´¢å¼ãä½æ¯ï¼å½å页æ¥è¯¢å½ä¸è¯¥ç´¢å¼åï¼ç±äºæåºå段æ æ³ä½¿ç¨ç´¢å¼ï¼äº§çäºãUsing filesortãï¼å¯¼è´é¨åºååç³»ç»åºç°äºä¸äºæ ¢æ¥è¯¢ã为äºè§£å³è¿ä¸ªé®é¢ï¼æä»¬å¯¹æ ¢æ¥è¯¢è¿è¡äºä¼åï¼ä¼åæè·¯æ¯å建ä¸ä¸ªæ°çç´¢å¼ï¼ä½¿è¯¥SQLå¯ä»¥ä½¿ç¨ç´¢å¼çæåºæ¥è§é¿ãUsing filesortãçè´é¢å½±åï¼æ°æ·» å çç´¢å¼ä¸ºãKEY idx_station_no_and_id (station_no, id)ããæ·» å 该索å¼åï¼ææç«ç«¿è§å½±ã
ç¶èï1/4æ们åç°ä»ç¶ææ ¢æ¥è ̄¢äº§çï1/4并ä ̧è¿äºæ ¢æ¥è ̄¢ä»ç¶ä1/2¿ç ̈ uniq_storegoodsç ́¢å1/4ï1/4èä ̧æ ̄ idx_station_no_and_idç ́¢å11 /4ãæ们å1/4å§æèï1/4a ̧ºä»ä¹MySQL没æä ̧ºæ»¬çç³»ç»æ ̈èä1/2¿ç ̈æä1/4çç ́¢å1/4ï1/4æ ̄MySQLç ́¢å1/4æ ̈èæ®é é¢ï1/4è¿æ ̄æ们å建ç ́¢å1/4æé®é¢ï1/4å¦ä1/2åæè1/2让MySQLå ̧®æ们æ ̈èæ们认a ̧ºæä1/4çç ́¢å1/4ï1/4
å1/2ç¶ï1/4æ们ä¹å ̄以ä1/2¿ç ̈FORCE INDEXå1/4ºè¡è®©MySQLèμ°æ们æåé¢è®3/4çç ́¢å1/4ï1/4ä1/2æ ̄è¿ç§æ¹å1/4å±é太大ï1 /4åæç ́¢å1/4ç» ́æ¤ææ¬åå3/4å3/4é«ï1/4çè³å ̄è1/2ä1/2¿ç ̈è ̄¥SQLçå ¶ä»ä ̧å¡æ§è1/2åä1/2ãä ̧ºäºçªç ́æ ́ä1/2ä1/4åçå¡ç¹ç¶æï1/4æ们éè¦äºè§£ä ̧ä ̧MySQLç ́¢å1/4æ ̈èåºå±é»è3/4ï1/4å³MySQL代»·æ ̈¡åãºè§£ç ̧åºè§ååï1/4ç°é¶æ®μçé®é¢å°è¿åè解ã
æ¡ä¾åæåä¼å
å ̈åé¡3/4åæçé®é¢æ¶ï1/4æ们åç°é®é¢æºäºåå§ç ́¢å1/4产çäºãUsing filesortãï1/4ä»èå ̄1/4è ́äºæ ¢æ¥è ̄¢çåºç°ãä ̧ºú解å³è¿§ªé®é¢ï1/4æ们æ°å¢äºä ̧ªçªç ́¢å1/4ï1/4å³ãKEY idx_station_no_and_id (station_no, id)ãï1/4以æ¿ä»£åæçç ́¢å1/4ãUNIQUE KEY uniq_storegoods (station_no, sku_id)ããç¶èï1/4å°1/2管æ°å¢ç ́¢å1/4å大é ̈åæ ¢æ¥è ̄¢å3/4å °äºè§£å³ï1/4ä1/2ä»æé ̈åæ ¢æ¥è ̄¢æªè1/2æ¶é¤ãè¿ä ̧æåç°ï1/4è¿äºæ ¢æ¥è ̄¢æ ̄ç±äºSQL没æä1/2¿ç ̈æ们ææçç ́¢å1/4ï1/4èæ ̄ä1/2¿ç ̈äºèç ́¢å1/4ï1/4ä»èå1/4åäºãUsing filesortãé®é¢ãå ̈éè¿explainè¿è¡åæåï1/4æ们ææ¶è¿æ²¡ææ3/4å°åéç解å³æ¹æ¡ã
é®é¢ï1/4å°1/2管æ们æ°å¢äºç ́¢å1/4ï1/4并ä ̧大é ̈åSQLå·²ç»è1/2å¤ä1/2¿ç ̈æ°ç ́¢å1/4è¿è¡ä1/4åï1/4ä1/2ä»åå ̈ä ̧äºSQL没æä1/2¿ç ̈æ°ç ́¢å1/4ã
// éè¿ä»£ä»·æ¨¡åè¿è¡åæ
// 使ç¨ä¸é¢çæµè¯æ°æ®è¿è¡åæ
// æ°å¢ç´¢å¼åé½æ²¡æèµ°æ°ç´¢å¼
// èç´¢å¼ï¼æ«æè¡æ°ï¼1999ï¼ä»£ä»·è®¡ç®å¼ï¼1842.80ï¼refç±»åç´¢å¼
// æ°ç´¢å¼ï¼æ«æè¡æ°ï¼1999ï¼ä»£ä»·è®¡ç®å¼ï¼1850.46ï¼rangeç±»åç´¢å¼
select å段1ï¼å段2 ... from store_goods_center where station_no = âé¨åºidâ and id > -1 order by id asc;
// æ°å¢ç´¢å¼åèµ°æ°ç´¢å¼
// èç´¢å¼ï¼æ«æè¡æ°ï¼1999ï¼ä»£ä»·è®¡ç®å¼ï¼1842.80ï¼refç±»åç´¢å¼
// æ°ç´¢å¼ï¼æ«æè¡æ°ï¼1299ï¼ä»£ä»·è®¡ç®å¼ï¼1819.61ï¼rangeç±»åç´¢å¼
select å段1ï¼å段2 ... from store_goods_center where station_no = âé¨åºidâ and id > 35018 order by id asc;
ç»è¿åæMySQLç代»·æ ̈¡åï1/4æ们åç°MySQLå ̈éæ©ä1/2¿ç ̈åªä ̧ªç ́¢å1/4æ¶ï1/4ä ̧»è¦åå³äºæ«æåºçæ°æ®æ¡æ°ãå ·ä1/2æ¥è ̄ ́ï1/4æ«æåºçæ°æ®æ¡æ°è¶å°ï1/4MySQLå°±è¶å3/4åäºéæ©è ̄¥ç ́¢å1/4ï1/4ç±äºMySQLçç ́¢å1/4æ°æ®è®¿é®ç±»ååå1/4ï1/4计ç®å ¬å1/4ä¹ä1/4ææä ̧ååå æ¤ï1/4å ̈å¤ä ̧ªç ́¢å1/4çæ«æè¡æ°ç ̧è¿çæ åμä ̧ï1/4æéç ̧ ̧è �¢å1/4å ̄è1/2ä ̧æ们ææçç ́¢å1/4ææä ̧åï1/4ã顺çè¿ä ̧ªæè· ̄ææ¥ï1/4æ们åç°å1/2id > -1æ¶ï1/4æ 论æ ̄ä1/2¿ç ̈storeId + skuIdè¿æ ̄storeId + idç ́¢å1/4è¿è¡æ¥è ̄¢ï1/4æ«æåºçæ°æ®æ¡æ°æ ̄ç ̧åçãè¿æ ̄å ä ̧ºè¿ä ̧¤ç§æ¥è ̄¢æ¹å1/4åå �1/2æ ̄æ ¹æ®é ̈åºæ¥è ̄¢ååæ°æ®ï1/4ä ̧idå1/4è ̄å®å¤§äº1ãå æ¤ï1/4å ̄¹äºMySQLæ¥è ̄ ́ï1/4ç±äºè¿ä ̧¤ç§ç ́¢å1/4æ«æåºçæ°æ®æ¡æ°ç ̧åï1/4æ以ä1/2¿ç ̈åªç§ç ́¢å1/4ææç ̧å·®ä ̧å¤ãè¿å°±æ ̄ä ̧ºä»ä¹ä ̧é ̈åæ¥è ̄¢èμ°æ°ç ́¢åå ́ 1/4ï1/4èå¦ä ̧é ̈åæ¥è ̄¢èμ°èç ́¢å1/4çåå ãç¶èï1/4å1/2æ¥è ̄¢æ¡ä»¶ä ̧ºid > næ¶ï1/4storeId + idç ́¢å1/4çä1/4å¿ä3/4¿å3/4以æ3/4ç°ãå ä ̧ºå®è1/2å¤ç ́æ¥ä»ç ́¢å1/4ä ̧æ«æ并跳è¿id <= nçæ°æ®ï1/4èstoreId + skuIdç ́¢å1/4å ́æ æ³ç ́æ ́æ ¥è·³è¿è¿é ̈åæ°æ®ï1/4å æ¤çæ£æ¦¦°æ®æ¡æ°storeId + skuIdè¦å¤§äºstoreId + idå æ¤ï1/4å ̈æ¥è ̄¢æ¡ä»¶ä ̧ºid > næ¶ï1/4MySQLæ ́å3/4åäºä1/2¿ç ̈æ°ç ́¢å1/4ãï1/4éè¦æ³ ̈æçæ ̄ï1/4示ä3/4ç»åºçæ°æ®ç ́¢å1/4æ°æ®è®¿é®ç±»åä ̧åï1/4ä ́a ́ �ä ̧ªæ ̄rangeç ́¢å1/4ç±»åï1/4a ̧ä ̧ªæ ̄refç ́¢å1/4ç±»åãç±äºç®æ³ä ̧åï1/4å³ä1/2¿æä ̧ªç ́¢å1/4çæ£ç ́¢æ°æ®çç¥é«äºå¦ä ̧ä ̧ªç ́¢å1/4ï1/4ä¹å ̄è1/2å ̄1/4è ́ç³»ç»å°å ¶æ ̈èä ̧ºæä1/4ç ́¢å1/4ï1/4
é®é¢å·²ç»åææ ̧ æ¥ï1/4ä ̧»è¦åå æ ̄åå ̈å¤ä ̧ªç ́¢å1/4ï1/4ä ̧æ ¹æ®ç ́¢å1/4代价计ç®å ¬å1/4ç代价ç ̧è¿ï1/44 å ̄1/4è ́é3/4以ææ©ãå æ¤ï1/4解å³è¿ä ̧ªé®é¢çæ¹æ³ä ̧åºè ̄¥æ ̄åæ¶å®ä¹ä ̧¤ä ̧ªä1/4让MySQL"çº ç»"çç ́¢å1/4éæ©ãç ̧åï1/4åºè ̄¥å°ä ̧¤ä ̧ªç ́¢å1/4èåä ̧ºä ̧ä ̧ªç ́¢å1/4ãå ·ä1/2ç解å³æ¹æ¡æ ̄æ ¹æ®é ̈åºæ¥è ̄¢ï1/4å °åæ¥çä ̧»é®idä1/2ä ̧ºä ̧次æ¥è ̄¢çæ大idæ¿æ¢ä ̧ºskuIdãå ̈ç®æ³åæ¢å®æåï1/4å é¤æ°çé ̈åº+ä ̧»é®idç ́¢å1/4ãç¶èï1/4è¿ç§æ¹å1/4å ̄è1/2ä1/4åå¦ä ̧ä ̧ªé®é¢ãç±äºåºå±æåºç®æ³åçäºååï1/4ç±åæ¥çä ̧»é®idæ¹ä ̧ºskuIdï1/4ï1/4å ̄è1/2å ̄1/4è ́æ æ³ç ́æ¥ä»åºå±æå¡åæ¢ãæ¤æ¶ï1/4åºèèä»ä ̧æ ̧ ̧ä1/2¿ç ̈æ¤æ¥å£æ¥¡çåºç ̈è¿è¡å榢ãé¦æ³ ̈æçó � ̄ï1/4å¦æä ̧æ ̧ ̧ç³»ç»æ ̄åæºåé¡μè¿ä»£æ¥è ̄¢é ̈åºæ°æ ï1/4é£ä¹ä®̧æ ̧ ̧ç³»ç»å ̄以ç ́æ¥è¿è¡åæ¢ãä1/2å¦æè¿ç§åé¡μæ¥è ̄¢å ̈ä1/2åæ¶äº¤ç»å¤å°åºç ̈æå¡å ̈æ§è¡ï1/4åæ¢è¿ç ̈å°åå3/4ç ̧å1/2å¤å �ï1/4ä»ä»¬çåæ¢ææ¬ä ̧åºå±åæ¢ææ¬ç ̧åãä1/2æ ̄ï1/4è¿ä ̧ªç³»ç»çå ̄¹å¤æå¡å±äºè¿ç§æ åμï1/4ä ̧æ ̧ ̧è°ç ̈ç³»ç»ä1/4æå¤å°åºç ̈æå¡å ̈åä1/2åé¡μè¿ä»£æ¥è ̄¢æ°æ®ï1/4ä ̧ºè¿æ¬¡ä1/4åå ̧¦æ¥å3/4大å1/2±åã
æç»ï¼è®©åºå±ç¬ç«å®æåæ¢æ¹å¼æ为åéãå¨åæ¢è¿ç¨ä¸ï¼å ³é®å¨äºæ£ç¡®åºåæ°èç®æ³ãèç®æ³å¨è¿ä»£è¿ç¨ä¸ä¸åºåæ¢è³æ°ç®æ³ãåç³»ç»å¯¹å¤æå¡æä¾çä¸æ¬¡è¿ä»£ç¨çidå¯ç¨æ¥è¿è¡åºåãæ°ç®æ³å¨è¿åä¸æ¬¡è¿ä»£ç¨çidåºç¡ä¸å¢å ä¸ä¸ªå¸¸éå¼ï¼ä¾å¦10亿ï¼å å®åä¸è½ä¸åæ°æ®å²çªï¼ä¹å¯ä»¥å°è¿ä»£idç±æ´æ°è½¬æ¢æè´æ°ä»¥åºåæ°èç®æ³ï¼ãå æ¤ï¼å¦ææ¯ç¬¬ä¸æ¬¡è®¿é®ï¼ç´æ¥ä½¿ç¨æ°ç®æ³ï¼å¦æä¸æ¯ç¬¬ä¸æ¬¡è®¿é®ï¼éè¦æ ¹æ®ä¸æ¬¡è¿ä»£ç¨çidå ·ä½è§åæ¥å¤ææ¯å¦åæ¢æ°èç®æ³ã
æ»ç»ä ̧åç»è§å
ä1/2¿ç ̈Explanæ§è¡è®¡ååå ̈æ æ³æåé¢ç¥ç ́¢å1/4éæ©çå±éæ§ãç¶èï1/4åªè¦çæMySQLåºå±ä»£»·æ ̈¡åç计ç®å ¬å1/4ï1/4æ们就è1/2é¢ç¥ç ́¢å1/4çèμ°ååãåå©ä»£ä»·æ ̈¡åï1/4æ们ä ̧ä» å ̄以åæç ́¢å1/4å²çªçåå ï1/4è¿å ̄以å ̈åçå²çªä¹åè¿è¡é¢è¦ãçè³å ̈æ·» å ç ́¢å1/4ä¹åï1/4æ们ä¹å ̄ä»¥æ ¹æ®ä»£ä»·æ ̈¡åå ¬å1/4æ¥æææåæ1/2å ̈é®é¢ãæ¤å¤ï1/4æ ¹æ®æ°æ®ä ̧å¡å ̄åº �ï1/4æ们è¿å ̄以é¢ä1/4°å1/2åç ́¢å1/4çåçæ§ï1/4以åæ ̄å¦å ̄è1/2åºç°å ̈è¡ ̈æ«æçæ åμãå æ¤ï1/4æ·±å ¥ç 究MySQL代价æ ̈¡åå ̄¹äºä1/4åç ́¢å1/4管çå ·æå ³é®æä¹ã
æªæ¥æä"¬çç³"ûç»åºç ̈å°ç"åMySQLä"£ä»·æ ̈¡åè¿è¡éæï1/4å®ç°èªå ̈åææ°æ®åºåè¡ ̈çä¿¡æ ̄ï1/4ä"¥åç°å1/2 Åç ́¢å1/4åå ̈çé®é¢ï1/4ä3/4å¦ç ́¢å1/4å²çªææªä1/2¿ç ̈ç ́¢å1/4å ̄1/4è ́çå ̈è¡ ̈æ«æ¤å¤ï1/4è ̄¥å·¥å · è¿å ̄以éå ̄¹å°æªæ·» Å ç ́¢å1/4çè¡ ̈ï1/4æ ¹æ®æ°æ®æ åμæä3/4åéçç ́¢å1/4æ ̈èãåæ¶ï1/4è ̄¥å·¥å ·è¿è1/2å¤é¢æμå1/2æ°æ®è3/43/4å°æç§å ̄度æ¶ï1/4å ̄è1/2åºç°å ̈è¡ ̈æ«æçé®é¢ï1/4ä"èå ̧®å©æååå¥1/2ä1/4å¤ã
ä ̧ºäºå®ç°è¿äºåè1/2ï1/4æ们å°é¦å å ̄¹MySQL代价æ ̈¡åè¿è¡æ·±å ¥ç 究ï1/4å ̈é¢äºè§£å ¶è®¡ç®å ¬å1/4åååçãè¿å°æå©äºæ们ç1/4åç ̧åºçç®æ³ï1/4èªå ̈åææ°æ®åºåè¡ ̈çä¿¡æ ̄ï1/4æ3/4åºæ1/2å ̈çç ́¢å1/4é®é¢ãæ¤å¤ï1/4æ们è¿å ³æ³ ̈æç ̈æ§åå®ç ̈æ§ï1/4ç¡®ä¿ç ̈æ·è1/2å¤è1/2»æ3/4å°è3/4å¥ç ̧å ³æ°æ®åºåè¡ ̈çä¿¡æ ̄ï1/4并è·åå³ä1/4å建议ã
è ̄¥å·¥å ·çå1/4åå°æå©äºæé«æ«æ®åºæ§è1/2ï1/4åå°å ̈è¡ ̈æ«æçåçï1/4éä1/2ç³»ç»èμæºæ¶èãåæ¶ï1/4å®è¿å ̄以ä ̧ºæ°æ®åºç®¡çåå1/4å人åää3/4ä3/4¿å©ï1/4ä1/2¿ä»ä»¬è1/2å¤æ ́å ä ̧æ³ ̈äºå ¶ä»æ ̧å¿ä ̧å¡ãéè¿ç»åMySQL代价æ ̈¡åï1/4æ们ç ̧ä¿¡è¿ä ̧ªå·¥å ·å°å ̈ä1/4åç ́¢å1/4管çæ¹é¢åæ¥éè¦ä1/2ç ̈ï1/4ä ̧ºä1/4ä ̧å ̧¦æ¥æ ́é«çæçã
åèèµæ
https://github.com/mysql/mysql-server
ä1/2è ï1/4京ä ̧é¶å® çå¤å
æ¥æºï¼äº¬ä¸äºå¼åè 社åº