Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

question about sorted, hashed tables, mindset when using OO concepts...

aris_hidalgo
Contributor
0 Kudos
206

Hello experts,

I just want to make sure if my idea about sorted and hashed table is correct.Please give tips and suggestions.

In one of my reports, I declared a structure and an itab.

TYPES: BEGIN OF t_mkpf,

mblnr LIKE mkpf-mblnr,

mjahr LIKE mkpf-mjahr,

budat LIKE mkpf-budat,

xblnr(10) TYPE c,

tcode2 LIKE mkpf-tcode2,

cputm LIKE mkpf-cputm,

blart LIKE mkpf-blart,

END OF t_mkpf.

it_mkpf TYPE SORTED TABLE OF t_mkpf WITH HEADER LINE

WITH NON-UNIQUE KEY mblnr mjahr.

Now, I declared it as a sorted table with a non-unique key MBLNR and MJAHR. Now suppose I have 1000 records in my itab. how will it search for a particular record?

2. Is it faster than sorting a standard table then reading it using binary search?

3. How do I use a hashed table effectively? lets say that I want to use hashed type instead of sorted table in my example above.

4. I am currently practicing ABAP Objects and my problem is that I think my mindset when programming a report is still the 'procedural one'. How do one use ABAP concepts effectively?

Again, thank you guys and have a nice day!

1 ACCEPTED SOLUTION

Former Member
0 Kudos
58

Hi,

1. Whenever, you are searching for data from a SORTED table, make sure you have the KEY you have declared in the WHERE clause and add the BINARY SEARCH operation. What will happen is while searching, the system divides the table into two parts and then depending on the value given in the WHERE clause it decides which part it has to search in. So, what happened is that you have already discarded half of the table and don't have to search in that part.

Now, with in the selected half, it again divides that into two and follow the same procedure. That is why search is faster with a SORTED table.

2. Having a SORTED is faster than having a STANDARD table and then SORTING it as the data when being stored is directly stored in SORTED manner in a SORTED table. The catch is you cannot use a APPEND statement with a SORTED table, will have to use a INSERT statement always.

3. HASHED table, usually used when the volume of data is huge and good thing is all you have to do is to declare a table as a HASHED table with whatever key you want. Then internall SAP uses the key to search for data. But unless the data is really huge, HASH tables are not effective.

4. In order to do this, use as much classes / methods you can and try NOT to use function modules especially the one for general utilities.

Regards,

Ravi

2 REPLIES 2

Former Member
0 Kudos
58

Hi Viray,

<b>The different ways to fill an Internal Table:</b>

<b>append&sort</b>

This is the simplest one. I do appends on a standard table and then a sort.

data: lt_tab type standard table of ...

do n times.

ls_line = ...

append ls_line to lt_tab.

enddo.

sort lt_tab.

The thing here is the fast appends and the slow sort - so this is interesting how this will compare to the following one.

<b>read binary search & insert index sy-tabix</b>

In this type I also use a standard table, but I read to find the correct insert index to get a sorted table also.

data: lt_tab type standard table of ...

do n times.

ls_line = ...

read table lt_tab transporting no fields with key ... binary search.

if sy-subrc <> 0.

insert ls_line into lt_tab index sy-tabix.

endif.

enddo.

<b>sorted table with non-unique key</b>

Here I used a sorted table with a non-unique key and did inserts...

data: lt_tab type sorted table of ... with non-unique key ...

do n times.

ls_line = ...

insert ls_line into table lt_tab.

enddo.

<b>sorted table with unique key</b>

The coding is the same instead the sorted table is with a unique key.

data: lt_tab type sorted table of ... with unique key ...

do n times.

ls_line = ...

insert ls_line into table lt_tab.

enddo.

<b>hashed table</b>

The last one is the hashed table (always with unique key).

data: lt_tab type hashed table of ... with unique key ...

do n times.

ls_line = ...

insert ls_line into table lt_tab.

enddo.

<b>You Can use this Program to Test:</b>

types:

begin of local_long,

key1 type char10,

key2 type char10,

data1 type char10,

data2 type char10,

data3 type i,

data4 type sydatum,

data5 type numc10,

data6 type char32,

data7 type i,

data8 type sydatum,

data9 type numc10,

dataa type char32,

datab type i,

datac type sydatum,

datad type numc10,

datae type char32,

dataf type i,

datag type sydatum,

datah type numc10,

datai type char32,

dataj type i,

datak type sydatum,

datal type numc10,

datam type char32,

datan type i,

datao type sydatum,

datap type numc10,

dataq type char32,

datar type i,

datas type sydatum,

datat type numc10,

datau type char32,

datav type i,

dataw type sydatum,

datax type numc10,

datay type char32,

dataz type i,

data11 type numc10,

data21 type char32,

data31 type i,

data41 type sydatum,

data51 type numc10,

data61 type char32,

data71 type i,

data81 type sydatum,

data91 type numc10,

dataa1 type char32,

datab1 type i,

datac1 type sydatum,

datad1 type numc10,

datae1 type char32,

dataf1 type i,

datag1 type sydatum,

datah1 type numc10,

datai1 type char32,

dataj1 type i,

datak1 type sydatum,

datal1 type numc10,

datam1 type char32,

datan1 type i,

datao1 type sydatum,

datap1 type numc10,

dataq1 type char32,

datar1 type i,

datas1 type sydatum,

datat1 type numc10,

datau1 type char32,

datav1 type i,

dataw1 type sydatum,

datax1 type numc10,

datay1 type char32,

dataz1 type i,

end of local_long.

data:

ls_long type local_long,

lt_binary type standard table of local_long,

lt_sort_u type sorted table of local_long with unique key key1 key2,

lt_sort_n type sorted table of local_long with non-unique key key1 key2,

lt_hash_u type hashed table of local_long with unique key key1 key2,

lt_apsort type standard table of local_long.

field-symbols:

<ls_long> type local_long.

parameters:

min1 type i default 1,

max1 type i default 1000,

min2 type i default 1,

max2 type i default 1000,

i1 type i default 100,

i2 type i default 200,

i3 type i default 300,

i4 type i default 400,

i5 type i default 500,

i6 type i default 600,

i7 type i default 700,

i8 type i default 800,

i9 type i default 900,

fax type i default 1000.

types:

begin of measure,

what(10) type c,

size(6) type c,

time type i,

lines type i,

reads type i,

readb type i,

fax_s type i,

fax_b type i,

fax(6) type c,

iter type i,

end of measure.

data:

lt_time type standard table of measure,

lt_meantimes type standard table of measure,

ls_time type measure,

lv_method(7) type c,

lv_i1 type char10,

lv_i2 type char10,

lv_f type f,

lv_start type i,

lv_end type i,

lv_normal type i,

lv_size type i,

lv_order type i,

lo_rnd1 type ref to cl_abap_random_int,

lo_rnd2 type ref to cl_abap_random_int.

get run time field lv_start.

lo_rnd1 = cl_abap_random_int=>create( seed = lv_start min = min1 max = max1 ).

add 1 to lv_start.

lo_rnd2 = cl_abap_random_int=>create( seed = lv_start min = min2 max = max2 ).

ls_time-fax = fax.

do 5 times.

do 9 times.

case sy-index.

when 1. lv_size = i1.

when 2. lv_size = i2.

when 3. lv_size = i3.

when 4. lv_size = i4.

when 5. lv_size = i5.

when 6. lv_size = i6.

when 7. lv_size = i7.

when 8. lv_size = i8.

when 9. lv_size = i9.

endcase.

if lv_size > 0.

ls_time-iter = 1.

clear lt_apsort.

ls_time-what = 'APSORT'.

ls_time-size = lv_size.

get run time field lv_start.

do lv_size times.

perform fill.

append ls_long to lt_apsort.

enddo.

sort lt_apsort by key1 key2.

get run time field lv_end.

ls_time-time = lv_end - lv_start.

ls_time-reads = 0.

ls_time-readb = 0.

ls_time-lines = lines( lt_apsort ).

get run time field lv_start.

do.

add 1 to ls_time-readb.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_apsort

assigning <ls_long>

with key key1 = lv_i1

key2 = lv_i2

binary search.

if sy-subrc = 0.

<ls_long>-data11 = sy-index.

endif.

get run time field lv_end.

subtract lv_start from lv_end.

if lv_end >= ls_time-time.

exit.

endif.

enddo.

get run time field lv_start.

do.

add 1 to ls_time-reads.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_apsort

assigning <ls_long>

with key key2 = lv_i1

key1 = lv_i2.

if sy-subrc = 0.

<ls_long>-data11 = sy-index.

endif.

get run time field lv_end.

subtract lv_start from lv_end.

if lv_end >= ls_time-time.

exit.

endif.

enddo.

get run time field lv_start.

do fax times.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_apsort

assigning <ls_long>

with key key1 = lv_i1

key2 = lv_i2

binary search.

if sy-subrc = 0.

<ls_long>-data21 = sy-index.

endif.

enddo.

get run time field lv_end.

ls_time-fax_b = lv_end - lv_start.

get run time field lv_start.

do fax times.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_apsort

assigning <ls_long>

with key key2 = lv_i1

key1 = lv_i2.

if sy-subrc = 0.

<ls_long>-data21 = sy-index.

endif.

enddo.

get run time field lv_end.

ls_time-fax_s = lv_end - lv_start.

collect ls_time into lt_time.

clear lt_binary.

ls_time-what = 'BINARY'.

ls_time-size = lv_size.

get run time field lv_start.

do lv_size times.

perform fill.

read table lt_binary

transporting no fields

with key key1 = ls_long-key1

key2 = ls_long-key2

binary search.

if sy-index <> 0.

insert ls_long into lt_binary index sy-tabix.

endif.

enddo.

get run time field lv_end.

ls_time-time = lv_end - lv_start.

ls_time-reads = 0.

ls_time-readb = 0.

ls_time-lines = lines( lt_binary ).

get run time field lv_start.

do.

add 1 to ls_time-readb.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_binary

assigning <ls_long>

with key key1 = lv_i1

key2 = lv_i2

binary search.

if sy-subrc = 0.

<ls_long>-data11 = sy-index.

endif.

get run time field lv_end.

subtract lv_start from lv_end.

if lv_end >= ls_time-time.

exit.

endif.

enddo.

get run time field lv_start.

do.

add 1 to ls_time-reads.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_binary

assigning <ls_long>

with key key2 = lv_i1

key1 = lv_i2.

if sy-subrc = 0.

<ls_long>-data11 = sy-index.

endif.

get run time field lv_end.

subtract lv_start from lv_end.

if lv_end >= ls_time-time.

exit.

endif.

enddo.

get run time field lv_start.

do fax times.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_binary

assigning <ls_long>

with key key1 = lv_i1

key2 = lv_i2

binary search.

if sy-subrc = 0.

<ls_long>-data21 = sy-index.

endif.

enddo.

get run time field lv_end.

ls_time-fax_b = lv_end - lv_start.

get run time field lv_start.

do fax times.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_binary

assigning <ls_long>

with key key2 = lv_i1

key1 = lv_i2.

if sy-subrc = 0.

<ls_long>-data21 = sy-index.

endif.

enddo.

get run time field lv_end.

ls_time-fax_s = lv_end - lv_start.

collect ls_time into lt_time.

clear lt_sort_n.

ls_time-what = 'SORT_N'.

ls_time-size = lv_size.

get run time field lv_start.

do lv_size times.

perform fill.

insert ls_long into table lt_sort_n.

enddo.

get run time field lv_end.

ls_time-time = lv_end - lv_start.

ls_time-reads = 0.

ls_time-readb = 0.

ls_time-lines = lines( lt_sort_n ).

get run time field lv_start.

do.

add 1 to ls_time-readb.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_sort_n

assigning <ls_long>

with table key key1 = lv_i1

key2 = lv_i2.

if sy-subrc = 0.

<ls_long>-data11 = sy-index.

endif.

get run time field lv_end.

subtract lv_start from lv_end.

if lv_end >= ls_time-time.

exit.

endif.

enddo.

get run time field lv_start.

do.

add 1 to ls_time-reads.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_sort_n

assigning <ls_long>

with key key2 = lv_i1

key1 = lv_i2.

if sy-subrc = 0.

<ls_long>-data11 = sy-index.

endif.

get run time field lv_end.

subtract lv_start from lv_end.

if lv_end >= ls_time-time.

exit.

endif.

enddo.

get run time field lv_start.

do fax times.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_sort_n

assigning <ls_long>

with table key key1 = lv_i1

key2 = lv_i2.

if sy-subrc = 0.

<ls_long>-data21 = sy-index.

endif.

enddo.

get run time field lv_end.

ls_time-fax_b = lv_end - lv_start.

get run time field lv_start.

do fax times.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_sort_n

assigning <ls_long>

with key key2 = lv_i1

key1 = lv_i2.

if sy-subrc = 0.

<ls_long>-data21 = sy-index.

endif.

enddo.

get run time field lv_end.

ls_time-fax_s = lv_end - lv_start.

collect ls_time into lt_time.

clear lt_sort_u.

ls_time-what = 'SORT_U'.

ls_time-size = lv_size.

get run time field lv_start.

do lv_size times.

perform fill.

insert ls_long into table lt_sort_u.

enddo.

get run time field lv_end.

ls_time-time = lv_end - lv_start.

ls_time-reads = 0.

ls_time-readb = 0.

ls_time-lines = lines( lt_sort_u ).

get run time field lv_start.

do.

add 1 to ls_time-readb.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_sort_u

assigning <ls_long>

with table key key1 = lv_i1

key2 = lv_i2.

if sy-subrc = 0.

<ls_long>-data11 = sy-index.

endif.

get run time field lv_end.

subtract lv_start from lv_end.

if lv_end >= ls_time-time.

exit.

endif.

enddo.

get run time field lv_start.

do.

add 1 to ls_time-reads.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_sort_u

assigning <ls_long>

with key key2 = lv_i1

key1 = lv_i2.

if sy-subrc = 0.

<ls_long>-data11 = sy-index.

endif.

get run time field lv_end.

subtract lv_start from lv_end.

if lv_end >= ls_time-time.

exit.

endif.

enddo.

get run time field lv_start.

do fax times.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_sort_u

assigning <ls_long>

with table key key1 = lv_i1

key2 = lv_i2.

if sy-subrc = 0.

<ls_long>-data21 = sy-index.

endif.

enddo.

get run time field lv_end.

ls_time-fax_b = lv_end - lv_start.

get run time field lv_start.

do fax times.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_sort_u

assigning <ls_long>

with key key2 = lv_i1

key1 = lv_i2.

if sy-subrc = 0.

<ls_long>-data21 = sy-index.

endif.

enddo.

get run time field lv_end.

ls_time-fax_s = lv_end - lv_start.

collect ls_time into lt_time.

clear lt_hash_u.

ls_time-what = 'HASH_U'.

ls_time-size = lv_size.

get run time field lv_start.

do lv_size times.

perform fill.

insert ls_long into table lt_hash_u.

enddo.

get run time field lv_end.

ls_time-time = lv_end - lv_start.

ls_time-reads = 0.

ls_time-readb = 0.

ls_time-lines = lines( lt_hash_u ).

get run time field lv_start.

do.

add 1 to ls_time-readb.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_hash_u

assigning <ls_long>

with table key key1 = lv_i1

key2 = lv_i2.

if sy-subrc = 0.

<ls_long>-data11 = sy-index.

endif.

get run time field lv_end.

subtract lv_start from lv_end.

if lv_end >= ls_time-time.

exit.

endif.

enddo.

get run time field lv_start.

do.

add 1 to ls_time-reads.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_hash_u

assigning <ls_long>

with key key2 = lv_i1

key1 = lv_i2.

if sy-subrc = 0.

<ls_long>-data11 = sy-index.

endif.

get run time field lv_end.

subtract lv_start from lv_end.

if lv_end >= ls_time-time.

exit.

endif.

enddo.

get run time field lv_start.

do fax times.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_hash_u

assigning <ls_long>

with table key key1 = lv_i1

key2 = lv_i2.

if sy-subrc = 0.

<ls_long>-data21 = sy-index.

endif.

enddo.

get run time field lv_end.

ls_time-fax_b = lv_end - lv_start.

get run time field lv_start.

do fax times.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

read table lt_hash_u

assigning <ls_long>

with key key2 = lv_i1

key1 = lv_i2.

if sy-subrc = 0.

<ls_long>-data21 = sy-index.

endif.

enddo.

get run time field lv_end.

ls_time-fax_s = lv_end - lv_start.

collect ls_time into lt_time.

endif.

enddo.

enddo.

sort lt_time by what size.

write: / ' type | size | time | tab-size | directread | std read | time direct | time std read'.

write: / sy-uline.

loop at lt_time into ls_time.

write: / ls_time-what, '|', ls_time-size, '|', ls_time-time, '|', ls_time-lines, '|', ls_time-readb, '|', ls_time-reads, '|', ls_time-fax_b, '|', ls_time-fax_s.

endloop.

*.

form fill.

lv_i1 = lo_rnd1->get_next( ).

lv_i2 = lo_rnd2->get_next( ).

ls_long-key1 = lv_i1.

ls_long-key2 = lv_i2.

ls_long-data1 = lv_i1.

ls_long-data2 = lv_i2.

ls_long-data3 = lv_i1.

ls_long-data4 = sy-datum + lv_i1.

ls_long-data5 = lv_i1.

ls_long-data6 = lv_i1.

ls_long-data7 = lv_i1.

ls_long-data8 = sy-datum + lv_i1.

ls_long-data9 = lv_i1.

ls_long-dataa = lv_i1.

ls_long-datab = lv_i1.

ls_long-datac = sy-datum + lv_i1.

ls_long-datad = lv_i1.

ls_long-datae = lv_i1.

ls_long-dataf = lv_i1.

ls_long-datag = sy-datum + lv_i1.

ls_long-datah = lv_i1.

ls_long-datai = lv_i1.

ls_long-dataj = lv_i1.

ls_long-datak = sy-datum + lv_i1.

ls_long-datal = lv_i1.

ls_long-datam = lv_i1.

ls_long-datan = sy-datum + lv_i1.

ls_long-datao = lv_i1.

ls_long-datap = lv_i1.

ls_long-dataq = lv_i1.

ls_long-datar = sy-datum + lv_i1.

ls_long-datas = lv_i1.

ls_long-datat = lv_i1.

ls_long-datau = lv_i1.

ls_long-datav = sy-datum + lv_i1.

ls_long-dataw = lv_i1.

ls_long-datax = lv_i1.

ls_long-datay = lv_i1.

ls_long-dataz = sy-datum + lv_i1.

ls_long-data11 = lv_i1.

ls_long-data21 = lv_i1.

ls_long-data31 = lv_i1.

ls_long-data41 = sy-datum + lv_i1.

ls_long-data51 = lv_i1.

ls_long-data61 = lv_i1.

ls_long-data71 = lv_i1.

ls_long-data81 = sy-datum + lv_i1.

ls_long-data91 = lv_i1.

ls_long-dataa1 = lv_i1.

ls_long-datab1 = lv_i1.

ls_long-datac1 = sy-datum + lv_i1.

ls_long-datad1 = lv_i1.

ls_long-datae1 = lv_i1.

ls_long-dataf1 = lv_i1.

ls_long-datag1 = sy-datum + lv_i1.

ls_long-datah1 = lv_i1.

ls_long-datai1 = lv_i1.

ls_long-dataj1 = lv_i1.

ls_long-datak1 = sy-datum + lv_i1.

ls_long-datal1 = lv_i1.

ls_long-datam1 = lv_i1.

ls_long-datan1 = sy-datum + lv_i1.

ls_long-datao1 = lv_i1.

ls_long-datap1 = lv_i1.

ls_long-dataq1 = lv_i1.

ls_long-datar1 = sy-datum + lv_i1.

ls_long-datas1 = lv_i1.

ls_long-datat1 = lv_i1.

ls_long-datau1 = lv_i1.

ls_long-datav1 = sy-datum + lv_i1.

ls_long-dataw1 = lv_i1.

ls_long-datax1 = lv_i1.

ls_long-datay1 = lv_i1.

ls_long-dataz1 = sy-datum + lv_i1.

endform.".

Thanks & Regards,

YJR.

Former Member
0 Kudos
59

Hi,

1. Whenever, you are searching for data from a SORTED table, make sure you have the KEY you have declared in the WHERE clause and add the BINARY SEARCH operation. What will happen is while searching, the system divides the table into two parts and then depending on the value given in the WHERE clause it decides which part it has to search in. So, what happened is that you have already discarded half of the table and don't have to search in that part.

Now, with in the selected half, it again divides that into two and follow the same procedure. That is why search is faster with a SORTED table.

2. Having a SORTED is faster than having a STANDARD table and then SORTING it as the data when being stored is directly stored in SORTED manner in a SORTED table. The catch is you cannot use a APPEND statement with a SORTED table, will have to use a INSERT statement always.

3. HASHED table, usually used when the volume of data is huge and good thing is all you have to do is to declare a table as a HASHED table with whatever key you want. Then internall SAP uses the key to search for data. But unless the data is really huge, HASH tables are not effective.

4. In order to do this, use as much classes / methods you can and try NOT to use function modules especially the one for general utilities.

Regards,

Ravi