Home » RDBMS Server » Performance Tuning » Use of Hints in Oracle 11g to get desired Execution Plan (Oracle 11g 2.0, Linux)
Use of Hints in Oracle 11g to get desired Execution Plan [message #610449] Thu, 20 March 2014 03:09 Go to next message
rekha.singhal@tcs.com
Messages: 6
Registered: March 2012
Location: India
Junior Member
I am using oracle 11g hints to get desired plan for one of the query in TPCH benchmark. Following is the query and the desired plan.

Query:
explain plan for select
        s_acctbal,
        s_name,
        n_name,
        p_partkey,
        p_mfgr,
        s_address,
        s_phone,
        s_comment
from
        part,
        supplier,
        partsupp,
        nation,
        region
where
        p_partkey = ps_partkey
        and s_suppkey = ps_suppkey
        and p_size = 50
        and p_type like '%COPPER'
        and s_nationkey = n_nationkey
        and n_regionkey = r_regionkey
        and r_name = 'ASIA'
	and ps_supplycost = (
                select
                        min(ps_supplycost)
                from
                        partsupp,
                        supplier,
                        nation,
                        region
                where
                        p_partkey = ps_partkey
                        and s_suppkey = ps_suppkey
                        and s_nationkey = n_nationkey
                        and n_regionkey = r_regionkey
                        and r_name = 'ASIA'
        )
order by
        s_acctbal desc,
        n_name,
        s_name,
        p_partkey;

DESIRED PLAN:

 Id  | Operation                          | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                   |             | 19866 |  4074K|   199K  (1)| 00:39:55 |
|   1 |  SORT ORDER BY                     |             | 19866 |  4074K|   199K  (1)| 00:39:55 |
|*  2 |   VIEW                             | VW_WIF_1    | 19866 |  4074K|   199K  (1)| 00:39:55 |
|   3 |    WINDOW SORT                     |             | 19866 |  5645K|   199K  (1)| 00:39:55 |
|*  4 |     HASH JOIN                      |             | 19866 |  5645K|   199K  (1)| 00:39:55 |
|*  5 |      TABLE ACCESS FULL             | REGION      |     1 |    29 |     3   (0)| 00:00:01 |

PLAN_TABLE_OUTPUT
 -------------------------------------------------------------------------------------------------
|*  6 |      HASH JOIN                     |             | 99328 |    24M|   199K  (1)| 00:39:55 |
|   7 |       TABLE ACCESS FULL            | NATION      |    25 |   800 |     3   (0)| 00:00:01 |
|*  8 |       HASH JOIN                    |             | 99328 |    21M|   199K  (1)| 00:39:55 |
|   9 |        NESTED LOOPS                |             |       |       |            |          |
|  10 |         NESTED LOOPS               |             | 99328 |  8342K|   192K  (1)| 00:38:27 |
|* 11 |          TABLE ACCESS FULL         | PART        | 24615 |  1370K|   118K  (1)| 00:23:43 |
|* 12 |          INDEX RANGE SCAN          | PK_PARTSUPP |     4 |       |     2   (0)| 00:00:01 |
|  13 |         TABLE ACCESS BY INDEX ROWID| PARTSUPP    |     4 |   116 |     3   (0)| 00:00:01 |
|  14 |        TABLE ACCESS FULL           | SUPPLIER    |  1280K|   175M|  7314   (1)| 00:01:28 |
--------------------------------------------------------------------------------------------------
                                                                                                  
PLAN_TABLE_OUTPUT                                                                                 
 -------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):                                               
---------------------------------------------------                                               
                                                                                                  
   2 - filter("VW_COL_9" IS NOT NULL)                                                             
   4 - access("N_REGIONKEY"="R_REGIONKEY")                                                        
   5 - filter("R_NAME"='ASIA')                                                                    
   6 - access("S_NATIONKEY"="N_NATIONKEY")                                                        
   8 - access("S_SUPPKEY"="PS_SUPPKEY")                                                           
  11 - filter("P_SIZE"=50 AND "P_TYPE" LIKE '%COPPER' AND "P_TYPE" IS NOT NULL)                   
  12 - access("P_PARTKEY"="PS_PARTKEY")                                                           


I tried using ORDERED hint to this plan but no use. FOllowing is the query with hint and the plan I got for it.

explain plan for select /* ORDERED USE_HASH(region) */
        s_acctbal,
        s_name,
        n_name,
        p_partkey,
        p_mfgr,
        s_address,
        s_phone,
        s_comment
from
        partsupp,
        part,
        supplier,
        nation,
        region
where
        p_partkey = ps_partkey
        and s_suppkey = ps_suppkey
        and p_size = 50
        and p_type like '%COPPER'
        and s_nationkey = n_nationkey
        and n_regionkey = r_regionkey
        and r_name = 'ASIA'
	and ps_supplycost = (
                select
                        min(ps_supplycost)
                from
                        partsupp,
                        part,
                        supplier,
                        nation,
                        region
                where
                        p_partkey = ps_partkey
                        and s_suppkey = ps_suppkey
                        and s_nationkey = n_nationkey
                        and n_regionkey = r_regionkey
                        and r_name = 'ASIA'
        )
order by
        s_acctbal desc,
        n_name,
        s_name,
        p_partkey;

PLAN FROM ORACLE 11g

Plan hash value: 1442262758



-----------------------------------------------------------------------------------------------------------

| Id  | Operation                              | Name             | Rows  | Bytes | Cost (%CPU)| Time     |

-----------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT                       |                  |     2 |   548 |  6057   (1)| 00:01:13 |

|   1 |  SORT ORDER BY                         |                  |     2 |   548 |  6057   (1)| 00:01:13 |

|*  2 |   HASH JOIN                            |                  |     2 |   548 |  1480   (1)| 00:00:18 |

|   3 |    NESTED LOOPS                        |                  |       |       |            |          |

|   4 |     NESTED LOOPS                       |                  |     8 |  1936 |  1477   (1)| 00:00:18 |

|   5 |      NESTED LOOPS                      |                  |     8 |   792 |  1469   (1)| 00:00:18 |


PLAN_TABLE_OUTPUT

 ------------------------------------------------------------------------------------------------------------------------------------- ---------
------------------------------------------------------------------------------------------------------------
|   6 |       MERGE JOIN CARTESIAN             |                  |   176 | 14960 |   941   (1)| 00:00:12 |

|*  7 |        TABLE ACCESS FULL               | REGION           |     1 |    29 |     3   (0)| 00:00:01 |

|   8 |        BUFFER SORT                     |                  |   176 |  9856 |   938   (1)| 00:00:12 |

|*  9 |         TABLE ACCESS FULL              | PART             |   176 |  9856 |   938   (1)| 00:00:12 |

|* 10 |       TABLE ACCESS BY INDEX ROWID      | PARTSUPP         |     1 |    14 |     3   (0)| 00:00:01 |

|* 11 |        INDEX RANGE SCAN                | PK_PARTSUPP      |     4 |       |     2   (0)| 00:00:01 |

|  12 |        SORT AGGREGATE                  |                  |     1 |    61 |            |          |

|  13 |         NESTED LOOPS                   |                  |   158K|  9438K|  4576   (1)| 00:00:55 |

|* 14 |          HASH JOIN                     |                  |   160K|  8750K|  4566   (1)| 00:00:55 |
|* 15 |           HASH JOIN                    |                  |  2000 | 84000 |    49   (5)| 00:00:01 |

|  16 |            MERGE JOIN                  |                  |     5 |   175 |     6  (17)| 00:00:01 |


PLAN_TABLE_OUTPUT

 ------------------------------------------------------------------------------------------------------------------------------------- ---------
------------------------------------------------------------------------------------------------------------
|* 17 |             TABLE ACCESS BY INDEX ROWID| REGION           |     1 |    29 |     2   (0)| 00:00:01 |

|  18 |              INDEX FULL SCAN           | PK_REGION        |     5 |       |     1   (0)| 00:00:01 |

|* 19 |             SORT JOIN                  |                  |    25 |   150 |     4  (25)| 00:00:01 |

|  20 |              TABLE ACCESS FULL         | NATION           |    25 |   150 |     3   (0)| 00:00:01 |

|  21 |            VIEW                        | index$_join$_008 | 10000 | 70000 |    43   (3)| 00:00:01 |

|* 22 |             HASH JOIN                  |                  |       |       |            |          |

|  23 |              INDEX FAST FULL SCAN      | PK_SUPPLIER      | 10000 | 70000 |    26   (0)| 00:00:01 |

|  24 |              INDEX FAST FULL SCAN      | SUPP_NK          | 10000 | 70000 |    26   (0)| 00:00:01 |

|  25 |           TABLE ACCESS FULL            | PARTSUPP         |   800K|    10M|  4514   (1)| 00:00:55 |

|* 26 |          INDEX UNIQUE SCAN             | PK_PART          |     1 |     5 |     0   (0)| 00:00:01 |

|* 27 |      INDEX UNIQUE SCAN                 | PK_SUPPLIER      |     1 |       |     0   (0)| 00:00:01 |


PLAN_TABLE_OUTPUT

 ------------------------------------------------------------------------------------------------------------------------------------- ---------
------------------------------------------------------------------------------------------------------------
|  28 |     TABLE ACCESS BY INDEX ROWID        | SUPPLIER         |     1 |   143 |     1   (0)| 00:00:01 |

|  29 |    TABLE ACCESS FULL                   | NATION           |    25 |   800 |     3   (0)| 00:00:01 |

-----------------------------------------------------------------------------------------------------------



Predicate Information (identified by operation id):

---------------------------------------------------
 2 - access("S_NATIONKEY"="N_NATIONKEY" AND "N_REGIONKEY"="R_REGIONKEY")

   7 - filter("R_NAME"='ASIA')

   9 - filter("P_SIZE"=50 AND "P_TYPE" LIKE '%COPPER' AND "P_TYPE" IS NOT NULL)

  10 - filter("PS_SUPPLYCOST"= (SELECT MIN("PS_SUPPLYCOST") FROM "REGION" "REGION","NATION"


PLAN_TABLE_OUTPUT

 ------------------------------------------------------------------------------------------------------------------------------------- ---------
------------------------------------------------------------------------------------------------------------
              "NATION", (SELECT "S_NATIONKEY" "S_NATIONKEY","S_SUPPKEY" "S_SUPPKEY",ROWID "ROWID" FROM

              "SUPPLIER" "indexjoin$_alias$_002","SUPPLIER" "indexjoin$_alias$_001" WHERE ROWID=ROWID)

              "SUPPLIER","PART" "PART","PARTSUPP" "PARTSUPP" WHERE "S_SUPPKEY"="PS_SUPPKEY" AND

              "P_PARTKEY"="PS_PARTKEY" AND "S_NATIONKEY"="N_NATIONKEY" AND "N_REGIONKEY"="R_REGIONKEY" AND

              "R_NAME"='ASIA'))

  11 - access("P_PARTKEY"="PS_PARTKEY")

  14 - access("S_SUPPKEY"="PS_SUPPKEY")

  15 - access("S_NATIONKEY"="N_NATIONKEY")

  17 - filter("R_NAME"='ASIA')

  19 - access("N_REGIONKEY"="R_REGIONKEY")

       filter("N_REGIONKEY"="R_REGIONKEY")


PLAN_TABLE_OUTPUT

 ------------------------------------------------------------------------------------------------------------------------------------- ---------
------------------------------------------------------------------------------------------------------------
  22 - access(ROWID=ROWID)

  26 - access("P_PARTKEY"="PS_PARTKEY")

  27 - access("S_SUPPKEY"="PS_SUPPKEY")



Kindly help me in getting the desired plan. I am working on Query ERT prediction model. This need is part of building my model. In fact, I need good documentation on hints which can be used to get desired plan for any complex query (involving 10-12 joins) like reporting queries etc.

I really appreciate any help in this regard.

Warm Regards

Rekha Singhal

--moderator update: added [code] tags

[Updated on: Sat, 22 March 2014 18:53] by Moderator

Report message to a moderator

Re: Use of Hints in Oracle 11g to get desired Execution Plan [message #610455 is a reply to message #610449] Thu, 20 March 2014 03:41 Go to previous messageGo to next message
John Watson
Messages: 8922
Registered: January 2010
Location: Global Village
Senior Member
Your code and exec plans were vey difficult to read, because they were not enclosed in [code] tags.
I have it for you this time, please read How to use [code] tags and make your code easier to read

From where do you get the plan that you like? Can you not create a stored outline for it?
Re: Use of Hints in Oracle 11g to get desired Execution Plan [message #610507 is a reply to message #610449] Thu, 20 March 2014 13:51 Go to previous messageGo to next message
LNossov
Messages: 318
Registered: July 2011
Location: Germany
Senior Member
Do you have an environment, where you are able to reproduce (with explain plan or with execute) the desired plan?
Re: Use of Hints in Oracle 11g to get desired Execution Plan [message #610526 is a reply to message #610507] Thu, 20 March 2014 23:48 Go to previous messageGo to next message
rekha.singhal@tcs.com
Messages: 6
Registered: March 2012
Location: India
Junior Member
Thanks to you all.

Actually I got this plan on 128GB TPCH database. I want the same plan for the query on 1GB database. I can get stored outline from 128GB.
Then I will like to know how to put those stored outline in 1GB database or use them as hint in the SQL.

Warm Regards,

Rekha
Re: Use of Hints in Oracle 11g to get desired Execution Plan [message #610535 is a reply to message #610526] Fri, 21 March 2014 02:11 Go to previous messageGo to next message
John Watson
Messages: 8922
Registered: January 2010
Location: Global Village
Senior Member
Export your outline tables from one database and import into the other. It's all in the docs.
Re: Use of Hints in Oracle 11g to get desired Execution Plan [message #610537 is a reply to message #610535] Fri, 21 March 2014 02:23 Go to previous messageGo to next message
rekha.singhal@tcs.com
Messages: 6
Registered: March 2012
Location: India
Junior Member
Thanks Watson,

I will follow the steps and will see the result.

Warm Regards,

Rekha
Re: Use of Hints in Oracle 11g to get desired Execution Plan [message #610693 is a reply to message #610537] Sat, 22 March 2014 19:20 Go to previous messageGo to next message
Kevin Meade
Messages: 2103
Registered: December 1999
Location: Connecticut USA
Senior Member
There is a good deal of confusion.

1. Are you saying that you are using a query plan prediction tool and that this tool predicated the first plan you show?  If so I would like to see that tool because that is a masterful query rewrite it is looking for.  A rewrite that only about 1% of the DBA and Developer community would know to look for.

2. The first query plan is incomplete, at least it appears so to me.  It does not show the ps_supplycost criteria being used to filter rows anywhere.

3. The first query plan also looks wrong.  It appears that the window sort is being done on rows filtered by the predicates p_size = 50 and p_type like '%COPPER' but that is not what the query is asking for.  Seems to me the analytic should be working on all rows from ASIA regardless of p_size and p_type since that is how the query is coded.

The first query plan is taking advantage of the overlap in rows between what you seek and what the nested select is using to get its min. You will notice please that the main query and the sub-query both look at the same tables and do the same joins. Additionally the sub-query is a SUPERSET of the rows from the main query. This allows for the use of a query rewrite that employs an analytic to do the filtering based on the aggregate value, rather than having to go back to the same data twice. You can easily do this yourself with the following rewrite of the query.

select 
        s_acctbal,
        s_name,
        n_name,
        p_partkey,
        p_mfgr,
        s_address,
        s_phone,
        s_comment
from (
        select
                s_acctbal,
                s_name,
                n_name,
                p_partkey,
                p_mfgr,
                s_address,
                s_phone,
                s_comment,
                p_size,
                p_type
        from
                part,
                supplier ,
                partsupp,
                nation,
                region
        where
                    p_partkey = ps_partkey
                and s_suppkey = ps_suppkey
                and s_nationkey = n_nationkey
                and n_regionkey = r_regionkey
                and r_name = 'ASIA'
                and ps_supplycost = min(ps_supplycost) over (partition by p_partkey,s_suppkey,s_nationkey,n_regionkey,r_name)
      )
where 
    p_size = 50
and p_type like '%COPPER'
/

Notice the use of the analytic to achieve the MIN() and corresponding filtering, without doing a second pass of the data and all those joins. Because of all the joins, there is potential for this rewrite to be substantially faster than the traditional query plan would be. So try the rewrite and see what happens.

It is also quite likely that your query is wrong or that you have shown us the wrong query. This is because it is unusual for an analytic to be computed on a superset of rows. Normally it is computed on the same set of you ultimately display (which is what the first query plan is suggesting). Please check the correctness of your query.

And... to my knowledge, Oracle has no database version that will automatically do this rewrite of your query to the analytic variation. This is a rewrite that so far must be done manually by a Developer or DBA. This is one reason why I am so keen to know how you got the first query plan.

Lastly, please tell us where you actually got the first query plan from and please look at it to confirm or not if you believe the first query plan is in fact wrong or if you missed something in a cut/paste somewhere.

Kevin
Re: Use of Hints in Oracle 11g to get desired Execution Plan [message #610737 is a reply to message #610693] Sun, 23 March 2014 21:54 Go to previous messageGo to next message
Kevin Meade
Messages: 2103
Registered: December 1999
Location: Connecticut USA
Senior Member
Wait a moment please. I see I made a slight error in my translation of the query. It in fact is doing what the first query plan suggests and which makes the most sense. My mistake was in incorrectly including the PART table in the sub-query. Since it is not there in your original query, the use of P_PARTKEY in the sub-query correlates the rows in the sub-query to the PART table rows of main query. Thus the p_size and p_type predicates are applied to the sub-query rows as well and we in turn are looking to do the analytic on the same rows as the main query is fetching. Hence this rewrite is what you are getting the first query plan for.

In my defense, I would point out that part of the problem of your query getting different plans is the fact that you have two different queries. the first query you show is different from the second one in the table list of the sub-query. I only noticed this just now. So I have provided the rewrite for the first query here into its analytic version.

As for what I said about the first query plan being wrong because it does not show the MIN() being used to filter, I am going to assume the filter predicate 2 - filter("VW_COL_9" IS NOT NULL) is taking care of this filtering in some obscured manner and thus the query plan is OK.

Now you have to figure out:

1. if someone actually ran this query rewrite or
2. how this masterful query rewrite was done because I have not seen this optimization in any version of Oracle yet.  I will try to reproduce it.
3. or tell us that a tool suggested this optimization in which case what was the tool.

        select
                s_acctbal,
                s_name,
                n_name,
                p_partkey,
                p_mfgr,
                s_address,
                s_phone,
                s_comment
        from
                part,
                supplier ,
                partsupp,
                nation,
                region
        where
                    p_partkey = ps_partkey
                and s_suppkey = ps_suppkey
                and s_nationkey = n_nationkey
                and n_regionkey = r_regionkey
                and r_name = 'ASIA'
                and p_size = 50
                and p_type like '%COPPER'
                and ps_supplycost = min(ps_supplycost) over (partition by p_partkey)
/



If I were to interpret this query I would say it is asking for

Quote:
the list of least expensive copper parts of size 50 from ASIA.

Kevin

[Updated on: Sun, 23 March 2014 22:07]

Report message to a moderator

Re: Use of Hints in Oracle 11g to get desired Execution Plan [message #610738 is a reply to message #610737] Sun, 23 March 2014 22:20 Go to previous messageGo to next message
Kevin Meade
Messages: 2103
Registered: December 1999
Location: Connecticut USA
Senior Member
Hi again. So I am wrong. I appears Oracle does do this query rewrite. Awesome. I did the following on a 11gR2 (11.2.0.1.0) on windows 7.

create table part (p_partkey integer not null, p_size integer not null,p_type varchar2(30) not null);
create table partsupp (ps_partkey integer not null,ps_suppkey integer not null,ps_supplycost integer not null);
create table supplier (s_suppkey integer not null,s_nationkey integer not null);
create table nation (n_nationkey integer not null,n_regionkey integer not null);
create table region (r_regionkey integer not null,r_name varchar2(30) not null);

explain plan for select *
from
        part,
        supplier,
        partsupp,
        nation,
        region
where
        p_partkey = ps_partkey
        and s_suppkey = ps_suppkey
        and p_size = 50
        and p_type like '%COPPER'
        and s_nationkey = n_nationkey
        and n_regionkey = r_regionkey
        and r_name = 'ASIA'
   and ps_supplycost = (
                select
                        min(ps_supplycost)
                from
                        partsupp,
                        supplier,
                        nation,
                        region
                where
                        p_partkey = ps_partkey
                        and s_suppkey = ps_suppkey
                        and s_nationkey = n_nationkey
                        and n_regionkey = r_regionkey
                        and r_name = 'ASIA'
        )
/

SELECT * FROM table(DBMS_XPLAN.DISPLAY)
/
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------
Plan hash value: 104864306

--------------------------------------------------------------------------------------
| Id  | Operation                 | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT          |          |     1 |   176 |    12  (17)| 00:00:01 |
|*  1 |  VIEW                     | VW_WIF_1 |     1 |   176 |    12  (17)| 00:00:01 |
|   2 |   WINDOW SORT             |          |     1 |   176 |    12  (17)| 00:00:01 |
|*  3 |    HASH JOIN              |          |     1 |   176 |    11  (10)| 00:00:01 |
|   4 |     MERGE JOIN CARTESIAN  |          |     1 |   125 |     9  (12)| 00:00:01 |
|*  5 |      HASH JOIN            |          |     1 |    82 |     7  (15)| 00:00:01 |
|   6 |       MERGE JOIN CARTESIAN|          |     1 |    56 |     4   (0)| 00:00:01 |
|*  7 |        TABLE ACCESS FULL  | REGION   |     1 |    30 |     2   (0)| 00:00:01 |
|   8 |        BUFFER SORT        |          |     1 |    26 |     2   (0)| 00:00:01 |
|   9 |         TABLE ACCESS FULL | SUPPLIER |     1 |    26 |     2   (0)| 00:00:01 |
|  10 |       TABLE ACCESS FULL   | NATION   |     1 |    26 |     2   (0)| 00:00:01 |
|  11 |      BUFFER SORT          |          |     1 |    43 |     7  (15)| 00:00:01 |
|* 12 |       TABLE ACCESS FULL   | PART     |     1 |    43 |     2   (0)| 00:00:01 |
|  13 |     TABLE ACCESS FULL     | PARTSUPP |     1 |    51 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("VW_COL_13" IS NOT NULL)
   3 - access("S_SUPPKEY"="PS_SUPPKEY" AND "P_PARTKEY"="PS_PARTKEY")
   5 - access("N_REGIONKEY"="R_REGIONKEY" AND "S_NATIONKEY"="N_NATIONKEY")
   7 - filter("R_NAME"='ASIA')
  12 - filter("P_SIZE"=50 AND "P_TYPE" LIKE '%COPPER')

Note
-----
   - dynamic sampling used for this statement (level=2)

33 rows selected.

SQL> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for 64-bit Windows: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production


How beautiful is that eh!

Thanks for sharing your problem. The reason your second query does not give the original query plan is because you have included the PART table in the sub-query. At least I am guessing that is the reason. Run the same query as before (as I did) and you should get the analytic rewrite.

Kevin

[Updated on: Sun, 23 March 2014 22:23]

Report message to a moderator

Re: Use of Hints in Oracle 11g to get desired Execution Plan [message #610741 is a reply to message #610738] Mon, 24 March 2014 00:29 Go to previous message
Kevin Meade
Messages: 2103
Registered: December 1999
Location: Connecticut USA
Senior Member
FYI, one additional update.

It appears that this specific query rewrite was introduced in 10g. Using the OPTIMIZER_FEATURES_ENABLE hint, we are able to downgrade available optimizer features on an 11gR2 instance to simulate other prior releases.

11.2.0.1 query rewrite happens.
10.2.0.3 query rewrite happens.
 9.2.0.8 query rewrite does NOT happen.

Kevin
Previous Topic: statement with big cost
Next Topic: sql result cache for improving the performance (merged 4)
Goto Forum:
  


Current Time: Fri Mar 29 10:43:16 CDT 2024