Jump to content

Slow Query...


js_280

Recommended Posts

I'm new to query optimization and seem to have a problem...

 

I have three tables that I am joining --

  • customer table - 300,000 rows
  • location table - 305,000 rows
  • tank table - 170,000 rows

 

I am joining the tables together with two fields each.  There is an index on the joined fields, along with all fields in the "where" statement.  When I use "explain" I get the information shown on the attached image...

Here's the query...

 

SELECT
DISTINCT
sqlar001.customerfile.customernumber,
sqlar001.customerfile.customercompanynumber,
sqlar001.customerfile.CustomerStatementName,
sqlar001.locationfile.locationnumber
FROM
sqlar001.customerfile
INNER JOIN
sqlar001.locationfile
ON
sqlar001.customerfile.customernumber = sqlar001.locationfile.locationcustomernumber AND
sqlar001.customerfile.customercompanynumber = sqlar001.locationfile.locationcompanynumber
INNER JOIN
sqlar001.tankfile
ON
sqlar001.customerfile.customernumber = sqlar001.tankfile.tankchargetocustomer AND
sqlar001.customerfile.customercompanynumber = sqlar001.tankfile.tankcompanynumber
WHERE
sqlar001.tankfile.tankrentaltank = "Y" 
AND
sqlar001.locationfile.locationnumber = ""
AND 
sqlar001.locationfile.LocationAutoFill != "Y"
AND 
sqlar001.customerfile.customercompanynumber NOT IN("355", "104");

 

The fields in the "WHERE" part of the statement are either Y/N fields or simple smallint(3) fields.

 

The query returns approx 70,000 rows and takes 17 seconds on a Intel server with 3.2GHz Xeon Processor and 4GB RAM.  MySQL, PHP and IIS are the only applications that are being utilized on this server.  This query time seems excessive to me, is there something I can change in the query to optimize it?

 

[attachment deleted by admin]

Link to comment
Share on other sites

There is a non-unique index on customerfile.customernumber, locationfile.locationcustomernumber, customerfile.customercompanynumber, locationfile.locationcompanynumber, tankfile.tankcompanynumber, and each column specified in the "Where" statement.

 

If != and NOT IN() are bad for performance, what are the other options beside listing everything I do need?  I have 355 stores and simply need to exclude two of them for reporting purposes.

 

Would it be faster performance-wise to use a sub-select than != ?

Link to comment
Share on other sites

15.075 seconds without where clauses...

 

SELECT
distinct
sqlar001.customerfile.customernumber,
sqlar001.customerfile.customercompanynumber,
sqlar001.customerfile.CustomerStatementName,
sqlar001.locationfile.locationnumber
FROM
sqlar001.customerfile
inner join
sqlar001.locationfile
on
sqlar001.customerfile.customernumber = sqlar001.locationfile.locationcustomernumber AND
sqlar001.customerfile.customercompanynumber = sqlar001.locationfile.locationcompanynumber
inner join
sqlar001.tankfile
on
sqlar001.customerfile.customernumber = sqlar001.tankfile.tankchargetocustomer and
sqlar001.customerfile.customercompanynumber = sqlar001.tankfile.tankcompanynumber;

 

[attachment deleted by admin]

Link to comment
Share on other sites

ID's are unique, however there can be multiple tanks tied to each location, and will add duplicates.

 

Indexes:

 

mysql> show indexes from customerfile \G;
*************************** 1. row ***************************
       Table: customerfile
  Non_unique: 1
    Key_name: comp_index
Seq_in_index: 1
Column_name: CustomerCompanyNumber
   Collation: A
Cardinality: 90
    Sub_part: NULL
      Packed: NULL
        Null:
  Index_type: BTREE
     Comment:
*************************** 2. row ***************************
       Table: customerfile
  Non_unique: 1
    Key_name: account_index
Seq_in_index: 1
Column_name: CustomerNumber
   Collation: A
Cardinality: 296830
    Sub_part: NULL
      Packed: NULL
        Null:
  Index_type: BTREE
     Comment:
2 rows in set (0.00 sec)


mysql> show indexes from locationfile \G;
*************************** 1. row ***************************
       Table: locationfile
  Non_unique: 1
    Key_name: locationIDX
Seq_in_index: 1
Column_name: LocationCustomerNumber
   Collation: A
Cardinality: 301336
    Sub_part: NULL
      Packed: NULL
        Null:
  Index_type: BTREE
     Comment:
*************************** 2. row ***************************
       Table: locationfile
  Non_unique: 1
    Key_name: productcodeIDX
Seq_in_index: 1
Column_name: LocationProductCategory
   Collation: A
Cardinality: 56
    Sub_part: NULL
      Packed: NULL
        Null: YES
  Index_type: BTREE
     Comment:
*************************** 3. row ***************************
       Table: locationfile
  Non_unique: 1
    Key_name: location_company
Seq_in_index: 1
Column_name: LocationCompanyNumber
   Collation: A
Cardinality: 91
    Sub_part: NULL
      Packed: NULL
        Null:
  Index_type: BTREE
     Comment:
*************************** 4. row ***************************
       Table: locationfile
  Non_unique: 1
    Key_name: location_locationnumber
Seq_in_index: 1
Column_name: LocationNumber
   Collation: A
Cardinality: 1969
    Sub_part: NULL
      Packed: NULL
        Null: YES
  Index_type: BTREE
     Comment:
4 rows in set (0.00 sec)

mysql> show indexes from tankfile \G;
*************************** 1. row ***************************
       Table: tankfile
  Non_unique: 1
    Key_name: tank_cust_index
Seq_in_index: 1
Column_name: TankChargeToCustomer
   Collation: A
Cardinality: 169650
    Sub_part: NULL
      Packed: NULL
        Null:
  Index_type: BTREE
     Comment:
*************************** 2. row ***************************
       Table: tankfile
  Non_unique: 1
    Key_name: serial_index
Seq_in_index: 1
Column_name: TankSerialNo
   Collation: A
Cardinality: 169650
    Sub_part: NULL
      Packed: NULL
        Null: YES
  Index_type: BTREE
     Comment:
*************************** 3. row ***************************
       Table: tankfile
  Non_unique: 1
    Key_name: tank_company
Seq_in_index: 1
Column_name: TankCompanyNumber
   Collation: A
Cardinality: 91
    Sub_part: NULL
      Packed: NULL
        Null:
  Index_type: BTREE
     Comment:
*************************** 4. row ***************************
       Table: tankfile
  Non_unique: 1
    Key_name: rental_tank
Seq_in_index: 1
Column_name: TankRentalTank
   Collation: A
Cardinality: 3
    Sub_part: NULL
      Packed: NULL
        Null: YES
  Index_type: BTREE
     Comment:
4 rows in set (0.00 sec)

Link to comment
Share on other sites

ID's are unique, however there can be multiple tanks tied to each location, and will add duplicates.

Then which one do you want?

 

Also, you may get some improvement from covering indexes across both columns in your on clause.

Link to comment
Share on other sites

I want to be able to get all customers using the criteria specified without having the customer listed multiple times simply because they have multiple tanks tied to their location.  Without the DISTINCT statement, I would get approximately 30,000 duplicates.

Link to comment
Share on other sites

I understand why you don't want duplicates.... but if you don't care which one, you should issue a subquery / dervied table query to limit the "extra overheard" of sorting 150K rows....

 

And still covering indexes would probably improve things, but the DISTINCT is what's killing you.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.