MySQL 8 оконная функция неверные результаты - PullRequest
0 голосов
/ 03 июля 2018

У меня проблема с оконными функциями в MySQL8 - они дают неверные результаты при применении к большим таблицам (либо: большое количество строк или большое количество столбцов).

Пример: Таблица: bureau.csv (1,7 млн. Строк) из https://www.kaggle.com/c/home-credit-default-risk/data

Я выполняю 3 простых запроса, меняя только количество строк в таблице и количество столбцов, которые нужно вычислить. Вы можете ясно видеть, что комбинация большого количества строк и большого количества столбцов с ошибками дает неверные результаты «count (*) over ()» - последний столбец.

большое количество строк, небольшое количество столбцов - результат: ОК;

большое количество строк, большое количество столбцов - результат: НЕПРАВИЛЬНО;

небольшое количество строк, высокое количество столбцов - результат: ОК;

Ubuntu 16.04, 32 ГБ ОЗУ

Большое спасибо за Вашу помощь! :)

Витольд

my.cnf:
[mysqld]

innodb_buffer_pool_size = 26G
default_authentication_plugin=mysql_native_password
thread_cache_size = 50
innodb-flush-method=O_DIRECT
local_infile=ON
innodb_thread_concurrency=2
internal_tmp_mem_storage_engine=MEMORY
join_buffer_size=1G
temptable_max_ram=4G
tmp_table_size=4G
max_heap_table_size=4G
mysqlx_connect_timeout=99999
mysqlx_read_timeout=99999
mysqlx_write_timeout=99999
net_read_timeout=99999
net_write_timeout=99999
regexp_time_limit=99999
mysqlx_port_open_timeout=99999
windowing-use-high-precision=OFF
sort_buffer_size=4G

Код для запуска:

select a.*
from
(
select #b.sk_id_curr,
       b.*,
       count(*) over(partition by b.sk_id_curr) as counter
from (select * from bureau limit 10000000) b
) a
order by a.sk_id_curr desc
limit 100
;

редактирование: объяснение и указатели картинка

И еще одна вещь, которую я заметил: на рисунке «НЕПРАВИЛЬНО» все столбцы неверны (не только последний) - сравните с изображениями с «ХОРОШИМ» результатом »(посмотрите на sk_id_curr).

По просьбе Уилсона Хаука: A) завершить (не редактировать) my.cnf-ini Текстовые результаты: B) SHOW GLOBAL STATUS; В) ПОКАЗАТЬ ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ; D) ПОКАЗАТЬ ДВИГАТЕЛЬ INNODB STATUS; ШОУ CREATE TABLE бюро; часть1 часть2

Пример 1000 строк в БД Fiddle: https://www.db -fiddle.com / f / fzXsN6vFzidhanxeUjWkiB / 0

То, как я импортировал данные в mysql:

Сначала Я заменил «пробелы» в csv на «NULL» в python:

import pandas as pd
bureau = pd.read_csv('../input/bureau.csv')
bureau.to_csv('../input/bureau2.csv',index=False,na_rep="NULL",header=True)

Секунда Я использовал код в MySQL:

LOAD DATA LOCAL INFILE '../input/bureau2.csv' INTO TABLE bureau
FIELDS TERMINATED BY ',' ENCLOSED BY '"' 
LINES TERMINATED BY '\n'
IGNORE 1 LINES
;

Ответы [ 3 ]

0 голосов
/ 23 июля 2018

Я скачал bureau.csv и импортировал его, используя вашу таблицу, как показано в вашей ссылке 'part2'. Мне пришлось отключить строгий режим

set session sql_mode='';)

иначе я получил ошибки при загрузке данных

(load data  infile 'bureau.csv' into table bureau columns terminated by "," ignore 1 lines;

Моя статистика немного отличалась от вашей: show indexes from bureau

Затем я выполнил ваш ошибочный запрос и получил ожидаемые результаты:

enter image description here

Какую точную версию MySQL 8 вы используете?

Текстовая версия запроса:

select a.*
   from
   (
   select #b.sk_id_curr,
          b.*,
          count(*) over(partition by b.sk_id_curr)
   from (select * from bureau limit 10000000000) b
   ) a
   order by a.sk_id_curr desc
   limit 100
   ;
0 голосов
/ 27 июля 2018

Эта версия дала ожидаемые результаты для 8.0.11 для меня (обратите внимание, что больше нет текстовых блобов). Вам также необходимо отключить --big_tables, если он установлен для этой работы.

CREATE TABLE `bureau` (
 `SK_ID_CURR` int(11) DEFAULT NULL,
 `SK_ID_BUREAU` int(11) DEFAULT NULL,
 `CREDIT_ACTIVE` varchar(20),
 `CREDIT_CURRENCY` varchar(20),
 `DAYS_CREDIT` int(11) DEFAULT NULL,
 `CREDIT_DAY_OVERDUE` int(11) DEFAULT NULL,
 `DAYS_CREDIT_ENDDATE` varchar(20),
 `DAYS_ENDDATE_FACT` varchar(20),
 `AMT_CREDIT_MAX_OVERDUE` varchar(20),
 `CNT_CREDIT_PROLONG` int(11) DEFAULT NULL,
 `AMT_CREDIT_SUM` double DEFAULT NULL,
 `AMT_CREDIT_SUM_DEBT` varchar(20),
 `AMT_CREDIT_SUM_LIMIT` varchar(20),
 `AMT_CREDIT_SUM_OVERDUE` double DEFAULT NULL,
 `CREDIT_TYPE` varchar(20),
 `DAYS_CREDIT_UPDATE` int(11) DEFAULT NULL,
 `AMT_ANNUITY` varchar(20),
 KEY `bureau` (`SK_ID_CURR`,`SK_ID_BUREAU`),
 KEY `bureau_i2` (`SK_ID_BUREAU`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

set session sql_mode='';
load data infile '/export/home/tmp/dag/git/mysql/bureau.csv' into table bureau columns terminated by "," ignore 1 lines;


select a.*
from
(
select #b.sk_id_curr,
       b.*,
       count(*) over(partition by b.sk_id_curr) as counter
from (select * from bureau) b
) a
order by a.sk_id_curr desc
limit 100
;
0 голосов
/ 18 июля 2018

Предложения для вашего раздела my.cnf-ini [mysqld]

temptable_max_ram=320M # from 4G for 1 percent of RAM 
tmp_table_size=320M # from 4G for 1 percent of RAM 
max_heap_table_size=320M # from 4G for 1 percent of RAM 
innodb_thread_concurrency=0 # from 2 throttle choking your server 
innodb_buffer_pool_size=24G # from 26G for 80% of RAM 
innodb_change_buffer_max_size=10 # from 25 percent set aside 
# sort_buffer_size=4G for default 
# join_buffer_size=4G for default 

только с 32G RAM, вы просили 26G, 1G, 4G, 4G, 4G, 4G = 43G, не оставляя ничего для MySQL и OS?

Для получения дополнительной помощи, проверьте профиль, профиль сети для контактной информации.

...