Thursday, 7 November 2024

Senarios for Queries

 

1. Top 5 rows (employees)  from each department in a single query

use Row_Number()over(partition by dept_id ) Then Filter


2.  ALL / ANY > Query

https://oracle-base.com/articles/misc/all-any-some-comparison-conditions-in-sql


3. Update a partition key value.

It is not possible to update partition key column value. We need to first enable table movement.

Alter table table name enable movement;

Now we can update the key value column.


Saturday, 26 October 2024

External Tables

 

External tables are created using the SQL CREATE TABLE...ORGANIZATION EXTERNAL statement.


TYPE — specifies the type of external table. Each type of external table is supported by its own access driver.

ORACLE_LOADER — this is the default access driver. It loads data from external tables to internal tables. The data must come from text data files.

ORACLE_DATAPUMP — this access driver can perform both loads and unloads. The data must come from binary dump files.

  • ORACLE_HIVE — extracts data stored in Apache HIVE.


SQL> CREATE TABLE emp_load
  2    (employee_number      CHAR(5),
  3     employee_dob         CHAR(20),
  4     employee_last_name   CHAR(20),
  5     employee_first_name  CHAR(15),
  6     employee_middle_name CHAR(15),
  7     employee_hire_date   DATE)
  8  ORGANIZATION EXTERNAL
  9    (TYPE ORACLE_LOADER
 10     DEFAULT DIRECTORY def_dir1
 11     ACCESS PARAMETERS
 12       (RECORDS DELIMITED BY NEWLINE
 13        FIELDS (employee_number      CHAR(2),
 14                employee_dob         CHAR(20),
 15                employee_last_name   CHAR(18),
 16                employee_first_name  CHAR(11),
 17                employee_middle_name CHAR(11),
 18                employee_hire_date   CHAR(10) date_format DATE mask "mm/dd/yyyy"
 19               )
 20       )
 21     LOCATION ('info.dat')
 22    );
 
Table created.


SQL> CREATE TABLE inventories_EXT
2 ORGANIZATION EXTERNAL
3 (
4 TYPE ORACLE_DATAPUMP
5 DEFAULT DIRECTORY def_dir1
6 LOCATION ('inv_xt.dmp')
7 )
8 AS SELECT * FROM inventories;
Table created.

Friday, 25 October 2024

LISTAGG Function

 https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/LISTAGG.html


As an Aggregate Function

SELECT department_id "Dept.", LISTAGG(last_name, '; ' ON OVERFLOW TRUNCATE '...') WITHIN GROUP (ORDER BY hire_date) "Employees" FROM employees GROUP BY department_id ORDER BY department_id;

Dept. Employees ------ ------------------------------------------------------------ 10 Whalen 20 Hartstein; Fay 30 Raphaely; Khoo; Tobias; Baida; Himuro; Colmenares 40 Mavris 50 Kaufling; Ladwig; Rajs; Sarchand; Bell; Mallin; Weiss; Davie s; Marlow; Bull; Everett; Fripp; Chung; Nayer; Dilly; Bissot ; Vollman; Stiles; Atkinson; Taylor; Seo; Fleaur; ... (23) 70 Baer . . .


As an Analytic Function

SELECT department_id "Dept", hire_date "Date", last_name "Name", LISTAGG(last_name, '; ') WITHIN GROUP (ORDER BY hire_date, last_name) OVER (PARTITION BY department_id) as "Emp_list" FROM employees WHERE hire_date < '01-SEP-2003' ORDER BY "Dept", "Date", "Name"; Dept Date Name Emp_list ----- --------- --------------- --------------------------------------------- 30 07-DEC-02 Raphaely Raphaely; Khoo 30 18-MAY-03 Khoo Raphaely; Khoo


Wednesday, 23 October 2024

Bulk Insertion - INSERT ALL

 

ALTER SESSION SET CURSOR_SHARING = FORCE;

  1. INSERT ALL
  2. INTO my_table (column1, column2, column_n) VALUES (expr1, expr2, expr_n)
  3. INTO my_table (column1, column2, column_n) VALUES (expr1, expr2, expr_n)
  4. INTO my_table2 (column1, column2, column_n) VALUES (expr1, expr2, expr_n)
  5. INTO my_table3 (column1, column2, column_n) VALUES (expr1, expr2, expr_n)
  6. WHEN CONDITION THEN
  7. INTO my_table4 (column1, column2, column_n) VALUES (expr1, expr2, expr_n)
  8. SELECT * FROM dual;

Thursday, 17 October 2024

DBMS_APPLICATION_INFO

 DBMS_APPLICATION_INFO.set_module
(
module_name => g_module_name||'.'||g_block_name,
action_name => 'Initializing ...'
);

DBMS_APPLICATION_INFO.read_module(l_prev_module_block,l_prev_action);

DBMS_APPLICATION_INFO.set_client_info
        (
        client_info =>g_module_name||'.'||g_block_name
        );

DBMS_APPLICATION_INFO.read_client_info (l_curr_module_block);


Monday, 14 October 2024

DBMS_REDEFINITION- DeFragamentation

 Defragamentation of Tables  in database

https://oracle-base.com/articles/11g/online-table-redefinition-enhancements-11gr1

https://medium.com/@dmitry.romanoff/how-to-check-fragmentation-in-an-oracle-database-a575b8a6e2ea

Calculate Fragmented Space in Tables

Check Db_Block_Size  parameter , here it is 8 KB.

SELECT      
  table_name,     
  avg_row_len, num_rows,    
  ROUND(((blocks*8/1024)),2) || 'MB' AS "TOTAL_SIZE",     
  ROUND((num_rows*avg_row_len/1024/1024),2) || 'MB' AS "ACTUAL_SIZE",     
  ROUND(((blocks*8/1024) - (num_rows*avg_row_len/1024/1024)),2) || 'MB' AS "FRAGMENTED_SPACE",     
  (ROUND(((blocks*8/1024) - (num_rows*avg_row_len/1024/1024)),2) / ROUND(((blocks*8/1024)),2)) * 100 AS "PERCENTAGE" 
FROM user_tables  
WHERE ROUND(((blocks*8/1024)),2) > 0 
ORDER BY 6 DESC;


Once you’ve identified fragmentation, consider the following methods to address it:

ALTER TABLE YOUR_TABLE_NAME MOVE;

ALTER INDEX YOUR_INDEX_NAME REBUILD;

For large tables, consider using online redefinition to minimize downtime:
BEGIN
   DBMS_REDEFINITION.START_REDEF_TABLE (
      uname => 'COMMON', orig_table => 'CITY', int_table => 'CITY_TMP');
END;
EXEC DBMS_REDEFINITION.sync_interim_table('COMMON', 'CITY', 'CITY_TMP'); 
ALTER TABLE COMMON.CITY_TMP ADD (CONSTRAINT CITY_pk2 PRIMARY KEY (CITY_ID));
EXEC DBMS_REDEFINITION.finish_redef_table('COMMON', 'CITY', 'CITY_TMP'); 

Online Table Redefinition Including Dependents (COPY_TABLE_DEPENDENTS)
The above process drops the dependent Trigger , indexes on the table.
So we use dbms_redefinition.copy_table_dependents   to copy dependent objects like triggers, indexes, constraints, grants and optionally its statistics and materialized view logs.
-- Copy dependents.
SET SERVEROUTPUT ON

DECLARE
  l_num_errors PLS_INTEGER;
BEGIN
  DBMS_REDEFINITION.copy_table_dependents(
    uname               => 'TEST',
    orig_table          => 'REDEF_TAB',
    int_table           => 'REDEF_TAB2',
    copy_indexes        => 1,             -- Default
    copy_triggers       => TRUE,          -- Default
    copy_constraints    => TRUE,          -- Default
    copy_privileges     => TRUE,          -- Default
    ignore_errors       => FALSE,         -- Default
    num_errors          => l_num_errors,
    copy_statistics     => FALSE,         -- Default
    copy_mvlog          => FALSE);        -- Default
    
  DBMS_OUTPUT.put_line('num_errors=' || l_num_errors); 
END;
/

Thursday, 26 September 2024

In-Memory Column Store in Oracle Database 12c

 

https://oracle-base.com/articles/12c/in-memory-column-store-12cr1



The In-Memory Column Store (IM column store) was the headline feature of the 12.1.0.2 patchset. This features allows you to store columns, tables, partitions and materialized views in memory in a columnar format, rather than the typical row format. The advantage of having data in memory is obvious, but the columnar storage lends itself extremely well to analytic queries found in business intelligence products.


ALTER SYSTEM SET INMEMORY_SIZE=2G SCOPE=SPFILE;
ALTER SYSTEM SET INMEMORY_QUERY=ENABLE;
CREATE TABLE im_tab (
  id  NUMBER
) INMEMORY;

CREATE TABLE noim_tab (
  id  NUMBER
) NO INMEMORY;
SELECT table_name,
       inmemory,
       inmemory_priority,
       inmemory_distribute,
       inmemory_compression,
       inmemory_duplicate  
FROM   user_tables
ORDER BY table_name;

Saturday, 14 September 2024

OLAP - Surrogate key

Surrogate keys can be used to join a dimension table to a fact table in a star schema database.

A surrogate key is a unique identifier for an entity or object in a database that's used when natural keys are not available.

Surrogate keys are  system generated, so it's not possible to create or store a duplicate value.

Dimension Tables 

Fact Tables 

Dimension Tables and Fact Tables are inter-related in 2 ways--

1. Star Schema.

2. Snowflake Schema.


OLAP Cube is a multi-dimensional data..

Four types of analytical operations in OLAP are:-

1. Roll-up  --             Summarize the data / Summation
2. Drill-down -         Reverse of roll-up / Detail view
3. Slice and dice -     Project and Select
4. Pivot (rotate) -       Re-orient the cube./ Transpose

Monday, 5 August 2024

Indexes

 https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/CREATE-INDEX.html

  • Normal indexes. (By default, Oracle Database creates B-tree indexes.), used for high cardinality column.

  • Bitmap indexes,   are small in size , used for low cardinality column., used in OLAP system where modification is rare as it locks the entire table. 


       refer https://tipsfororacle.blogspot.com/2016/09/oracle-indexes.html

  • Partitioned indexes, which consist of partitions containing an entry for each value that appears in the indexed column(s) of the table.

  • Function-based indexes, which are based on expressions. They enable you to construct queries that evaluate the value returned by an expression, which in turn may include built-in or user-defined functions.

  • Domain indexes, which are instances of an application-specific index of type indextype.
    Refer https://tipsfororacle.blogspot.com/2017/02/index-usage-with-like-operator-and.html

Thursday, 1 August 2024

Configure keep cache in Oracle

PIN Packages in the Shared Memory Pool- 

 DBMS_SHARED_POOL.KEEP ( name Varchar2, flag char default 'P');

Configure Keep Cache in Oracle-

Usually small objects should be kept in Keep buffer Cache .  DB_KEEP_CACHE_SIZE initialization parameter is used to create keep buffer pool. If  DB_KEEP_CACHE_SIZE  is not used then no Keep Buffer is created.

Step 1.  Check the current keep cache size

SQL> show parameter keep;

Step 2.  Check the table size need to keep in cache.

SQL> select bytes/1024/1024 from dba_segments where segment_name='&Tablename';

Step 3. Configure Keep cache

 SQL> alter system set db_keep_cache_size = 7G scope=both;

Step 4. Move the table into cache.

SQL> Alter table table_owner.table_name storage(buffer_pool Keep);

Step 5. Check the table is part of the keep pool using below query

SQL> select  segment_name, buffer_pool from dba_segments where segment_name=&Table_name;

SQL> select segment_name, segment_type from dba_segments where buffer_pool='KEEP' and segment_type='TABLES' ;


After moving objects to keep cache you can observe the performance and check the "segment ordered by logical reads" in segment statistics of AWR Report.

By pinning objects you can reduce /eliminate IOs. You can make response time for specific query predictable .

Server Result Cache 

A result cache is an area of memory ,  in the shared global area(SGA) that stores the result of the database query for reuse. 

SQL> select /*+ RESULT_CACHE */ dept_id , avg(salary)   FROM hr.employees
       GROUP BY department_id;

Good candidate for caching are queries that access a high number of rows but return a small number of rows, such as those in datawarehouse.

https://docs.oracle.com/en/database/oracle/oracle-database/19/tgdba/tuning-result-cache.htm


Monday, 20 May 2024

Steps to open Debug in Oracle

 https://asktom.oracle.com/ords/f?p=100:11:0::::P11_QUESTION_ID:9528615800346614204

select * from dba_network_acls;

grant execute on DBMS_DEBUG_JDWP to  <User>

grant   DEBUG CONNECT SESSION , DEBUG ANY PROCEDURE to  <USER>;


 begin

         dbms_network_acl_admin.append_host_ace

          (host=>'127.0.0.1',

           ace=> sys.xs$ace_type(privilege_list=>sys.XS$NAME_LIST('JDWP') ,

                         principal_name=>'<USER>',

                           principal_type=>sys.XS_ACL.PTYPE_DB) );

       end;

    /

exec dbms_network_acl_admin.drop_acl( ACL_NAME);


Monday, 15 April 2024

Index usage with like operator and Domain Index

 https://tipsfororacle.blogspot.com/2017/02/index-usage-with-like-operator-and.html?m=1


Dynamic sql

Retrieving DML Results into a Collection with the RETURNING INTO Clause

http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/tuning.htm


sql_stmt := 'UPDATE Scott.emp
SET sal = (sal+ sal * :a)
where empno = :b
RETURNING sal
INTO :c';

/* Executing a Dynamic SQL for Oracle Version 8.1.7 onwards */

EXECUTE IMMEDIATE sql_stmt USING VarSalPercentage,VarEmpno RETURNING INTO UpdatedSalary;

/* You can use this way als0
EXECUTE IMMEDIATE sql_stmt USING VarSalPercentage,VarEmpno,OUT UpdatedSalary; */

------------------------------------------------------------------------------
COPY is Undead: copy data from one database to another.

Copy command is obsolete now, but still useful when you need to copy large amount of data (espcially LONG datatype)  without filling the undo/rollback segments.

http://docs.oracle.com/cd/B10500_01/server.920/a90842/apb.htm

--------------------------------------------------------
Dont Forget: http://www.oracle.com/technetwork/articles/sql/11g-misc-091388.html

Reference Cursor

 

Create procedure (dept_in  Number,  emp_ref_cur  SYS_REFCURSOR)

IS
Begin

Open emp_ref_cur  FOR   select * from employees where dept_id = dept_in;

If emp_cur%rowcount = 0 Then

....

End if;


End;
/

Saturday, 13 April 2024

Bulk Exception with FORALL .. SAVE EXCEPTION

 The Bulk Exception are used to save the exception information and continue processing .

In order to  bulk collect exception information, we use FORALL clause with SAVE EXCEPTIONS keyword.

All exceptions raised during execution as saved in %BULK_Exception attribute.

SQL%BULK_EXCEPTION(i).ERROR_CODE  hold the corresponding Oracle error code.

SQL%BULK_EXCEPTION(i).ERROR_INDEX  holds the iteration number of the FORALL statement.

SQL%BUK_EXCEPTION.COUNT  holds the total number of exceptions encountered.


Select * BULK COLLECT INTO  v_collections
From TestTable;

FORALL  idx  IN  v_collections.FIRST .. v_collections.LAST  SAVE EXCEPTIONs
.....
.....

EXCEPTION

 WHEN OTHERS THEN

 FOR idx IN 1..  SQL%BULK_EXCEPTIONS.COUNT
 LOOP
   v_ind := 
SQL%BULK_EXCEPTIONS(idx).Error_index ;   

 Dbms_output.Put_Line('Error encountered at '||SQL%BULK_EXCEPTIONS(idx).Error_index);

 Dbms_output.Put_Line('Values '||v_collections(v_ind).Emp_id
                                || v_collections(v_ind).First_name
                                || v_collections(v_ind).Last_name );

 Dbms_output.Put_Line('Oracle Error Ora-Code '||SQL%BULK_EXCEPTIONS(idx).Error_code);

 End Loop;

End;


Friday, 12 April 2024

WHERE CURRENT OF Cursor Loop


WHERE CURRENT OF  clause is used in conjuction with  FOR UPDATE   to update / delete current working row in a cursor for loop.

The  WHERE CURRENT OF  clause in an UPDATE or DELETE statement states that the most recent row fetched from the table should be updated or deleted. We must declare the cursor with the  FOR UPDATE clause to use this feature

Inside a cursor loop, WHERE CURRENT OF allows the current row to be directly updated

Declare
cursor c1 is
  Select    row_number()over(order by process_id)  lineno , process_id, line_item_no
  from wbbs_to_ar where notional_invoice_no='11011875' for update;
Begin
  For cx in c1
  Loop

   update wbbs_to_ar set line_item_no = cx.lineno where current of c1;
  End Loop;
End;

Diagnose Performance Issue Using Dynamic v$Performance Views

Diagnose Performance Issues Using DYNAMIC Performance Views:



v$session Session Complete Details Type= USER/ BACKGROUND. sid, serial#, event, parameter, etc.. 

v$session_event -- summary of sessions wait-events  prior to Oracle 10g,

v$system_event -- wait experieced by Instace, from the time it started (but only Summary)

View for High Load Session:-  Consuming intensive Resource (CPU, PIO, LIO,No of commits/rollback)
v$sesstat, v$sysstat.   

Get complete details of wait events experienced, for eg. the time (how long), Sql Statment, Event  and corresponding parameter details so as  to drill down to the problem resolution.
v$active_session_history 


RANK & DENSE_RANK


RANK calculates the rank of a value in a group of values. The return type is NUMBER. The ranks may not be consecutive number.

DENSE_RANK computes the rank of a row in an ordered group of rows . The ranks are consecutive integers beginning with 1. Rank values are not skipped in the event of ties. Rows with equal values for the ranking criteria receive the same rank. This function is useful for top-N and bottom-N reporting.


 Q, Give me the set of sales people making the top 3 salaries in each department"?

scott@TKYTE816> break on deptno skip 1

scott@TKYTE816> select *
  2    from ( select deptno, ename, sal,
  3                  dense_rank() over ( partition by deptno
  4                                      order by sal desc ) dr
  5            from emp )
  6   where dr <= 3
  7   order by deptno, sal desc
  8  /

    DEPTNO ENAME             SAL         DR
---------- ---------- ---------- ----------
        10 KING             5000          1
           CLARK            2450          2
           MILLER           1300          3

        20 SCOTT            3000          1
           FORD             3000          1
           JONES            2975          2
           ADAMS            1100          3

        30 BLAKE            2850          1
           ALLEN            1600          2
           TURNER           1500          3

Materialized View

 Materialized View

Query rewrite feature of Materialized view depends on 2 parameters:

1. QUERY_REWRITE_INTEGRITY = { enforced | trusted | stale_tolerated } , This  determines the degree to which Oracle must enforce query rewriting .

enforced =Oracle enforces and guarantees consistency and integrity.

stale_tolerated Materialized views are eligible for rewrite even if they are known to be inconsistent with the underlying detail data.

2. QUERY_REWRITE_ENABLED = {TRUE | False }

Realtime Materialized View can be created using  ENABLE QUERY COMPUTATION keyword, it nake use of mview logs and base table.


Tips for Materialized view

https://danischnider.wordpress.com/2019/02/18/materialized-view-refresh-for-dummies/


https://docs.oracle.com/en/database/oracle/oracle-database/18/dwhsg/refreshing-materialized-views.html#GUID-E4E896C7-8173-4A36-A43F-188158981EB7


Sunday, 3 March 2024

How does the METHOD_OPT parameter work?

 

How does the METHOD_OPT parameter work?

The METHOD_OPT parameter is probably the most misunderstood parameter in the DBMS_STATS.GATHER_*_STATS procedures. It’s most commonly known as the parameter that controls the creation of histograms but it actually does so much more than that. The METHOD_OPT parameter actually controls the following,

  • which columns will or will not have base column statistics gathered on them
  • the histogram creation,
  • the creation of extended statistics

The METHOD_OPT parameter syntax is made up of multiple parts. The first two parts are mandatory and are broken down in the diagram below.

The leading part of the METHOD_OPT syntax controls which columns will have base column statistics (min, max, NDV, number of nulls, etc) gathered on them. The default, FOR ALL COLUMNS, will collects base column statistics for all of the columns (including hidden columns) in the table.  The alternative values limit the collection of base column statistics as follows;


The SIZE part of the METHOD_OPT syntax controls the creation of histograms and can have the following settings;

AUTO, REPEAT, SKEWONLY,  Size Must be in the range [1,254]. 

The second part of the parameter setting needs to specify that a histogram is needed on the CUST_ID column. 

 

https://blogs.oracle.com/optimizer/post/how-does-the-method-opt-parameter-work

Saturday, 2 March 2024

Dynamic sampling and its impact on the Optimizer

Dynamic sampling and its impact on the Optimizer

12c 

Dynamic sampling (DS) was introduced to improve the optimizer's ability to generate good execution plans. This feature was enhanced and renamed Dynamic Statistics in Oracle Database 12c. The most common misconception is that DS can be used as a substitute for optimizer statistics, whereas the goal of DS is to  augment optimizer statistics; it is used when regular statistics are not sufficient to get good quality cardinality estimates.

Parallel Hint

 PARALLEL HINT


Parallel Hint instructs the optimizer to make use the given degree of parallelism in processing  the sql statement parallelly, instead of processing it serially.  

Parallel  execution can improve the performance of the query by dividing the work  among multiple processers or cpus,  Thus reducing the overall cost of Execution Plan. but you have to keep in mind that you MUST have enough CPU power available on the server, or else it can cause performance issues. 

Also Parallel execution can consume a significant amount of system resources, including CPU and memory.Therefore, it is important to monitor the system’s resources when using parallel execution and to adjust the degree of parallelism as necessary.



Refer https://expertoracle.com/2022/12/04/parallel-hint-in-oracle-database-ways-to-use-and-how-to-monitor/

Thursday, 29 February 2024

Index Rebuild condition

Every so often, we need to rebuild indexes in Oracle, because indexes become fragmented over time. This causes their performance - and by extension - that of your database queries, to degrade. 

There are 2 rules of thumb to help determine if the index needs to be rebuilt:

    1. If the index has height greater than four, rebuild the index.

    2. The deleted leaf rows should be less than 20%.

    3. To re-create an existing index or one of its partitions or subpartitions. If the index is marked unusable, then a successful rebuild will mark it usable.




ALTER INDEX [schema.]index REBUILD  /ONLINE / PARTITION partition  

Wednesday, 28 February 2024

How to trace SQL sessions to identify Oracle Database bottlenecks DBMS_MONITOR

How to trace SQL sessions to identify Oracle Database bottlenecks

   Refer  Blog Theme - Details (oracle.com)

 To start the session trace, you first need to know the unique identifiers of the session: the SID and the SERIAL#. Use the following query

select sid, serial#
from v$session
where username = 'SH';

Using the SID and SERIAL# returned, turn on tracing for the session by executing the following SQL statement as the SYS user:

begin
  dbms_monitor.session_trace_enable (
    session_id => <SID>, 
    serial_num => <serial#>, 
    waits      => true, 
    binds      => true
    plan_stat  => 'all_executions');
end;
/

After tracing is enabled, the trace file— a text file—is generated on the database server at the location specified by the DIAGNOSTIC_DEST database initialization parameter. For RAC Server there can be multiple location.

Now execute the activities need to be Traced...

Then close / disable the Tracing thru dbms_monitor.session_trace_disable.

Run the Tkprof upon the raw trace file xe_ora_<spid>.trc that is generated.

>Tkprof xe_ora_4736.trc xe_ora_4736.out sys=no waits=yes aggregate=no width=180.

Code listing 3: tkprof output, part 1

... output truncated ...
SELECT     sum(s.amount_sold) AS dollars
  FROM     sales s
  ,        times t
  WHERE    s.time_id = t.time_id
  AND      t.calendar_month_desc = '1998-05'
call     count      cpu    elapsed      disk      query    current        rows
————— ———————— ———————— —————————— ————————— —————————— —————————— ———————————
Parse        1     0.00       0.00         0          0          0           0
Execute      1     0.00       0.00         0          0          0           0
Fetch        2     0.00       0.01         0          3          0           1
————— ———————— ———————— —————————— ————————— —————————— —————————— ———————————
total        4     0.00       0.01         0          3          0           1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
—————————— —————————— —————————— ———————————————————————————————————————————
         1          1          1 SORT AGGREGATE (cr=3 pr=0 pw=0 time=61 us)
         1          1          1  MAT_VIEW REWRITE ACCESS FULL CAL_MONTH_
                                  SALES_MV (cr=3 pr=0 pw=0 time=52 us cost=3 
                                  size=15 card=1)
... output truncated …
..