简体   繁体   中英

How to speed up MYSQL query with multiple joins?

looking for help to speed up this query:

SELECT tickets.ticketid, datenew, products.name 
FROM tickets 
INNER JOIN ticketlines ON tickets.id = ticketlines.ticket 
INNER JOIN products ON ticketlines.product = products.id 
INNER JOIN receipts ON receipts.id = tickets.id 
WHERE (category !='feb765ef-c8a8-4fa2-969c-90f67fe6b3be' AND category!='888f4893-f300-43b5-9933-d549ade744e0' AND category !='8f2031e8-64a4-4abf-8175-3d2bedd9f950' AND category !='ca370ced-1c3b-434c-905e-ec1bc709543b' AND category !='f92ff0ac-fa11-4a5f-a3dd-e0d9ed9c171a' AND category !='445e8605-1cd9-4714-b3fd-7389ac29c206' and category !='05143c54-8a7e-4ce2-97cc-f84f9cf41395' AND category !='8c78afea-b9e2-44cf-b497-c384045b3202' AND category !='95919f7f-ff2e-4aa1-8110-ef63c022c01b' AND category !='f4f88b05-38a1-4956-9182-4c04a0808df7') AND datedone IS NULL 
ORDER BY ticketid

This is from a cash register database that I am using to pull data for order display. The structure is the receipt has the primary id, the timein and timedone(DATEDONE) timestamps. The ticket table has ticket id which is the same as receipt id. Ticketlines table is the line items on the receipt/ticket. And then Products table has the human readable definitions of the products.

The query is to pull all items that aren't completed, ie DATEDONE is null, and display the items that were ordered.

Ticket and Receipt tables have 15K rows, Ticketlines has ~20K rows, Products has 1.5k.

Pretty small data. But this query takes over 20 seconds. I think since I am using primary key IDs for everything, I don't need to index anything, but I am a total noob, so I'm happy to be told I'm wrong. I'll appreciate any help and can provide any further details. Thanks!

EDIT:

per comments, I am showing table structures. I'm sorry for the formatting nightmare, I'm unfamiliar with this platform and unsure how to make it more readable:-(

| receipts | CREATE TABLE `receipts` (
  `ID` varchar(255) NOT NULL,
  `MONEY` varchar(255) NOT NULL,
  `DATENEW` datetime NOT NULL,
  `ATTRIBUTES` mediumblob,
  `PERSON` varchar(255) DEFAULT NULL,
  `DATEDONE` datetime DEFAULT NULL,
  PRIMARY KEY (`ID`),
  KEY `RECEIPTS_FK_MONEY` (`MONEY`),
  KEY `RECEIPTS_INX_1` (`DATENEW`),
  CONSTRAINT `RECEIPTS_FK_MONEY` FOREIGN KEY (`MONEY`) REFERENCES `closedcash` (`MONEY`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |


| tickets | CREATE TABLE `tickets` (
  `ID` varchar(255) NOT NULL,
  `TICKETTYPE` int(11) NOT NULL DEFAULT '0',
  `TICKETID` int(11) NOT NULL,
  `PERSON` varchar(255) NOT NULL,
  `CUSTOMER` varchar(255) DEFAULT NULL,
  `STATUS` int(11) NOT NULL DEFAULT '0',
  `DONE` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`ID`),
  KEY `TICKETS_FK_2` (`PERSON`),
  KEY `TICKETS_CUSTOMERS_FK` (`CUSTOMER`),
  KEY `TICKETS_TICKETID` (`TICKETTYPE`,`TICKETID`),
  CONSTRAINT `TICKETS_CUSTOMERS_FK` FOREIGN KEY (`CUSTOMER`) REFERENCES `customers` (`ID`),
  CONSTRAINT `TICKETS_FK_2` FOREIGN KEY (`PERSON`) REFERENCES `people` (`ID`),
  CONSTRAINT `TICKETS_FK_ID` FOREIGN KEY (`ID`) REFERENCES `receipts` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |


| ticketlines | CREATE TABLE `ticketlines` (
  `TICKET` varchar(255) NOT NULL,
  `LINE` int(11) NOT NULL,
  `PRODUCT` varchar(255) DEFAULT NULL,
  `ATTRIBUTESETINSTANCE_ID` varchar(255) DEFAULT NULL,
  `UNITS` double NOT NULL,
  `PRICE` double NOT NULL,
  `TAXID` varchar(255) NOT NULL,
  `ATTRIBUTES` mediumblob,
  PRIMARY KEY (`TICKET`,`LINE`),
  KEY `TICKETLINES_FK_2` (`PRODUCT`),
  KEY `TICKETLINES_ATTSETINST` (`ATTRIBUTESETINSTANCE_ID`),
  KEY `TICKETLINES_FK_3` (`TAXID`),
  CONSTRAINT `TICKETLINES_ATTSETINST` FOREIGN KEY (`ATTRIBUTESETINSTANCE_ID`) REFERENCES `attributesetinstance` (`ID`),
  CONSTRAINT `TICKETLINES_FK_2` FOREIGN KEY (`PRODUCT`) REFERENCES `products` (`ID`),
  CONSTRAINT `TICKETLINES_FK_3` FOREIGN KEY (`TAXID`) REFERENCES `taxes` (`ID`),
  CONSTRAINT `TICKETLINES_FK_TICKET` FOREIGN KEY (`TICKET`) REFERENCES `tickets` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

| products | CREATE TABLE `products` (
  `ID` varchar(255) NOT NULL,
  `REFERENCE` varchar(255) NOT NULL,
  `CODE` varchar(255) NOT NULL,
  `CODETYPE` varchar(255) DEFAULT NULL,
  `NAME` varchar(255) NOT NULL,
  `PRICEBUY` double NOT NULL,
  `PRICESELL` double NOT NULL,
  `CATEGORY` varchar(255) NOT NULL,
  `TAXCAT` varchar(255) NOT NULL,
  `ATTRIBUTESET_ID` varchar(255) DEFAULT NULL,
  `STOCKCOST` double DEFAULT NULL,
  `STOCKVOLUME` double DEFAULT NULL,
  `IMAGE` mediumblob,
  `ISCOM` bit(1) NOT NULL DEFAULT b'0',
  `ISSCALE` bit(1) NOT NULL DEFAULT b'0',
  `ISKITCHEN` bit(1) NOT NULL DEFAULT b'0',
  `PRINTKB` bit(1) NOT NULL DEFAULT b'0',
  `SENDSTATUS` bit(1) NOT NULL DEFAULT b'0',
  `ISSERVICE` bit(1) NOT NULL DEFAULT b'0',
  `ATTRIBUTES` mediumblob,
  `DISPLAY` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE KEY `PRODUCTS_INX_0` (`REFERENCE`),
  UNIQUE KEY `PRODUCTS_INX_1` (`CODE`),
  UNIQUE KEY `PRODUCTS_NAME_INX` (`NAME`),
  KEY `PRODUCTS_FK_1` (`CATEGORY`),
  KEY `PRODUCTS_TAXCAT_FK` (`TAXCAT`),
  KEY `PRODUCTS_ATTRSET_FK` (`ATTRIBUTESET_ID`),
  CONSTRAINT `PRODUCTS_ATTRSET_FK` FOREIGN KEY (`ATTRIBUTESET_ID`) REFERENCES `attributeset` (`ID`),
  CONSTRAINT `PRODUCTS_FK_1` FOREIGN KEY (`CATEGORY`) REFERENCES `categories` (`ID`),
  CONSTRAINT `PRODUCTS_TAXCAT_FK` FOREIGN KEY (`TAXCAT`) REFERENCES `taxcategories` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

Also, here is EXPLAIN output:

| id | select_type | table       | partitions | type   | possible_keys            | key     | key_len | ref                                | rows  | filtered | Extra                                        |
+----+-------------+-------------+------------+--------+--------------------------+---------+---------+------------------------------------+-------+----------+----------------------------------------------+
|  1 | SIMPLE      | receipts    | NULL       | ALL    | PRIMARY                  | NULL    | NULL    | NULL                               | 14624 |    10.00 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | tickets     | NULL       | eq_ref | PRIMARY                  | PRIMARY | 767     | receipts.ID         |     1 |   100.00 | NULL                                         |
|  1 | SIMPLE      | ticketlines | NULL       | ref    | PRIMARY,TICKETLINES_FK_2 | PRIMARY | 767     | receipts.ID         |     1 |   100.00 | Using where                                  |
|  1 | SIMPLE      | products    | NULL       | eq_ref | PRIMARY,PRODUCTS_FK_1    | PRIMARY | 767     | ticketlines.PRODUCT |     1 |    97.97 | Using where                                  |
+----+-------------+-------------+------------+--------+--------------------------+---------+---------+------------------------------------+-------+----------+----------------------------------------------+
4 rows in set, 1 warning (0.04 sec)

Try changing data types of all columns to the minimal required ones. Add indexes on columns in WHERE. Add index on ticketlines.ticket.

I ended up deleted 10K rows from every linked table and it queries running in.2 seconds now. I guess absent any more advice, i will be doing annual cleanup of old tickets.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM