Форум OlegON > Компьютеры и Программное обеспечение > Операционные системы и программное обеспечение > MySQL & MariaDB

УКМ4, стандартный экспорт 4. Как сделать запрос быстрее? : MySQL & MariaDB

23.04.2024 11:10


22.08.2013 16:21
Aleks_Str
 
УКМ4 версия 49СП8. Но это и не важно, так как вопрос про стандартный экспорт 4. Поэтому не описываю его таблицы.
Надо получить чеки за определенный день.
Пишу вот так:
Код:
SELECT r.store,r.cash_id,ri.`id`,r.date,r.`local_number`,r.`type`,ri.`item`,ri.`quantity`,
ri.`price`,if(ISNULL(rid.increment),0,rid.increment) as skid_r from receipt_item ri 
left join receipt_item_discount rid on (rid.cash_id=ri.cash_id and rid.receipt_item=ri.id) 
left join receipt r on (r.cash_id=ri.cash_id and r.id=ri.`receipt_header`) 
where r.date>"2013-08-15 05:00:00" and r.date<"2013-08-16 05:00:00" and
r.result=0
в результате время выполнения от 5 до 8 минут (для примера):
Код:
/* Результат : "записей извлечено: 82719 (00:08:55)" */
Пытался сделать без receipt_item_discount и потом засунуть результат во временную таблицу (create temporary tables XXX; insert into XXX selexct .....), и потом вЯзать временную таблицу с receipt_item_discount - вообще все зависло (запрос пришлось снять руками).
Индексы добавилял следующие:
Для receipt:
Код:
  PRIMARY KEY (`cash_id`,`id`),
  KEY `receipt_idx1` (`store`),
  KEY `receipt_idx2` (`cash_number`),
  KEY `receipt_idx3` (`local_number`),
  KEY `receipt_idx4` (`type`),
  KEY `receipt_idx5` (`date`),
  KEY `receipt_idx6` (`result`),
  KEY `receipt_idx7` (`footer_date`),
  KEY `receipt_idx8` (`ext_host`),
  KEY `receipt_idx9` (`ext_fox`),
  KEY `store_date` (`store`,`date`),
  KEY `ext_processed` (`ext_processed`)
receipt_item:
Код:
  PRIMARY KEY (`cash_id`,`id`),
  KEY `receipt_item_idx1` (`store`),
  KEY `receipt_item_idx2` (`cash_number`),
  KEY `receipt_item_idx4` (`item`),
  KEY `receipt_item_idx5` (`type`),
  KEY `receipt_item_idx3` (`receipt_header`,`cash_id`)
и для receipt_item_discount:
Код:
  PRIMARY KEY (`cash_id`,`id`),
  KEY `receipt_item_discount_idx1` (`receipt_item`),
  KEY `receipt_item_discount_idx2` (`receipt_discount`,`cash_id`)
Что поковырять можно для облегчения?
22.08.2013 16:28
OlegON
 
а почему дата со строкой сравнивается?
22.08.2013 16:39
Aleks_Str
 
эээ...вродебы именно такой формат даты в мускуле:
Код:
Как строка в формате 'YYYY-MM-DD HH:MM:SS' или в формате 'YY-MM-DD HH:MM:SS'. 
Допускается ``облегченный'' синтаксис - можно использовать любой знак пунктуации в
качестве разделительного между частями разделов даты или времени. Например, величины 
'98-12-31 11:30:45', '98.12.31 11+30+45', '98/12/31 11*30*45' и '98@12@31 11^30^45' 
являются эквивалентными.
22.08.2013 16:54
whitewizard
 
а что с версией мускула и его настройками?
22.08.2013 17:00
OlegON
 
это неявное приведение типов, не рекомендую им пользоваться. с датой это не работает, левая сторона будет приведена к строке и в итоге - фулскан, индекс-то по дате...
22.08.2013 17:06
Aleks_Str
 
версия 5.5.29 64бит
4 гб оперативки
my.ini:
Код:
[client]
	port=3306
[mysql]
	default-character-set=latin1
[mysqld]
	max_allowed_packet = 32M
	port=3306
	basedir="C:/Program Files/MySQL/MySQL Server 5.5/"
	datadir="e:/MySQL/Data/"
	slow-query-log-file="e:/MySQL/Data/show_query_log.sql"
	slow-query-log
	long_query_time=5
	character-set-server=latin1
	default-storage-engine=INNODB
	sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
	max_connections=800
	query_cache_size=350M
	table_cache=2000
	tmp_table_size=512M
	thread_cache_size=38
	myisam_max_sort_file_size=100G
	myisam_sort_buffer_size=125M
	key_buffer_size=548M
	read_rnd_buffer_size=1024K
	sort_buffer_size=1024K
	
	innodb_data_home_dir="E:/MySQL Datafiles/"
	innodb_additional_mem_pool_size=22M
	innodb_flush_log_at_trx_commit=1
	innodb_log_buffer_size=11M
	innodb_buffer_pool_size=2G
	innodb_log_file_size=213M
	innodb_thread_concurrency=10
22.08.2013 18:01
vdm
 
explain на запрос сделай. Там и смотри по каким индексам, в какой очередности таблиц отбор идет.

А "строковые" даты - для mysql это нормально, не в них дело.
26.08.2013 13:52
Aleks_Str
 
Решил "через сидячее место", но работает.
Правда, записей пока мало, и что будет дальше - неизвестно.
Создал таблицу
Код:
CREATE TABLE `ploskie_ch` (
  `store` varchar(100) NOT NULL DEFAULT '',
  `cash_number` int(11) NOT NULL DEFAULT '0',
  `cash_id` int(11) NOT NULL DEFAULT '0',
  `local_number` bigint(20) unsigned NOT NULL DEFAULT '0',
  `type` bigint(20) unsigned DEFAULT NULL,
  `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `result` bigint(20) unsigned DEFAULT NULL,
  `link_receipt` bigint(20) unsigned DEFAULT NULL,
  `link_cash_id` bigint(20) unsigned DEFAULT NULL,
  `id_ch` bigint(20) unsigned NOT NULL DEFAULT '0',
  `item` varchar(40) NOT NULL DEFAULT '',
  `name` varchar(100) NOT NULL DEFAULT '',
  `quantity` decimal(20,4) DEFAULT NULL,
  `price` decimal(20,4) NOT NULL DEFAULT '0.0000',
  `id_item` bigint(20) unsigned NOT NULL DEFAULT '0',
  `skid_r` decimal(20,4) NOT NULL DEFAULT '0.0000',
  `fio` varchar(40) NOT NULL DEFAULT '',
  PRIMARY KEY (`cash_id`,`id_ch`,`id_item`),
  KEY `idx1` (`store`),
  KEY `idx2` (`cash_number`),
  KEY `idx3` (`type`),
  KEY `idx4` (`date`),
  KEY `idx5` (`result`),
  KEY `idx6` (`id_item`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AVG_ROW_LENGTH=76;
На receipt_item подвесил триггер:
Код:
CREATE DEFINER = 'root'@'%' TRIGGER `receipt_item_after_ins_tr` AFTER INSERT ON `receipt_item`
  FOR EACH ROW
BEGIN
	set @r_cash_number := (select r.cash_number from `receipt` r where r.cash_id=NEW.cash_id and r.id=NEW.receipt_header);
	set @r_local_number := (select r.local_number from `receipt` r where r.cash_id=NEW.cash_id and r.id=NEW.receipt_header);
    set @r_type := (select r.type from `receipt` r where r.cash_id=NEW.cash_id and r.id=NEW.receipt_header);
    set @r_date := (select r.date from `receipt` r where r.cash_id=NEW.cash_id and r.id=NEW.receipt_header);
    set @r_result := (select r.result from `receipt` r where r.cash_id=NEW.cash_id and r.id=NEW.receipt_header);
    set @r_link_receipt := (select r.link_receipt from `receipt` r where r.cash_id=NEW.cash_id and r.id=NEW.receipt_header);
    set @r_link_cash_id := (select r.link_cash_id from `receipt` r where r.cash_id=NEW.cash_id and r.id=NEW.receipt_header);
    
    insert into ploskie_ch (store,cash_number,cash_id,local_number,type,date,result,link_receipt,link_cash_id,
    	id_ch,item,name,quantity,price,id_item) values (NEW.store,@r_cash_number,NEW.cash_id,@r_local_number,
        @r_type,@r_date,@r_result,@r_link_receipt,@r_link_cash_id,NEW.receipt_header,NEW.item,NEW.name,
        NEW.quantity,NEW.price,NEW.id);
END;
и на receipt_item_discount:
Код:
CREATE DEFINER = 'root'@'%' TRIGGER `receipt_item_discount_after_ins_tr` AFTER INSERT ON `receipt_item_discount`
  FOR EACH ROW
BEGIN
	if NEW.increment<>0 then
        update ploskie_ch pp set pp.skid_r=NEW.increment where
            pp.`cash_id` = NEW.cash_id and
            pp.`id_item` = NEW.receipt_item;
    end if;
END;
и на receipt_item_properties:
Код:
CREATE DEFINER = 'root'@'%' TRIGGER `receipt_item_properties_after_ins_tr` AFTER INSERT ON `receipt_item_properties`
  FOR EACH ROW
BEGIN
	if NEW.display_name="Консультант" then
        update ploskie_ch pp set pp.`fio`=NEW.value where
            pp.`cash_id` = NEW.cash_id and
            pp.`id_item` = NEW.receipt_item;
    end if;
END;
Не самое изящное решение, но пока работает!!!
Часовой пояс GMT +3, время: 11:10.

Форум на базе vBulletin®
Copyright © Jelsoft Enterprises Ltd.
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.