FAQ
Folks

What standard best practices may be followed to Tune (Minimize the CPU Consumption) of the below SQL having 2 OR conditions?
NOTE - All Tables are relatively small in size i.e. upto 1 GB (NON-partitioned)

Fields which are part of the OR Conditions i.e. bo16_opportunities.assigneduserid, bo16_opportunities.salesownerid may have some NULL Values.
Qs Is breaking the single SQL into 3 separate SQLs & hence removing the OR statements Advisable? .. (the Outputs of these 3 break-down SQLs can later be merged at the Application level,)
Qs How can the Nulls (which would seemingly prevent index scan, if Null input value is passed) issue be overcome?
Qs Will partitioning help?
Other ideas pls?

Config - Oracle 10gR2 (NON-RAC) on HP-UX

Bad SQL:-

SELECT bo24_sales.applcreationdate, ...
FROM opportunities bo16_opportunities,

opportunity_products bo16_opportunity_products,
products bo21_products,
sales bo24_sales
WHERE bo16_opportunity_products.productid = bo21_products.productid
AND bo16_opportunities.opportunityid = bo16_opportunity_products.jobid(+)
AND bo16_opportunities.opportunityid = bo24_sales.opportunityid(+)
AND bo16_opportunity_products.bank_id = bo21_products.bank_id

AND bo16_opportunities.bank_id = bo16_opportunity_products.bank_id(+)
AND bo16_opportunities.bank_id = bo24_sales.bank_id(+)
AND (( ( ( (bo16_opportunities.mergedwith IS NULL)

AND (bo16_opportunities.status IN (:"SYS_B_11", :"SYS_B_12"))
)
AND (( (bo16_opportunities.owneruserid = :"SYS_B_13")
OR ( (bo16_opportunities.assigneduserid = :"SYS_B_14")
OR (bo16_opportunities.salesownerid = :"SYS_B_15")
) ) ) )
AND (ROWNUM <= :"SYS_B_16")
AND bo16_opportunities.bank_id = :"SYS_B_17") )

**************** CAUTION - Disclaimer *****************

This e-mail contains PRIVILEGED AND CONFIDENTIAL INFORMATION intended solely
for the use of the addressee(s). If you are not the intended recipient, please
notify the sender by e-mail and delete the original message. Further, you are not
to copy, disclose, or distribute this e-mail or its contents to any other person and
any such actions are unlawful. This e-mail may contain viruses. Infosys has taken
every reasonable precaution to minimize this risk, but is not liable for any damage
you may sustain as a result of any virus in this e-mail. You should carry out your
own virus checks before opening the e-mail or attachment. Infosys reserves the
right to monitor and review the content of all messages sent to or from this e-mail
address. Messages sent to or from this e-mail address may be stored on the
Infosys e-mail system.
***INFOSYS******** End of Disclaimer ********INFOSYS***

Search Discussions

  • William Robertson at Nov 19, 2008 at 8:15 am
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

    CPU is only one thing to look at when tuning. Are you saying I/O is not
    worth looking at?
    How do you know there is anything wrong with the current execution plan?
    I'm hoping that's generated code btw. Most of the brackets are
    unnecessary, the outer join is defeated by a later inner join to the
    outer-joined table, and I'm rather suspicious of the ROWNUM clause.
    This all rather leaps out at you when you format it for human
    readability (untested):
    SELECT bo24_sales.applcreationdate
    FROM   opportunities o, opportunity_products op, products p, sales s

    WHERE  o.bank_id = :"SYS_B_17"
    AND    o.mergedwith IS NULL
    AND    o.status IN (:"SYS_B_11", :"SYS_B_12")
    AND    (    o.owneruserid = :"SYS_B_13"
            OR  o.assigneduserid = :"SYS_B_14"
            OR  o.salesownerid = :"SYS_B_15" )

    AND    s.opportunityid(+) = o.opportunityid
    AND    s.bank_id(+) = o.bank_id

    AND    op.jobid(+) = o.opportunityid
    AND    op.bank_id(+) = o.bank_id

    AND    p.bank_id = op.bank_id
    AND    p.productid = op.productid

    AND    ROWNUM <= :"SYS_B_16"

    Standard Best Practice begins with confirming that there is a real
    problem, then getting the execution plan and checking the stats. Not to
    mention formatting the code.

    -----Original message-----
    From: VIVEK_SHARMA
    Date: 18/11/08 20:18

    <!--
    /* Style Definitions */
    p.MsoNormal, li.MsoNormal, div.MsoNormal
    {margin:0in;
    margin-bottom:.0001pt;
    font-size:12.0pt;
    font-family:"Times New Roman";
    color:black;}
    a:link, span.MsoHyperlink
    {color:blue;
    text-decoration:underline;}
    a:visited, span.MsoHyperlinkFollowed
    {color:blue;
    text-decoration:underline;}
    p
    {mso-margin-top-alt:auto;
    margin-right:0in;
    mso-margin-bottom-alt:auto;
    margin-left:0in;
    font-size:12.0pt;
    font-family:"Times New Roman";
    color:black;}
    span.EmailStyle18
    {mso-style-type:personal;
    font-family:Arial;
    color:navy;}
    span.EmailStyle19
    {mso-style-type:personal;
    font-family:Arial;
    color:navy;}
    span.EmailStyle20
    {mso-style-type:personal-reply;
    font-family:Arial;
    color:navy;}
    @page Section1
    {size:8.5in 11.0in;
    margin:1.0in 1.25in 1.0in 1.25in;}
    div.Section1
    {page:Section1;}
    -->

    Folks

    What
    standard best practices
    may be followed to Tune
    (Minimize the CPU Consumption) of the below SQL having 2 OR conditions?
    NOTE
    – All Tables
    are relatively small in size i.e. upto 1 GB (NON-partitioned)

    Fields
    which are part
    of the OR Conditions i.e.  bo16_opportunities.assigneduserid,
    bo16_opportunities.salesownerid
    may have some NULL Values.
    Qs
    Is breaking the
    single SQL into 3 separate SQLs & hence removing the OR statements
    Advisable? .. (the Outputs of these 3 break-down SQLs can later be
    merged at
    the Application level,)
    Qs
    How can the Nulls
    (which would seemingly prevent index scan, if Null input value is
    passed) issue
    be overcome?
    Qs
    Will partitioning
    help?
    Other
    ideas pls?

    Config
    -
    Oracle 10gR2
    (NON-RAC) on HP-UX

    Bad
    SQL:-

    SELECT
    bo24_sales.applcreationdate, …
      FROM
    opportunities
    bo16_opportunities,

    opportunity_products bo16_opportunity_products,

    products bo21_products,

    sales bo24_sales
     WHERE
    bo16_opportunity_products.productid = bo21_products.productid
       AND
    bo16_opportunities.opportunityid = bo16_opportunity_products.jobid(+)
       AND
    bo16_opportunities.opportunityid = bo24_sales.opportunityid(+)
       AND
    bo16_opportunity_products.bank_id = bo21_products.bank_id
       AND
    bo16_opportunities.bank_id = bo16_opportunity_products.bank_id(+)
       AND
    bo16_opportunities.bank_id = bo24_sales.bank_id(+)
       AND
    ((    (    (  Â
    (bo16_opportunities.mergedwith IS NULL)

    AND (bo16_opportunities.status IN (:"SYS_B_11",
    :"SYS_B_12"))

    )

    AND ((   (bo16_opportunities.owneruserid = :"SYS_B_13")

    OR ( Â
    (bo16_opportunities.assigneduserid = :"SYS_B_14")

    OR
    (bo16_opportunities.salesownerid = :"SYS_B_15")

    )                 Â
    )                Â
    )             )

    AND (ROWNUM <= :"SYS_B_16")

    AND bo16_opportunities.bank_id = :"SYS_B_17") )
  • Stefan Knecht at Nov 19, 2008 at 8:22 am
    First thing that pokes me in the eye is the rownum without any order by, nor
    a proper inline view. Do your developers realize they're fetching "SYS_B_16"
    number of RANDOM rows ?

    Stefan

    Stefan P Knecht
    Senior Consultant
    Systems Engineering

    OPITZ CONSULTING Schweiz GmbH
    Seestrasse 97
    CH-8800 Thalwil

    Mobile +41-79-571 36 27
    stefan.knecht_at_opitz-consulting.ch
    http://www.opitz-consulting.ch

    OCP 9i/10g SCSA SCNA
    On Tue, Nov 18, 2008 at 9:18 PM, VIVEK_SHARMA wrote:

    Folks



    What *standard best practices* may be followed to Tune (Minimize the CPU
    Consumption) of the below SQL having 2 OR conditions?

    NOTE � All Tables are relatively small in size i.e. upto 1 GB
    (NON-partitioned)



    Fields which are part of the OR Conditions i.e.
    bo16_opportunities.assigneduserid, bo16_opportunities.salesownerid may have
    some NULL Values.

    Qs Is breaking the single SQL into 3 separate SQLs & hence removing the OR
    statements Advisable? .. (the Outputs of these 3 break-down SQLs can later
    be merged at the Application level,)

    Qs How can the Nulls (which would seemingly prevent index scan, if Null
    input value is passed) issue be overcome?

    Qs Will partitioning help?

    Other ideas pls?



    *Config *- Oracle 10gR2 (NON-RAC) on HP-UX



    *Bad SQL:-*

    * *

    SELECT bo24_sales.applcreationdate, �

    FROM opportunities bo16_opportunities,

    opportunity_products bo16_opportunity_products,

    products bo21_products,

    sales bo24_sales

    WHERE bo16_opportunity_products.productid = bo21_products.productid

    AND bo16_opportunities.opportunityid =
    bo16_opportunity_products.jobid(+)

    AND bo16_opportunities.opportunityid = bo24_sales.opportunityid(+)

    AND bo16_opportunity_products.bank_id = bo21_products.bank_id

    AND bo16_opportunities.bank_id = bo16_opportunity_products.bank_id(+)

    AND bo16_opportunities.bank_id = bo24_sales.bank_id(+)

    AND (( ( ( (bo16_opportunities.mergedwith IS NULL)

    AND (bo16_opportunities.status IN (:"SYS_B_11",
    :"SYS_B_12"))
    )

    AND (( (bo16_opportunities.owneruserid = :"SYS_B_13")

    *OR* ( (bo16_opportunities.assigneduserid =
    :"SYS_B_14")
    *OR* (bo16_opportunities.salesownerid =
    :"SYS_B_15")
    ) ) )
    )

    AND (ROWNUM <= :"SYS_B_16")

    AND bo16_opportunities.bank_id = :"SYS_B_17") )



    **************** CAUTION - Disclaimer *****************
    This e-mail contains PRIVILEGED AND CONFIDENTIAL INFORMATION intended solely
    for the use of the addressee(s). If you are not the intended recipient, please
    notify the sender by e-mail and delete the original message. Further, you are not
    to copy, disclose, or distribute this e-mail or its contents to any other person and
    any such actions are unlawful. This e-mail may contain viruses. Infosys has taken
    every reasonable precaution to minimize this risk, but is not liable for any damage
    you may sustain as a result of any virus in this e-mail. You should carry out your
    own virus checks before opening the e-mail or attachment. Infosys reserves the
    right to monitor and review the content of all messages sent to or from this e-mail
    address. Messages sent to or from this e-mail address may be stored on the
    Infosys e-mail system.
    ***INFOSYS******** End of Disclaimer ********INFOSYS***
    --
    http://www.freelists.org/webpage/oracle-l
  • Stefan Knecht at Nov 19, 2008 at 8:23 am
    First thing that pokes me in the eye is the rownum without any order by, nor
    a proper inline view. Do your developers realize they're fetching "SYS_B_16"
    number of RANDOM rows ?

    Stefan

    Stefan P Knecht
    Senior Consultant
    Systems Engineering

    OPITZ CONSULTING Schweiz GmbH
    Seestrasse 97
    CH-8800 Thalwil

    Mobile +41-79-571 36 27
    stefan.knecht_at_opitz-consulting.ch
    http://www.opitz-consulting.ch

    OCP 9i/10g SCSA SCNA
    On Tue, Nov 18, 2008 at 9:18 PM, VIVEK_SHARMA wrote:

    Folks



    What *standard best practices* may be followed to Tune (Minimize the CPU
    Consumption) of the below SQL having 2 OR conditions?

    NOTE � All Tables are relatively small in size i.e. upto 1 GB
    (NON-partitioned)



    Fields which are part of the OR Conditions i.e.
    bo16_opportunities.assigneduserid, bo16_opportunities.salesownerid may have
    some NULL Values.

    Qs Is breaking the single SQL into 3 separate SQLs & hence removing the OR
    statements Advisable? .. (the Outputs of these 3 break-down SQLs can later
    be merged at the Application level,)

    Qs How can the Nulls (which would seemingly prevent index scan, if Null
    input value is passed) issue be overcome?

    Qs Will partitioning help?

    Other ideas pls?



    *Config *- Oracle 10gR2 (NON-RAC) on HP-UX



    *Bad SQL:-*

    * *

    SELECT bo24_sales.applcreationdate, �

    FROM opportunities bo16_opportunities,

    opportunity_products bo16_opportunity_products,

    products bo21_products,

    sales bo24_sales

    WHERE bo16_opportunity_products.productid = bo21_products.productid

    AND bo16_opportunities.opportunityid =
    bo16_opportunity_products.jobid(+)

    AND bo16_opportunities.opportunityid = bo24_sales.opportunityid(+)

    AND bo16_opportunity_products.bank_id = bo21_products.bank_id

    AND bo16_opportunities.bank_id = bo16_opportunity_products.bank_id(+)

    AND bo16_opportunities.bank_id = bo24_sales.bank_id(+)

    AND (( ( ( (bo16_opportunities.mergedwith IS NULL)

    AND (bo16_opportunities.status IN (:"SYS_B_11",
    :"SYS_B_12"))
    )

    AND (( (bo16_opportunities.owneruserid = :"SYS_B_13")

    *OR* ( (bo16_opportunities.assigneduserid =
    :"SYS_B_14")
    *OR* (bo16_opportunities.salesownerid =
    :"SYS_B_15")
    ) ) )
    )

    AND (ROWNUM <= :"SYS_B_16")

    AND bo16_opportunities.bank_id = :"SYS_B_17") )



    **************** CAUTION - Disclaimer *****************
    This e-mail contains PRIVILEGED AND CONFIDENTIAL INFORMATION intended solely
    for the use of the addressee(s). If you are not the intended recipient, please
    notify the sender by e-mail and delete the original message. Further, you are not
    to copy, disclose, or distribute this e-mail or its contents to any other person and
    any such actions are unlawful. This e-mail may contain viruses. Infosys has taken
    every reasonable precaution to minimize this risk, but is not liable for any damage
    you may sustain as a result of any virus in this e-mail. You should carry out your
    own virus checks before opening the e-mail or attachment. Infosys reserves the
    right to monitor and review the content of all messages sent to or from this e-mail
    address. Messages sent to or from this e-mail address may be stored on the
    Infosys e-mail system.
    ***INFOSYS******** End of Disclaimer ********INFOSYS***
    --
    http://www.freelists.org/webpage/oracle-l
  • Subodh Deshpande at Nov 19, 2008 at 9:12 am
    Hi Vivek,
    primafacie, I think the design is incorrect as you are using 'OR' on different columns to get your resultset.
    coming back to the query, usuage of OR is definately going to affect the performance and check whether usuage of ROWUN will affect the behavour of default indexes on your query. Think of joining first not null columns then null allowed columns, that too, as far as possible keeping the column sequence (from c1 to c10, c1, c3 are NN take first, then say c2, c4,c5 etc) in table unchanged.
    By breaking down the sql I assume you mean inline or pivoting do it if possible
    If you can treat NULLs with some different value (eg nvl (c1,'ZZ') that index can understand and will not affect your result set use it
    Sorry I do not think partitioning can help unless it is application specific requirement, as again there are different partitions that you have to decide.
    think of bitmap or reversey key index as per the occurance of data elements.

    thanks and take care..subodh

    ________________________________
    From: VIVEK_SHARMA
    To: ORACLE-L
    Sent: Wednesday, 19 November, 2008 1:48:13
    Subject: SQL Tuning Case .... Basic Qs ?

    Folks
    Â
    What standard best practices may be followed to Tune (Minimize the CPU Consumption) of the below SQL having 2 OR conditions?
    NOTE – All Tables are relatively small in size i.e. upto 1 GB (NON-partitioned)
    Â
    Fields which are part of the OR Conditions i.e.  bo16_opportunities.assigneduserid, bo16_opportunities.salesownerid may have some NULL Values.
    Qs Is breaking the single SQL into 3 separate SQLs & hence removing the OR statements Advisable? .. (the Outputs of these 3 break-down SQLs can later be merged at the Application level,)
    Qs How can the Nulls (which would seemingly prevent index scan, if Null input value is passed) issue be overcome?
    Qs Will partitioning help?
    Other ideas pls?
    Â
    Config - Oracle 10gR2 (NON-RAC) on HP-UX
    Â
    Bad SQL:-
    Â
    SELECT bo24_sales.applcreationdate, …
      FROM opportunities bo16_opportunities,
           opportunity_products bo16_opportunity_products,
           products bo21_products,
           sales bo24_sales
     WHERE bo16_opportunity_products.productid = bo21_products.productid
       AND bo16_opportunities.opportunityid = bo16_opportunity_products.jobid(+)
       AND bo16_opportunities.opportunityid = bo24_sales.opportunityid(+)
       AND bo16_opportunity_products.bank_id = bo21_products.bank_id
       AND bo16_opportunities.bank_id = bo16_opportunity_products.bank_id(+)
       AND bo16_opportunities.bank_id = bo24_sales.bank_id(+)
       AND ((    (    (    (bo16_opportunities.mergedwith IS NULL)
                       AND (bo16_opportunities.status IN (:"SYS_B_11", :"SYS_B_12"))
                      )
                  AND ((   (bo16_opportunities.owneruserid = :"SYS_B_13")
                        OR (   (bo16_opportunities.assigneduserid = :"SYS_B_14")
                           OR (bo16_opportunities.salesownerid = :"SYS_B_15")
                           )                   )                  )             )
             AND (ROWNUM <= :"SYS_B_16")
             AND bo16_opportunities.bank_id = :"SYS_B_17") )
    Â
    **************** CAUTION - Disclaimer *****************
    This e-mail contains PRIVILEGED AND CONFIDENTIAL INFORMATION intended solely
    for the use of the addressee(s). If you are not the intended recipient, please
    notify the sender by e-mail and delete the original message. Further, you are not
    to copy, disclose, or distribute this e-mail or its contents to any other person and
    any such actions are unlawful. This e-mail may contain viruses. Infosys has taken
    every reasonable precaution to minimize this risk, but is not liable for any damage
    you may sustain as a result of any virus in this e-mail. You should carry out your
    own virus checks before opening the e-mail or attachment. Infosys reserves the
    right to monitor and review the content of all messages sent to or from this e-mail
    address. Messages sent to or from this e-mail address may be stored on the
    Infosys e-mail system.
    ***INFOSYS******** End of Disclaimer ********INFOSYS***
  • William Robertson at Nov 20, 2008 at 7:32 am
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

    I don't think we can assume anything about the design from the use of
    OR here. Perhaps in the app the logic is something like: "find rows
    where a given employee is either the  owner, the assignee or the sale
    owner" (whatever those mean). That could be a perfectly valid business
    query.
    Rather than speculating about whether index use might be being
    prevented by some construction and whether it would help (sorry, reduce
    the CPU metric) to use them, it would be better to see actual
    explain plans and test timings along with table and index
    definitions etc.
    I can't really see where you are going with "joining first not null
    columns then null allowed columns" - not a rule of thumb I've come
    across before.
    Separate bitmap indexes MIGHT be worth a look for owneruserid,
    assigneduserid and salesownerid if there are enough queries like this
    to offset the additional index maintenance and locking overhead on
    insert/update/delete. However bitmap indexes are normally only
    recommended in warehouse type applications where tables can be
    populated in one shot, rather than in OLTP systems where rows are
    constantly being individually added and updated, so I would be very
    cautious about using them. (Also they are only available in Enterprise
    Edition, if that makes a difference here.)
    William Robertson
    -----Original message-----
    From: Subodh Deshpande
    Date: 19/11/08 09:12

    <!-- DIV {margin:0px;} -->

    Hi Vivek,
    primafacie, I think the design is incorrect as you are using
    'OR' on different columns to get your resultset.
    coming back to the query, usuage of OR is definately going to
    affect the performance and check whether usuage of ROWUN will affect
    the behavour of default indexes on your query. Think of joining first
    not null columns then null allowed columns, that too, as far as
    possible keeping the column sequence (from c1 to c10, c1, c3 are NN
    take first, then say c2, c4,c5 etc) in table unchanged.
    By breaking down the sql I assume you mean inline or pivoting do
    it if possible
    If you can treat NULLs with some different value (eg nvl
    (c1,'ZZ') that index can understand and will not affect your result set
    use it
    Sorry I do not think partitioning can help unless it is
    application specific requirement, as again there are different
    partitions that you have to decide.
    think of bitmap or reversey key index as per the occurance of
    data elements.

    thanks and take care..subodh

    From:
    VIVEK_SHARMA
    To: ORACLE-L

    Sent: Wednesday, 19
    November, 2008 1:48:13
    Subject: SQL Tuning
    Case .... Basic Qs ?

    <!--

    p.MsoNormal, li.MsoNormal, div.MsoNormal
    {margin:0in;margin-bottom:.0001pt;font-size:12.0pt;font-family:"Times New Roman";color:black;}
    a:link, span.MsoHyperlink
    {color:blue;text-decoration:underline;}
    a:visited, span.MsoHyperlinkFollowed
    {color:blue;text-decoration:underline;}
    p
    {margin-right:0in;margin-left:0in;font-size:12.0pt;font-family:"Times New Roman";color:black;}
    span.EmailStyle18
    {font-family:Arial;color:navy;}
    span.EmailStyle19
    {font-family:Arial;color:navy;}
    span.EmailStyle20
    {font-family:Arial;color:navy;}
    _filtered {margin:1.0in 1.25in 1.0in 1.25in;}
    div.Section1
    {}
    -->

    Folks

    What
    standard best practices
    may be followed to Tune (Minimize the CPU Consumption) of the below SQL
    having 2 OR conditions?
    NOTE
    – All Tables are relatively small in size i.e. upto 1 GB
    (NON-partitioned)

    Fields
    which are part of the OR Conditions i.e.
     bo16_opportunities.assigneduserid, bo16_opportunities.salesownerid may
    have some NULL Values.
    Qs
    Is breaking the single SQL into 3 separate SQLs & hence removing
    the OR statements Advisable? .. (the Outputs of these 3 break-down SQLs
    can later be merged at the Application level,)
    Qs
    How can the Nulls (which would seemingly prevent index scan, if Null
    input value is passed) issue be overcome?
    Qs
    Will partitioning help?
    Other
    ideas pls?

    Config
    -
    Oracle 10gR2 (NON-RAC) on HP-UX

    Bad
    SQL:-

    SELECT
    bo24_sales.applcreationdate, …
    FROM opportunities bo16_opportunities,

    opportunity_products bo16_opportunity_products,
           products
    bo21_products,
           sales
    bo24_sales
     WHERE
    bo16_opportunity_products.productid = bo21_products.productid
       AND
    bo16_opportunities.opportunityid = bo16_opportunity_products.jobid(+)
       AND
    bo16_opportunities.opportunityid = bo24_sales.opportunityid(+)
       AND
    bo16_opportunity_products.bank_id = bo21_products.bank_id
       AND
    bo16_opportunities.bank_id = bo16_opportunity_products.bank_id(+)
       AND
    bo16_opportunities.bank_id = bo24_sales.bank_id(+)
       AND ((    (  Â
    (    (bo16_opportunities.mergedwith IS NULL)

    AND (bo16_opportunities.status IN (:"SYS_B_11", :"SYS_B_12"))

    )
                  AND
    ((   (bo16_opportunities.owneruserid = :"SYS_B_13")

    OR ( Â
    (bo16_opportunities.assigneduserid = :"SYS_B_14")

    OR
    (bo16_opportunities.salesownerid = :"SYS_B_15")

    )                   )                  )             )
             AND
    (ROWNUM <= :"SYS_B_16")
             AND
    bo16_opportunities.bank_id = :"SYS_B_17") )
  • Rumpi Gravenstein at Nov 25, 2008 at 12:13 am
    tuning should start with a stated goal. I don't see that. without
    that how do you know when your done?

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouporacle-l @
categoriesoracle
postedNov 18, '08 at 8:18p
activeNov 25, '08 at 12:13a
posts7
users5
websiteoracle.com

People

Translate

site design / logo © 2023 Grokbase