mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-31 10:56:12 +01:00 
			
		
		
		
	 52c29f3bdc
			
		
	
	
	52c29f3bdc
	
	
	
		
			
			Heap tables are allocated blocks to store rows according to my_default_record_cache (mapped to the server global variable read_buffer_size). This causes performance issues when the record length is big (> 1000 bytes) and the my_default_record_cache is small. Changed to instead split the default heap allocation to 1/16 of the allowed space and not use my_default_record_cache anymore when creating the heap. The allocation is also aligned to be just under a power of 2. For some test that I have been running, which was using record length=633, the speed of the query doubled thanks to this change. Other things: - Fixed calculation of max_records passed to hp_create() to take into account padding between records. - Updated calculation of memory needed by heap tables. Before we did not take into account internal structures needed to access rows. - Changed block sized for memory_table from 1 to 16384 to get less fragmentation. This also avoids a problem where we need 1K to manage index and row storage which was not counted for before. - Moved heap memory usage to a separate test for 32 bit. - Allocate all data blocks in heap in powers of 2. Change reported memory usage for heap to reflect this. Reviewed-by: Sergei Golubchik <serg@mariadb.org>
		
			
				
	
	
		
			139 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 | |
| 
 | |
|    This program is free software; you can redistribute it and/or modify
 | |
|    it under the terms of the GNU General Public License as published by
 | |
|    the Free Software Foundation; version 2 of the License.
 | |
| 
 | |
|    This program is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|    GNU General Public License for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU General Public License
 | |
|    along with this program; if not, write to the Free Software
 | |
|    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335  USA */
 | |
| 
 | |
| /* This file is included in all heap-files */
 | |
| 
 | |
| #include <my_global.h>
 | |
| #include <my_base.h>
 | |
| C_MODE_START
 | |
| #include <my_pthread.h>
 | |
| #include "heap.h"			/* Structs & some defines */
 | |
| #include "my_tree.h"
 | |
| 
 | |
| /*
 | |
|   When allocating keys /rows in the internal block structure, do it
 | |
|   within the following boundaries.
 | |
| 
 | |
|   The challenge is to find the balance between allocate as few blocks
 | |
|   as possible and keep memory consumption down.
 | |
| */
 | |
| 
 | |
| #define HP_MIN_RECORDS_IN_BLOCK 16
 | |
| #define HP_MAX_RECORDS_IN_BLOCK 8192
 | |
| 
 | |
| 	/* Some extern variables */
 | |
| 
 | |
| extern LIST *heap_open_list,*heap_share_list;
 | |
| 
 | |
| #define test_active(info) \
 | |
| if (!(info->update & HA_STATE_AKTIV))\
 | |
| { my_errno=HA_ERR_NO_ACTIVE_RECORD; DBUG_RETURN(-1); }
 | |
| #define hp_find_hash(A,B) ((HASH_INFO*) hp_find_block((A),(B)))
 | |
| 
 | |
| 	/* Find pos for record and update it in info->current_ptr */
 | |
| #define hp_find_record(info,pos) (info)->current_ptr= hp_find_block(&(info)->s->block,pos)
 | |
| 
 | |
| typedef struct st_hp_hash_info
 | |
| {
 | |
|   struct st_hp_hash_info *next_key;
 | |
|   uchar *ptr_to_rec;
 | |
|   ulong hash_of_key;
 | |
| } HASH_INFO;
 | |
| 
 | |
| typedef struct {
 | |
|   HA_KEYSEG *keyseg;
 | |
|   uint key_length;
 | |
|   uint search_flag;
 | |
| } heap_rb_param;
 | |
|       
 | |
| 	/* Prototypes for intern functions */
 | |
| 
 | |
| extern HP_SHARE *hp_find_named_heap(const char *name);
 | |
| extern int hp_rectest(HP_INFO *info,const uchar *old);
 | |
| extern uchar *hp_find_block(HP_BLOCK *info,ulong pos);
 | |
| extern int hp_get_new_block(HP_SHARE *info, HP_BLOCK *block,
 | |
|                             size_t* alloc_length);
 | |
| extern void hp_free(HP_SHARE *info);
 | |
| extern uchar *hp_free_level(HP_BLOCK *block,uint level,HP_PTRS *pos,
 | |
| 			   uchar *last_pos);
 | |
| extern int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
 | |
| 			const uchar *record, uchar *recpos);
 | |
| extern int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, 
 | |
| 			   const uchar *record, uchar *recpos);
 | |
| extern int hp_rb_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
 | |
| 			    const uchar *record,uchar *recpos,int flag);
 | |
| extern int hp_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
 | |
| 			 const uchar *record,uchar *recpos,int flag);
 | |
| extern HASH_INFO *_heap_find_hash(HP_BLOCK *block,ulong pos);
 | |
| extern uchar *hp_search(HP_INFO *info,HP_KEYDEF *keyinfo,const uchar *key,
 | |
| 		       uint nextflag);
 | |
| extern uchar *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo,
 | |
| 			    const uchar *key, HASH_INFO *pos);
 | |
| extern ulong hp_rec_hashnr(HP_KEYDEF *keyinfo,const uchar *rec);
 | |
| extern void hp_movelink(HASH_INFO *pos,HASH_INFO *next_link,
 | |
| 			 HASH_INFO *newlink);
 | |
| extern int hp_rec_key_cmp(HP_KEYDEF *keydef,const uchar *rec1,
 | |
| 			  const uchar *rec2);
 | |
| extern int hp_key_cmp(HP_KEYDEF *keydef,const uchar *rec,
 | |
| 		      const uchar *key);
 | |
| extern void hp_make_key(HP_KEYDEF *keydef,uchar *key,const uchar *rec);
 | |
| extern uint hp_rb_make_key(HP_KEYDEF *keydef, uchar *key,
 | |
| 			   const uchar *rec, uchar *recpos);
 | |
| extern uint hp_rb_key_length(HP_KEYDEF *keydef, const uchar *key);
 | |
| extern uint hp_rb_null_key_length(HP_KEYDEF *keydef, const uchar *key);
 | |
| extern uint hp_rb_var_key_length(HP_KEYDEF *keydef, const uchar *key);
 | |
| extern my_bool hp_if_null_in_key(HP_KEYDEF *keyinfo, const uchar *record);
 | |
| extern int hp_close(HP_INFO *info);
 | |
| extern void hp_clear(HP_SHARE *info);
 | |
| extern void hp_clear_keys(HP_SHARE *info);
 | |
| extern uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
 | |
|                            key_part_map keypart_map);
 | |
| extern ha_rows hp_rows_in_memory(size_t reclength, size_t index_size,
 | |
|                           size_t memory_limit);
 | |
| extern size_t hp_memory_needed_per_row(size_t reclength);
 | |
| 
 | |
| extern mysql_mutex_t THR_LOCK_heap;
 | |
| 
 | |
| extern PSI_memory_key hp_key_memory_HP_SHARE;
 | |
| extern PSI_memory_key hp_key_memory_HP_INFO;
 | |
| extern PSI_memory_key hp_key_memory_HP_PTRS;
 | |
| extern PSI_memory_key hp_key_memory_HP_KEYDEF;
 | |
| 
 | |
| #ifdef HAVE_PSI_INTERFACE
 | |
| void init_heap_psi_keys();
 | |
| #else
 | |
| #define init_heap_psi_keys() do { } while(0)
 | |
| #endif /* HAVE_PSI_INTERFACE */
 | |
| 
 | |
| C_MODE_END
 | |
| 
 | |
| /*
 | |
|   Calculate position number for hash value.
 | |
|   SYNOPSIS
 | |
|     hp_mask()
 | |
|       hashnr     Hash value
 | |
|       buffmax    Value such that
 | |
|                  2^(n-1) < maxlength <= 2^n = buffmax
 | |
|       maxlength
 | |
| 
 | |
|   RETURN
 | |
|     Array index, in [0..maxlength)
 | |
| */
 | |
| 
 | |
| static inline ulong hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
 | |
| {
 | |
|   if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1));
 | |
|   return (hashnr & ((buffmax >> 1) -1));
 | |
| }
 |